Loading lib/imap.c +113 −7 Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms Loading Loading @@ -70,6 +70,7 @@ #include "multiif.h" #include "url.h" #include "rawstr.h" #include "curl_sasl.h" #define _MPRINTF_REPLACE /* use our functions only */ #include <curl/mprintf.h> Loading Loading @@ -320,7 +321,8 @@ static char* imap_atom(const char* str) } /* Function that checks for an ending imap status code at the start of the given string. */ given string but also detects the supported mechanisms from the CAPABILITY response. */ static int imap_endofresp(struct pingpong *pp, int *resp) { char *line = pp->linestart_resp; Loading @@ -328,6 +330,7 @@ static int imap_endofresp(struct pingpong *pp, int *resp) struct imap_conn *imapc = &pp->conn->proto.imapc; const char *id = imapc->idstr; size_t id_len = strlen(id); size_t wordlen; /* Do we have a generic command response? */ if(len >= id_len + 3) { Loading @@ -337,6 +340,64 @@ static int imap_endofresp(struct pingpong *pp, int *resp) } } /* Are we processing CAPABILITY command responses? */ if(imapc->state == IMAP_CAPABILITY) { /* Do we have a valid response? */ if(len >= 2 && !memcmp("* ", line, 2)) { line += 2; len -= 2; /* Loop through the data line */ for(;;) { while(len && (*line == ' ' || *line == '\t' || *line == '\r' || *line == '\n')) { if(*line == '\n') return FALSE; line++; len--; } if(!len) break; /* Extract the word */ for(wordlen = 0; wordlen < len && line[wordlen] != ' ' && line[wordlen] != '\t' && line[wordlen] != '\r' && line[wordlen] != '\n';) wordlen++; /* Do we have an AUTH capability? */ if(wordlen > 5 && !memcmp(line, "AUTH=", 5)) { line += 5; len -= 5; wordlen -= 5; /* Test the word for a matching authentication mechanism */ if(wordlen == 5 && !memcmp(line, "LOGIN", 5)) imapc->authmechs |= SASL_MECH_LOGIN; if(wordlen == 5 && !memcmp(line, "PLAIN", 5)) imapc->authmechs |= SASL_MECH_PLAIN; else if(wordlen == 8 && !memcmp(line, "CRAM-MD5", 8)) imapc->authmechs |= SASL_MECH_CRAM_MD5; else if(wordlen == 10 && !memcmp(line, "DIGEST-MD5", 10)) imapc->authmechs |= SASL_MECH_DIGEST_MD5; else if(wordlen == 6 && !memcmp(line, "GSSAPI", 6)) imapc->authmechs |= SASL_MECH_GSSAPI; else if(wordlen == 8 && !memcmp(line, "EXTERNAL", 8)) imapc->authmechs |= SASL_MECH_EXTERNAL; else if(wordlen == 4 && !memcmp(line, "NTLM", 4)) imapc->authmechs |= SASL_MECH_NTLM; } line += wordlen; len -= wordlen; } } } /* Are we processing FETCH command responses? */ if(imapc->state == IMAP_FETCH) { /* Do we have a valid response? */ Loading @@ -346,7 +407,7 @@ static int imap_endofresp(struct pingpong *pp, int *resp) } } return FALSE; /* nothing for us */ return FALSE; /* Nothing for us */ } /* This is the ONLY way to change IMAP state! */ Loading @@ -361,6 +422,7 @@ static void state(struct connectdata *conn, "SERVERGREET", "STARTTLS", "UPGRADETLS", "CAPABILITY", "LOGIN", "SELECT", "FETCH", Loading @@ -376,6 +438,35 @@ static void state(struct connectdata *conn, imapc->state = newstate; } static CURLcode imap_state_capability(struct connectdata *conn) { CURLcode result = CURLE_OK; struct imap_conn *imapc = &conn->proto.imapc; const char *str; imapc->authmechs = 0; /* No known authentication mechanisms yet */ /* Check we have a username and password to authenticate with and end the connect phase if we don't */ if(!conn->bits.user_passwd) { state(conn, IMAP_STOP); return result; } str = getcmdid(conn); /* Send the CAPABILITY command */ result = imap_sendf(conn, str, "%s CAPABILITY", str); if(result) return result; state(conn, IMAP_CAPABILITY); return CURLE_OK; } static CURLcode imap_state_login(struct connectdata *conn) { CURLcode result; Loading Loading @@ -439,7 +530,7 @@ static CURLcode imap_state_servergreet_resp(struct connectdata *conn, state(conn, IMAP_STARTTLS); } else result = imap_state_login(conn); result = imap_state_capability(conn); return result; } Loading @@ -460,7 +551,7 @@ static CURLcode imap_state_starttls_resp(struct connectdata *conn, result = CURLE_USE_SSL_FAILED; } else result = imap_state_login(conn); result = imap_state_capability(conn); } else { if(data->state.used_interface == Curl_if_multi) { Loading @@ -471,7 +562,7 @@ static CURLcode imap_state_starttls_resp(struct connectdata *conn, result = Curl_ssl_connect(conn, FIRSTSOCKET); if(CURLE_OK == result) { imap_to_imaps(conn); result = imap_state_login(conn); result = imap_state_capability(conn); } } } Loading @@ -488,12 +579,23 @@ static CURLcode imap_state_upgrade_tls(struct connectdata *conn) if(imapc->ssldone) { imap_to_imaps(conn); result = imap_state_login(conn); result = imap_state_capability(conn); } return result; } /* For CAPABILITY responses */ static CURLcode imap_state_capability_resp(struct connectdata *conn, int imapcode, imapstate instate) { (void)imapcode; /* no use for this yet */ (void)instate; /* no use for this yet */ return imap_state_login(conn); } /* For LOGIN responses */ static CURLcode imap_state_login_resp(struct connectdata *conn, int imapcode, Loading Loading @@ -694,6 +796,10 @@ static CURLcode imap_statemach_act(struct connectdata *conn) result = imap_state_starttls_resp(conn, imapcode, imapc->state); break; case IMAP_CAPABILITY: result = imap_state_capability_resp(conn, imapcode, imapc->state); break; case IMAP_LOGIN: result = imap_state_login_resp(conn, imapcode, imapc->state); break; Loading lib/imap.h +9 −7 Original line number Diff line number Diff line Loading @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 2009 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2009 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms Loading @@ -34,6 +34,7 @@ typedef enum { IMAP_STARTTLS, IMAP_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS (multi mode only) */ IMAP_CAPABILITY, IMAP_LOGIN, IMAP_SELECT, IMAP_FETCH, Loading @@ -46,6 +47,7 @@ typedef enum { struct imap_conn { struct pingpong pp; char *mailbox; /* Message ID to fetch */ unsigned int authmechs; /* Accepted authentication mechanisms */ imapstate state; /* Always use imap.c:state() to change state! */ int cmdid; /* Next command ID */ const char *idstr; /* String based response ID to wait for */ Loading tests/data/test1321 +5 −4 Original line number Diff line number Diff line Loading @@ -56,10 +56,11 @@ imap://%HOSTIP:%IMAPPORT/1321 -u user:secret -p -x %HOSTIP:%PROXYPORT ^User-Agent: curl/.* </strip> <protocol> B LOGIN user secret C SELECT 1321 D FETCH 1 BODY[TEXT] A LOGOUT B CAPABILITY C LOGIN user secret D SELECT 1321 A FETCH 1 BODY[TEXT] B LOGOUT </protocol> <proxy> CONNECT %HOSTIP:%IMAPPORT HTTP/1.1 Loading tests/data/test801 +5 −4 Original line number Diff line number Diff line Loading @@ -38,10 +38,11 @@ imap://%HOSTIP:%IMAPPORT/801 -u user:secret # Verify data after the test has been "shot" <verify> <protocol> B LOGIN user secret C SELECT 801 D FETCH 1 BODY[TEXT] A LOGOUT B CAPABILITY C LOGIN user secret D SELECT 801 A FETCH 1 BODY[TEXT] B LOGOUT </protocol> </verify> </testcase> Loading
lib/imap.c +113 −7 Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms Loading Loading @@ -70,6 +70,7 @@ #include "multiif.h" #include "url.h" #include "rawstr.h" #include "curl_sasl.h" #define _MPRINTF_REPLACE /* use our functions only */ #include <curl/mprintf.h> Loading Loading @@ -320,7 +321,8 @@ static char* imap_atom(const char* str) } /* Function that checks for an ending imap status code at the start of the given string. */ given string but also detects the supported mechanisms from the CAPABILITY response. */ static int imap_endofresp(struct pingpong *pp, int *resp) { char *line = pp->linestart_resp; Loading @@ -328,6 +330,7 @@ static int imap_endofresp(struct pingpong *pp, int *resp) struct imap_conn *imapc = &pp->conn->proto.imapc; const char *id = imapc->idstr; size_t id_len = strlen(id); size_t wordlen; /* Do we have a generic command response? */ if(len >= id_len + 3) { Loading @@ -337,6 +340,64 @@ static int imap_endofresp(struct pingpong *pp, int *resp) } } /* Are we processing CAPABILITY command responses? */ if(imapc->state == IMAP_CAPABILITY) { /* Do we have a valid response? */ if(len >= 2 && !memcmp("* ", line, 2)) { line += 2; len -= 2; /* Loop through the data line */ for(;;) { while(len && (*line == ' ' || *line == '\t' || *line == '\r' || *line == '\n')) { if(*line == '\n') return FALSE; line++; len--; } if(!len) break; /* Extract the word */ for(wordlen = 0; wordlen < len && line[wordlen] != ' ' && line[wordlen] != '\t' && line[wordlen] != '\r' && line[wordlen] != '\n';) wordlen++; /* Do we have an AUTH capability? */ if(wordlen > 5 && !memcmp(line, "AUTH=", 5)) { line += 5; len -= 5; wordlen -= 5; /* Test the word for a matching authentication mechanism */ if(wordlen == 5 && !memcmp(line, "LOGIN", 5)) imapc->authmechs |= SASL_MECH_LOGIN; if(wordlen == 5 && !memcmp(line, "PLAIN", 5)) imapc->authmechs |= SASL_MECH_PLAIN; else if(wordlen == 8 && !memcmp(line, "CRAM-MD5", 8)) imapc->authmechs |= SASL_MECH_CRAM_MD5; else if(wordlen == 10 && !memcmp(line, "DIGEST-MD5", 10)) imapc->authmechs |= SASL_MECH_DIGEST_MD5; else if(wordlen == 6 && !memcmp(line, "GSSAPI", 6)) imapc->authmechs |= SASL_MECH_GSSAPI; else if(wordlen == 8 && !memcmp(line, "EXTERNAL", 8)) imapc->authmechs |= SASL_MECH_EXTERNAL; else if(wordlen == 4 && !memcmp(line, "NTLM", 4)) imapc->authmechs |= SASL_MECH_NTLM; } line += wordlen; len -= wordlen; } } } /* Are we processing FETCH command responses? */ if(imapc->state == IMAP_FETCH) { /* Do we have a valid response? */ Loading @@ -346,7 +407,7 @@ static int imap_endofresp(struct pingpong *pp, int *resp) } } return FALSE; /* nothing for us */ return FALSE; /* Nothing for us */ } /* This is the ONLY way to change IMAP state! */ Loading @@ -361,6 +422,7 @@ static void state(struct connectdata *conn, "SERVERGREET", "STARTTLS", "UPGRADETLS", "CAPABILITY", "LOGIN", "SELECT", "FETCH", Loading @@ -376,6 +438,35 @@ static void state(struct connectdata *conn, imapc->state = newstate; } static CURLcode imap_state_capability(struct connectdata *conn) { CURLcode result = CURLE_OK; struct imap_conn *imapc = &conn->proto.imapc; const char *str; imapc->authmechs = 0; /* No known authentication mechanisms yet */ /* Check we have a username and password to authenticate with and end the connect phase if we don't */ if(!conn->bits.user_passwd) { state(conn, IMAP_STOP); return result; } str = getcmdid(conn); /* Send the CAPABILITY command */ result = imap_sendf(conn, str, "%s CAPABILITY", str); if(result) return result; state(conn, IMAP_CAPABILITY); return CURLE_OK; } static CURLcode imap_state_login(struct connectdata *conn) { CURLcode result; Loading Loading @@ -439,7 +530,7 @@ static CURLcode imap_state_servergreet_resp(struct connectdata *conn, state(conn, IMAP_STARTTLS); } else result = imap_state_login(conn); result = imap_state_capability(conn); return result; } Loading @@ -460,7 +551,7 @@ static CURLcode imap_state_starttls_resp(struct connectdata *conn, result = CURLE_USE_SSL_FAILED; } else result = imap_state_login(conn); result = imap_state_capability(conn); } else { if(data->state.used_interface == Curl_if_multi) { Loading @@ -471,7 +562,7 @@ static CURLcode imap_state_starttls_resp(struct connectdata *conn, result = Curl_ssl_connect(conn, FIRSTSOCKET); if(CURLE_OK == result) { imap_to_imaps(conn); result = imap_state_login(conn); result = imap_state_capability(conn); } } } Loading @@ -488,12 +579,23 @@ static CURLcode imap_state_upgrade_tls(struct connectdata *conn) if(imapc->ssldone) { imap_to_imaps(conn); result = imap_state_login(conn); result = imap_state_capability(conn); } return result; } /* For CAPABILITY responses */ static CURLcode imap_state_capability_resp(struct connectdata *conn, int imapcode, imapstate instate) { (void)imapcode; /* no use for this yet */ (void)instate; /* no use for this yet */ return imap_state_login(conn); } /* For LOGIN responses */ static CURLcode imap_state_login_resp(struct connectdata *conn, int imapcode, Loading Loading @@ -694,6 +796,10 @@ static CURLcode imap_statemach_act(struct connectdata *conn) result = imap_state_starttls_resp(conn, imapcode, imapc->state); break; case IMAP_CAPABILITY: result = imap_state_capability_resp(conn, imapcode, imapc->state); break; case IMAP_LOGIN: result = imap_state_login_resp(conn, imapcode, imapc->state); break; Loading
lib/imap.h +9 −7 Original line number Diff line number Diff line Loading @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 2009 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2009 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms Loading @@ -34,6 +34,7 @@ typedef enum { IMAP_STARTTLS, IMAP_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS (multi mode only) */ IMAP_CAPABILITY, IMAP_LOGIN, IMAP_SELECT, IMAP_FETCH, Loading @@ -46,6 +47,7 @@ typedef enum { struct imap_conn { struct pingpong pp; char *mailbox; /* Message ID to fetch */ unsigned int authmechs; /* Accepted authentication mechanisms */ imapstate state; /* Always use imap.c:state() to change state! */ int cmdid; /* Next command ID */ const char *idstr; /* String based response ID to wait for */ Loading
tests/data/test1321 +5 −4 Original line number Diff line number Diff line Loading @@ -56,10 +56,11 @@ imap://%HOSTIP:%IMAPPORT/1321 -u user:secret -p -x %HOSTIP:%PROXYPORT ^User-Agent: curl/.* </strip> <protocol> B LOGIN user secret C SELECT 1321 D FETCH 1 BODY[TEXT] A LOGOUT B CAPABILITY C LOGIN user secret D SELECT 1321 A FETCH 1 BODY[TEXT] B LOGOUT </protocol> <proxy> CONNECT %HOSTIP:%IMAPPORT HTTP/1.1 Loading
tests/data/test801 +5 −4 Original line number Diff line number Diff line Loading @@ -38,10 +38,11 @@ imap://%HOSTIP:%IMAPPORT/801 -u user:secret # Verify data after the test has been "shot" <verify> <protocol> B LOGIN user secret C SELECT 801 D FETCH 1 BODY[TEXT] A LOGOUT B CAPABILITY C LOGIN user secret D SELECT 801 A FETCH 1 BODY[TEXT] B LOGOUT </protocol> </verify> </testcase>