Loading lib/imap.c +115 −2 Original line number Diff line number Diff line Loading @@ -18,7 +18,9 @@ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * RFC2222 Simple Authentication and Security Layer (SASL) * RFC3501 IMAPv4 protocol * RFC4616 PLAIN authentication * RFC5092 IMAP URL Scheme * ***************************************************************************/ Loading Loading @@ -430,6 +432,8 @@ static void state(struct connectdata *conn, "STARTTLS", "UPGRADETLS", "CAPABILITY", "AUTHENTICATE_PLAIN", "AUTHENTICATE", "LOGIN", "SELECT", "FETCH", Loading @@ -452,6 +456,7 @@ static CURLcode imap_state_capability(struct connectdata *conn) const char *str; imapc->authmechs = 0; /* No known authentication mechanisms yet */ imapc->authused = 0; /* Clear the authentication mechanism used */ /* Check we have a username and password to authenticate with and end the connect phase if we don't */ Loading Loading @@ -497,6 +502,37 @@ static CURLcode imap_state_login(struct connectdata *conn) return CURLE_OK; } static CURLcode imap_authenticate(struct connectdata *conn) { CURLcode result = CURLE_OK; struct imap_conn *imapc = &conn->proto.imapc; const char *mech = NULL; imapstate authstate = IMAP_STOP; /* Check supported authentication mechanisms by decreasing order of security */ if(imapc->authmechs & SASL_MECH_PLAIN) { mech = "PLAIN"; authstate = IMAP_AUTHENTICATE_PLAIN; imapc->authused = SASL_MECH_PLAIN; } else { infof(conn->data, "No known authentication mechanisms supported!\n"); result = CURLE_LOGIN_DENIED; /* Other mechanisms not supported */ } if(!result) { const char *str = getcmdid(conn); result = imap_sendf(conn, str, "%s AUTHENTICATE %s", str, mech); if(!result) state(conn, authstate); } return result; } /* For the IMAP "protocol connect" and "doing" phases only */ static int imap_getsock(struct connectdata *conn, curl_socket_t *socks, Loading Loading @@ -597,10 +633,76 @@ static CURLcode imap_state_capability_resp(struct connectdata *conn, int imapcode, imapstate instate) { (void)imapcode; /* no use for this yet */ CURLcode result = CURLE_OK; struct imap_conn *imapc = &conn->proto.imapc; (void)instate; /* no use for this yet */ if(imapcode == 'O' && imapc->authmechs) result = imap_authenticate(conn); else result = imap_state_login(conn); return result; } /* For AUTHENTICATE PLAIN responses */ static CURLcode imap_state_auth_plain_resp(struct connectdata *conn, int imapcode, imapstate instate) { CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; size_t len = 0; char *plainauth = NULL; (void)instate; /* no use for this yet */ if(imapcode != '+') { failf(data, "Access denied. %c", imapcode); result = CURLE_LOGIN_DENIED; } else { /* Create the authorisation message */ result = Curl_sasl_create_plain_message(data, conn->user, conn->passwd, &plainauth, &len); /* Send the message */ if(!result) { if(plainauth) { result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", plainauth); if(!result) state(conn, IMAP_AUTHENTICATE); } Curl_safefree(plainauth); } } return result; } /* For final responses to the AUTHENTICATE sequence */ static CURLcode imap_state_auth_final_resp(struct connectdata *conn, int imapcode, imapstate instate) { CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; (void)instate; /* no use for this yet */ return imap_state_login(conn); if(imapcode != 'O') { failf(data, "Authentication failed: %d", imapcode); result = CURLE_LOGIN_DENIED; } /* End of connect phase */ state(conn, IMAP_STOP); return result; } /* For LOGIN responses */ Loading Loading @@ -807,6 +909,14 @@ static CURLcode imap_statemach_act(struct connectdata *conn) result = imap_state_capability_resp(conn, imapcode, imapc->state); break; case IMAP_AUTHENTICATE_PLAIN: result = imap_state_auth_plain_resp(conn, imapcode, imapc->state); break; case IMAP_AUTHENTICATE: result = imap_state_auth_final_resp(conn, imapcode, imapc->state); break; case IMAP_LOGIN: result = imap_state_login_resp(conn, imapcode, imapc->state); break; Loading Loading @@ -1117,6 +1227,9 @@ static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection) /* Disconnect from the server */ Curl_pp_disconnect(&imapc->pp); /* Cleanup the SASL module */ Curl_sasl_cleanup(conn, imapc->authused); /* Cleanup our connection based variables */ Curl_safefree(imapc->mailbox); Loading lib/imap.h +3 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,8 @@ typedef enum { IMAP_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS (multi mode only) */ IMAP_CAPABILITY, IMAP_AUTHENTICATE_PLAIN, IMAP_AUTHENTICATE, IMAP_LOGIN, IMAP_SELECT, IMAP_FETCH, Loading @@ -48,6 +50,7 @@ struct imap_conn { struct pingpong pp; char *mailbox; /* Message ID to fetch */ unsigned int authmechs; /* Accepted authentication mechanisms */ unsigned int authused; /* Auth mechanism used for the connection */ 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 Loading
lib/imap.c +115 −2 Original line number Diff line number Diff line Loading @@ -18,7 +18,9 @@ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * RFC2222 Simple Authentication and Security Layer (SASL) * RFC3501 IMAPv4 protocol * RFC4616 PLAIN authentication * RFC5092 IMAP URL Scheme * ***************************************************************************/ Loading Loading @@ -430,6 +432,8 @@ static void state(struct connectdata *conn, "STARTTLS", "UPGRADETLS", "CAPABILITY", "AUTHENTICATE_PLAIN", "AUTHENTICATE", "LOGIN", "SELECT", "FETCH", Loading @@ -452,6 +456,7 @@ static CURLcode imap_state_capability(struct connectdata *conn) const char *str; imapc->authmechs = 0; /* No known authentication mechanisms yet */ imapc->authused = 0; /* Clear the authentication mechanism used */ /* Check we have a username and password to authenticate with and end the connect phase if we don't */ Loading Loading @@ -497,6 +502,37 @@ static CURLcode imap_state_login(struct connectdata *conn) return CURLE_OK; } static CURLcode imap_authenticate(struct connectdata *conn) { CURLcode result = CURLE_OK; struct imap_conn *imapc = &conn->proto.imapc; const char *mech = NULL; imapstate authstate = IMAP_STOP; /* Check supported authentication mechanisms by decreasing order of security */ if(imapc->authmechs & SASL_MECH_PLAIN) { mech = "PLAIN"; authstate = IMAP_AUTHENTICATE_PLAIN; imapc->authused = SASL_MECH_PLAIN; } else { infof(conn->data, "No known authentication mechanisms supported!\n"); result = CURLE_LOGIN_DENIED; /* Other mechanisms not supported */ } if(!result) { const char *str = getcmdid(conn); result = imap_sendf(conn, str, "%s AUTHENTICATE %s", str, mech); if(!result) state(conn, authstate); } return result; } /* For the IMAP "protocol connect" and "doing" phases only */ static int imap_getsock(struct connectdata *conn, curl_socket_t *socks, Loading Loading @@ -597,10 +633,76 @@ static CURLcode imap_state_capability_resp(struct connectdata *conn, int imapcode, imapstate instate) { (void)imapcode; /* no use for this yet */ CURLcode result = CURLE_OK; struct imap_conn *imapc = &conn->proto.imapc; (void)instate; /* no use for this yet */ if(imapcode == 'O' && imapc->authmechs) result = imap_authenticate(conn); else result = imap_state_login(conn); return result; } /* For AUTHENTICATE PLAIN responses */ static CURLcode imap_state_auth_plain_resp(struct connectdata *conn, int imapcode, imapstate instate) { CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; size_t len = 0; char *plainauth = NULL; (void)instate; /* no use for this yet */ if(imapcode != '+') { failf(data, "Access denied. %c", imapcode); result = CURLE_LOGIN_DENIED; } else { /* Create the authorisation message */ result = Curl_sasl_create_plain_message(data, conn->user, conn->passwd, &plainauth, &len); /* Send the message */ if(!result) { if(plainauth) { result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", plainauth); if(!result) state(conn, IMAP_AUTHENTICATE); } Curl_safefree(plainauth); } } return result; } /* For final responses to the AUTHENTICATE sequence */ static CURLcode imap_state_auth_final_resp(struct connectdata *conn, int imapcode, imapstate instate) { CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; (void)instate; /* no use for this yet */ return imap_state_login(conn); if(imapcode != 'O') { failf(data, "Authentication failed: %d", imapcode); result = CURLE_LOGIN_DENIED; } /* End of connect phase */ state(conn, IMAP_STOP); return result; } /* For LOGIN responses */ Loading Loading @@ -807,6 +909,14 @@ static CURLcode imap_statemach_act(struct connectdata *conn) result = imap_state_capability_resp(conn, imapcode, imapc->state); break; case IMAP_AUTHENTICATE_PLAIN: result = imap_state_auth_plain_resp(conn, imapcode, imapc->state); break; case IMAP_AUTHENTICATE: result = imap_state_auth_final_resp(conn, imapcode, imapc->state); break; case IMAP_LOGIN: result = imap_state_login_resp(conn, imapcode, imapc->state); break; Loading Loading @@ -1117,6 +1227,9 @@ static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection) /* Disconnect from the server */ Curl_pp_disconnect(&imapc->pp); /* Cleanup the SASL module */ Curl_sasl_cleanup(conn, imapc->authused); /* Cleanup our connection based variables */ Curl_safefree(imapc->mailbox); Loading
lib/imap.h +3 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,8 @@ typedef enum { IMAP_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS (multi mode only) */ IMAP_CAPABILITY, IMAP_AUTHENTICATE_PLAIN, IMAP_AUTHENTICATE, IMAP_LOGIN, IMAP_SELECT, IMAP_FETCH, Loading @@ -48,6 +50,7 @@ struct imap_conn { struct pingpong pp; char *mailbox; /* Message ID to fetch */ unsigned int authmechs; /* Accepted authentication mechanisms */ unsigned int authused; /* Auth mechanism used for the connection */ 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