From 542e41ae940e81eb03d49fddd744c74941a5ff12 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Wilfried=20G=C3=B6esgens?= Date: Fri, 22 Jan 2010 21:55:22 +0000 Subject: [PATCH] * add literal support to imap login / passwords; this should fix our communication with nginx as proxy. --- citadel/modules/imap/serv_imap.c | 92 +++++++++++++++++++++++--------- citadel/modules/imap/serv_imap.h | 4 +- 2 files changed, 71 insertions(+), 25 deletions(-) diff --git a/citadel/modules/imap/serv_imap.c b/citadel/modules/imap/serv_imap.c index 9bd44105a..e3f9e4b5f 100644 --- a/citadel/modules/imap/serv_imap.c +++ b/citadel/modules/imap/serv_imap.c @@ -541,21 +541,35 @@ void imaps_greeting(void) { */ void imap_login(int num_parms, char *parms[]) { - if (num_parms != 4) { - cprintf("%s BAD incorrect number of parameters\r\n", parms[0]); - return; - } - if (CtdlLoginExistingUser(NULL, parms[2]) == login_ok) { - if (CtdlTryPassword(parms[3]) == pass_ok) { - cprintf("%s OK [", parms[0]); - imap_output_capability_string(); - cprintf("] Hello, %s\r\n", CC->user.fullname); + switch (num_parms) { + case 3: + if (parms[2][0] == '{') { + cprintf("+ go ahead\r\n"); + IMAP->authstate = imap_as_expecting_multilineusername; + strcpy(IMAP->authseq, parms[0]); + return; + } + else { + cprintf("%s BAD incorrect number of parameters\r\n", parms[0]); return; } + case 4: + if (CtdlLoginExistingUser(NULL, parms[2]) == login_ok) { + if (CtdlTryPassword(parms[3]) == pass_ok) { + cprintf("%s OK [", parms[0]); + imap_output_capability_string(); + cprintf("] Hello, %s\r\n", CC->user.fullname); + return; + } + } + + cprintf("%s BAD Login incorrect\r\n", parms[0]); + default: + cprintf("%s BAD incorrect number of parameters\r\n", parms[0]); + return; } - cprintf("%s BAD Login incorrect\r\n", parms[0]); } @@ -634,26 +648,46 @@ void imap_auth_plain(char *cmd) } -void imap_auth_login_user(char *cmd) +void imap_auth_login_user(char *cmd, long state) { char buf[SIZ]; - CtdlDecodeBase64(buf, cmd, SIZ); - CtdlLoginExistingUser(NULL, buf); - CtdlEncodeBase64(buf, "Password:", 9, 0); - cprintf("+ %s\r\n", buf); - IMAP->authstate = imap_as_expecting_password; - return; + switch (state){ + case imap_as_expecting_username: + CtdlDecodeBase64(buf, cmd, SIZ); + CtdlLoginExistingUser(NULL, buf); + CtdlEncodeBase64(buf, "Password:", 9, 0); + cprintf("+ %s\r\n", buf); + + IMAP->authstate = imap_as_expecting_password; + return; + case imap_as_expecting_multilineusername: + extract_token(buf, cmd, 1, ' ', sizeof(buf)); + CtdlLoginExistingUser(NULL, cmd); + cprintf("+ go ahead\r\n"); + IMAP->authstate = imap_as_expecting_multilinepassword; + return; + } } -void imap_auth_login_pass(char *cmd) +void imap_auth_login_pass(char *cmd, long state) { + char *pass = NULL; char buf[SIZ]; - memset(buf, 0, sizeof(buf)); - CtdlDecodeBase64(buf, cmd, SIZ); - if (CtdlTryPassword(buf) == pass_ok) { + switch (state) { + default: + case imap_as_expecting_password: + memset(buf, 0, sizeof(buf)); + CtdlDecodeBase64(buf, cmd, SIZ); + pass = buf; + break; + case imap_as_expecting_multilinepassword: + pass = cmd; + break; + } + if (CtdlTryPassword(pass) == pass_ok) { cprintf("%s OK authentication succeeded\r\n", IMAP->authseq); } else { cprintf("%s NO authentication failed\r\n", IMAP->authseq); @@ -1381,7 +1415,8 @@ void imap_command_loop(void) else if (IMAP->authstate == imap_as_expecting_plainauth) { CtdlLogPrintf(CTDL_INFO, "IMAP: \n"); } - else if (bmstrcasestr(cmdbuf, " LOGIN ")) { + else if ((IMAP->authstate == imap_as_expecting_multilineusername) || + bmstrcasestr(cmdbuf, " LOGIN ")) { CtdlLogPrintf(CTDL_INFO, "IMAP: LOGIN...\n"); } else { @@ -1400,7 +1435,11 @@ void imap_command_loop(void) /* If we're in the middle of a multi-line command, handle that */ if (IMAP->authstate == imap_as_expecting_username) { - imap_auth_login_user(cmdbuf); + imap_auth_login_user(cmdbuf, imap_as_expecting_username); + return; + } + if (IMAP->authstate == imap_as_expecting_multilineusername) { + imap_auth_login_user(cmdbuf, imap_as_expecting_multilineusername); return; } if (IMAP->authstate == imap_as_expecting_plainauth) { @@ -1408,9 +1447,14 @@ void imap_command_loop(void) return; } if (IMAP->authstate == imap_as_expecting_password) { - imap_auth_login_pass(cmdbuf); + imap_auth_login_pass(cmdbuf, imap_as_expecting_password); return; } + if (IMAP->authstate == imap_as_expecting_multilinepassword) { + imap_auth_login_pass(cmdbuf, imap_as_expecting_multilinepassword); + return; + } + /* Ok, at this point we're in normal command mode. * If the command just submitted does not contain a literal, we diff --git a/citadel/modules/imap/serv_imap.h b/citadel/modules/imap/serv_imap.h index e2b3f4334..27ace03bf 100644 --- a/citadel/modules/imap/serv_imap.h +++ b/citadel/modules/imap/serv_imap.h @@ -48,7 +48,9 @@ enum { imap_as_normal, imap_as_expecting_username, imap_as_expecting_password, - imap_as_expecting_plainauth + imap_as_expecting_plainauth, + imap_as_expecting_multilineusername, + imap_as_expecting_multilinepassword }; /* Flags for the above struct. Note that some of these are for internal use, -- 2.30.2