From: Art Cancro Date: Thu, 29 May 2008 16:49:28 +0000 (+0000) Subject: getuserbynumber() now uses a proper indexed database X-Git-Tag: v7.86~2194 X-Git-Url: https://code.citadel.org/?a=commitdiff_plain;h=6e1b646b62cd5be85e15a432ca8fd399d97531c5;p=citadel.git getuserbynumber() now uses a proper indexed database --- diff --git a/citadel/citadel.h b/citadel/citadel.h index 044392379..4fba49041 100644 --- a/citadel/citadel.h +++ b/citadel/citadel.h @@ -38,7 +38,7 @@ extern "C" { * usually more strict because you're not really supposed to dump/load and * upgrade at the same time. */ -#define REV_LEVEL 735 /* This version */ +#define REV_LEVEL 736 /* This version */ #define REV_MIN 591 /* Oldest compatible database */ #define EXPORT_REV_MIN 733 /* Oldest compatible export files */ #define LIBCITADEL_MIN 113 /* Minimum required version of libcitadel */ diff --git a/citadel/database_cleanup.sh.in b/citadel/database_cleanup.sh.in index fa1d8b3ce..0d3aeb93d 100755 --- a/citadel/database_cleanup.sh.in +++ b/citadel/database_cleanup.sh.in @@ -99,7 +99,7 @@ case "$yesno" in exit esac -for x in 00 01 02 03 04 05 06 07 08 09 0a +for x in 00 01 02 03 04 05 06 07 08 09 0a 0b do filename=cdb.$x echo Dumping $filename @@ -110,7 +110,7 @@ done echo Removing old databases rm -f ./data/* -for x in 00 01 02 03 04 05 06 07 08 09 0a +for x in 00 01 02 03 04 05 06 07 08 09 0a 0b do filename=cdb.$x echo Loading $filename diff --git a/citadel/database_sleepycat.c b/citadel/database_sleepycat.c index 907a15aff..f6ac91179 100644 --- a/citadel/database_sleepycat.c +++ b/citadel/database_sleepycat.c @@ -145,7 +145,7 @@ static void bailIfCursor(DBC ** cursors, const char *msg) for (i = 0; i < MAXCDB; i++) if (cursors[i] != NULL) { CtdlLogPrintf(CTDL_EMERG, - "cdb_*: cursor still in progress on cdb %d: %s\n", + "cdb_*: cursor still in progress on cdb %02x: %s\n", i, msg); abort(); } @@ -391,7 +391,7 @@ void open_databases(void) DB_CREATE | DB_AUTO_COMMIT | DB_THREAD, 0600); if (ret) { - CtdlLogPrintf(CTDL_EMERG, "db_open[%d]: %s\n", i, + CtdlLogPrintf(CTDL_EMERG, "db_open[%02x]: %s\n", i, db_strerror(ret)); exit(CTDLEXIT_DB); } @@ -454,7 +454,7 @@ void close_databases(void) /* close the tables */ for (a = 0; a < MAXCDB; ++a) { - CtdlLogPrintf(CTDL_INFO, "Closing database %d\n", a); + CtdlLogPrintf(CTDL_INFO, "Closing database %02x\n", a); ret = dbp[a]->close(dbp[a], 0); if (ret) { CtdlLogPrintf(CTDL_EMERG, diff --git a/citadel/modules/openid/serv_openid_rp.c b/citadel/modules/openid/serv_openid_rp.c index eaccbc6dd..0657f5acf 100644 --- a/citadel/modules/openid/serv_openid_rp.c +++ b/citadel/modules/openid/serv_openid_rp.c @@ -39,6 +39,55 @@ struct ctdl_openid { }; + + + +/**************************************************************************/ +/* */ +/* Functions in this section handle Citadel internal OpenID mapping stuff */ +/* */ +/**************************************************************************/ + + +/* + * Attach or detach an OpenID to a Citadel account + */ + +enum { + moa_detach, + moa_attach +}; + +int modify_openid_associations(struct ctdluser *who, char *claimed_id, int operation) +{ + if (!who) return(1); + if (!claimed_id) return(1); + if (IsEmptyStr(claimed_id)) return(1); + + return(2); // error because we are not done yet FIXME +} + + +/* + * When a user is being deleted, we have to delete any OpenID associations + */ +void openid_purge(struct ctdluser *usbuf) { + /* FIXME finish this */ +} + + + + + + + +/**************************************************************************/ +/* */ +/* Functions in this section handle OpenID protocol */ +/* */ +/**************************************************************************/ + + /* * Locate a tag and, given its 'rel=' parameter, return its 'href' parameter */ @@ -203,10 +252,14 @@ void cmd_oids(char *argbuf) { struct CitContext *CCC = CC; /* CachedCitContext - performance boost */ struct ctdl_openid *oiddata; + /* commented out because we may be attempting to attach an OpenID to + * an existing account that is logged in + * if (CCC->logged_in) { cprintf("%d Already logged in.\n", ERROR + ALREADY_LOGGED_IN); return; } + */ if (CCC->openid_data != NULL) { free(CCC->openid_data); @@ -329,8 +382,8 @@ void cmd_oidf(char *argbuf) { char k_keyname[128]; char k_o_keyname[128]; char *k_value = NULL; - char valbuf[1024]; + struct fh_data fh = { valbuf, 0, @@ -408,17 +461,37 @@ void cmd_oidf(char *argbuf) { curl_formfree(formpost); valbuf[fh.total_bytes_received] = 0; + int success = 0; + if (bmstrcasestr(valbuf, "is_valid:true")) { - CtdlLogPrintf(CTDL_DEBUG, "AUTHENTICATION SUCCEEDED\n", valbuf); - } - else { - CtdlLogPrintf(CTDL_DEBUG, "AUTHENTICATION FAILED\n", valbuf); + success = 1; } - /* FIXME do something with the results */ + CtdlLogPrintf(CTDL_DEBUG, "Authentication %s.\n", (success ? "succeeded" : "failed") ); /* Respond to the client */ - cprintf("message|FIXME finish this\n"); + + if (success) { + + /* If we were already logged in, attach the OpenID to the user's account */ + if (CC->logged_in) { + if (modify_openid_associations(&CC->user, oiddata->claimed_id, moa_attach) == 0) { + cprintf("attach\n"); + } + else { + cprintf("fail\n"); + } + } + + /* Otherwise, a user is attempting to log in using the validated OpenID */ + else { + cprintf("fail\n"); // FIXME do the login here!! + } + + } + else { + cprintf("fail\n"); + } cprintf("000\n"); /* Free the hash list */ @@ -448,6 +521,15 @@ void cmd_oidf(char *argbuf) { // sig = [28] vixxxU4MAqWfxxxxCfrHv3TxxxhEw= + + +/**************************************************************************/ +/* */ +/* Functions in this section handle module initialization and shutdown */ +/* */ +/**************************************************************************/ + + /* * This cleanup function blows away the temporary memory used by this module. */ @@ -459,7 +541,6 @@ void openid_cleanup_function(void) { } - CTDL_MODULE_INIT(openid_rp) { if (!threading) @@ -468,6 +549,7 @@ CTDL_MODULE_INIT(openid_rp) CtdlRegisterProtoHook(cmd_oids, "OIDS", "Setup OpenID authentication"); CtdlRegisterProtoHook(cmd_oidf, "OIDF", "Finalize OpenID authentication"); CtdlRegisterSessionHook(openid_cleanup_function, EVT_STOP); + CtdlRegisterUserHook(openid_purge, EVT_PURGEUSER); } /* return our Subversion id for the Log */ diff --git a/citadel/modules/upgrade/serv_upgrade.c b/citadel/modules/upgrade/serv_upgrade.c index ce147b9b9..df2c197aa 100644 --- a/citadel/modules/upgrade/serv_upgrade.c +++ b/citadel/modules/upgrade/serv_upgrade.c @@ -269,9 +269,12 @@ void check_server_upgrades(void) { if ((CitControl.version > 000) && (CitControl.version < 659)) { rebuild_euid_index(); } - if (CitControl.version > 734) { + if (CitControl.version < 735) { fix_sys_user_name(); } + if (CitControl.version < 736) { + rebuild_usersbynumber(); + } CitControl.version = REV_LEVEL; put_control(); } @@ -280,6 +283,7 @@ void check_server_upgrades(void) { CTDL_MODULE_UPGRADE(upgrade) { check_server_upgrades(); + rebuild_usersbynumber(); // FIXME take this out /* return our Subversion id for the Log */ return "$Id$"; diff --git a/citadel/server.h b/citadel/server.h index e0a21acac..1c2af0e4f 100644 --- a/citadel/server.h +++ b/citadel/server.h @@ -291,6 +291,7 @@ enum { CDB_BIGMSGS, /* larger message bodies */ CDB_FULLTEXT, /* full text search index */ CDB_EUIDINDEX, /* locate msgs by EUID */ + CDB_USERSBYNUMBER, /* index of users by number */ MAXCDB /* total number of CDB's defined */ }; diff --git a/citadel/user_ops.c b/citadel/user_ops.c index b78e8a3e9..ac25b1a89 100644 --- a/citadel/user_ops.c +++ b/citadel/user_ops.c @@ -196,6 +196,9 @@ int rename_user(char *oldname, char *newname) { cdb_delete(CDB_USERS, oldnamekey, strlen(oldnamekey)); safestrncpy(usbuf.fullname, newname, sizeof usbuf.fullname); putuser(&usbuf); + cdb_store(CDB_USERSBYNUMBER, &usbuf.usernum, sizeof(long), + usbuf.fullname, strlen(usbuf.fullname)+1 ); + retcode = RENAMEUSER_OK; } } @@ -355,33 +358,83 @@ int is_room_aide(void) } /* - * getuserbynumber() - get user by number - * returns 0 if user was found + * getuserbynumber() - get user by number + * returns 0 if user was found * - * WARNING: don't use this function unless you absolutely have to. It does - * a sequential search and therefore is computationally expensive. + * Note: fetching a user this way requires one additional database operation. */ -int getuserbynumber(struct ctdluser *usbuf, long int number) +int getuserbynumber(struct ctdluser *usbuf, long number) { - struct cdbdata *cdbus; + struct cdbdata *cdbun; + int r; - cdb_rewind(CDB_USERS); + cdbun = cdb_fetch(CDB_USERSBYNUMBER, &number, sizeof(long)); + if (cdbun == NULL) { + CtdlLogPrintf(CTDL_INFO, "User %ld not found\n", number); + return(-1); + } - while (cdbus = cdb_next_item(CDB_USERS), cdbus != NULL) { - memset(usbuf, 0, sizeof(struct ctdluser)); - memcpy(usbuf, cdbus->ptr, - ((cdbus->len > sizeof(struct ctdluser)) ? - sizeof(struct ctdluser) : cdbus->len)); - cdb_free(cdbus); - if (usbuf->usernum == number) { - cdb_close_cursor(CDB_USERS); - return (0); - } + CtdlLogPrintf(CTDL_INFO, "User %ld maps to %s\n", number, cdbun->ptr); + r = getuser(usbuf, cdbun->ptr); + cdb_free(cdbun); + return(r); +} + + + +/* + * Helper function for rebuild_usersbynumber() + */ +void rebuild_ubn_for_user(struct ctdluser *usbuf, void *data) { + + struct ubnlist { + struct ubnlist *next; + char username[USERNAME_SIZE]; + long usernum; + }; + + static struct ubnlist *u = NULL; + struct ubnlist *ptr = NULL; + + /* Lazy programming here. Call this function as a ForEachUser backend + * in order to queue up the room names, or call it with a null user + * to make it do the processing. + */ + if (usbuf != NULL) { + ptr = (struct ubnlist *) malloc(sizeof (struct ubnlist)); + if (ptr == NULL) return; + + ptr->usernum = usbuf->usernum; + safestrncpy(ptr->username, usbuf->fullname, sizeof ptr->username); + ptr->next = u; + u = ptr; + return; } - return (-1); + + while (u != NULL) { + CtdlLogPrintf(CTDL_DEBUG, "Rebuilding usersbynumber index %10ld : %s\n", + u->usernum, u->username); + cdb_store(CDB_USERSBYNUMBER, &u->usernum, sizeof(long), u->username, strlen(u->username)+1); + + ptr = u; + u = u->next; + free(ptr); + } +} + + + +/* + * Rebuild the users-by-number index + */ +void rebuild_usersbynumber(void) { + cdb_trunc(CDB_USERSBYNUMBER); /* delete the old indices */ + ForEachUser(rebuild_ubn_for_user, NULL); /* enumerate the users */ + rebuild_ubn_for_user(NULL, NULL); /* and index them */ } + /* * getuserbyuid() - get user by system uid (for PAM mode authentication) * returns 0 if user was found @@ -911,6 +964,9 @@ int purge_user(char pname[]) /* delete any existing user/room relationships */ cdb_delete(CDB_VISIT, &usbuf.usernum, sizeof(long)); + /* delete the users-by-number index record */ + cdb_delete(CDB_USERSBYNUMBER, &usbuf.usernum, sizeof(long)); + /* delete the userlog entry */ cdb_delete(CDB_USERS, usernamekey, strlen(usernamekey)); @@ -1018,8 +1074,9 @@ int create_user(char *newusername, int become_user) usbuf.axlevel = 6; } - /* add user to userlog */ + /* add user to the database */ putuser(&usbuf); + cdb_store(CDB_USERSBYNUMBER, &usbuf.usernum, sizeof(long), usbuf.fullname, strlen(usbuf.fullname)+1); /* * Give the user a private mailbox and a configuration room. diff --git a/citadel/user_ops.h b/citadel/user_ops.h index bf1be2cfb..70c1b00c6 100644 --- a/citadel/user_ops.h +++ b/citadel/user_ops.h @@ -7,6 +7,7 @@ void lputuser (struct ctdluser *); int is_aide (void); int is_room_aide (void); int getuserbynumber (struct ctdluser *usbuf, long int number); +void rebuild_usersbynumber(void); void cmd_user (char *cmdbuf); void session_startup (void); void logout (void);