static CURLcode pop3_authenticate(struct connectdata *conn) { CURLcode result = CURLE_OK; struct pop3_conn *pop3c = &conn->proto.pop3c; const char *mech = NULL; pop3state authstate = POP3_STOP; /* Check we have a username and password to authenticate with and end the connect phase if we don't */ if(!conn->bits.user_passwd) { state(conn, POP3_STOP); return result; } /* Calculate the supported authentication mechanism by decreasing order of security */ if(pop3c->authtypes & POP3_TYPE_SASL) { #ifndef CURL_DISABLE_CRYPTO_AUTH if(pop3c->authmechs & SASL_MECH_DIGEST_MD5) { mech = "DIGEST-MD5"; authstate = POP3_AUTH_DIGESTMD5; pop3c->authused = SASL_MECH_DIGEST_MD5; } else if(pop3c->authmechs & SASL_MECH_CRAM_MD5) { mech = "CRAM-MD5"; authstate = POP3_AUTH_CRAMMD5; pop3c->authused = SASL_MECH_CRAM_MD5; } else #endif #ifdef USE_NTLM if(pop3c->authmechs & SASL_MECH_NTLM) { mech = "NTLM"; authstate = POP3_AUTH_NTLM; pop3c->authused = SASL_MECH_NTLM; } else #endif if(pop3c->authmechs & SASL_MECH_LOGIN) { mech = "LOGIN"; authstate = POP3_AUTH_LOGIN; pop3c->authused = SASL_MECH_LOGIN; } else if(pop3c->authmechs & SASL_MECH_PLAIN) { mech = "PLAIN"; authstate = POP3_AUTH_PLAIN; pop3c->authused = SASL_MECH_PLAIN; } } if(mech) { /* Perform SASL based authentication */ result = Curl_pp_sendf(&pop3c->pp, "AUTH %s", mech); if(!result) state(conn, authstate); } #ifndef CURL_DISABLE_CRYPTO_AUTH else if(pop3c->authtypes & POP3_TYPE_APOP) /* Perform APOP authentication */ result = pop3_state_apop(conn); #endif else if(pop3c->authtypes & POP3_TYPE_CLEARTEXT) /* Perform clear text authentication */ result = pop3_state_user(conn); else { /* Other mechanisms not supported */ infof(conn->data, "No known authentication mechanisms supported!\n"); result = CURLE_LOGIN_DENIED; } return result; }
/* Start the DO phase */ static CURLcode smtp_mail(struct connectdata *conn) { char *from = NULL; char *auth = NULL; char *size = NULL; CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; /* Calculate the FROM parameter */ if(!data->set.str[STRING_MAIL_FROM]) /* Null reverse-path, RFC-2821, sect. 3.7 */ from = strdup("<>"); else if(data->set.str[STRING_MAIL_FROM][0] == '<') from = aprintf("%s", data->set.str[STRING_MAIL_FROM]); else from = aprintf("<%s>", data->set.str[STRING_MAIL_FROM]); if(!from) return CURLE_OUT_OF_MEMORY; /* Calculate the optional AUTH parameter */ if(data->set.str[STRING_MAIL_AUTH] && conn->proto.smtpc.authused) { if(data->set.str[STRING_MAIL_AUTH][0] != '\0') auth = aprintf("%s", data->set.str[STRING_MAIL_AUTH]); else /* Empty AUTH, RFC-2554, sect. 5 */ auth = strdup("<>"); if(!auth) { Curl_safefree(from); return CURLE_OUT_OF_MEMORY; } } /* calculate the optional SIZE parameter */ if(conn->data->set.infilesize > 0) { size = aprintf("%" FORMAT_OFF_T, data->set.infilesize); if(!size) { Curl_safefree(from); Curl_safefree(auth); return CURLE_OUT_OF_MEMORY; } } /* Send the MAIL command */ if(!auth && !size) result = Curl_pp_sendf(&conn->proto.smtpc.pp, "MAIL FROM:%s", from); else if(auth && !size) result = Curl_pp_sendf(&conn->proto.smtpc.pp, "MAIL FROM:%s AUTH=%s", from, auth); else if(auth && size) result = Curl_pp_sendf(&conn->proto.smtpc.pp, "MAIL FROM:%s AUTH=%s SIZE=%s", from, auth, size); else result = Curl_pp_sendf(&conn->proto.smtpc.pp, "MAIL FROM:%s SIZE=%s", from, size); Curl_safefree(from); Curl_safefree(auth); Curl_safefree(size); if(result) return result; state(conn, SMTP_MAIL); return result; }
static CURLcode pop3_statemach_act(struct connectdata *conn) { CURLcode result; curl_socket_t sock = conn->sock[FIRSTSOCKET]; struct SessionHandle *data=conn->data; int pop3code; struct pop3_conn *pop3c = &conn->proto.pop3c; struct pingpong *pp = &pop3c->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, &pop3code, &nread); if(result) return result; if(pop3code) { /* we have now received a full POP3 server response */ switch(pop3c->state) { case POP3_SERVERGREET: if(pop3code != 'O') { failf(data, "Got unexpected pop3-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 */ result = Curl_pp_sendf(&pop3c->pp, "STLS"); state(conn, POP3_STARTTLS); } else result = pop3_state_user(conn); if(result) return result; break; case POP3_USER: result = pop3_state_user_resp(conn, pop3code, pop3c->state); break; case POP3_PASS: result = pop3_state_pass_resp(conn, pop3code, pop3c->state); break; case POP3_STARTTLS: result = pop3_state_starttls_resp(conn, pop3code, pop3c->state); break; case POP3_RETR: result = pop3_state_retr_resp(conn, pop3code, pop3c->state); break; case POP3_LIST: result = pop3_state_list_resp(conn, pop3code, pop3c->state); break; case POP3_LIST_SINGLE: result = pop3_state_list_single_resp(conn, pop3code, pop3c->state); break; case POP3_QUIT: /* fallthrough, just stop! */ default: /* internal error */ state(conn, POP3_STOP); break; } } return result; }
static CURLcode smtp_authenticate(struct connectdata *conn) { CURLcode result = CURLE_OK; struct smtp_conn *smtpc = &conn->proto.smtpc; char *initresp = NULL; const char *mech = NULL; size_t len = 0; smtpstate state1 = SMTP_STOP; smtpstate state2 = SMTP_STOP; /* Check we have a username and password to authenticate with and end the connect phase if we don't */ if(!conn->bits.user_passwd) { state(conn, SMTP_STOP); return result; } /* Check supported authentication mechanisms by decreasing order of security */ #ifndef CURL_DISABLE_CRYPTO_AUTH if(smtpc->authmechs & SASL_MECH_DIGEST_MD5) { mech = "DIGEST-MD5"; state1 = SMTP_AUTH_DIGESTMD5; smtpc->authused = SASL_MECH_DIGEST_MD5; } else if(smtpc->authmechs & SASL_MECH_CRAM_MD5) { mech = "CRAM-MD5"; state1 = SMTP_AUTH_CRAMMD5; smtpc->authused = SASL_MECH_CRAM_MD5; } else #endif #ifdef USE_NTLM if(smtpc->authmechs & SASL_MECH_NTLM) { mech = "NTLM"; state1 = SMTP_AUTH_NTLM; state2 = SMTP_AUTH_NTLM_TYPE2MSG; smtpc->authused = SASL_MECH_NTLM; result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd, &conn->ntlm, &initresp, &len); } else #endif if(smtpc->authmechs & SASL_MECH_LOGIN) { mech = "LOGIN"; state1 = SMTP_AUTH_LOGIN; state2 = SMTP_AUTH_PASSWD; smtpc->authused = SASL_MECH_LOGIN; result = Curl_sasl_create_login_message(conn->data, conn->user, &initresp, &len); } else if(smtpc->authmechs & SASL_MECH_PLAIN) { mech = "PLAIN"; state1 = SMTP_AUTH_PLAIN; state2 = SMTP_AUTH; smtpc->authused = SASL_MECH_PLAIN; result = Curl_sasl_create_plain_message(conn->data, conn->user, conn->passwd, &initresp, &len); } else { infof(conn->data, "No known authentication mechanisms supported!\n"); result = CURLE_LOGIN_DENIED; /* Other mechanisms not supported */ } if(!result) { if(initresp && strlen(mech) + len <= 512 - 8) { /* AUTH <mech> ...<crlf> */ result = Curl_pp_sendf(&smtpc->pp, "AUTH %s %s", mech, initresp); if(!result) state(conn, state2); } else { result = Curl_pp_sendf(&smtpc->pp, "AUTH %s", mech); if(!result) state(conn, state1); } Curl_safefree(initresp); } return result; }
/* for AUTH CRAM-MD5 responses. */ static CURLcode smtp_state_authcram_resp(struct connectdata *conn, int smtpcode, smtpstate instate) { CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; char * chlg64 = data->state.buffer; unsigned char * chlg; size_t chlglen; size_t l; char * rplyb64; HMAC_context * ctxt; unsigned char digest[16]; char reply[MAX_CURL_USER_LENGTH + 32 /* 2 * size of MD5 digest */ + 1]; (void)instate; /* no use for this yet */ if(smtpcode != 334) { failf(data, "Access denied: %d", smtpcode); return CURLE_LOGIN_DENIED; } /* Get the challenge. */ for (chlg64 += 4; *chlg64 == ' ' || *chlg64 == '\t'; chlg64++) ; chlg = (unsigned char *) NULL; chlglen = 0; if(*chlg64 != '=') { for (l = strlen(chlg64); l--;) if(chlg64[l] != '\r' && chlg64[l] != '\n' && chlg64[l] != ' ' && chlg64[l] != '\t') break; if(++l) { chlg64[l] = '\0'; chlglen = Curl_base64_decode(chlg64, &chlg); if(!chlglen) return CURLE_OUT_OF_MEMORY; } } /* Compute digest. */ ctxt = Curl_HMAC_init(Curl_HMAC_MD5, (const unsigned char *) conn->passwd, (unsigned int)(strlen(conn->passwd))); if(!ctxt) { if(chlg) free(chlg); return CURLE_OUT_OF_MEMORY; } if(chlglen > 0) Curl_HMAC_update(ctxt, chlg, (unsigned int)(chlglen)); if(chlg) free(chlg); Curl_HMAC_final(ctxt, digest); /* Prepare the reply. */ snprintf(reply, sizeof reply, "%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", conn->user, digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7], digest[8], digest[9], digest[10], digest[11], digest[12], digest[13], digest[14], digest[15]); /* Encode it to base64 and send it. */ l = Curl_base64_encode(data, reply, 0, &rplyb64); if(!l) result = CURLE_OUT_OF_MEMORY; else { result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", rplyb64); free(rplyb64); if(!result) state(conn, SMTP_AUTH); } return result; }
static CURLcode smtp_authenticate(struct connectdata *conn) { CURLcode result = CURLE_OK; struct smtp_conn *smtpc = &conn->proto.smtpc; char * initresp; const char * mech; size_t l; smtpstate state1; smtpstate state2; if(!conn->bits.user_passwd) state(conn, SMTP_STOP); /* End of connect phase. */ else { initresp = (char *) NULL; l = 1; /* Check supported authentication mechanisms by decreasing order of preference. */ mech = (const char *) NULL; /* Avoid compiler warnings. */ state1 = SMTP_STOP; state2 = SMTP_STOP; #ifndef CURL_DISABLE_CRYPTO_AUTH if(smtpc->authmechs & SMTP_AUTH_CRAM_MD5) { mech = "CRAM-MD5"; state1 = SMTP_AUTHCRAM; } else #endif if(smtpc->authmechs & SMTP_AUTH_PLAIN) { mech = "PLAIN"; state1 = SMTP_AUTHPLAIN; state2 = SMTP_AUTH; l = smtp_auth_plain_data(conn, &initresp); } else if(smtpc->authmechs & SMTP_AUTH_LOGIN) { mech = "LOGIN"; state1 = SMTP_AUTHLOGIN; state2 = SMTP_AUTHPASSWD; l = smtp_auth_login_user(conn, &initresp); } else { infof(conn->data, "No known auth mechanisms supported!\n"); result = CURLE_LOGIN_DENIED; /* Other mechanisms not supported. */ } if(!result) { if(!l) result = CURLE_OUT_OF_MEMORY; else if(initresp && l + strlen(mech) <= 512 - 8) { /* AUTH <mech> ...<crlf> */ result = Curl_pp_sendf(&smtpc->pp, "AUTH %s %s", mech, initresp); free(initresp); if(!result) state(conn, state2); } else { Curl_safefree(initresp); result = Curl_pp_sendf(&smtpc->pp, "AUTH %s", mech); if(!result) state(conn, state1); } } } return result; }
/*********************************************************************** * * smtp_continue_auth() * * Sends SASL continuation data or cancellation. */ static CURLcode smtp_continue_auth(struct connectdata *conn, const char *resp) { struct smtp_conn *smtpc = &conn->proto.smtpc; return Curl_pp_sendf(&smtpc->pp, "%s", resp); }
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; }