/* For STARTTLS responses */ static CURLcode imap_state_starttls_resp(struct connectdata *conn, int imapcode, imapstate instate) { CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; (void)instate; /* no use for this yet */ if(imapcode != 'O') { if(data->set.use_ssl != CURLUSESSL_TRY) { failf(data, "STARTTLS denied. %c", imapcode); result = CURLE_USE_SSL_FAILED; } else result = imap_state_login(conn); } else { if(data->state.used_interface == Curl_if_multi) { state(conn, IMAP_UPGRADETLS); result = imap_state_upgrade_tls(conn); } else { result = Curl_ssl_connect(conn, FIRSTSOCKET); if(CURLE_OK == result) { imap_to_imaps(conn); result = imap_state_login(conn); } } } return result; }
/* For the initial server greeting */ static CURLcode imap_state_servergreet_resp(struct connectdata *conn, int imapcode, imapstate instate) { CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; (void)instate; /* no use for this yet */ if(imapcode != 'O') { failf(data, "Got unexpected imap-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 */ const char *str = getcmdid(conn); result = imap_sendf(conn, str, "%s STARTTLS", str); state(conn, IMAP_STARTTLS); } else result = imap_state_login(conn); return result; }
/* for STARTTLS responses */ static CURLcode imap_state_starttls_resp(struct connectdata *conn, int imapcode, imapstate instate) { CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; (void)instate; /* no use for this yet */ if (imapcode != 'O') { failf(data, "STARTTLS denied. %c", imapcode); result = CURLE_LOGIN_DENIED; } else { /* Curl_ssl_connect is BLOCKING */ result = Curl_ssl_connect(conn, FIRSTSOCKET); if (CURLE_OK == result) { conn->protocol |= PROT_IMAPS; result = imap_state_login(conn); } } state(conn, IMAP_STOP); return result; }
static CURLcode imap_state_upgrade_tls(struct connectdata *conn) { struct imap_conn *imapc = &conn->proto.imapc; CURLcode result; result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &imapc->ssldone); if(imapc->ssldone) { imap_to_imaps(conn); result = imap_state_login(conn); } return result; }
/* For CAPABILITY responses */ static CURLcode imap_state_capability_resp(struct connectdata *conn, int imapcode, imapstate instate) { 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; }
static CURLcode imap_statemach_act(struct connectdata *conn) { CURLcode result; curl_socket_t sock = conn->sock[FIRSTSOCKET]; struct SessionHandle *data=conn->data; int imapcode; struct imap_conn *imapc = &conn->proto.imapc; struct pingpong *pp = &imapc->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, &imapcode, &nread); if(result) return result; if(imapcode) /* we have now received a full IMAP server response */ switch(imapc->state) { case IMAP_SERVERGREET: if(imapcode != 'O') { failf(data, "Got unexpected imap-server response"); 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 */ const char *str; str = getcmdid(conn); result = imapsendf(conn, str, "%s STARTTLS", str); state(conn, IMAP_STARTTLS); } else result = imap_state_login(conn); if(result) return result; break; case IMAP_LOGIN: result = imap_state_login_resp(conn, imapcode, imapc->state); break; case IMAP_STARTTLS: result = imap_state_starttls_resp(conn, imapcode, imapc->state); break; case IMAP_FETCH: result = imap_state_fetch_resp(conn, imapcode, imapc->state); break; case IMAP_SELECT: result = imap_state_select_resp(conn, imapcode, imapc->state); break; case IMAP_LOGOUT: /* fallthrough, just stop! */ default: /* internal error */ state(conn, IMAP_STOP); break; } return result; }