diff options
Diffstat (limited to 'lib/smtp.c')
-rw-r--r-- | lib/smtp.c | 365 |
1 files changed, 185 insertions, 180 deletions
diff --git a/lib/smtp.c b/lib/smtp.c index 509d802f1..84d4d5744 100644 --- a/lib/smtp.c +++ b/lib/smtp.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, 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 @@ -91,24 +91,29 @@ #include "memdebug.h" /* Local API functions */ -static CURLcode smtp_regular_transfer(struct connectdata *conn, bool *done); -static CURLcode smtp_do(struct connectdata *conn, bool *done); -static CURLcode smtp_done(struct connectdata *conn, CURLcode status, +static CURLcode smtp_regular_transfer(struct Curl_easy *data, bool *done); +static CURLcode smtp_do(struct Curl_easy *data, bool *done); +static CURLcode smtp_done(struct Curl_easy *data, CURLcode status, bool premature); -static CURLcode smtp_connect(struct connectdata *conn, bool *done); -static CURLcode smtp_disconnect(struct connectdata *conn, bool dead); -static CURLcode smtp_multi_statemach(struct connectdata *conn, bool *done); -static int smtp_getsock(struct connectdata *conn, curl_socket_t *socks); -static CURLcode smtp_doing(struct connectdata *conn, bool *dophase_done); -static CURLcode smtp_setup_connection(struct connectdata *conn); +static CURLcode smtp_connect(struct Curl_easy *data, bool *done); +static CURLcode smtp_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead); +static CURLcode smtp_multi_statemach(struct Curl_easy *data, bool *done); +static int smtp_getsock(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t *socks); +static CURLcode smtp_doing(struct Curl_easy *data, bool *dophase_done); +static CURLcode smtp_setup_connection(struct Curl_easy *data, + struct connectdata *conn); static CURLcode smtp_parse_url_options(struct connectdata *conn); -static CURLcode smtp_parse_url_path(struct connectdata *conn); -static CURLcode smtp_parse_custom_request(struct connectdata *conn); +static CURLcode smtp_parse_url_path(struct Curl_easy *data); +static CURLcode smtp_parse_custom_request(struct Curl_easy *data); static CURLcode smtp_parse_address(struct connectdata *conn, const char *fqma, char **address, struct hostname *host); -static CURLcode smtp_perform_auth(struct connectdata *conn, const char *mech, +static CURLcode smtp_perform_auth(struct Curl_easy *data, + struct connectdata *conn, const char *mech, const char *initresp); -static CURLcode smtp_continue_auth(struct connectdata *conn, const char *resp); +static CURLcode smtp_continue_auth(struct Curl_easy *data, + struct connectdata *conn, const char *resp); static void smtp_get_message(char *buffer, char **outptr); /* @@ -199,11 +204,12 @@ static void smtp_to_smtps(struct connectdata *conn) * also detects various capabilities from the EHLO response including the * supported authentication mechanisms. */ -static bool smtp_endofresp(struct connectdata *conn, char *line, size_t len, - int *resp) +static bool smtp_endofresp(struct Curl_easy *data, struct connectdata *conn, + char *line, size_t len, int *resp) { struct smtp_conn *smtpc = &conn->proto.smtpc; bool result = FALSE; + (void)data; /* Nothing for us */ if(len < 4 || !ISDIGIT(line[0]) || !ISDIGIT(line[1]) || !ISDIGIT(line[2])) @@ -277,9 +283,9 @@ static void smtp_get_message(char *buffer, char **outptr) * * This is the ONLY way to change SMTP state! */ -static void state(struct connectdata *conn, smtpstate newstate) +static void state(struct Curl_easy *data, smtpstate newstate) { - struct smtp_conn *smtpc = &conn->proto.smtpc; + struct smtp_conn *smtpc = &data->conn->proto.smtpc; #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) /* for debug purposes */ static const char * const names[] = { @@ -300,7 +306,7 @@ static void state(struct connectdata *conn, smtpstate newstate) }; if(smtpc->state != newstate) - infof(conn->data, "SMTP %p state change from %s to %s\n", + infof(data, "SMTP %p state change from %s to %s\n", (void *)smtpc, names[smtpc->state], names[newstate]); #endif @@ -314,9 +320,10 @@ static void state(struct connectdata *conn, smtpstate newstate) * Sends the EHLO command to not only initialise communication with the ESMTP * server but to also obtain a list of server side supported capabilities. */ -static CURLcode smtp_perform_ehlo(struct connectdata *conn) +static CURLcode smtp_perform_ehlo(struct Curl_easy *data) { CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; struct smtp_conn *smtpc = &conn->proto.smtpc; smtpc->sasl.authmechs = SASL_AUTH_NONE; /* No known auth. mechanism yet */ @@ -326,10 +333,10 @@ static CURLcode smtp_perform_ehlo(struct connectdata *conn) smtpc->auth_supported = FALSE; /* Clear the AUTH capability */ /* Send the EHLO command */ - result = Curl_pp_sendf(&smtpc->pp, "EHLO %s", smtpc->domain); + result = Curl_pp_sendf(data, &smtpc->pp, "EHLO %s", smtpc->domain); if(!result) - state(conn, SMTP_EHLO); + state(data, SMTP_EHLO); return result; } @@ -340,7 +347,8 @@ static CURLcode smtp_perform_ehlo(struct connectdata *conn) * * Sends the HELO command to initialise communication with the SMTP server. */ -static CURLcode smtp_perform_helo(struct connectdata *conn) +static CURLcode smtp_perform_helo(struct Curl_easy *data, + struct connectdata *conn) { CURLcode result = CURLE_OK; struct smtp_conn *smtpc = &conn->proto.smtpc; @@ -349,10 +357,10 @@ static CURLcode smtp_perform_helo(struct connectdata *conn) in smtp connections */ /* Send the HELO command */ - result = Curl_pp_sendf(&smtpc->pp, "HELO %s", smtpc->domain); + result = Curl_pp_sendf(data, &smtpc->pp, "HELO %s", smtpc->domain); if(!result) - state(conn, SMTP_HELO); + state(data, SMTP_HELO); return result; } @@ -363,13 +371,15 @@ static CURLcode smtp_perform_helo(struct connectdata *conn) * * Sends the STLS command to start the upgrade to TLS. */ -static CURLcode smtp_perform_starttls(struct connectdata *conn) +static CURLcode smtp_perform_starttls(struct Curl_easy *data, + struct connectdata *conn) { /* Send the STARTTLS command */ - CURLcode result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "STARTTLS"); + CURLcode result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, + "%s", "STARTTLS"); if(!result) - state(conn, SMTP_STARTTLS); + state(data, SMTP_STARTTLS); return result; } @@ -380,20 +390,21 @@ static CURLcode smtp_perform_starttls(struct connectdata *conn) * * Performs the upgrade to TLS. */ -static CURLcode smtp_perform_upgrade_tls(struct connectdata *conn) +static CURLcode smtp_perform_upgrade_tls(struct Curl_easy *data) { /* Start the SSL connection */ + struct connectdata *conn = data->conn; struct smtp_conn *smtpc = &conn->proto.smtpc; CURLcode result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &smtpc->ssldone); if(!result) { if(smtpc->state != SMTP_UPGRADETLS) - state(conn, SMTP_UPGRADETLS); + state(data, SMTP_UPGRADETLS); if(smtpc->ssldone) { smtp_to_smtps(conn); - result = smtp_perform_ehlo(conn); + result = smtp_perform_ehlo(data); } } @@ -407,7 +418,8 @@ static CURLcode smtp_perform_upgrade_tls(struct connectdata *conn) * Sends an AUTH command allowing the client to login with the given SASL * authentication mechanism. */ -static CURLcode smtp_perform_auth(struct connectdata *conn, +static CURLcode smtp_perform_auth(struct Curl_easy *data, + struct connectdata *conn, const char *mech, const char *initresp) { @@ -416,11 +428,11 @@ static CURLcode smtp_perform_auth(struct connectdata *conn, if(initresp) { /* AUTH <mech> ...<crlf> */ /* Send the AUTH command with the initial response */ - result = Curl_pp_sendf(&smtpc->pp, "AUTH %s %s", mech, initresp); + result = Curl_pp_sendf(data, &smtpc->pp, "AUTH %s %s", mech, initresp); } else { /* Send the AUTH command */ - result = Curl_pp_sendf(&smtpc->pp, "AUTH %s", mech); + result = Curl_pp_sendf(data, &smtpc->pp, "AUTH %s", mech); } return result; @@ -432,11 +444,12 @@ static CURLcode smtp_perform_auth(struct connectdata *conn, * * Sends SASL continuation data or cancellation. */ -static CURLcode smtp_continue_auth(struct connectdata *conn, const char *resp) +static CURLcode smtp_continue_auth(struct Curl_easy *data, + struct connectdata *conn, const char *resp) { struct smtp_conn *smtpc = &conn->proto.smtpc; - return Curl_pp_sendf(&smtpc->pp, "%s", resp); + return Curl_pp_sendf(data, &smtpc->pp, "%s", resp); } /*********************************************************************** @@ -446,9 +459,10 @@ static CURLcode smtp_continue_auth(struct connectdata *conn, const char *resp) * Initiates the authentication sequence, with the appropriate SASL * authentication mechanism. */ -static CURLcode smtp_perform_authentication(struct connectdata *conn) +static CURLcode smtp_perform_authentication(struct Curl_easy *data) { CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; struct smtp_conn *smtpc = &conn->proto.smtpc; saslprogress progress; @@ -456,7 +470,7 @@ static CURLcode smtp_perform_authentication(struct connectdata *conn) server supports authentiation, and end the connect phase if not */ if(!smtpc->auth_supported || !Curl_sasl_can_authenticate(&smtpc->sasl, conn)) { - state(conn, SMTP_STOP); + state(data, SMTP_STOP); return result; } @@ -465,10 +479,10 @@ static CURLcode smtp_perform_authentication(struct connectdata *conn) if(!result) { if(progress == SASL_INPROGRESS) - state(conn, SMTP_AUTH); + state(data, SMTP_AUTH); else { /* Other mechanisms not supported */ - infof(conn->data, "No known authentication mechanisms supported!\n"); + infof(data, "No known authentication mechanisms supported!\n"); result = CURLE_LOGIN_DENIED; } } @@ -482,10 +496,10 @@ static CURLcode smtp_perform_authentication(struct connectdata *conn) * * Sends a SMTP based command. */ -static CURLcode smtp_perform_command(struct connectdata *conn) +static CURLcode smtp_perform_command(struct Curl_easy *data) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct SMTP *smtp = data->req.p.smtp; if(smtp->rcpt) { @@ -514,7 +528,7 @@ static CURLcode smtp_perform_command(struct connectdata *conn) /* Send the VRFY command (Note: The host name part may be absent when the host is a local system) */ - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "VRFY %s%s%s%s", + result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "VRFY %s%s%s%s", address, host.name ? "@" : "", host.name ? host.name : "", @@ -530,19 +544,20 @@ static CURLcode smtp_perform_command(struct connectdata *conn) (!strcmp(smtp->custom, "EXPN")); /* Send the custom recipient based command such as the EXPN command */ - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s %s%s", smtp->custom, + result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, + "%s %s%s", smtp->custom, smtp->rcpt->data, utf8 ? " SMTPUTF8" : ""); } } else /* Send the non-recipient based command such as HELP */ - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", + result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "%s", smtp->custom && smtp->custom[0] != '\0' ? smtp->custom : "HELP"); if(!result) - state(conn, SMTP_COMMAND); + state(data, SMTP_COMMAND); return result; } @@ -553,13 +568,13 @@ static CURLcode smtp_perform_command(struct connectdata *conn) * * Sends an MAIL command to initiate the upload of a message. */ -static CURLcode smtp_perform_mail(struct connectdata *conn) +static CURLcode smtp_perform_mail(struct Curl_easy *data) { char *from = NULL; char *auth = NULL; char *size = NULL; CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; /* We notify the server we are sending UTF-8 data if a) it supports the SMTPUTF8 extension and b) The mailbox contains UTF-8 charaacters, in @@ -660,7 +675,7 @@ static CURLcode smtp_perform_mail(struct connectdata *conn) NULL, MIMESTRATEGY_MAIL); if(!result) - if(!Curl_checkheaders(conn, "Mime-Version")) + if(!Curl_checkheaders(data, "Mime-Version")) result = Curl_mime_add_header(&data->set.mimepost.curlheaders, "Mime-Version: 1.0"); @@ -712,7 +727,7 @@ static CURLcode smtp_perform_mail(struct connectdata *conn) } /* Send the MAIL command */ - result = Curl_pp_sendf(&conn->proto.smtpc.pp, + result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "MAIL FROM:%s%s%s%s%s%s", from, /* Mandatory */ auth ? " AUTH=" : "", /* Optional on AUTH support */ @@ -727,7 +742,7 @@ static CURLcode smtp_perform_mail(struct connectdata *conn) free(size); if(!result) - state(conn, SMTP_MAIL); + state(data, SMTP_MAIL); return result; } @@ -739,10 +754,10 @@ static CURLcode smtp_perform_mail(struct connectdata *conn) * Sends a RCPT TO command for a given recipient as part of the message upload * process. */ -static CURLcode smtp_perform_rcpt_to(struct connectdata *conn) +static CURLcode smtp_perform_rcpt_to(struct Curl_easy *data) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct SMTP *smtp = data->req.p.smtp; char *address = NULL; struct hostname host = { NULL, NULL, NULL, NULL }; @@ -756,18 +771,19 @@ static CURLcode smtp_perform_rcpt_to(struct connectdata *conn) /* Send the RCPT TO command */ if(host.name) - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:<%s@%s>", address, - host.name); + result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "RCPT TO:<%s@%s>", + address, host.name); else /* An invalid mailbox was provided but we'll simply let the server worry about that and reply with a 501 error */ - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:<%s>", address); + result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "RCPT TO:<%s>", + address); Curl_free_idnconverted_hostname(&host); free(address); if(!result) - state(conn, SMTP_RCPT); + state(data, SMTP_RCPT); return result; } @@ -778,25 +794,24 @@ static CURLcode smtp_perform_rcpt_to(struct connectdata *conn) * * Performs the quit action prior to sclose() being called. */ -static CURLcode smtp_perform_quit(struct connectdata *conn) +static CURLcode smtp_perform_quit(struct Curl_easy *data, + struct connectdata *conn) { /* Send the QUIT command */ - CURLcode result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "QUIT"); + CURLcode result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "%s", "QUIT"); if(!result) - state(conn, SMTP_QUIT); + state(data, SMTP_QUIT); return result; } /* For the initial server greeting */ -static CURLcode smtp_state_servergreet_resp(struct connectdata *conn, +static CURLcode smtp_state_servergreet_resp(struct Curl_easy *data, int smtpcode, smtpstate instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; - (void)instate; /* no use for this yet */ if(smtpcode/100 != 2) { @@ -804,19 +819,17 @@ static CURLcode smtp_state_servergreet_resp(struct connectdata *conn, result = CURLE_WEIRD_SERVER_REPLY; } else - result = smtp_perform_ehlo(conn); + result = smtp_perform_ehlo(data); return result; } /* For STARTTLS responses */ -static CURLcode smtp_state_starttls_resp(struct connectdata *conn, +static CURLcode smtp_state_starttls_resp(struct Curl_easy *data, int smtpcode, smtpstate instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; - (void)instate; /* no use for this yet */ if(smtpcode != 220) { @@ -825,20 +838,20 @@ static CURLcode smtp_state_starttls_resp(struct connectdata *conn, result = CURLE_USE_SSL_FAILED; } else - result = smtp_perform_authentication(conn); + result = smtp_perform_authentication(data); } else - result = smtp_perform_upgrade_tls(conn); + result = smtp_perform_upgrade_tls(data); return result; } /* For EHLO responses */ -static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode, +static CURLcode smtp_state_ehlo_resp(struct Curl_easy *data, + struct connectdata *conn, int smtpcode, smtpstate instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; struct smtp_conn *smtpc = &conn->proto.smtpc; const char *line = data->state.buffer; size_t len = strlen(line); @@ -847,7 +860,7 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode, if(smtpcode/100 != 2 && smtpcode != 1) { if(data->set.use_ssl <= CURLUSESSL_TRY || conn->ssl[FIRSTSOCKET].use) - result = smtp_perform_helo(conn); + result = smtp_perform_helo(data, conn); else { failf(data, "Remote access denied: %d", smtpcode); result = CURLE_REMOTE_ACCESS_DENIED; @@ -915,17 +928,17 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode, /* We don't have a SSL/TLS connection yet, but SSL is requested */ if(smtpc->tls_supported) /* Switch to TLS connection now */ - result = smtp_perform_starttls(conn); + result = smtp_perform_starttls(data, conn); else if(data->set.use_ssl == CURLUSESSL_TRY) /* Fallback and carry on with authentication */ - result = smtp_perform_authentication(conn); + result = smtp_perform_authentication(data); else { failf(data, "STARTTLS not supported."); result = CURLE_USE_SSL_FAILED; } } else - result = smtp_perform_authentication(conn); + result = smtp_perform_authentication(data); } } else { @@ -937,12 +950,10 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode, } /* For HELO responses */ -static CURLcode smtp_state_helo_resp(struct connectdata *conn, int smtpcode, +static CURLcode smtp_state_helo_resp(struct Curl_easy *data, int smtpcode, smtpstate instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; - (void)instate; /* no use for this yet */ if(smtpcode/100 != 2) { @@ -951,18 +962,18 @@ static CURLcode smtp_state_helo_resp(struct connectdata *conn, int smtpcode, } else /* End of connect phase */ - state(conn, SMTP_STOP); + state(data, SMTP_STOP); return result; } /* For SASL authentication responses */ -static CURLcode smtp_state_auth_resp(struct connectdata *conn, +static CURLcode smtp_state_auth_resp(struct Curl_easy *data, int smtpcode, smtpstate instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct smtp_conn *smtpc = &conn->proto.smtpc; saslprogress progress; @@ -972,7 +983,7 @@ static CURLcode smtp_state_auth_resp(struct connectdata *conn, if(!result) switch(progress) { case SASL_DONE: - state(conn, SMTP_STOP); /* Authenticated */ + state(data, SMTP_STOP); /* Authenticated */ break; case SASL_IDLE: /* No mechanism left after cancellation */ failf(data, "Authentication cancelled"); @@ -986,11 +997,10 @@ static CURLcode smtp_state_auth_resp(struct connectdata *conn, } /* For command responses */ -static CURLcode smtp_state_command_resp(struct connectdata *conn, int smtpcode, +static CURLcode smtp_state_command_resp(struct Curl_easy *data, int smtpcode, smtpstate instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; struct SMTP *smtp = data->req.p.smtp; char *line = data->state.buffer; size_t len = strlen(line); @@ -1006,7 +1016,7 @@ static CURLcode smtp_state_command_resp(struct connectdata *conn, int smtpcode, /* Temporarily add the LF character back and send as body to the client */ if(!data->set.opt_no_body) { line[len] = '\n'; - result = Curl_client_write(conn, CLIENTWRITE_BODY, line, len + 1); + result = Curl_client_write(data, CLIENTWRITE_BODY, line, len + 1); line[len] = '\0'; } @@ -1016,15 +1026,15 @@ static CURLcode smtp_state_command_resp(struct connectdata *conn, int smtpcode, if(smtp->rcpt) { /* Send the next command */ - result = smtp_perform_command(conn); + result = smtp_perform_command(data); } else /* End of DO phase */ - state(conn, SMTP_STOP); + state(data, SMTP_STOP); } else /* End of DO phase */ - state(conn, SMTP_STOP); + state(data, SMTP_STOP); } } @@ -1032,12 +1042,10 @@ static CURLcode smtp_state_command_resp(struct connectdata *conn, int smtpcode, } /* For MAIL responses */ -static CURLcode smtp_state_mail_resp(struct connectdata *conn, int smtpcode, +static CURLcode smtp_state_mail_resp(struct Curl_easy *data, int smtpcode, smtpstate instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; - (void)instate; /* no use for this yet */ if(smtpcode/100 != 2) { @@ -1046,17 +1054,17 @@ static CURLcode smtp_state_mail_resp(struct connectdata *conn, int smtpcode, } else /* Start the RCPT TO command */ - result = smtp_perform_rcpt_to(conn); + result = smtp_perform_rcpt_to(data); return result; } /* For RCPT responses */ -static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode, +static CURLcode smtp_state_rcpt_resp(struct Curl_easy *data, + struct connectdata *conn, int smtpcode, smtpstate instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; struct SMTP *smtp = data->req.p.smtp; bool is_smtp_err = FALSE; bool is_smtp_blocking_err = FALSE; @@ -1090,7 +1098,7 @@ static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode, if(smtp->rcpt) /* Send the next RCPT TO command */ - result = smtp_perform_rcpt_to(conn); + result = smtp_perform_rcpt_to(data); else { /* We weren't able to issue a successful RCPT TO command while going over recipients (potentially multiple). Sending back last error. */ @@ -1100,10 +1108,10 @@ static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode, } else { /* Send the DATA command */ - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "DATA"); + result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "%s", "DATA"); if(!result) - state(conn, SMTP_DATA); + state(data, SMTP_DATA); } } } @@ -1112,12 +1120,10 @@ static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode, } /* For DATA response */ -static CURLcode smtp_state_data_resp(struct connectdata *conn, int smtpcode, +static CURLcode smtp_state_data_resp(struct Curl_easy *data, int smtpcode, smtpstate instate) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; - (void)instate; /* no use for this yet */ if(smtpcode != 354) { @@ -1132,7 +1138,7 @@ static CURLcode smtp_state_data_resp(struct connectdata *conn, int smtpcode, Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); /* End of DO phase */ - state(conn, SMTP_STOP); + state(data, SMTP_STOP); } return result; @@ -1140,7 +1146,7 @@ static CURLcode smtp_state_data_resp(struct connectdata *conn, int smtpcode, /* For POSTDATA responses, which are received after the entire DATA part has been sent to the server */ -static CURLcode smtp_state_postdata_resp(struct connectdata *conn, +static CURLcode smtp_state_postdata_resp(struct Curl_easy *data, int smtpcode, smtpstate instate) { @@ -1152,16 +1158,16 @@ static CURLcode smtp_state_postdata_resp(struct connectdata *conn, result = CURLE_RECV_ERROR; /* End of DONE phase */ - state(conn, SMTP_STOP); + state(data, SMTP_STOP); return result; } -static CURLcode smtp_statemach_act(struct connectdata *conn) +static CURLcode smtp_statemachine(struct Curl_easy *data, + struct connectdata *conn) { CURLcode result = CURLE_OK; curl_socket_t sock = conn->sock[FIRSTSOCKET]; - struct Curl_easy *data = conn->data; int smtpcode; struct smtp_conn *smtpc = &conn->proto.smtpc; struct pingpong *pp = &smtpc->pp; @@ -1169,7 +1175,7 @@ static CURLcode smtp_statemach_act(struct connectdata *conn) /* Busy upgrading the connection; right now all I/O is SSL/TLS, not SMTP */ if(smtpc->state == SMTP_UPGRADETLS) - return smtp_perform_upgrade_tls(conn); + return smtp_perform_upgrade_tls(data); /* Flush any data that needs to be sent */ if(pp->sendleft) @@ -1177,7 +1183,7 @@ static CURLcode smtp_statemach_act(struct connectdata *conn) do { /* Read the response from the server */ - result = Curl_pp_readresp(sock, pp, &smtpcode, &nread); + result = Curl_pp_readresp(data, sock, pp, &smtpcode, &nread); if(result) return result; @@ -1191,50 +1197,50 @@ static CURLcode smtp_statemach_act(struct connectdata *conn) /* We have now received a full SMTP server response */ switch(smtpc->state) { case SMTP_SERVERGREET: - result = smtp_state_servergreet_resp(conn, smtpcode, smtpc->state); + result = smtp_state_servergreet_resp(data, smtpcode, smtpc->state); break; case SMTP_EHLO: - result = smtp_state_ehlo_resp(conn, smtpcode, smtpc->state); + result = smtp_state_ehlo_resp(data, conn, smtpcode, smtpc->state); break; case SMTP_HELO: - result = smtp_state_helo_resp(conn, smtpcode, smtpc->state); + result = smtp_state_helo_resp(data, smtpcode, smtpc->state); break; case SMTP_STARTTLS: - result = smtp_state_starttls_resp(conn, smtpcode, smtpc->state); + result = smtp_state_starttls_resp(data, smtpcode, smtpc->state); break; case SMTP_AUTH: - result = smtp_state_auth_resp(conn, smtpcode, smtpc->state); + result = smtp_state_auth_resp(data, smtpcode, smtpc->state); break; case SMTP_COMMAND: - result = smtp_state_command_resp(conn, smtpcode, smtpc->state); + result = smtp_state_command_resp(data, smtpcode, smtpc->state); break; case SMTP_MAIL: - result = smtp_state_mail_resp(conn, smtpcode, smtpc->state); + result = smtp_state_mail_resp(data, smtpcode, smtpc->state); break; case SMTP_RCPT: - result = smtp_state_rcpt_resp(conn, smtpcode, smtpc->state); + result = smtp_state_rcpt_resp(data, conn, smtpcode, smtpc->state); break; case SMTP_DATA: - result = smtp_state_data_resp(conn, smtpcode, smtpc->state); + result = smtp_state_data_resp(data, smtpcode, smtpc->state); break; case SMTP_POSTDATA: - result = smtp_state_postdata_resp(conn, smtpcode, smtpc->state); + result = smtp_state_postdata_resp(data, smtpcode, smtpc->state); break; case SMTP_QUIT: /* fallthrough, just stop! */ default: /* internal error */ - state(conn, SMTP_STOP); + state(data, SMTP_STOP); break; } } while(!result && smtpc->state != SMTP_STOP && Curl_pp_moredata(pp)); @@ -1243,9 +1249,10 @@ static CURLcode smtp_statemach_act(struct connectdata *conn) } /* Called repeatedly until done from multi.c */ -static CURLcode smtp_multi_statemach(struct connectdata *conn, bool *done) +static CURLcode smtp_multi_statemach(struct Curl_easy *data, bool *done) { CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; struct smtp_conn *smtpc = &conn->proto.smtpc; if((conn->handler->flags & PROTOPT_SSL) && !smtpc->ssldone) { @@ -1254,30 +1261,30 @@ static CURLcode smtp_multi_statemach(struct connectdata *conn, bool *done) return result; } - result = Curl_pp_statemach(&smtpc->pp, FALSE, FALSE); + result = Curl_pp_statemach(data, &smtpc->pp, FALSE, FALSE); *done = (smtpc->state == SMTP_STOP) ? TRUE : FALSE; return result; } -static CURLcode smtp_block_statemach(struct connectdata *conn, +static CURLcode smtp_block_statemach(struct Curl_easy *data, + struct connectdata *conn, bool disconnecting) { CURLcode result = CURLE_OK; struct smtp_conn *smtpc = &conn->proto.smtpc; while(smtpc->state != SMTP_STOP && !result) - result = Curl_pp_statemach(&smtpc->pp, TRUE, disconnecting); + result = Curl_pp_statemach(data, &smtpc->pp, TRUE, disconnecting); return result; } /* Allocate and initialize the SMTP struct for the current Curl_easy if required */ -static CURLcode smtp_init(struct connectdata *conn) +static CURLcode smtp_init(struct Curl_easy *data) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; struct SMTP *smtp; smtp = data->req.p.smtp = calloc(sizeof(struct SMTP), 1); @@ -1288,8 +1295,10 @@ static CURLcode smtp_init(struct connectdata *conn) } /* For the SMTP "protocol connect" and "doing" phases only */ -static int smtp_getsock(struct connectdata *conn, curl_socket_t *socks) +static int smtp_getsock(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t *socks) { + (void)data; return Curl_pp_getsock(&conn->proto.smtpc.pp, socks); } @@ -1303,9 +1312,10 @@ static int smtp_getsock(struct connectdata *conn, curl_socket_t *socks) * The variable pointed to by 'done' will be TRUE if the protocol-layer * connect phase is done when this function returns, or FALSE if not. */ -static CURLcode smtp_connect(struct connectdata *conn, bool *done) +static CURLcode smtp_connect(struct Curl_easy *data, bool *done) { CURLcode result = CURLE_OK; + struct connectdata *conn = data->conn; struct smtp_conn *smtpc = &conn->proto.smtpc; struct pingpong *pp = &smtpc->pp; @@ -1314,18 +1324,14 @@ static CURLcode smtp_connect(struct connectdata *conn, bool *done) /* We always support persistent connections in SMTP */ connkeep(conn, "SMTP default"); - /* Set the default response time-out */ - pp->response_time = RESP_TIMEOUT; - pp->statemach_act = smtp_statemach_act; - pp->endofresp = smtp_endofresp; - pp->conn = conn; + PINGPONG_SETUP(pp, smtp_statemachine, smtp_endofresp); /* Initialize the SASL storage */ Curl_sasl_init(&smtpc->sasl, &saslsmtp); /* Initialise the pingpong layer */ Curl_pp_setup(pp); - Curl_pp_init(pp); + Curl_pp_init(data, pp); /* Parse the URL options */ result = smtp_parse_url_options(conn); @@ -1333,14 +1339,14 @@ static CURLcode smtp_connect(struct connectdata *conn, bool *done) return result; /* Parse the URL path */ - result = smtp_parse_url_path(conn); + result = smtp_parse_url_path(data); if(result) return result; /* Start off waiting for the server greeting response */ - state(conn, SMTP_SERVERGREET); + state(data, SMTP_SERVERGREET); - result = smtp_multi_statemach(conn, done); + result = smtp_multi_statemach(data, done); return result; } @@ -1354,11 +1360,11 @@ static CURLcode smtp_connect(struct connectdata *conn, bool *done) * * Input argument is already checked for validity. */ -static CURLcode smtp_done(struct connectdata *conn, CURLcode status, +static CURLcode smtp_done(struct Curl_easy *data, CURLcode status, bool premature) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct SMTP *smtp = data->req.p.smtp; struct pingpong *pp = &conn->proto.smtpc.pp; char *eob; @@ -1367,7 +1373,7 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status, (void)premature; - if(!smtp || !pp->conn) + if(!smtp) return CURLE_OK; /* Cleanup our per-request based variables */ @@ -1387,7 +1393,7 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status, fail when using a different pointer following a previous write, that returned CURLE_AGAIN, we duplicate the EOB now rather than when the bytes written doesn't equal len. */ - if(smtp->trailing_crlf || !conn->data->state.infilesize) { + if(smtp->trailing_crlf || !data->state.infilesize) { eob = strdup(&SMTP_EOB[2]); len = SMTP_EOB_LEN - 2; } @@ -1400,7 +1406,7 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status, return CURLE_OUT_OF_MEMORY; /* Send the end of block data */ - result = Curl_write(conn, conn->writesockfd, eob, len, &bytes_written); + result = Curl_write(data, conn->writesockfd, eob, len, &bytes_written); if(result) { free(eob); return result; @@ -1420,10 +1426,10 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status, free(eob); } - state(conn, SMTP_POSTDATA); + state(data, SMTP_POSTDATA); /* Run the state-machine */ - result = smtp_block_statemach(conn, FALSE); + result = smtp_block_statemach(data, conn, FALSE); } /* Clear the transfer mode for the next request */ @@ -1439,15 +1445,15 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status, * This is the actual DO function for SMTP. Transfer a mail, send a command * or get some data according to the options previously setup. */ -static CURLcode smtp_perform(struct connectdata *conn, bool *connected, +static CURLcode smtp_perform(struct Curl_easy *data, bool *connected, bool *dophase_done) { /* This is SMTP and no proxy */ CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct SMTP *smtp = data->req.p.smtp; - DEBUGF(infof(conn->data, "DO phase starts\n")); + DEBUGF(infof(data, "DO phase starts\n")); if(data->set.opt_no_body) { /* Requested no body means no transfer */ @@ -1473,21 +1479,21 @@ static CURLcode smtp_perform(struct connectdata *conn, bool *connected, /* Start the first command in the DO phase */ if((data->set.upload || data->set.mimepost.kind) && data->set.mail_rcpt) /* MAIL transfer */ - result = smtp_perform_mail(conn); + result = smtp_perform_mail(data); else /* SMTP based command (VRFY, EXPN, NOOP, RSET or HELP) */ - result = smtp_perform_command(conn); + result = smtp_perform_command(data); if(result) return result; /* Run the state-machine */ - result = smtp_multi_statemach(conn, dophase_done); + result = smtp_multi_statemach(data, dophase_done); *connected = conn->bits.tcpconnect[FIRSTSOCKET]; if(*dophase_done) - DEBUGF(infof(conn->data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete\n")); return result; } @@ -1501,18 +1507,17 @@ static CURLcode smtp_perform(struct connectdata *conn, bool *connected, * * The input argument is already checked for validity. */ -static CURLcode smtp_do(struct connectdata *conn, bool *done) +static CURLcode smtp_do(struct Curl_easy *data, bool *done) { CURLcode result = CURLE_OK; - *done = FALSE; /* default to false */ /* Parse the custom request */ - result = smtp_parse_custom_request(conn); + result = smtp_parse_custom_request(data); if(result) return result; - result = smtp_regular_transfer(conn, done); + result = smtp_regular_transfer(data, done); return result; } @@ -1524,19 +1529,21 @@ static CURLcode smtp_do(struct connectdata *conn, bool *done) * Disconnect from an SMTP server. Cleanup protocol-specific per-connection * resources. BLOCKING. */ -static CURLcode smtp_disconnect(struct connectdata *conn, bool dead_connection) +static CURLcode smtp_disconnect(struct Curl_easy *data, + struct connectdata *conn, + bool dead_connection) { struct smtp_conn *smtpc = &conn->proto.smtpc; + (void)data; /* We cannot send quit unconditionally. If this connection is stale or bad in any way, sending quit and waiting around here will make the disconnect wait in vain and cause more problems than we need to. */ - /* The SMTP session may or may not have been allocated/setup at this - point! */ - if(!dead_connection && smtpc->pp.conn && smtpc->pp.conn->bits.protoconnstart) - if(!smtp_perform_quit(conn)) - (void)smtp_block_statemach(conn, TRUE); /* ignore errors on QUIT */ + if(!dead_connection && conn->bits.protoconnstart) { + if(!smtp_perform_quit(data, conn)) + (void)smtp_block_statemach(data, conn, TRUE); /* ignore errors on QUIT */ + } /* Disconnect from the server */ Curl_pp_disconnect(&smtpc->pp); @@ -1551,30 +1558,30 @@ static CURLcode smtp_disconnect(struct connectdata *conn, bool dead_connection) } /* Call this when the DO phase has completed */ -static CURLcode smtp_dophase_done(struct connectdata *conn, bool connected) +static CURLcode smtp_dophase_done(struct Curl_easy *data, bool connected) { - struct SMTP *smtp = conn->data->req.p.smtp; + struct SMTP *smtp = data->req.p.smtp; (void)connected; if(smtp->transfer != FTPTRANSFER_BODY) /* no data to transfer */ - Curl_setup_transfer(conn->data, -1, -1, FALSE, -1); + Curl_setup_transfer(data, -1, -1, FALSE, -1); return CURLE_OK; } /* Called from multi.c while DOing */ -static CURLcode smtp_doing(struct connectdata *conn, bool *dophase_done) +static CURLcode smtp_doing(struct Curl_easy *data, bool *dophase_done) { - CURLcode result = smtp_multi_statemach(conn, dophase_done); + CURLcode result = smtp_multi_statemach(data, dophase_done); if(result) - DEBUGF(infof(conn->data, "DO phase failed\n")); + DEBUGF(infof(data, "DO phase failed\n")); else if(*dophase_done) { - result = smtp_dophase_done(conn, FALSE /* not connected */); + result = smtp_dophase_done(data, FALSE /* not connected */); - DEBUGF(infof(conn->data, "DO phase is complete\n")); + DEBUGF(infof(data, "DO phase is complete\n")); } return result; @@ -1589,12 +1596,11 @@ static CURLcode smtp_doing(struct connectdata *conn, bool *dophase_done) * Performs all commands done before a regular transfer between a local and a * remote host. */ -static CURLcode smtp_regular_transfer(struct connectdata *conn, +static CURLcode smtp_regular_transfer(struct Curl_easy *data, bool *dophase_done) { CURLcode result = CURLE_OK; bool connected = FALSE; - struct Curl_easy *data = conn->data; /* Make sure size is unknown at this point */ data->req.size = -1; @@ -1606,16 +1612,17 @@ static CURLcode smtp_regular_transfer(struct connectdata *conn, Curl_pgrsSetDownloadSize(data, -1); /* Carry out the perform */ - result = smtp_perform(conn, &connected, dophase_done); + result = smtp_perform(data, &connected, dophase_done); /* Perform post DO phase operations if necessary */ if(!result && *dophase_done) - result = smtp_dophase_done(conn, connected); + result = smtp_dophase_done(data, connected); return result; } -static CURLcode smtp_setup_connection(struct connectdata *conn) +static CURLcode smtp_setup_connection(struct Curl_easy *data, + struct connectdata *conn) { CURLcode result; @@ -1623,7 +1630,7 @@ static CURLcode smtp_setup_connection(struct connectdata *conn) conn->bits.tls_upgraded = FALSE; /* Initialise the SMTP layer */ - result = smtp_init(conn); + result = smtp_init(data); if(result) return result; @@ -1675,10 +1682,10 @@ static CURLcode smtp_parse_url_options(struct connectdata *conn) * * Parse the URL path into separate path components. */ -static CURLcode smtp_parse_url_path(struct connectdata *conn) +static CURLcode smtp_parse_url_path(struct Curl_easy *data) { /* The SMTP struct is already initialised in smtp_connect() */ - struct Curl_easy *data = conn->data; + struct connectdata *conn = data->conn; struct smtp_conn *smtpc = &conn->proto.smtpc; const char *path = &data->state.up.path[1]; /* skip leading path */ char localhost[HOSTNAME_MAX + 1]; @@ -1692,7 +1699,7 @@ static CURLcode smtp_parse_url_path(struct connectdata *conn) } /* URL decode the path and use it as the domain in our EHLO */ - return Curl_urldecode(conn->data, path, 0, &smtpc->domain, NULL, + return Curl_urldecode(data, path, 0, &smtpc->domain, NULL, REJECT_CTRL); } @@ -1702,10 +1709,9 @@ static CURLcode smtp_parse_url_path(struct connectdata *conn) * * Parse the custom request. */ -static CURLcode smtp_parse_custom_request(struct connectdata *conn) +static CURLcode smtp_parse_custom_request(struct Curl_easy *data) { CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; struct SMTP *smtp = data->req.p.smtp; const char *custom = data->set.str[STRING_CUSTOMREQUEST]; @@ -1788,7 +1794,7 @@ static CURLcode smtp_parse_address(struct connectdata *conn, const char *fqma, return result; } -CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread) +CURLcode Curl_smtp_escape_eob(struct Curl_easy *data, const ssize_t nread) { /* When sending a SMTP payload we must detect CRLF. sequences making sure they are sent as CRLF.. instead, as a . on the beginning of a line will @@ -1798,7 +1804,6 @@ CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread) */ ssize_t i; ssize_t si; - struct Curl_easy *data = conn->data; struct SMTP *smtp = data->req.p.smtp; char *scratch = data->state.scratch; char *newscratch = NULL; |