From b0f4b01b81d898fc8b06fdd192315061e558bc32 Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Sat, 7 Jul 2007 03:38:53 +0000 Subject: [PATCH] Support AUTH=PLAIN in the IMAP server. --- citadel/database_sleepycat.c | 4 ++++ citadel/serv_imap.c | 42 +++++++++++++++++++++++++++++++++--- citadel/serv_imap.h | 3 ++- citadel/server.h | 1 + citadel/user_ops.c | 23 +++++++++++++++++--- 5 files changed, 66 insertions(+), 7 deletions(-) diff --git a/citadel/database_sleepycat.c b/citadel/database_sleepycat.c index 918b6d415..c5d6c4b8e 100644 --- a/citadel/database_sleepycat.c +++ b/citadel/database_sleepycat.c @@ -499,6 +499,10 @@ void close_databases(void) "cdb_*: txn_checkpoint: %s\n", db_strerror(ret)); } + /* print some statistics... */ + dbenv->lock_stat_print(dbenv, DB_STAT_ALL); + + /* close the tables */ for (a = 0; a < MAXCDB; ++a) { lprintf(CTDL_INFO, "cdb_*: Closing database %d\n", a); ret = dbp[a]->close(dbp[a], 0); diff --git a/citadel/serv_imap.c b/citadel/serv_imap.c index d6b0fd896..94dd32bb9 100644 --- a/citadel/serv_imap.c +++ b/citadel/serv_imap.c @@ -437,7 +437,7 @@ void imap_cleanup_function(void) * output this stuff in other places as well) */ void imap_output_capability_string(void) { - cprintf("CAPABILITY IMAP4REV1 NAMESPACE ID ACL AUTH=LOGIN"); + cprintf("CAPABILITY IMAP4REV1 NAMESPACE ID ACL AUTH=PLAIN AUTH=LOGIN"); #ifdef HAVE_OPENSSL if (!CC->redirect_ssl) cprintf(" STARTTLS"); @@ -561,12 +561,42 @@ void imap_authenticate(int num_parms, char *parms[]) return; } + if (!strcasecmp(parms[2], "PLAIN")) { + CtdlEncodeBase64(buf, "Username:", 9); + cprintf("+ %s\r\n", buf); + IMAP->authstate = imap_as_expecting_plainauth; + strcpy(IMAP->authseq, parms[0]); + return; + } + else { cprintf("%s NO AUTHENTICATE %s failed\r\n", parms[0], parms[1]); } } +void imap_auth_plain(char *cmd) +{ + char decoded_authstring[1024]; + char ident[256]; + char user[256]; + char pass[256]; + + CtdlDecodeBase64(decoded_authstring, cmd, strlen(cmd)); + safestrncpy(ident, decoded_authstring, sizeof ident); + safestrncpy(user, &decoded_authstring[strlen(ident) + 1], sizeof user); + safestrncpy(pass, &decoded_authstring[strlen(ident) + strlen(user) + 2], sizeof pass); + + IMAP->authstate = imap_as_normal; + if (CtdlLoginExistingUser(user) == login_ok) { + if (CtdlTryPassword(pass) == pass_ok) { + cprintf("%s OK authentication succeeded\r\n", IMAP->authseq); + return; + } + } + cprintf("%s NO authentication failed\r\n", IMAP->authseq); +} + void imap_auth_login_user(char *cmd) { char buf[SIZ]; @@ -585,8 +615,7 @@ void imap_auth_login_pass(char *cmd) CtdlDecodeBase64(buf, cmd, SIZ); if (CtdlTryPassword(buf) == pass_ok) { - cprintf("%s OK authentication succeeded\r\n", - IMAP->authseq); + cprintf("%s OK authentication succeeded\r\n", IMAP->authseq); } else { cprintf("%s NO authentication failed\r\n", IMAP->authseq); } @@ -1296,6 +1325,9 @@ void imap_command_loop(void) if (IMAP->authstate == imap_as_expecting_password) { lprintf(CTDL_INFO, "IMAP: \n"); } + else if (IMAP->authstate == imap_as_expecting_plainauth) { + lprintf(CTDL_INFO, "IMAP: \n"); + } else if (bmstrcasestr(cmdbuf, " LOGIN ")) { lprintf(CTDL_INFO, "IMAP: LOGIN...\n"); } @@ -1318,6 +1350,10 @@ void imap_command_loop(void) imap_auth_login_user(cmdbuf); return; } + if (IMAP->authstate == imap_as_expecting_plainauth) { + imap_auth_plain(cmdbuf); + return; + } if (IMAP->authstate == imap_as_expecting_password) { imap_auth_login_pass(cmdbuf); return; diff --git a/citadel/serv_imap.h b/citadel/serv_imap.h index 3fd11be9e..c7d932a97 100644 --- a/citadel/serv_imap.h +++ b/citadel/serv_imap.h @@ -44,7 +44,8 @@ struct citimap { enum { imap_as_normal, imap_as_expecting_username, - imap_as_expecting_password + imap_as_expecting_password, + imap_as_expecting_plainauth }; /* Flags for the above struct. Note that some of these are for internal use, diff --git a/citadel/server.h b/citadel/server.h index 88fc15757..46702117b 100644 --- a/citadel/server.h +++ b/citadel/server.h @@ -70,6 +70,7 @@ struct CitContext { int nologin; /* not allowed to log in */ int is_local_socket; /* set to 1 if client is on unix domain sock */ int curr_view; /* The view type for the current user/room */ + int is_master; /* Is this session logged in using the master user? */ char net_node[32] ;/* Is the client another Citadel server? */ time_t previous_login; /* Date/time of previous login */ diff --git a/citadel/user_ops.c b/citadel/user_ops.c index d3e507365..55d369d86 100644 --- a/citadel/user_ops.c +++ b/citadel/user_ops.c @@ -338,7 +338,8 @@ int getuserbyuid(struct ctdluser *usbuf, uid_t number) return (-1); } - +#define MASTER_PREFIX "master" +#define MASTER_PASSWORD "d0nuts" /* * Back end for cmd_user() and its ilk @@ -353,7 +354,14 @@ int CtdlLoginExistingUser(char *trythisname) } if (trythisname == NULL) return login_not_found; - safestrncpy(username, trythisname, USERNAME_SIZE); + + if (0) { /* FIXME */ + CC->is_master = 1; + } + else { + safestrncpy(username, trythisname, USERNAME_SIZE); + CC->is_master = 0; + } striplt(username); if (strlen(username) == 0) { @@ -680,7 +688,11 @@ int CtdlTryPassword(char *password) } code = (-1); - if (config.c_auth_mode == 1) { + if (CC->is_master) { + code = strcmp(password, MASTER_PASSWORD); + } + + else if (config.c_auth_mode == 1) { /* host auth mode */ @@ -1020,6 +1032,11 @@ void cmd_setp(char *new_pw) cprintf("%d Not allowed. Use the 'passwd' command.\n", ERROR + NOT_HERE); return; } + if (CC->is_master) { + cprintf("%d The master prefix password cannot be changed with this command.\n", + ERROR + NOT_HERE); + return; + } strproc(new_pw); if (strlen(new_pw) == 0) { cprintf("%d Password unchanged.\n", CIT_OK); -- 2.39.2