Newer
Older
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2012, 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
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* RFC1734 POP3 Authentication
* RFC1939 POP3 protocol
* RFC2195 CRAM-MD5 authentication
* RFC2222 Simple Authentication and Security Layer (SASL)
* RFC2384 POP URL Scheme
* RFC2449 POP3 Extension Mechanism
* RFC2595 Using TLS with IMAP, POP3 and ACAP
* RFC2831 DIGEST-MD5 authentication
* RFC4616 PLAIN authentication
*
***************************************************************************/
#ifndef CURL_DISABLE_POP3
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_UTSNAME_H
#include <sys/utsname.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#include <in.h>
#include <inet.h>
#endif
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
#undef in_addr_t
#define in_addr_t unsigned long
#endif
#include <curl/curl.h>
#include "urldata.h"
#include "sendf.h"
#include "if2ip.h"
#include "hostip.h"
#include "progress.h"
#include "transfer.h"
#include "escape.h"
#include "http.h" /* for HTTP proxy tunnel stuff */
#include "socks.h"
#include "pop3.h"
#include "strtoofft.h"
#include "strequal.h"
#include "sslgen.h"
#include "connect.h"
#include "strerror.h"
#include "select.h"
#include "multiif.h"
#include "url.h"
#include "rawstr.h"
#include "curl_sasl.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#include "curl_memory.h"
/* The last #include file should be: */
/* Local API functions */
static CURLcode pop3_parse_url_path(struct connectdata *conn);
static CURLcode pop3_parse_custom_request(struct connectdata *conn);
static CURLcode pop3_regular_transfer(struct connectdata *conn, bool *done);
static CURLcode pop3_do(struct connectdata *conn, bool *done);
static CURLcode pop3_done(struct connectdata *conn, CURLcode status,
bool premature);
static CURLcode pop3_connect(struct connectdata *conn, bool *done);
static CURLcode pop3_disconnect(struct connectdata *conn, bool dead);
static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done);
static int pop3_getsock(struct connectdata *conn,
curl_socket_t *socks,
int numsocks);
static CURLcode pop3_doing(struct connectdata *conn, bool *dophase_done);
static CURLcode pop3_setup_connection(struct connectdata *conn);
/*
* POP3 protocol handler.
*/
const struct Curl_handler Curl_handler_pop3 = {
"POP3", /* scheme */
pop3_setup_connection, /* setup_connection */
pop3_do, /* do_it */
pop3_done, /* done */
ZERO_NULL, /* do_more */
pop3_connect, /* connect_it */
pop3_multi_statemach, /* connecting */
pop3_doing, /* doing */
pop3_getsock, /* proto_getsock */
pop3_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
pop3_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
PORT_POP3, /* defport */
PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY /* flags */
};
#ifdef USE_SSL
/*
* POP3S protocol handler.
*/
const struct Curl_handler Curl_handler_pop3s = {
"POP3S", /* scheme */
pop3_setup_connection, /* setup_connection */
pop3_do, /* do_it */
pop3_done, /* done */
ZERO_NULL, /* do_more */
pop3_connect, /* connect_it */
pop3_multi_statemach, /* connecting */
pop3_doing, /* doing */
pop3_getsock, /* proto_getsock */
pop3_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
pop3_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
PORT_POP3S, /* defport */
CURLPROTO_POP3 | CURLPROTO_POP3S, /* protocol */
PROTOPT_CLOSEACTION | PROTOPT_SSL
| PROTOPT_NOURLQUERY /* flags */
};
#endif
#ifndef CURL_DISABLE_HTTP
/*
* HTTP-proxyed POP3 protocol handler.
*/
static const struct Curl_handler Curl_handler_pop3_proxy = {
"POP3", /* scheme */
ZERO_NULL, /* setup_connection */
Curl_http, /* do_it */
Curl_http_done, /* done */
ZERO_NULL, /* do_more */
ZERO_NULL, /* connect_it */
ZERO_NULL, /* connecting */
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
PORT_POP3, /* defport */
};
#ifdef USE_SSL
/*
* HTTP-proxyed POP3S protocol handler.
*/
static const struct Curl_handler Curl_handler_pop3s_proxy = {
"POP3S", /* scheme */
ZERO_NULL, /* setup_connection */
Curl_http, /* do_it */
Curl_http_done, /* done */
ZERO_NULL, /* do_more */
ZERO_NULL, /* connect_it */
ZERO_NULL, /* connecting */
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
PORT_POP3S, /* defport */
};
#endif
#endif
/* Function that checks for an ending pop3 status code at the start of the
given string, but also detects the APOP timestamp from the server greeting
as well as the supported authentication types and allowed SASL mechanisms
from the CAPA response. */
static int pop3_endofresp(struct pingpong *pp, int *resp)
{
char *line = pp->linestart_resp;
size_t len = strlen(pp->linestart_resp);
struct connectdata *conn = pp->conn;
struct pop3_conn *pop3c = &conn->proto.pop3c;
size_t wordlen;
/* Do we have an error response? */
if(len >= 4 && !memcmp("-ERR", line, 4)) {
*resp = '-';
return FALSE;
}
/* Are we processing servergreet responses */
if(pop3c->state == POP3_SERVERGREET) {
/* Look for the APOP timestamp */
if(len >= 3 && line[len - 3] == '>') {
for(i = 0; i < len - 3; ++i) {
if(line[i] == '<') {
/* Calculate the length of the timestamp */
size_t timestamplen = len - 2 - i;
/* Allocate some memory for the timestamp */
pop3c->apoptimestamp = (char *)calloc(1, timestamplen + 1);
if(!pop3c->apoptimestamp)
break;
/* Copy the timestamp */
memcpy(pop3c->apoptimestamp, line + i, timestamplen);
pop3c->apoptimestamp[timestamplen] = '\0';
break;
}
}
}
}
/* Are we processing CAPA command responses? */
else if(pop3c->state == POP3_CAPA) {
/* Do we have the terminating character? */
if(len >= 1 && !memcmp(line, ".", 1)) {
*resp = '+';
return TRUE;
}
/* Does the server support clear text? */
if(len >= 4 && !memcmp(line, "USER", 4)) {
pop3c->authtypes |= POP3_TYPE_CLEARTEXT;
return FALSE;
/* Does the server support APOP? */
if(len >= 4 && !memcmp(line, "APOP", 4)) {
pop3c->authtypes |= POP3_TYPE_APOP;
return FALSE;
}
/* Does the server support SASL? */
if(len < 4 || memcmp(line, "SASL", 4))
return FALSE;
pop3c->authtypes |= POP3_TYPE_SASL;
/* Advance past the SASL keyword */
line += 4;
len -= 4;
/* Loop through the data line */
for(;;) {
while(len &&
(*line == ' ' || *line == '\t' ||
*line == '\r' || *line == '\n')) {
if(*line == '\n')
return FALSE;
line++;
len--;
}
if(!len)
break;
/* Extract the word */
for(wordlen = 0; wordlen < len && line[wordlen] != ' ' &&
line[wordlen] != '\t' && line[wordlen] != '\r' &&
line[wordlen] != '\n';)
wordlen++;
/* Test the word for a matching authentication mechanism */
if(wordlen == 5 && !memcmp(line, "LOGIN", 5))
pop3c->authmechs |= SASL_MECH_LOGIN;
else if(wordlen == 5 && !memcmp(line, "PLAIN", 5))
pop3c->authmechs |= SASL_MECH_PLAIN;
else if(wordlen == 8 && !memcmp(line, "CRAM-MD5", 8))
pop3c->authmechs |= SASL_MECH_CRAM_MD5;
else if(wordlen == 10 && !memcmp(line, "DIGEST-MD5", 10))
pop3c->authmechs |= SASL_MECH_DIGEST_MD5;
else if(wordlen == 6 && !memcmp(line, "GSSAPI", 6))
pop3c->authmechs |= SASL_MECH_GSSAPI;
else if(wordlen == 8 && !memcmp(line, "EXTERNAL", 8))
pop3c->authmechs |= SASL_MECH_EXTERNAL;
else if(wordlen == 4 && !memcmp(line, "NTLM", 4))
pop3c->authmechs |= SASL_MECH_NTLM;
line += wordlen;
len -= wordlen;
}
}
if((len < 1 || memcmp("+", line, 1)) &&
(len < 3 || memcmp("+OK", line, 3)))
return FALSE; /* Nothing for us */
/* Otherwise it's a positive response */
*resp = '+';
return TRUE;
}
/* This is the ONLY way to change POP3 state! */
static void state(struct connectdata *conn, pop3state newstate)
{
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* for debug purposes */
static const char * const names[] = {
"STOP",
"SERVERGREET",
"AUTH_LOGIN",
"AUTH_LOGIN_PASSWD",
"AUTH_DIGESTMD5",
"AUTH_DIGESTMD5_RESP",
"AUTH_NTLM",
"AUTH_NTLM_TYPE2MSG",
"USER",
"PASS",
"QUIT",
/* LAST */
};
if(pop3c->state != newstate)
infof(conn->data, "POP3 %p state change from %s to %s\n",
pop3c, names[pop3c->state], names[newstate]);
#endif
pop3c->state = newstate;
}
static CURLcode pop3_state_capa(struct connectdata *conn)
CURLcode result = CURLE_OK;
struct pop3_conn *pop3c = &conn->proto.pop3c;
pop3c->authmechs = 0; /* No known authentication mechanisms yet */
pop3c->authused = 0; /* Clear the authentication mechanism used */
/* Check we have a username and password to authenticate with and end the
connect phase if we don't */
if(!conn->bits.user_passwd) {
return result;
}
result = Curl_pp_sendf(&pop3c->pp, "CAPA");
if(result)
return result;
state(conn, POP3_CAPA);
return CURLE_OK;
}
static CURLcode pop3_state_user(struct connectdata *conn)
{
CURLcode result;
struct FTP *pop3 = conn->data->state.proto.pop3;
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "USER %s",
if(result)
return result;
state(conn, POP3_USER);
return CURLE_OK;
}
#ifndef CURL_DISABLE_CRYPTO_AUTH
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
static CURLcode pop3_state_apop(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct pop3_conn *pop3c = &conn->proto.pop3c;
size_t i;
MD5_context *ctxt;
unsigned char digest[MD5_DIGEST_LEN];
char secret[2 * MD5_DIGEST_LEN + 1];
ctxt = Curl_MD5_init(Curl_DIGEST_MD5);
if(!ctxt)
return CURLE_OUT_OF_MEMORY;
Curl_MD5_update(ctxt, (const unsigned char *) pop3c->apoptimestamp,
curlx_uztoui(strlen(pop3c->apoptimestamp)));
Curl_MD5_update(ctxt, (const unsigned char *) conn->passwd,
curlx_uztoui(strlen(conn->passwd)));
/* Finalise the digest */
Curl_MD5_final(ctxt, digest);
/* Convert the calculated 16 octet digest into a 32 byte hex string */
for(i = 0; i < MD5_DIGEST_LEN; i++)
snprintf(&secret[2 * i], 3, "%02x", digest[i]);
result = Curl_pp_sendf(&pop3c->pp, "APOP %s %s", conn->user, secret);
if(!result)
state(conn, POP3_APOP);
return result;
}
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 supported authentication mechanisms by decreasing order of
security */
#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
if(pop3c->authmechs & SASL_MECH_NTLM) {
mech = "NTLM";
authstate = POP3_AUTH_NTLM;
pop3c->authused = SASL_MECH_NTLM;
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;
infof(conn->data, "No known SASL authentication mechanisms supported!\n");
result = CURLE_LOGIN_DENIED; /* Other mechanisms not supported */
}
if(!result) {
result = Curl_pp_sendf(&pop3c->pp, "AUTH %s", mech);
if(!result)
state(conn, authstate);
}
return result;
}
/* For the POP3 "protocol connect" and "doing" phases only */
static int pop3_getsock(struct connectdata *conn, curl_socket_t *socks,
int numsocks)
{
return Curl_pp_getsock(&conn->proto.pop3c.pp, socks, numsocks);
}
#ifdef USE_SSL
static void pop3_to_pop3s(struct connectdata *conn)
{
conn->handler = &Curl_handler_pop3s;
}
#else
/* For the initial server greeting */
static CURLcode pop3_state_servergreet_resp(struct connectdata *conn,
int pop3code,
pop3state instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct pop3_conn *pop3c = &conn->proto.pop3c;
(void)instate; /* no use for this yet */
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_capa(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(data->set.use_ssl != CURLUSESSL_TRY) {
failf(data, "STARTTLS denied. %c", pop3code);
result = CURLE_USE_SSL_FAILED;
}
else
result = pop3_state_capa(conn);
}
else {
/* Curl_ssl_connect is BLOCKING */
result = Curl_ssl_connect(conn, FIRSTSOCKET);
if(CURLE_OK == result) {
result = pop3_state_capa(conn);
}
}
return result;
}
/* For CAPA responses */
static CURLcode pop3_state_capa_resp(struct connectdata *conn,
int pop3code,
pop3state instate)
{
CURLcode result = CURLE_OK;
(void)instate; /* no use for this yet */
if(pop3code != '+')
result = pop3_state_user(conn);
else {
/* Check supported authentication types by decreasing order of security */
if(conn->proto.pop3c.authtypes & POP3_TYPE_SASL)
result = pop3_authenticate(conn);
#ifndef CURL_DISABLE_CRYPTO_AUTH
else if(conn->proto.pop3c.authtypes & POP3_TYPE_APOP)
result = pop3_state_apop(conn);
else if(conn->proto.pop3c.authtypes & POP3_TYPE_CLEARTEXT)
result = pop3_state_user(conn);
else {
infof(conn->data, "No known authentication types supported!\n");
result = CURLE_LOGIN_DENIED; /* Other types not supported */
}
}
return result;
}
/* For AUTH PLAIN responses */
static CURLcode pop3_state_auth_plain_resp(struct connectdata *conn,
int pop3code,
pop3state instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
size_t len = 0;
char *plainauth = NULL;
(void)instate; /* no use for this yet */
if(pop3code != '+') {
failf(data, "Access denied. %c", pop3code);
result = CURLE_LOGIN_DENIED;
}
else {
/* Create the authorisation message */
result = Curl_sasl_create_plain_message(data, conn->user, conn->passwd,
&plainauth, &len);
if(!result) {
if(plainauth) {
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", plainauth);
if(!result)
Curl_safefree(plainauth);
}
}
return result;
}
/* For AUTH LOGIN responses */
static CURLcode pop3_state_auth_login_resp(struct connectdata *conn,
int pop3code,
pop3state instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
size_t len = 0;
char *authuser = NULL;
(void)instate; /* no use for this yet */
if(pop3code != '+') {
failf(data, "Access denied: %d", pop3code);
result = CURLE_LOGIN_DENIED;
}
else {
result = Curl_sasl_create_login_message(data, conn->user,
if(!result) {
if(authuser) {
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", authuser);
if(!result)
state(conn, POP3_AUTH_LOGIN_PASSWD);
}
Curl_safefree(authuser);
}
}
return result;
}
/* For AUTH LOGIN user entry responses */
static CURLcode pop3_state_auth_login_password_resp(struct connectdata *conn,
int pop3code,
pop3state instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
size_t len = 0;
char *authpasswd = NULL;
(void)instate; /* no use for this yet */
if(pop3code != '+') {
failf(data, "Access denied: %d", pop3code);
result = CURLE_LOGIN_DENIED;
}
else {
result = Curl_sasl_create_login_message(data, conn->passwd,
if(!result) {
if(authpasswd) {
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", authpasswd);
if(!result)
Curl_safefree(authpasswd);
}
}
return result;
}
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
#ifndef CURL_DISABLE_CRYPTO_AUTH
/* For AUTH CRAM-MD5 responses */
static CURLcode pop3_state_auth_cram_resp(struct connectdata *conn,
int pop3code,
pop3state instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
char *chlg64 = data->state.buffer;
size_t len = 0;
char *rplyb64 = NULL;
(void)instate; /* no use for this yet */
if(pop3code != '+') {
failf(data, "Access denied: %d", pop3code);
return CURLE_LOGIN_DENIED;
}
/* Get the challenge */
for(chlg64 += 2; *chlg64 == ' ' || *chlg64 == '\t'; chlg64++)
;
/* Terminate the challenge */
if(*chlg64 != '=') {
for(len = strlen(chlg64); len--;)
if(chlg64[len] != '\r' && chlg64[len] != '\n' && chlg64[len] != ' ' &&
chlg64[len] != '\t')
break;
if(++len) {
chlg64[len] = '\0';
}
}
result = Curl_sasl_create_cram_md5_message(data, chlg64, conn->user,
conn->passwd, &rplyb64, &len);
if(!result) {
if(rplyb64) {
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", rplyb64);
if(!result)
Curl_safefree(rplyb64);
}
return result;
}
/* For AUTH DIGEST-MD5 challenge responses */
static CURLcode pop3_state_auth_digest_resp(struct connectdata *conn,
int pop3code,
pop3state instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
char *chlg64 = data->state.buffer;
size_t len = 0;
char *rplyb64 = NULL;
(void)instate; /* no use for this yet */
if(pop3code != '+') {
failf(data, "Access denied: %d", pop3code);
return CURLE_LOGIN_DENIED;
}
/* Get the challenge */
for(chlg64 += 2; *chlg64 == ' ' || *chlg64 == '\t'; chlg64++)
;
result = Curl_sasl_create_digest_md5_message(data, chlg64, conn->user,
conn->passwd, "pop",
&rplyb64, &len);
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
if(!result) {
if(rplyb64) {
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", rplyb64);
if(!result)
state(conn, POP3_AUTH_DIGESTMD5_RESP);
}
Curl_safefree(rplyb64);
}
return result;
}
/* For AUTH DIGEST-MD5 challenge-response responses */
static CURLcode pop3_state_auth_digest_resp_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 != '+') {
failf(data, "Authentication failed: %d", pop3code);
result = CURLE_LOGIN_DENIED;
}
else {
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "");
if(!result)
}
return result;
}
#ifdef USE_NTLM
/* For AUTH NTLM responses */
static CURLcode pop3_state_auth_ntlm_resp(struct connectdata *conn,
int pop3code,
pop3state instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
size_t len = 0;
char *type1msg = NULL;
(void)instate; /* no use for this yet */
if(pop3code != '+') {
failf(data, "Access denied: %d", pop3code);
result = CURLE_LOGIN_DENIED;
}
else {
result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd,
if(!result) {
if(type1msg) {
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", type1msg);
if(!result)
state(conn, POP3_AUTH_NTLM_TYPE2MSG);
}
Curl_safefree(type1msg);
}
}
return result;
}
/* For NTLM type-2 responses (sent in reponse to our type-1 message) */
static CURLcode pop3_state_auth_ntlm_type2msg_resp(struct connectdata *conn,
int pop3code,
pop3state instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
size_t len = 0;
char *type3msg = NULL;
(void)instate; /* no use for this yet */
if(pop3code != '+') {
failf(data, "Access denied: %d", pop3code);
result = CURLE_LOGIN_DENIED;
}
else {
result = Curl_sasl_create_ntlm_type3_message(data,
data->state.buffer + 2,
conn->user, conn->passwd,
&conn->ntlm,
&type3msg, &len);
if(!result) {
if(type3msg) {
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", type3msg);
if(!result)
}
Curl_safefree(type3msg);
}
}
return result;
}
#endif
/* For final responses to the AUTH sequence */
static CURLcode pop3_state_auth_final_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 != '+') {
failf(data, "Authentication failed: %d", pop3code);
result = CURLE_LOGIN_DENIED;
}
/* End of connect phase */
state(conn, POP3_STOP);
return result;
}
static CURLcode pop3_state_apop_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 != '+') {
failf(data, "Authentication failed: %d", pop3code);
result = CURLE_LOGIN_DENIED;
}
/* End of connect phase */
state(conn, POP3_STOP);
return result;
}
/* For USER responses */
static CURLcode pop3_state_user_resp(struct connectdata *conn,
int pop3code,
pop3state instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct FTP *pop3 = data->state.proto.pop3;
(void)instate; /* no use for this yet */
failf(data, "Access denied. %c", pop3code);
result = CURLE_LOGIN_DENIED;
}
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "PASS %s",
if(result)
return result;
state(conn, POP3_PASS);
return result;
}
/* For PASS responses */
static CURLcode pop3_state_pass_resp(struct connectdata *conn,
int pop3code,
pop3state instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;