From 0c90ed3253337bfd864b4d780df4701d0cc0f2c4 Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Wed, 25 Sep 2019 09:49:27 -0400 Subject: [PATCH] The index key for user records now omits non-alphanumeric characters, in addition to the previous behavior of converting to lower case. --- citadel/citadel.h | 4 +-- citadel/citserver.c | 7 +++++ citadel/server_main.c | 2 +- citadel/threads.c | 1 - citadel/user_ops.c | 62 +++++++++++++++++++++++++++++++++++++++---- citadel/user_ops.h | 1 + 6 files changed, 68 insertions(+), 9 deletions(-) diff --git a/citadel/citadel.h b/citadel/citadel.h index 881faac63..96908acce 100644 --- a/citadel/citadel.h +++ b/citadel/citadel.h @@ -35,7 +35,7 @@ extern "C" { */ #define CITADEL PACKAGE_STRING -#define REV_LEVEL 927 // This version +#define REV_LEVEL 928 // This version #define REV_MIN 591 // Oldest compatible database #define EXPORT_REV_MIN 760 // Oldest compatible export files #define LIBCITADEL_MIN 922 // Minimum required version of libcitadel @@ -176,7 +176,7 @@ struct floor { /* number of items which may be handled by the CONF command */ #define NUM_CONFIGS 71 -#define TRACE syslog(LOG_DEBUG, "\033[31mCheckpoint: %s : %d\033[0m", __FILE__, __LINE__) +#define TRACE syslog(LOG_DEBUG, "\033[7m Checkpoint: %s : %d \033[0m", __FILE__, __LINE__) #ifndef LONG_MAX #define LONG_MAX 2147483647L diff --git a/citadel/citserver.c b/citadel/citserver.c index 6e287a706..3eb8cf2a7 100644 --- a/citadel/citserver.c +++ b/citadel/citserver.c @@ -71,6 +71,13 @@ void master_startup(void) validate_config(); migrate_legacy_control_record(); + // If we have an existing database that is older than version 928, reindex the user records. + // Unfortunately we cannot do this in serv_upgrade.c because it needs to happen VERY early during startup. + int existing_db = CtdlGetConfigInt("MM_hosted_upgrade_level"); + if ( (existing_db > 0) && (existing_db < 928) ) { + ForEachUser(reindex_user_928, NULL); + } + /* Check floor reference counts */ check_ref_counts(); diff --git a/citadel/server_main.c b/citadel/server_main.c index 9bd9be89e..8e3a8d254 100644 --- a/citadel/server_main.c +++ b/citadel/server_main.c @@ -252,7 +252,7 @@ int main(int argc, char **argv) ctdl_lockfile(1); init_sysdep(); // Initialize... master_startup(); // Do non system dependent startup functions - check_control(); // Check, sanitize, initialize the control record + check_control(); // Check/sanitize/initialize control record, fix user indexes syslog(LOG_INFO, "main: upgrading modules"); // Run any upgrade entry points upgrade_modules(); diff --git a/citadel/threads.c b/citadel/threads.c index b0856bf22..ab7157bd8 100644 --- a/citadel/threads.c +++ b/citadel/threads.c @@ -137,7 +137,6 @@ void CtdlThreadCreate(void *(*start_routine)(void*)) void InitializeMasterTSD(void) { - TRACE; memset(&masterTSD, 0, sizeof(struct thread_tsd)); } diff --git a/citadel/user_ops.c b/citadel/user_ops.c index 0a74759ae..aaf26a5b3 100644 --- a/citadel/user_ops.c +++ b/citadel/user_ops.c @@ -49,18 +49,22 @@ long cutusername(char *username) { /* * makeuserkey() - convert a username into the format used as a database key - * (it's just the username converted into lower case) + * (Key format is the username with all non-alphanumeric characters removed, and converted to lower case.) */ void makeuserkey(char *key, const char *username, long len) { int i; + int keylen = 0; if (len >= USERNAME_SIZE) { syslog(LOG_INFO, "Username too long: %s", username); len = USERNAME_SIZE - 1; } for (i=0; i<=len; ++i) { - key[i] = tolower(username[i]); + if (isalnum((username[i]))) { + key[keylen++] = tolower(username[i]); + } } + key[keylen++] = 0; } @@ -198,6 +202,57 @@ int rename_user(char *oldname, char *newname) { } +/* + * Convert a username into the format used as a database key prior to version 928 + * (This is only used during database upgrade) + */ +void makeuserkey_pre928(char *key, const char *username, long len) { + int i; + + if (len >= USERNAME_SIZE) { + syslog(LOG_INFO, "Username too long: %s", username); + len = USERNAME_SIZE - 1; + } + for (i=0; i<=len; ++i) { + key[i] = tolower(username[i]); + } +} + + +/* + * Read a user record using the pre-v928 index format, and write it back using the v928-and-higher index format. + * This ONLY gets called by... + */ +void reindex_user_928(char *username, void *out_data) { + + char oldkey[USERNAME_SIZE]; + char newkey[USERNAME_SIZE]; + struct cdbdata *cdbus; + long len = cutusername(username); + struct ctdluser usbuf; + + makeuserkey_pre928(oldkey, username, len); + makeuserkey(newkey, username, len); + + syslog(LOG_DEBUG, "user_ops: reindex_user_928 <%s> <%s> <%s>", username, oldkey, newkey); + + // Fetch the user record using the old index format + cdbus = cdb_fetch(CDB_USERS, oldkey, strlen(oldkey)); + if (cdbus == NULL) { + syslog(LOG_INFO, "user_ops: <%s> not found, were they already reindexed?", username); + return; + } + memcpy(&usbuf, cdbus->ptr, ((cdbus->len > sizeof(struct ctdluser)) ? sizeof(struct ctdluser) : cdbus->len)); + cdb_free(cdbus); + + // delete the old record + cdb_delete(CDB_USERS, oldkey, strlen(oldkey)); + + // write the new record + cdb_store(CDB_USERS, newkey, strlen(newkey), &usbuf, sizeof(struct ctdluser)); +} + + /* * Index-generating function used by Ctdl[Get|Set]Relationship */ @@ -1170,9 +1225,6 @@ void ForEachUser(void (*CallBack) (char *, void *out_data), void *in_data) // Phase 2 : perform the callback for each username for (i=0; i