X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fuser_ops.c;h=0dc5ae3276b4909587f673041368b5f53cc2fc8a;hb=882ff5a53c3b4e440520a073cf07dc60b2671876;hp=f8c74445d9a89bd3ed4068042bb511fe6b85fd1c;hpb=27014176ee36ef29b80da016f3fd5772189f8377;p=citadel.git diff --git a/citadel/user_ops.c b/citadel/user_ops.c index f8c74445d..0dc5ae327 100644 --- a/citadel/user_ops.c +++ b/citadel/user_ops.c @@ -1,7 +1,7 @@ /* * Server functions which perform operations on user objects. * - * Copyright (c) 1987-2019 by the citadel.org team + * Copyright (c) 1987-2020 by the citadel.org team * * This program is open source software; you can redistribute it and/or * modify it under the terms of the GNU General Public License, version 3. @@ -31,37 +31,42 @@ int chkpwd_write_pipe[2]; int chkpwd_read_pipe[2]; + /* - * Trim a string down to the maximum username size and return the new length + * makeuserkey() - convert a username into the format used as a database key + * "key" must be a buffer of at least USERNAME_SIZE + * (Key format is the username with all non-alphanumeric characters removed, and converted to lower case.) */ -long cutusername(char *username) { - long len; - len = strlen(username); - if (len >= USERNAME_SIZE) - { - syslog(LOG_INFO, "Username too long: %s", username); - len = USERNAME_SIZE - 1; - username[len]='\0'; +void makeuserkey(char *key, const char *username) { + int i; + int keylen = 0; + + if (IsEmptyStr(username)) { + key[0] = 0; + return; } - return len; + + int len = strlen(username); + for (i=0; ((i<=len) && (i= 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]); - } + makeuserkey(k1, s1); + makeuserkey(k2, s2); + return(strcmp(k1,k2)); } @@ -73,13 +78,12 @@ int CtdlGetUser(struct ctdluser *usbuf, char *name) { char usernamekey[USERNAME_SIZE]; struct cdbdata *cdbus; - long len = cutusername(name); if (usbuf != NULL) { memset(usbuf, 0, sizeof(struct ctdluser)); } - makeuserkey(usernamekey, name, len); + makeuserkey(usernamekey, name); cdbus = cdb_fetch(CDB_USERS, usernamekey, strlen(usernamekey)); if (cdbus == NULL) { /* user not found */ @@ -122,7 +126,7 @@ void CtdlPutUser(struct ctdluser *usbuf) { char usernamekey[USERNAME_SIZE]; - makeuserkey(usernamekey, usbuf->fullname, cutusername(usbuf->fullname)); + makeuserkey(usernamekey, usbuf->fullname); usbuf->version = REV_LEVEL; cdb_store(CDB_USERS, usernamekey, strlen(usernamekey), usbuf, sizeof(struct ctdluser)); } @@ -158,8 +162,8 @@ int rename_user(char *oldname, char *newname) { char newnamekey[USERNAME_SIZE]; /* Create the database keys... */ - makeuserkey(oldnamekey, oldname, cutusername(oldname)); - makeuserkey(newnamekey, newname, cutusername(newname)); + makeuserkey(oldnamekey, oldname); + makeuserkey(newnamekey, newname); /* Lock up and get going */ begin_critical_section(S_USERS); @@ -178,10 +182,8 @@ int rename_user(char *oldname, char *newname) { if (CtdlGetUser(&usbuf, oldname) != 0) { retcode = RENAMEUSER_NOT_FOUND; } - else { /* Sanity checks succeeded. Now rename the user. */ - if (usbuf.usernum == 0) - { + if (usbuf.usernum == 0) { syslog(LOG_DEBUG, "user_ops: can not rename user \"Citadel\"."); retcode = RENAMEUSER_NOT_FOUND; } else { @@ -201,6 +203,58 @@ int rename_user(char *oldname, char *newname) { } +/* + * Convert a username into the format used as a database key prior to version 928 + * This only gets called by reindex_user_928() + */ +void makeuserkey_pre928(char *key, const char *username) { + int i; + + int len = strlen(username); + + 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 during an upgrade from version <928 to version >=928. + */ +void reindex_user_928(char *username, void *out_data) { + + char oldkey[USERNAME_SIZE]; + char newkey[USERNAME_SIZE]; + struct cdbdata *cdbus; + struct ctdluser usbuf; + + makeuserkey_pre928(oldkey, username); + makeuserkey(newkey, username); + + 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 */ @@ -209,7 +263,6 @@ int GenerateRelationshipIndex(char *IndexBuf, long RoomGen, long UserID) { - struct { long iRoomID; long iRoomGen; @@ -247,10 +300,7 @@ void put_visit(visit *newvisit) /* * Define a relationship between a user and a room */ -void CtdlSetRelationship(visit *newvisit, - struct ctdluser *rel_user, - struct ctdlroom *rel_room) -{ +void CtdlSetRelationship(visit *newvisit, struct ctdluser *rel_user, struct ctdlroom *rel_room) { /* We don't use these in Citadel because they're implicit by the * index, but they must be present if the database is exported. */ @@ -265,10 +315,7 @@ void CtdlSetRelationship(visit *newvisit, /* * Locate a relationship between a user and a room */ -void CtdlGetRelationship(visit *vbuf, - struct ctdluser *rel_user, - struct ctdlroom *rel_room) -{ +void CtdlGetRelationship(visit *vbuf, struct ctdluser *rel_user, struct ctdlroom *rel_room) { char IndexBuf[32]; int IndexLen; struct cdbdata *cdbvisit; @@ -576,7 +623,7 @@ int CtdlLoginExistingUser(const char *trythisname) else { /* native auth mode */ - recptypes *valid = NULL; + struct recptypes *valid = NULL; /* First, try to log in as if the supplied name is a display name */ found_user = CtdlGetUser(&CC->user, username); @@ -651,6 +698,12 @@ void do_login(void) AutoGenerateEmailAddressForUser(&CC->user); } + /* Populate the user principal identity, which is consistent and never aliased */ + strcpy(CC->cs_principal_id, ""); + makeuserkey(CC->cs_principal_id, CC->user.fullname); + strcat(CC->cs_principal_id, "@"); + strcat(CC->cs_principal_id, CtdlGetConfigStr("c_fqdn")); + /* * Populate cs_inet_email and cs_inet_other_emails with valid email addresses from the user record */ @@ -918,7 +971,7 @@ int purge_user(char pname[]) struct ctdluser usbuf; char usernamekey[USERNAME_SIZE]; - makeuserkey(usernamekey, pname, cutusername(pname)); + makeuserkey(usernamekey, pname); /* If the name is empty we can't find them in the DB any way so just return */ if (IsEmptyStr(pname)) { @@ -1149,44 +1202,46 @@ int CtdlForgetThisRoom(void) { */ void ForEachUser(void (*CallBack) (char *, void *out_data), void *in_data) { + struct cdbdata *cdbus; + struct ctdluser *usptr; + struct feu { + struct feu *next; char username[USERNAME_SIZE]; - int version; }; - - struct cdbdata *cdbus; - struct ctdluser *usptr; - int i = 0; - struct feu *usernames = NULL; - int num_users = 0; - int num_users_alloc = 0; + struct feu *ufirst = NULL; + struct feu *ulast = NULL; + struct feu *f = NULL; cdb_rewind(CDB_USERS); - // Phase 1 : load list of usernames + // Phase 1 : build a linked list of all our user account names while (cdbus = cdb_next_item(CDB_USERS), cdbus != NULL) { usptr = (struct ctdluser *) cdbus->ptr; if (strlen(usptr->fullname) > 0) { - ++num_users; - if (num_users > num_users_alloc) { - num_users_alloc = ((num_users_alloc == 0) ? 1 : (num_users_alloc * 2)); - usernames = realloc(usernames, num_users_alloc * sizeof(struct feu)); + f = malloc(sizeof(struct feu)); + f->next = NULL; + strncpy(f->username, usptr->fullname, USERNAME_SIZE); + + if (ufirst == NULL) { + ufirst = f; + ulast = f; + } + else { + ulast->next = f; + ulast = f; } - strcpy(usernames[num_users-1].username, usptr->fullname); - usernames[num_users-1].version = usptr->version; } } - // Phase 2 : perform the callback for each username - for (i=0; iusername, in_data); + f = ufirst; + ufirst = ufirst->next; + free(f); } - - free(usernames); }