/* for STARTTLS responses */ static CURLcode smtp_state_starttls_resp(struct connectdata *conn, int smtpcode, smtpstate instate) { CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; (void)instate; /* no use for this yet */ if(smtpcode != 220) { if(data->set.ftp_ssl != CURLUSESSL_TRY) { failf(data, "STARTTLS denied. %c", smtpcode); result = CURLE_LOGIN_DENIED; } else result = smtp_authenticate(conn); } else { /* Curl_ssl_connect is BLOCKING */ result = Curl_ssl_connect(conn, FIRSTSOCKET); if(CURLE_OK == result) { conn->protocol |= PROT_SMTPS; result = smtp_state_ehlo(conn); } } return result; }
/* For STARTTLS responses */ static CURLcode smtp_state_starttls_resp(struct connectdata *conn, int smtpcode, smtpstate instate) { CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; (void)instate; /* no use for this yet */ if(smtpcode != 220) { if(data->set.use_ssl != CURLUSESSL_TRY) { failf(data, "STARTTLS denied. %c", smtpcode); result = CURLE_USE_SSL_FAILED; } else result = smtp_authenticate(conn); } else { if(data->state.used_interface == Curl_if_multi) { state(conn, SMTP_UPGRADETLS); result = smtp_state_upgrade_tls(conn); } else { result = Curl_ssl_connect(conn, FIRSTSOCKET); if(CURLE_OK == result) { smtp_to_smtps(conn); result = smtp_state_ehlo(conn); } } } return result; }
static CURLcode smtp_state_upgrade_tls(struct connectdata *conn) { struct smtp_conn *smtpc = &conn->proto.smtpc; CURLcode result; result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &smtpc->ssldone); if(smtpc->ssldone) { smtp_to_smtps(conn); result = smtp_state_ehlo(conn); } return result; }
/* For the initial server greeting */ static CURLcode smtp_state_servergreet_resp(struct connectdata *conn, int smtpcode, smtpstate instate) { CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; (void)instate; /* no use for this yet */ if(smtpcode/100 != 2) { failf(data, "Got unexpected smtp-server response: %d", smtpcode); return CURLE_FTP_WEIRD_SERVER_REPLY; } result = smtp_state_ehlo(conn); return result; }
static CURLcode smtp_state_upgrade_tls(struct connectdata *conn) { CURLcode result = CURLE_OK; struct smtp_conn *smtpc = &conn->proto.smtpc; /* Start the SSL connection */ result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &smtpc->ssldone); if(!result) { if(smtpc->state != SMTP_UPGRADETLS) state(conn, SMTP_UPGRADETLS); if(smtpc->ssldone) { smtp_to_smtps(conn); result = smtp_state_ehlo(conn); } } return result; }
static CURLcode smtp_statemach_act(struct connectdata *conn) { CURLcode result; curl_socket_t sock = conn->sock[FIRSTSOCKET]; struct SessionHandle *data=conn->data; int smtpcode; struct smtp_conn *smtpc = &conn->proto.smtpc; struct pingpong *pp = &smtpc->pp; size_t nread = 0; if(pp->sendleft) /* we have a piece of a command still left to send */ return Curl_pp_flushsend(pp); /* we read a piece of response */ result = Curl_pp_readresp(sock, pp, &smtpcode, &nread); if(result) return result; if(smtpcode) { /* we have now received a full SMTP server response */ switch(smtpc->state) { case SMTP_SERVERGREET: if(smtpcode/100 != 2) { failf(data, "Got unexpected smtp-server response: %d", smtpcode); return CURLE_FTP_WEIRD_SERVER_REPLY; } result = smtp_state_ehlo(conn); if(result) return result; break; case SMTP_EHLO: result = smtp_state_ehlo_resp(conn, smtpcode, smtpc->state); break; case SMTP_HELO: result = smtp_state_helo_resp(conn, smtpcode, smtpc->state); break; case SMTP_STARTTLS: result = smtp_state_starttls_resp(conn, smtpcode, smtpc->state); break; case SMTP_AUTHPLAIN: result = smtp_state_authplain_resp(conn, smtpcode, smtpc->state); break; case SMTP_AUTHLOGIN: result = smtp_state_authlogin_resp(conn, smtpcode, smtpc->state); break; case SMTP_AUTHPASSWD: result = smtp_state_authpasswd_resp(conn, smtpcode, smtpc->state); break; #ifndef CURL_DISABLE_CRYPTO_AUTH case SMTP_AUTHCRAM: result = smtp_state_authcram_resp(conn, smtpcode, smtpc->state); break; #endif case SMTP_AUTH: result = smtp_state_auth_resp(conn, smtpcode, smtpc->state); break; case SMTP_MAIL: result = smtp_state_mail_resp(conn, smtpcode, smtpc->state); break; case SMTP_RCPT: result = smtp_state_rcpt_resp(conn, smtpcode, smtpc->state); break; case SMTP_DATA: result = smtp_state_data_resp(conn, smtpcode, smtpc->state); break; case SMTP_POSTDATA: result = smtp_state_postdata_resp(conn, smtpcode, smtpc->state); break; case SMTP_QUIT: /* fallthrough, just stop! */ default: /* internal error */ state(conn, SMTP_STOP); break; } } return result; }
static CURLcode smtp_statemach_act(struct connectdata *conn) { CURLcode result; curl_socket_t sock = conn->sock[FIRSTSOCKET]; struct SessionHandle *data=conn->data; int smtpcode; struct smtp_conn *smtpc = &conn->proto.smtpc; struct pingpong *pp = &smtpc->pp; size_t nread = 0; if(pp->sendleft) /* we have a piece of a command still left to send */ return Curl_pp_flushsend(pp); /* we read a piece of response */ result = Curl_pp_readresp(sock, pp, &smtpcode, &nread); if(result) return result; if(smtpcode) { /* we have now received a full SMTP server response */ switch(smtpc->state) { case SMTP_SERVERGREET: if(smtpcode/100 != 2) { failf(data, "Got unexpected smtp-server response: %d", smtpcode); return CURLE_FTP_WEIRD_SERVER_REPLY; } if(data->set.ftp_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(&smtpc->pp, "STARTTLS", NULL); state(conn, SMTP_STARTTLS); } else result = smtp_state_ehlo(conn); if(result) return result; break; case SMTP_EHLO: result = smtp_state_ehlo_resp(conn, smtpcode, smtpc->state); break; case SMTP_MAIL: result = smtp_state_mail_resp(conn, smtpcode, smtpc->state); break; case SMTP_RCPT: result = smtp_state_rcpt_resp(conn, smtpcode, smtpc->state); break; case SMTP_STARTTLS: result = smtp_state_starttls_resp(conn, smtpcode, smtpc->state); break; case SMTP_DATA: result = smtp_state_data_resp(conn, smtpcode, smtpc->state); break; case SMTP_QUIT: /* fallthrough, just stop! */ default: /* internal error */ state(conn, SMTP_STOP); break; } } return result; }