/* 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 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 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; }
/* 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; }
/* 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_capability(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_capability(conn); } } } 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; }
CURLcode Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex, bool *done) { #if defined(USE_SSL) && defined(USE_SSLEAY) /* mark this is being ssl enabled from here on. */ conn->ssl[sockindex].use = TRUE; return Curl_ossl_connect_nonblocking(conn, sockindex, done); #else /* not implemented! fallback to BLOCKING call. */ *done = TRUE; return Curl_ssl_connect(conn, sockindex); #endif }
CURLcode Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex, bool *done) { #ifdef curlssl_connect_nonblocking CURLcode res; /* mark this is being ssl requested from here on. */ conn->ssl[sockindex].use = TRUE; res = curlssl_connect_nonblocking(conn, sockindex, done); if(!res && *done) Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */ return res; #else *done = TRUE; /* fallback to BLOCKING */ return Curl_ssl_connect(conn, sockindex); #endif /* non-blocking connect support */ }
static CURLcode ldap_connect(struct connectdata *conn, bool *done) { ldapconninfo *li = conn->proto.generic; struct SessionHandle *data=conn->data; int rc, proto = LDAP_VERSION3; char hosturl[1024], *ptr; strcpy(hosturl, "ldap"); ptr = hosturl+4; if(conn->handler->flags & PROTOPT_SSL) *ptr++ = 's'; snprintf(ptr, sizeof(hosturl)-(ptr-hosturl), "://%s:%d", conn->host.name, conn->remote_port); rc = ldap_init_fd(conn->sock[FIRSTSOCKET], li->proto, hosturl, &li->ld); if(rc) { failf(data, "LDAP local: Cannot connect to %s, %s", hosturl, ldap_err2string(rc)); return CURLE_COULDNT_CONNECT; } ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto); #ifdef USE_SSL if(conn->handler->flags & PROTOPT_SSL) { CURLcode res; if(data->state.used_interface == Curl_if_easy) { res = Curl_ssl_connect(conn, FIRSTSOCKET); if(res) return res; li->ssldone = TRUE; } else { res = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &li->ssldone); if(res) return res; } } #endif if(data->state.used_interface == Curl_if_easy) return ldap_connecting(conn, done); return CURLE_OK; }
/*********************************************************************** * * 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; }
/* * 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; }
/*********************************************************************** * * 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 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 */ /* 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); /* 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); 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; }
/* * 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; }
static CURLcode ldap_connect(struct connectdata *conn, bool *done) { ldapconninfo *li = conn->proto.generic; struct SessionHandle *data=conn->data; int rc, proto = LDAP_VERSION3; char hosturl[1024], *ptr; strcpy(hosturl, "ldap"); ptr = hosturl+4; if (conn->handler->flags & PROTOPT_SSL) *ptr++ = 's'; snprintf(ptr, sizeof(hosturl)-(ptr-hosturl), "://%s:%d", conn->host.name, conn->remote_port); rc = ldap_init_fd(conn->sock[FIRSTSOCKET], li->proto, hosturl, &li->ld); if (rc) { failf(data, "LDAP local: Cannot connect to %s, %s", hosturl, ldap_err2string(rc)); return CURLE_COULDNT_CONNECT; } ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto); if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { /* for LDAP over HTTP proxy */ struct HTTP http_proxy; ldapconninfo *li_save; CURLcode result; /* BLOCKING */ /* We want "seamless" LDAP operations through HTTP proxy tunnel */ /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the member * conn->proto.http; we want LDAP 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 * LDAP pointer */ li_save = data->state.proto.generic; 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.generic = li_save; if(CURLE_OK != result) return result; } #ifdef USE_SSL if (conn->handler->flags & PROTOPT_SSL) { CURLcode res; if (data->state.used_interface == Curl_if_easy) { res = Curl_ssl_connect(conn, FIRSTSOCKET); if (res) return res; li->ssldone = TRUE; } else { res = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &li->ssldone); if (res) return res; } } #endif if (data->state.used_interface == Curl_if_easy) return ldap_connecting(conn, done); return CURLE_OK; }