* You must free the returned pointer when done.
*/
struct CitContext *CtdlGetContextArray (int *count);
+void CtdlFillPrivateContext(struct CitContext *context, char *name);
CtdlLogPrintf(CTDL_DEBUG, "checkpoint_thread() initializing\n");
- memset(&checkpointCC, 0, sizeof(struct CitContext));
- checkpointCC.internal_pgm = 1;
- checkpointCC.cs_pid = 0;
- pthread_setspecific(MyConKey, (void *)&checkpointCC );
+ CtdlFillPrivateContext(&checkpointCC, "checkpoint");
+ citthread_setspecific(MyConKey, (void *)&checkpointCC );
while (!CtdlThreadCheckStop()) {
cdb_checkpoint();
int messages_purged;
int users_not_purged;
char *users_corrupt_msg = NULL;
+char *users_zero_msg = NULL;
struct ctdlroomref *rr = NULL;
{
users_corrupt_msg = malloc(SIZ);
strcpy(users_corrupt_msg, "The auto-purger found the following user numbers with no name.\n"
+ "If the user number is 0 you should report this to the Citadel development\n"
+ "team either by a bugzilla report at http://bugzilla.citadel.org or\n"
+ "posting a message in the Citadel Support room on Uncensored at\n"
+ "https://uncensored.citadel.org You should make it clear that you have seen a\n"
+ "user 0 messages in the Aide room which means a module has not named its\n"
+ "private context.\n"
"Unfortunately the auto-purger is not yet able to fix this problem.\n"
"This problem is not considered serious since a user with no name can\n"
"not log in.\n");
users_corrupt_msg=realloc(users_corrupt_msg, strlen(users_corrupt_msg)+SIZ);
snprintf(&users_corrupt_msg[strlen(users_corrupt_msg)], SIZ, " %ld\n", us->usernum);
}
+ else if (us->usernum == 0L)
+ {
+ purge=0;
+ if (users_zero_msg == NULL)
+ {
+ users_zero_msg = malloc(SIZ);
+ strcpy(users_zero_msg, "The auto-purger found a user with a user number of 0 but no name.\n"
+ "This is the result of a bug where a private contaxt has been created but\n"
+ "not named.\n\n"
+ "Please report this to the Citadel development team either by a bugzilla\n"
+ "report at http://bugzilla.citadel.org or by posting a message in the\n"
+ "Citadel Support room on Uncensored at https://uncensored.citadel.org\n"
+ "You should make it clear that you have seen a user 0 messages in the\n"
+ "Aide room which means a module has not named its private context.\n\n"
+ "This problem is not considered serious since it does not constitute a\n"
+ "security risk and should not impare system operation.\n"
+ );
+ }
+ }
+
}
users_corrupt_msg = NULL;
}
+ if(users_zero_msg)
+ {
+ aide_message(users_zero_msg, "User Zero Message");
+ free (users_zero_msg);
+ users_zero_msg = NULL;
+ }
CtdlLogPrintf(CTDL_DEBUG, "Purged %d users.\n", num_users_purged);
return(num_users_purged);
CtdlLogPrintf(CTDL_DEBUG, "Auto-purger_thread() initializing\n");
- memset(&purgerCC, 0, sizeof(struct CitContext));
- purgerCC.internal_pgm = 1;
- purgerCC.cs_pid = 0;
- pthread_setspecific(MyConKey, (void *)&purgerCC );
+ CtdlFillPrivateContext(&purgerCC, "purger");
+ citthread_setspecific(MyConKey, (void *)&purgerCC );
while (!CtdlThreadCheckStop()) {
/* Do the auto-purge if the current hour equals the purge hour,
CtdlLogPrintf(CTDL_DEBUG, "indexer_thread() initializing\n");
- memset(&indexerCC, 0, sizeof(struct CitContext));
- indexerCC.internal_pgm = 1;
- indexerCC.cs_pid = 0;
- pthread_setspecific(MyConKey, (void *)&indexerCC );
+ CtdlFillPrivateContext(&indexerCC, "indexer");
+ citthread_setspecific(MyConKey, (void *)&indexerCC );
while (!CtdlThreadCheckStop()) {
do_fulltext_indexing();
struct CitContext networkerCC;
/* Give the networker its own private CitContext */
- memset(&networkerCC, 0, sizeof(struct CitContext));
- networkerCC.internal_pgm = 1;
- networkerCC.cs_pid = 0;
- pthread_setspecific(MyConKey, (void *)&networkerCC );
+ CtdlFillPrivateContext(&networkerCC, "network");
+ citthread_setspecific(MyConKey, (void *)&networkerCC );
/*
* Run the full set of processing tasks no more frequently
struct CitContext rssclientCC;
/* Give this thread its own private CitContext */
- memset(&rssclientCC, 0, sizeof(struct CitContext));
- rssclientCC.internal_pgm = 1;
- rssclientCC.cs_pid = 0;
- pthread_setspecific(MyConKey, (void *)&rssclientCC );
+ CtdlFillPrivateContext(&rssclientCC, "rssclient");
+ citthread_setspecific(MyConKey, (void *)&rssclientCC );
CtdlThreadAllocTSD();
#include "ctdl_module.h"
+
+/*
+ * Fix up the name for Citadel user 0 and try to remove any extra users with number 0
+ */
+void fix_sys_user_name(void)
+{
+ struct ctdluser usbuf;
+ char usernamekey[USERNAME_SIZE];
+
+ /** If we have a user called Citadel rename them to SYS_Citadel */
+ if (getuser(&usbuf, "Citadel") == 0)
+ {
+ rename_user("Citadel", "SYS_Citadel");
+ }
+
+ while (getuserbynumber(&usbuf, 0) == 0)
+ {
+ /* delete user with number 0 and no name */
+ if (IsEmptyStr(usbuf.fullname))
+ cdb_delete(CDB_USERS, "", 0);
+ else
+ { /* temporarily set this user to -1 */
+ usbuf.usernum = -1;
+ putuser(&usbuf);
+ }
+ }
+
+ /** Make sure user SYS_* is user 0 */
+ while (getuserbynumber(&usbuf, -1) == 0)
+ {
+ if (strncmp(usbuf.fullname, "SYS_", 4))
+ { /** Delete any user 0 that doesn't start with SYS_ */
+ makeuserkey(usernamekey, usbuf.fullname);
+ cdb_delete(CDB_USERS, usernamekey, strlen(usernamekey));
+ }
+ else
+ {
+ usbuf.usernum = 0;
+ putuser(&usbuf);
+ }
+ }
+}
+
+
/*
* Back end processing function for cmd_bmbx
*/
if ((CitControl.version > 000) && (CitControl.version < 659)) {
rebuild_euid_index();
}
-
+ if (CitControl.version > 734) {
+ fix_sys_user_name();
+ }
CitControl.version = REV_LEVEL;
put_control();
}
*/
master_startup();
+ /*
+ * Run any upgrade entry points
+ */
+ CtdlLogPrintf(CTDL_INFO, "Upgrading modules.\n");
+ upgrade_modules();
-/*
- * Initialise the user 0 to have a name. It would be nice to do it in InitializeMasterCC
- * since it is contained within the MasterCC but we can't because the DB isn't available
- * at that time so we do it seperate.
+/**
+ * Load the user for the masterCC or create them if they don't exist
*/
- /** Give user 0 a name and create them if necessary */
- if (getuser(&masterCC.user, "Citadel"))
+ if (getuser(&masterCC.user, "SYS_Citadel"))
{
- getuserbynumber(&masterCC.user, 0);
- strcpy (masterCC.user.fullname, "Citadel");
+ /** User doesn't exist. We can't use create user here as the user number needs to be 0 */
+ strcpy (masterCC.user.fullname, "SYS_Citadel") ;
putuser(&masterCC.user);
+ getuser(&masterCC.user, "SYS_Citadel"); /** Just to be safe */
}
/*
CitadelServiceTCP);
- /*
- * Run any upgrade entry points
- */
- CtdlLogPrintf(CTDL_INFO, "Upgrading modules.\n");
- upgrade_modules();
/*
#include "ctdl_module.h"
#include "threads.h"
+#include "user_ops.h"
+
#ifdef DEBUG_MEMORY_LEAKS
struct igheap {
return nptr;
}
+
+
+/**
+ * This function returns a private context with the user filled in correctly
+ */
+void CtdlFillPrivateContext(struct CitContext *context, char *name)
+{
+ char sysname[USERNAME_SIZE];
+
+ memset(context, 0, sizeof(struct CitContext));
+ context->internal_pgm = 1;
+ context->cs_pid = 0;
+ strcpy (sysname, "SYS_");
+ strcat (sysname, name);
+ if (getuser(&(context->user), sysname))
+ {
+ strcpy(context->user.fullname, sysname);
+ putuser(&(context->user));
+ }
+}
+
/*
* The following functions implement output buffering. If the kernel supplies
* native TCP buffering (Linux & *BSD), use that; otherwise, emulate it with
* makeuserkey() - convert a username into the format used as a database key
* (it's just the username converted into lower case)
*/
-static INLINE void makeuserkey(char *key, char *username) {
+INLINE void makeuserkey(char *key, char *username) {
int i, len;
len = strlen(username);
if (trythisname == NULL) return login_not_found;
- if (!strcasecmp(trythisname, "Citadel"))
+ if (!strncasecmp(trythisname, "SYS_", 4))
{
- CtdlLogPrintf(CTDL_DEBUG, "System user \"Citadel\" is not allowed to log in.\n");
+ CtdlLogPrintf(CTDL_DEBUG, "System user \"%s\" is not allowed to log in.\n", trythisname);
return login_not_found;
}
#define RENAMEUSER_ALREADY_EXISTS 3 /* An account with the desired new name already exists */
int rename_user(char *oldname, char *newname);
+INLINE void makeuserkey(char *key, char *username);