+/*
+ * Create a new user account, manually specifying the name, after successfully
+ * verifying an OpenID (which will of course be attached to the account)
+ */
+void cmd_oidc(char *argbuf) {
+ ctdl_openid *oiddata = (ctdl_openid *) CC->openid_data;
+
+ if (CtdlGetConfigInt("c_disable_newu"))
+ {
+ cprintf("%d this system does not support openid.\n",
+ ERROR + CMD_NOT_SUPPORTED);
+ return;
+ }
+ if ( (!oiddata) || (!oiddata->verified) ) {
+ cprintf("%d You have not verified an OpenID yet.\n", ERROR);
+ return;
+ }
+
+ /* We can make the semantics of OIDC exactly the same as NEWU, simply
+ * by _calling_ cmd_newu() and letting it run. Very clever!
+ */
+ cmd_newu(argbuf);
+
+ /* Now, if this logged us in, we have to attach the OpenID */
+ if (CC->logged_in) {
+ attach_extauth(&CC->user, oiddata->claimed_id);
+ }
+
+}
+
+
+/*
+ * Detach an OpenID from the currently logged in account
+ */
+void cmd_oidd(char *argbuf) {
+ struct cdbdata *cdboi;
+ char id_to_detach[1024];
+ int this_is_mine = 0;
+ long usernum = 0L;
+
+ if (CtdlGetConfigInt("c_disable_newu"))
+ {
+ cprintf("%d this system does not support openid.\n",
+ ERROR + CMD_NOT_SUPPORTED);
+ return;
+ }
+ if (CtdlAccessCheck(ac_logged_in)) return;
+ extract_token(id_to_detach, argbuf, 0, '|', sizeof id_to_detach);
+ if (IsEmptyStr(id_to_detach)) {
+ cprintf("%d An empty OpenID URL is not allowed.\n", ERROR + ILLEGAL_VALUE);
+ }
+
+ cdb_rewind(CDB_EXTAUTH);
+ while (cdboi = cdb_next_item(CDB_EXTAUTH), cdboi != NULL) {
+ if (cdboi->len > sizeof(long)) {
+ memcpy(&usernum, cdboi->ptr, sizeof(long));
+ if (usernum == CC->user.usernum) {
+ this_is_mine = 1;
+ }
+ }
+ cdb_free(cdboi);
+ }
+
+ if (!this_is_mine) {
+ cprintf("%d That OpenID was not found or not associated with your account.\n",
+ ERROR + ILLEGAL_VALUE);
+ return;
+ }
+
+ cdb_delete(CDB_EXTAUTH, id_to_detach, strlen(id_to_detach));
+ cprintf("%d %s detached from your account.\n", CIT_OK, id_to_detach);
+}
+
+
+/*
+ * Attempt to auto-create a new Citadel account using the nickname from Attribute Exchange
+ */
+int openid_create_user_via_ax(StrBuf *claimed_id, HashList *sreg_keys)
+{
+ char *nickname = NULL;
+ char *firstname = NULL;
+ char *lastname = NULL;
+ char new_password[32];
+ long len;
+ const char *Key;
+ void *Value;
+
+ if (CtdlGetConfigInt("c_auth_mode") != AUTHMODE_NATIVE) return(1);
+ if (CtdlGetConfigInt("c_disable_newu")) return(2);
+ if (CC->logged_in) return(3);
+
+ HashPos *HashPos = GetNewHashPos(sreg_keys, 0);
+ while (GetNextHashPos(sreg_keys, HashPos, &len, &Key, &Value) != 0) {
+ syslog(LOG_DEBUG, "openid: %s = %s", Key, (char *)Value);
+
+ if (cbmstrcasestr(Key, "value.nickname") != NULL) {
+ nickname = (char *)Value;
+ }
+ else if ( (nickname == NULL) && (cbmstrcasestr(Key, "value.nickname") != NULL)) {
+ nickname = (char *)Value;
+ }
+ else if (cbmstrcasestr(Key, "value.firstname") != NULL) {
+ firstname = (char *)Value;
+ }
+ else if (cbmstrcasestr(Key, "value.lastname") != NULL) {
+ lastname = (char *)Value;
+ }
+
+ }
+ DeleteHashPos(&HashPos);
+
+ if (nickname == NULL) {
+ if ((firstname != NULL) || (lastname != NULL)) {
+ char fullname[1024] = "";
+ if (firstname) strcpy(fullname, firstname);
+ if (firstname && lastname) strcat(fullname, " ");
+ if (lastname) strcat(fullname, lastname);
+ nickname = fullname;
+ }
+ }
+
+ if (nickname == NULL) {
+ return(4);
+ }
+ syslog(LOG_DEBUG, "openid: the desired account name is <%s>", nickname);
+
+ len = cutusername(nickname);
+ if (!CtdlGetUser(&CC->user, nickname)) {
+ syslog(LOG_DEBUG, "openid: <%s> is already taken by another user.", nickname);
+ memset(&CC->user, 0, sizeof(struct ctdluser));
+ return(5);
+ }
+
+ /* The desired account name is available. Create the account and log it in! */
+ if (create_user(nickname, CREATE_USER_BECOME_USER, NATIVE_AUTH_UID)) return(6);
+
+ /* Generate a random password.
+ * The user doesn't care what the password is since he is using OpenID.
+ */
+ snprintf(new_password, sizeof new_password, "%08lx%08lx", random(), random());
+ CtdlSetPassword(new_password);
+
+ /* Now attach the verified OpenID to this account. */
+ attach_extauth(&CC->user, claimed_id);
+
+ return(0);
+}
+