/* for STARTTLS responses */ static CURLcode pop3_state_starttls_resp(struct connectdata *conn, int pop3code, pop3state instate) { CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; (void)instate; /* no use for this yet */ if(pop3code != 'O') { if(data->set.use_ssl != CURLUSESSL_TRY) { failf(data, "STARTTLS denied. %c", pop3code); result = CURLE_USE_SSL_FAILED; state(conn, POP3_STOP); } else result = pop3_state_user(conn); } else { /* Curl_ssl_connect is BLOCKING */ result = Curl_ssl_connect(conn, FIRSTSOCKET); if(CURLE_OK == result) { pop3_to_pop3s(conn); result = pop3_state_user(conn); } else { state(conn, POP3_STOP); } } return result; }
/* For CAPA responses */ static CURLcode pop3_state_capa_resp(struct connectdata *conn, int pop3code, pop3state instate) { CURLcode result = CURLE_OK; (void)instate; /* no use for this yet */ if(pop3code == '+' && conn->proto.pop3c.authtypes) { /* Check supported authentication types by decreasing order of security */ if(conn->proto.pop3c.authtypes & POP3_TYPE_SASL) result = pop3_authenticate(conn); #ifndef CURL_DISABLE_CRYPTO_AUTH else if(conn->proto.pop3c.authtypes & POP3_TYPE_APOP) result = pop3_state_apop(conn); #endif else if(conn->proto.pop3c.authtypes & POP3_TYPE_CLEARTEXT) result = pop3_state_user(conn); else { infof(conn->data, "No known authentication types supported!\n"); result = CURLE_LOGIN_DENIED; /* Other types not supported */ } } else result = pop3_state_user(conn); return result; }
/* For CAPA responses */ static CURLcode pop3_state_capa_resp(struct connectdata *conn, int pop3code, pop3state instate) { CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; struct pop3_conn *pop3c = &conn->proto.pop3c; (void)instate; /* no use for this yet */ if(pop3code != '+') result = pop3_state_user(conn); else if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) { /* We don't have a SSL/TLS connection yet, but SSL is requested */ if(pop3c->tls_supported) /* Switch to TLS connection now */ result = pop3_state_starttls(conn); else if(data->set.use_ssl == CURLUSESSL_TRY) /* Fallback and carry on with authentication */ result = pop3_authenticate(conn); else { failf(data, "STLS not supported."); result = CURLE_USE_SSL_FAILED; } } else result = pop3_authenticate(conn); return result; }
/* For CAPA responses */ static CURLcode pop3_state_capa_resp(struct connectdata *conn, int pop3code, pop3state instate) { CURLcode result = CURLE_OK; (void)instate; /* no use for this yet */ if(pop3code == '+') result = pop3_authenticate(conn); else result = pop3_state_user(conn); return result; }
/* for STARTTLS responses */ static CURLcode pop3_state_starttls_resp(struct connectdata *conn, int pop3code, pop3state instate) { CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; (void)instate; /* no use for this yet */ if(pop3code != 'O') { failf(data, "STARTTLS denied. %c", pop3code); result = CURLE_LOGIN_DENIED; } else { /* Curl_ssl_connect is BLOCKING */ result = Curl_ssl_connect(conn, FIRSTSOCKET); if(CURLE_OK == result) { conn->protocol |= PROT_POP3S; result = pop3_state_user(conn); } } state(conn, POP3_STOP); return result; }
static CURLcode pop3_statemach_act(struct connectdata *conn) { CURLcode result; curl_socket_t sock = conn->sock[FIRSTSOCKET]; struct SessionHandle *data=conn->data; int pop3code; struct pop3_conn *pop3c = &conn->proto.pop3c; struct pingpong *pp = &pop3c->pp; size_t nread = 0; if(pp->sendleft) return Curl_pp_flushsend(pp); /* we read a piece of response */ result = Curl_pp_readresp(sock, pp, &pop3code, &nread); if(result) return result; if(pop3code) { /* we have now received a full POP3 server response */ switch(pop3c->state) { case POP3_SERVERGREET: if(pop3code != 'O') { failf(data, "Got unexpected pop3-server response"); return CURLE_FTP_WEIRD_SERVER_REPLY; } if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) { /* We don't have a SSL/TLS connection yet, but SSL is requested. Switch to TLS connection now */ result = Curl_pp_sendf(&pop3c->pp, "STLS"); state(conn, POP3_STARTTLS); } else result = pop3_state_user(conn); if(result) return result; break; case POP3_USER: result = pop3_state_user_resp(conn, pop3code, pop3c->state); break; case POP3_PASS: result = pop3_state_pass_resp(conn, pop3code, pop3c->state); break; case POP3_STARTTLS: result = pop3_state_starttls_resp(conn, pop3code, pop3c->state); break; case POP3_RETR: result = pop3_state_retr_resp(conn, pop3code, pop3c->state); break; case POP3_LIST: result = pop3_state_list_resp(conn, pop3code, pop3c->state); break; case POP3_LIST_SINGLE: result = pop3_state_list_single_resp(conn, pop3code, pop3c->state); break; case POP3_QUIT: /* fallthrough, just stop! */ default: /* internal error */ state(conn, POP3_STOP); break; } } return result; }
static CURLcode pop3_authenticate(struct connectdata *conn) { CURLcode result = CURLE_OK; struct pop3_conn *pop3c = &conn->proto.pop3c; const char *mech = NULL; pop3state authstate = POP3_STOP; /* 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, POP3_STOP); return result; } /* Calculate the supported authentication mechanism by decreasing order of security */ if(pop3c->authtypes & POP3_TYPE_SASL) { #ifndef CURL_DISABLE_CRYPTO_AUTH if(pop3c->authmechs & SASL_MECH_DIGEST_MD5) { mech = "DIGEST-MD5"; authstate = POP3_AUTH_DIGESTMD5; pop3c->authused = SASL_MECH_DIGEST_MD5; } else if(pop3c->authmechs & SASL_MECH_CRAM_MD5) { mech = "CRAM-MD5"; authstate = POP3_AUTH_CRAMMD5; pop3c->authused = SASL_MECH_CRAM_MD5; } else #endif #ifdef USE_NTLM if(pop3c->authmechs & SASL_MECH_NTLM) { mech = "NTLM"; authstate = POP3_AUTH_NTLM; pop3c->authused = SASL_MECH_NTLM; } else #endif if(pop3c->authmechs & SASL_MECH_LOGIN) { mech = "LOGIN"; authstate = POP3_AUTH_LOGIN; pop3c->authused = SASL_MECH_LOGIN; } else if(pop3c->authmechs & SASL_MECH_PLAIN) { mech = "PLAIN"; authstate = POP3_AUTH_PLAIN; pop3c->authused = SASL_MECH_PLAIN; } } if(mech) { /* Perform SASL based authentication */ result = Curl_pp_sendf(&pop3c->pp, "AUTH %s", mech); if(!result) state(conn, authstate); } #ifndef CURL_DISABLE_CRYPTO_AUTH else if(pop3c->authtypes & POP3_TYPE_APOP) /* Perform APOP authentication */ result = pop3_state_apop(conn); #endif else if(pop3c->authtypes & POP3_TYPE_CLEARTEXT) /* Perform clear text authentication */ result = pop3_state_user(conn); else { /* Other mechanisms not supported */ infof(conn->data, "No known authentication mechanisms supported!\n"); result = CURLE_LOGIN_DENIED; } return result; }