? ChangeLog Index: folder_imap.c =================================================================== RCS file: /cvsroot/mailutils/mailutils/mailbox/folder_imap.c,v retrieving revision 1.38 diff -u -r1.38 folder_imap.c --- folder_imap.c 2001/10/20 04:19:38 1.38 +++ folder_imap.c 2001/10/30 05:33:39 @@ -153,8 +153,8 @@ } /* Simple User/pass authentication for imap. */ -static int -imap_user (authority_t auth) +int +authenticate_imap_login (authority_t auth) { folder_t folder = authority_get_owner (auth); f_imap_t f_imap = folder->data; @@ -230,6 +230,131 @@ return 0; } +/* +The anonymous SASL mechanism is defined in rfc2245.txt as a single +message from client to server: + +message = [email / token] + +So the message is optional. + +The command is: + +C: authenticate anonymous + +The server responds with a request for continuation data (the "message" +in the SASL syntax). We respond with no data, which is legal. + +S: + +C: + +The server should then respond with OK on success, or else a failure +code (NO or BAD). + +If OK, then we are authenticated! + +So, states are: + +AUTH_ANON_REQ + +> g%u AUTHENTICATE ANONYMOUS + +AUTH_ANON_WAIT_CONT + +< + + +AUTH_ANON_MSG + +> + +AUTH_ANON_WAIT_RESP + +< NO/BAD/OK + + + +*/ + +int +authenticate_imap_sasl_anon (authority_t auth) +{ + folder_t folder = authority_get_owner (auth); + f_imap_t f_imap = folder->data; + int status = 0; + + assert (f_imap->state == IMAP_AUTH); + + switch (f_imap->auth_state) + { + case IMAP_AUTH_ANON_REQ_WRITE: + { + FOLDER_DEBUG1 (folder, MU_DEBUG_PROT, "g%u AUTHENTICATE ANONYMOUS\n", + f_imap->seq); + + status = imap_writeline (f_imap, "g%u AUTHENTICATE ANONYMOUS\r\n", + f_imap->seq); + + f_imap->seq++; + + CHECK_ERROR_CLOSE (folder, f_imap, status); + + f_imap->state = IMAP_AUTH_ANON_REQ_SEND; + } + + case IMAP_AUTH_ANON_REQ_SEND: + status = imap_send (f_imap); + + CHECK_EAGAIN (f_imap, status); + + f_imap->state = IMAP_AUTH_ANON_WAIT_CONT; + + case IMAP_AUTH_ANON_WAIT_CONT: + status = imap_parse (f_imap); + + CHECK_EAGAIN (f_imap, status); + + FOLDER_DEBUG0 (folder, MU_DEBUG_PROT, f_imap->buffer); + + if (strncmp ("+", f_imap->buffer, 2) == 0) + { + f_imap->state = IMAP_AUTH_ANON_MSG; + } + else + { + /* something is wrong! */ + } + f_imap->state = IMAP_AUTH_ANON_MSG; + + case IMAP_AUTH_ANON_MSG: + FOLDER_DEBUG0 (folder, MU_DEBUG_PROT, "\n"); + + status = imap_writeline (f_imap, "\r\n"); + + CHECK_ERROR_CLOSE (folder, f_imap, status); + + f_imap->state = IMAP_AUTH_ANON_MSG_SEND; + + case IMAP_AUTH_ANON_MSG_SEND: + status = imap_send (f_imap); + + CHECK_EAGAIN (f_imap, status); + + f_imap->state = IMAP_AUTH_ANON_WAIT_RESP; + + case IMAP_AUTH_ANON_WAIT_RESP: + status = imap_parse (f_imap); + + CHECK_EAGAIN (f_imap, status); + + FOLDER_DEBUG0 (folder, MU_DEBUG_PROT, f_imap->buffer); + + default: + break; /* We're outta here. */ + } + CLEAR_STATE (f_imap); + return 0; +} + /* Create/Open the stream for IMAP. */ static int folder_imap_open (folder_t folder, int flags) @@ -239,7 +364,6 @@ long port = 143; /* default imap port. */ int status = 0; size_t len = 0; - int preauth = 0; /* Do we have "preauth"orisation ? */ /* If we are already open for business, noop. */ monitor_wrlock (folder->monitor); @@ -252,7 +376,7 @@ } monitor_unlock (folder->monitor); - /* Fetch the pop server name and the port in the url_t. */ + /* Fetch the server name and the port in the url_t. */ status = url_get_host (folder->url, NULL, 0, &len); if (status != 0) return status; @@ -320,38 +444,22 @@ /* Are they open for business ? The server send an untag response for greeting. Thenically it can be OK/PREAUTH/BYE. The BYE is the one that we do not want, server being unfriendly. */ - preauth = (strncasecmp (f_imap->buffer, "* PREAUTH", 9) == 0); - if (strncasecmp (f_imap->buffer, "* OK", 4) != 0 && ! preauth) - { - CHECK_ERROR_CLOSE (folder, f_imap, EACCES); - } - - if (folder->authority == NULL && !preauth) - { - char auth[64] = ""; - size_t n = 0; - url_get_auth (folder->url, auth, 64, &n); - if (n == 0 || strcasecmp (auth, "*") == 0) - { - authority_create (&(folder->authority), folder->ticket, - folder); - authority_set_authenticate (folder->authority, imap_user, - folder); - } - else - { - /* No other type of Authentication is supported yet. */ - /* What can we do ? flag an error ? */ - CHECK_ERROR_CLOSE (folder, f_imap, ENOSYS); - } - } - f_imap->state = IMAP_AUTH; + if (strncasecmp (f_imap->buffer, "* PREAUTH", 9) == 0) + { + f_imap->state = IMAP_AUTH_DONE; + } + else + { + if (strncasecmp (f_imap->buffer, "* OK", 4) != 0) + CHECK_ERROR_CLOSE (folder, f_imap, EACCES); + f_imap->state = IMAP_AUTH; + } } case IMAP_AUTH: case IMAP_LOGIN: case IMAP_LOGIN_ACK: - if (!preauth) + assert (folder->authority); { status = authority_authenticate (folder->authority); CHECK_EAGAIN (f_imap, status); Index: mbx_imap.c =================================================================== RCS file: /cvsroot/mailutils/mailutils/mailbox/mbx_imap.c,v retrieving revision 1.52 diff -u -r1.52 mbx_imap.c --- mbx_imap.c 2001/10/24 04:23:20 1.52 +++ mbx_imap.c 2001/10/30 05:33:39 @@ -34,6 +34,8 @@ #include #include #include +#include + #undef min #define min(a,b) ((a) < (b) ? (a) : (b)) @@ -107,7 +109,13 @@ { m_imap_t m_imap; size_t name_len = 0; - m_imap = mailbox->data = calloc (1, sizeof *m_imap); + folder_t folder = NULL; + + assert(mailbox); + + folder = mailbox->folder; + + m_imap = mailbox->data = calloc (1, sizeof (*m_imap)); if (m_imap == NULL) return ENOMEM; @@ -156,6 +164,33 @@ mailbox_get_property (mailbox, &property); property_set_value (property, "TYPE", "IMAP4", 1); } + + assert(folder); + assert(folder->url); + + if (folder->authority == NULL) + { + const char *auth = folder->url->auth; + + if (auth == NULL || strcasecmp (auth, "*") == 0) + { + authority_create (&(folder->authority), folder->ticket, folder); + authority_set_authenticate (folder->authority, + authenticate_imap_login, folder); + } + else if (strcasecmp (auth, "anon") == 0) + { + authority_create (&(folder->authority), folder->ticket, folder); + authority_set_authenticate (folder->authority, + authenticate_imap_sasl_anon, folder); + } + else + { + /* Not a supported authentication mechanism. */ + return ENOTSUP; + } + } + return 0; } @@ -759,7 +794,6 @@ static int imap_append_message (mailbox_t mailbox, message_t msg) { - size_t total; int status = 0; m_imap_t m_imap = mailbox->data; f_imap_t f_imap = m_imap->f_imap; Index: include/imap0.h =================================================================== RCS file: /cvsroot/mailutils/mailutils/mailbox/include/imap0.h,v retrieving revision 1.10 diff -u -r1.10 imap0.h --- include/imap0.h 2001/10/14 04:08:21 1.10 +++ include/imap0.h 2001/10/30 05:33:40 @@ -25,6 +25,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -118,6 +119,18 @@ IMAP_UNSUBSCRIBE, IMAP_UNSUBSCRIBE_ACK }; +enum imap_auth_state +{ + /* ANONYMOUS */ + IMAP_AUTH_ANON_REQ_WRITE, + IMAP_AUTH_ANON_REQ_SEND, + IMAP_AUTH_ANON_WAIT_CONT, + IMAP_AUTH_ANON_MSG, + IMAP_AUTH_ANON_MSG_SEND, + IMAP_AUTH_ANON_WAIT_RESP, + +}; + struct literal_string { char *buffer; @@ -169,6 +182,9 @@ /* Login */ char *user; char *passwd; + + /* AUTHENTICATE states */ + enum imap_auth_state auth_state; }; struct _m_imap @@ -215,7 +231,10 @@ int imap_send __P ((f_imap_t)); int imap_parse __P ((f_imap_t)); int imap_readline __P ((f_imap_t)); -char *section_name __P ((msg_imap_t)); +char *section_name __P ((msg_imap_t)); + +int authenticate_imap_login __P ((authority_t auth)); +int authenticate_imap_sasl_anon __P ((authority_t auth)); #ifdef __cplusplus }