/*********************************************************************** * * smtp_connect() * * This function should do everything that is to be considered a part of * the connection phase. * * 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. When * called as a part of the easy interface, it will always be TRUE. */ static CURLcode smtp_connect(struct connectdata *conn, bool *done) { CURLcode result; struct smtp_conn *smtpc = &conn->proto.smtpc; struct pingpong *pp = &smtpc->pp; const char *path = conn->data->state.path; char localhost[HOSTNAME_MAX + 1]; *done = FALSE; /* default to not done yet */ /* If there already is a protocol-specific struct allocated for this sessionhandle, deal with it */ Curl_reset_reqproto(conn); result = smtp_init(conn); if(CURLE_OK != result) return result; /* We always support persistent connections on smtp */ conn->bits.close = FALSE; pp->response_time = RESP_TIMEOUT; /* set default response time-out */ pp->statemach_act = smtp_statemach_act; pp->endofresp = smtp_endofresp; pp->conn = conn; /* Initialise the response reader stuff */ Curl_pp_init(pp); /* Set the default response time-out */ pp->response_time = RESP_TIMEOUT; pp->statemach_act = smtp_statemach_act; pp->endofresp = smtp_endofresp; pp->conn = conn; /* Calculate the path if necessary */ if(!*path) { if(!Curl_gethostname(localhost, sizeof(localhost))) path = localhost; else path = "localhost"; } /* URL decode the path and use it as the domain in our EHLO */ result = Curl_urldecode(conn->data, path, 0, &smtpc->domain, NULL, TRUE); if(result) return result; /* Start off waiting for the server greeting response */ state(conn, SMTP_SERVERGREET); result = smtp_multi_statemach(conn, done); return result; }
/*********************************************************************** * * imap_connect() should do everything that is to be considered a part of * the connection phase. * * The variable 'done' points to will be TRUE if the protocol-layer connect * phase is done when this function returns, or FALSE is not. When called as * a part of the easy interface, it will always be TRUE. */ static CURLcode imap_connect(struct connectdata *conn, bool *done) /* see description above */ { CURLcode result; struct imap_conn *imapc = &conn->proto.imapc; struct SessionHandle *data=conn->data; struct pingpong *pp = &imapc->pp; *done = FALSE; /* default to not done yet */ /* If there already is a protocol-specific struct allocated for this sessionhandle, deal with it */ Curl_reset_reqproto(conn); result = imap_init(conn); if(CURLE_OK != result) return result; /* We always support persistent connections on imap */ conn->bits.close = FALSE; pp->response_time = RESP_TIMEOUT; /* set default response time-out */ pp->statemach_act = imap_statemach_act; pp->endofresp = imap_endofresp; pp->conn = conn; if((conn->handler->flags & PROTOPT_SSL) && data->state.used_interface != Curl_if_multi) { /* IMAPS is simply imap with SSL for the control channel */ /* so perform the SSL initialization for this socket */ result = Curl_ssl_connect(conn, FIRSTSOCKET); if(result) return result; } /* Initialise the response reader stuff */ Curl_pp_init(pp); /* Start off waiting for the server greeting response */ state(conn, IMAP_SERVERGREET); /* Start off with an id of '*' */ imapc->idstr = "*"; if(data->state.used_interface == Curl_if_multi) result = imap_multi_statemach(conn, done); else { result = imap_easy_statemach(conn); if(!result) *done = TRUE; } return result; }
/* * pop3_connect() should do everything that is to be considered a part of * the connection phase. * * The variable 'done' points to will be TRUE if the protocol-layer connect * phase is done when this function returns, or FALSE is not. When called as * a part of the easy interface, it will always be TRUE. */ static CURLcode pop3_connect(struct connectdata *conn, bool *done) /* see description above */ { CURLcode result; struct pop3_conn *pop3c = &conn->proto.pop3c; struct SessionHandle *data=conn->data; struct pingpong *pp = &pop3c->pp; *done = FALSE; /* default to not done yet */ /* If there already is a protocol-specific struct allocated for this sessionhandle, deal with it */ Curl_reset_reqproto(conn); result = pop3_init(conn); if(CURLE_OK != result) return result; /* We always support persistent connections on pop3 */ conn->bits.close = FALSE; pp->response_time = RESP_TIMEOUT; /* set default response time-out */ pp->statemach_act = pop3_statemach_act; pp->endofresp = pop3_endofresp; pp->conn = conn; if(conn->handler->flags & PROTOPT_SSL) { /* BLOCKING */ result = Curl_ssl_connect(conn, FIRSTSOCKET); if(result) return result; } Curl_pp_init(pp); /* init the response reader stuff */ /* When we connect, we start in the state where we await the server greet response */ state(conn, POP3_SERVERGREET); if(data->state.used_interface == Curl_if_multi) result = pop3_multi_statemach(conn, done); else { result = pop3_easy_statemach(conn); if(!result) *done = TRUE; } return result; }
/*********************************************************************** * * pop3_connect() * * This function should do everything that is to be considered a part of the * connection phase. * * The variable 'done' points to will be TRUE if the protocol-layer connect * phase is done when this function returns, or FALSE is not. When called as * a part of the easy interface, it will always be TRUE. */ static CURLcode pop3_connect(struct connectdata *conn, bool *done) { CURLcode result; struct pop3_conn *pop3c = &conn->proto.pop3c; struct pingpong *pp = &pop3c->pp; *done = FALSE; /* default to not done yet */ /* If there already is a protocol-specific struct allocated for this sessionhandle, deal with it */ Curl_reset_reqproto(conn); result = pop3_init(conn); if(CURLE_OK != result) return result; /* We always support persistent connections on pop3 */ conn->bits.close = FALSE; pp->response_time = RESP_TIMEOUT; /* set default response time-out */ pp->statemach_act = pop3_statemach_act; pp->endofresp = pop3_endofresp; pp->conn = conn; if(conn->handler->flags & PROTOPT_SSL) { /* POP3S is simply pop3 with SSL for the control channel */ /* so perform the SSL initialization for this socket */ result = Curl_ssl_connect(conn, FIRSTSOCKET); if(result) return result; } /* Initialise the response reader stuff */ Curl_pp_init(pp); /* Start off waiting for the server greeting response */ state(conn, POP3_SERVERGREET); result = pop3_multi_statemach(conn, done); return result; }
/*********************************************************************** * * smtp_connect() * * This function should do everything that is to be considered a part of * the connection phase. * * 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) { CURLcode result = CURLE_OK; struct smtp_conn *smtpc = &conn->proto.smtpc; struct pingpong *pp = &smtpc->pp; *done = FALSE; /* default to not done yet */ /* 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; /* Initialize the SASL storage */ Curl_sasl_init(&smtpc->sasl, &saslsmtp); /* Initialise the pingpong layer */ Curl_pp_init(pp); /* Parse the URL options */ result = smtp_parse_url_options(conn); if(result) return result; /* Parse the URL path */ result = smtp_parse_url_path(conn); if(result) return result; /* Start off waiting for the server greeting response */ state(conn, SMTP_SERVERGREET); result = smtp_multi_statemach(conn, done); return result; }
/*********************************************************************** * * pop3_connect() * * This function should do everything that is to be considered a part of the * connection phase. * * The variable 'done' points to will be TRUE if the protocol-layer connect * phase is done when this function returns, or FALSE if not. */ static CURLcode pop3_connect(struct connectdata *conn, bool *done) { CURLcode result = CURLE_OK; struct pop3_conn *pop3c = &conn->proto.pop3c; struct pingpong *pp = &pop3c->pp; *done = FALSE; /* default to not done yet */ /* We always support persistent connections in POP3 */ connkeep(conn, "POP3 default"); /* Set the default response time-out */ pp->response_time = RESP_TIMEOUT; pp->statemach_act = pop3_statemach_act; pp->endofresp = pop3_endofresp; pp->conn = conn; /* Set the default preferred authentication type and mechanism */ pop3c->preftype = POP3_TYPE_ANY; Curl_sasl_init(&pop3c->sasl, &saslpop3); /* Initialise the pingpong layer */ Curl_pp_init(pp); /* Parse the URL options */ result = pop3_parse_url_options(conn); if(result) return result; /* Start off waiting for the server greeting response */ state(conn, POP3_SERVERGREET); result = pop3_multi_statemach(conn, done); return result; }
/*********************************************************************** * * pop3_connect() * * This function should do everything that is to be considered a part of the * connection phase. * * The variable 'done' points to will be TRUE if the protocol-layer connect * phase is done when this function returns, or FALSE is not. When called as * a part of the easy interface, it will always be TRUE. */ static CURLcode pop3_connect(struct connectdata *conn, bool *done) { CURLcode result = CURLE_OK; struct pop3_conn *pop3c = &conn->proto.pop3c; struct pingpong *pp = &pop3c->pp; *done = FALSE; /* default to not done yet */ /* If there already is a protocol-specific struct allocated for this sessionhandle, deal with it */ Curl_reset_reqproto(conn); /* Initialise the POP3 layer */ result = pop3_init(conn); if(result) return result; /* We always support persistent connections in POP3 */ conn->bits.close = FALSE; /* Set the default response time-out */ pp->response_time = RESP_TIMEOUT; pp->statemach_act = pop3_statemach_act; pp->endofresp = pop3_endofresp; pp->conn = conn; /* Initialise the pingpong layer */ Curl_pp_init(pp); /* Start off waiting for the server greeting response */ state(conn, POP3_SERVERGREET); result = pop3_multi_statemach(conn, done); return result; }
/* * pop3_connect() should do everything that is to be considered a part of * the connection phase. * * The variable 'done' points to will be TRUE if the protocol-layer connect * phase is done when this function returns, or FALSE is not. When called as * a part of the easy interface, it will always be TRUE. */ static CURLcode pop3_connect(struct connectdata *conn, bool *done) /* see description above */ { CURLcode result; struct pop3_conn *pop3c = &conn->proto.pop3c; struct SessionHandle *data=conn->data; struct pingpong *pp = &pop3c->pp; *done = FALSE; /* default to not done yet */ /* If there already is a protocol-specific struct allocated for this sessionhandle, deal with it */ Curl_reset_reqproto(conn); result = pop3_init(conn); if(CURLE_OK != result) return result; /* We always support persistent connections on pop3 */ conn->bits.close = FALSE; pp->response_time = RESP_TIMEOUT; /* set default response time-out */ pp->statemach_act = pop3_statemach_act; pp->endofresp = pop3_endofresp; pp->conn = conn; if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { /* for POP3 over HTTP proxy */ struct HTTP http_proxy; struct FTP *pop3_save; /* BLOCKING */ /* We want "seamless" POP3 operations through HTTP proxy tunnel */ /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the member * conn->proto.http; we want POP3 through HTTP and we have to change the * member temporarily for connecting to the HTTP proxy. After * Curl_proxyCONNECT we have to set back the member to the original struct * POP3 pointer */ pop3_save = data->state.proto.pop3; memset(&http_proxy, 0, sizeof(http_proxy)); data->state.proto.http = &http_proxy; result = Curl_proxyCONNECT(conn, FIRSTSOCKET, conn->host.name, conn->remote_port); data->state.proto.pop3 = pop3_save; if(CURLE_OK != result) return result; } if(conn->handler->flags & PROTOPT_SSL) { /* BLOCKING */ result = Curl_ssl_connect(conn, FIRSTSOCKET); if(result) return result; } Curl_pp_init(pp); /* init the response reader stuff */ /* When we connect, we start in the state where we await the server greet response */ state(conn, POP3_SERVERGREET); if(data->state.used_interface == Curl_if_multi) result = pop3_multi_statemach(conn, done); else { result = pop3_easy_statemach(conn); if(!result) *done = TRUE; } return result; }
/* * smtp_connect() should do everything that is to be considered a part of * the connection phase. * * The variable 'done' points to will be TRUE if the protocol-layer connect * phase is done when this function returns, or FALSE is not. When called as * a part of the easy interface, it will always be TRUE. */ static CURLcode smtp_connect(struct connectdata *conn, bool *done) /* see description above */ { CURLcode result; struct smtp_conn *smtpc = &conn->proto.smtpc; struct SessionHandle *data=conn->data; struct pingpong *pp=&smtpc->pp; const char *path = conn->data->state.path; int len; char localhost[1024 + 1]; *done = FALSE; /* default to not done yet */ /* If there already is a protocol-specific struct allocated for this sessionhandle, deal with it */ Curl_reset_reqproto(conn); result = smtp_init(conn); if(CURLE_OK != result) return result; /* We always support persistant connections on smtp */ conn->bits.close = FALSE; pp->response_time = RESP_TIMEOUT; /* set default response time-out */ pp->statemach_act = smtp_statemach_act; pp->endofresp = smtp_endofresp; pp->conn = conn; #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_PROXY) if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { /* for SMTP over HTTP proxy */ struct HTTP http_proxy; struct FTP *smtp_save; /* BLOCKING */ /* We want "seamless" SMTP operations through HTTP proxy tunnel */ /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the member * conn->proto.http; we want SMTP through HTTP and we have to change the * member temporarily for connecting to the HTTP proxy. After * Curl_proxyCONNECT we have to set back the member to the original struct * SMTP pointer */ smtp_save = data->state.proto.smtp; memset(&http_proxy, 0, sizeof(http_proxy)); data->state.proto.http = &http_proxy; result = Curl_proxyCONNECT(conn, FIRSTSOCKET, conn->host.name, conn->remote_port); data->state.proto.smtp = smtp_save; if(CURLE_OK != result) return result; } #endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_PROXY */ if(conn->protocol & PROT_SMTPS) { /* BLOCKING */ /* SMTPS is simply smtp with SSL for the control channel */ /* now, perform the SSL initialization for this socket */ result = Curl_ssl_connect(conn, FIRSTSOCKET); if(result) return result; } Curl_pp_init(pp); /* init the response reader stuff */ pp->response_time = RESP_TIMEOUT; /* set default response time-out */ pp->statemach_act = smtp_statemach_act; pp->endofresp = smtp_endofresp; pp->conn = conn; if(!*path) { if(!Curl_gethostname(localhost, sizeof localhost)) path = localhost; else path = "localhost"; } /* url decode the path and use it as domain with EHLO */ smtpc->domain = curl_easy_unescape(conn->data, path, 0, &len); if(!smtpc->domain) return CURLE_OUT_OF_MEMORY; /* When we connect, we start in the state where we await the server greeting */ state(conn, SMTP_SERVERGREET); if(data->state.used_interface == Curl_if_multi) result = smtp_multi_statemach(conn, done); else { result = smtp_easy_statemach(conn); if(!result) *done = TRUE; } return result; }
/*********************************************************************** * * Curl_pp_sendfv() * * Send the formated string as a command to a pingpong server. Note that * the string should not have any CRLF appended, as this function will * append the necessary things itself. * * NOTE: we build the command in a fixed-length buffer, which sets length * restrictions on the command! * * made to never block */ CURLcode Curl_pp_vsendf(struct pingpong *pp, const char *fmt, va_list args) { ssize_t bytes_written; /* may still not be big enough for some krb5 tokens */ #define SBUF_SIZE 1024 char s[SBUF_SIZE]; size_t write_len; char *sptr=s; CURLcode res = CURLE_OK; struct connectdata *conn = pp->conn; struct SessionHandle *data = conn->data; #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) enum protection_level data_sec = conn->data_prot; #endif vsnprintf(s, SBUF_SIZE-3, fmt, args); strcat(s, "\r\n"); /* append a trailing CRLF */ bytes_written=0; write_len = strlen(s); Curl_pp_init(pp); #ifdef CURL_DOES_CONVERSIONS res = Curl_convert_to_network(data, s, write_len); /* Curl_convert_to_network calls failf if unsuccessful */ if(res != CURLE_OK) { return res; } #endif /* CURL_DOES_CONVERSIONS */ #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) conn->data_prot = prot_cmd; #endif res = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len, &bytes_written); #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) conn->data_prot = data_sec; #endif if(CURLE_OK != res) return res; if(conn->data->set.verbose) Curl_debug(conn->data, CURLINFO_HEADER_OUT, sptr, (size_t)bytes_written, conn); if(bytes_written != (ssize_t)write_len) { /* the whole chunk was not sent, store the rest of the data */ write_len -= bytes_written; sptr += bytes_written; pp->sendthis = malloc(write_len); if(pp->sendthis) { memcpy(pp->sendthis, sptr, write_len); pp->sendsize = pp->sendleft = write_len; } else { failf(data, "out of memory"); res = CURLE_OUT_OF_MEMORY; } } else pp->response = Curl_tvnow(); return res; }
/*********************************************************************** * * Curl_pp_vsendf() * * Send the formatted string as a command to a pingpong server. Note that * the string should not have any CRLF appended, as this function will * append the necessary things itself. * * made to never block */ CURLcode Curl_pp_vsendf(struct pingpong *pp, const char *fmt, va_list args) { ssize_t bytes_written; size_t write_len; char *fmt_crlf; char *s; CURLcode result; struct connectdata *conn = pp->conn; struct Curl_easy *data; #ifdef HAVE_GSSAPI enum protection_level data_sec; #endif DEBUGASSERT(pp->sendleft == 0); DEBUGASSERT(pp->sendsize == 0); DEBUGASSERT(pp->sendthis == NULL); if(!conn) /* can't send without a connection! */ return CURLE_SEND_ERROR; data = conn->data; fmt_crlf = aprintf("%s\r\n", fmt); /* append a trailing CRLF */ if(!fmt_crlf) return CURLE_OUT_OF_MEMORY; s = vaprintf(fmt_crlf, args); /* trailing CRLF appended */ free(fmt_crlf); if(!s) return CURLE_OUT_OF_MEMORY; bytes_written = 0; write_len = strlen(s); Curl_pp_init(pp); result = Curl_convert_to_network(data, s, write_len); /* Curl_convert_to_network calls failf if unsuccessful */ if(result) { free(s); return result; } #ifdef HAVE_GSSAPI conn->data_prot = PROT_CMD; #endif result = Curl_write(conn, conn->sock[FIRSTSOCKET], s, write_len, &bytes_written); #ifdef HAVE_GSSAPI data_sec = conn->data_prot; DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST); conn->data_prot = data_sec; #endif if(result) { free(s); return result; } if(conn->data->set.verbose) Curl_debug(conn->data, CURLINFO_HEADER_OUT, s, (size_t)bytes_written, conn); if(bytes_written != (ssize_t)write_len) { /* the whole chunk was not sent, keep it around and adjust sizes */ pp->sendthis = s; pp->sendsize = write_len; pp->sendleft = write_len - bytes_written; } else { free(s); pp->sendthis = NULL; pp->sendleft = pp->sendsize = 0; pp->response = Curl_now(); } return CURLE_OK; }
/* * imap_connect() should do everything that is to be considered a part of * the connection phase. * * The variable 'done' points to will be TRUE if the protocol-layer connect * phase is done when this function returns, or FALSE is not. When called as * a part of the easy interface, it will always be TRUE. */ static CURLcode imap_connect(struct connectdata *conn, bool *done) /* see description above */ { CURLcode result; struct imap_conn *imapc = &conn->proto.imapc; struct SessionHandle *data=conn->data; struct pingpong *pp = &imapc->pp; *done = FALSE; /* default to not done yet */ /* If there already is a protocol-specific struct allocated for this sessionhandle, deal with it */ Curl_reset_reqproto(conn); result = imap_init(conn); if(CURLE_OK != result) return result; /* We always support persistant connections on imap */ conn->bits.close = FALSE; pp->response_time = RESP_TIMEOUT; /* set default response time-out */ pp->statemach_act = imap_statemach_act; pp->endofresp = imap_endofresp; pp->conn = conn; #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_PROXY) if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { /* for IMAP over HTTP proxy */ struct HTTP http_proxy; struct FTP *imap_save; /* BLOCKING */ /* We want "seamless" IMAP operations through HTTP proxy tunnel */ /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the member * conn->proto.http; we want IMAP through HTTP and we have to change the * member temporarily for connecting to the HTTP proxy. After * Curl_proxyCONNECT we have to set back the member to the original struct * IMAP pointer */ imap_save = data->state.proto.imap; memset(&http_proxy, 0, sizeof(http_proxy)); data->state.proto.http = &http_proxy; result = Curl_proxyCONNECT(conn, FIRSTSOCKET, conn->host.name, conn->remote_port); data->state.proto.imap = imap_save; if(CURLE_OK != result) return result; } #endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_PROXY */ if(conn->protocol & PROT_IMAPS) { /* BLOCKING */ /* IMAPS is simply imap with SSL for the control channel */ /* now, perform the SSL initialization for this socket */ result = Curl_ssl_connect(conn, FIRSTSOCKET); if(result) return result; } Curl_pp_init(pp); /* init generic pingpong data */ /* When we connect, we start in the state where we await the server greeting response */ state(conn, IMAP_SERVERGREET); imapc->idstr = "*"; /* we start off waiting for a '*' response */ if(data->state.used_interface == Curl_if_multi) result = imap_multi_statemach(conn, done); else { result = imap_easy_statemach(conn); if(!result) *done = TRUE; } return result; }
/* * smtp_connect() should do everything that is to be considered a part of * the connection phase. * * 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. When * called as a part of the easy interface, it will always be TRUE. */ static CURLcode smtp_connect(struct connectdata *conn, bool *done) /* see description above */ { CURLcode result; struct smtp_conn *smtpc = &conn->proto.smtpc; struct SessionHandle *data = conn->data; struct pingpong *pp = &smtpc->pp; const char *path = conn->data->state.path; char localhost[HOSTNAME_MAX + 1]; *done = FALSE; /* default to not done yet */ /* If there already is a protocol-specific struct allocated for this sessionhandle, deal with it */ Curl_reset_reqproto(conn); result = smtp_init(conn); if(CURLE_OK != result) return result; /* We always support persistent connections on smtp */ conn->bits.close = FALSE; pp->response_time = RESP_TIMEOUT; /* set default response time-out */ pp->statemach_act = smtp_statemach_act; pp->endofresp = smtp_endofresp; pp->conn = conn; if((conn->handler->protocol & CURLPROTO_SMTPS) && data->state.used_interface != Curl_if_multi) { /* SMTPS is simply smtp with SSL for the control channel */ /* now, perform the SSL initialization for this socket */ result = Curl_ssl_connect(conn, FIRSTSOCKET); if(result) return result; } Curl_pp_init(pp); /* init the response reader stuff */ pp->response_time = RESP_TIMEOUT; /* set default response time-out */ pp->statemach_act = smtp_statemach_act; pp->endofresp = smtp_endofresp; pp->conn = conn; if(!*path) { if(!Curl_gethostname(localhost, sizeof(localhost))) path = localhost; else path = "localhost"; } /* Url decode the path and use it as the domain in our EHLO */ result = Curl_urldecode(conn->data, path, 0, &smtpc->domain, NULL, TRUE); if(result) return result; /* Set the state as we are waiting the server greeting */ state(conn, SMTP_SERVERGREET); if(data->state.used_interface == Curl_if_multi) result = smtp_multi_statemach(conn, done); else { result = smtp_easy_statemach(conn); if(!result) *done = TRUE; } return result; }