aboutsummaryrefslogtreecommitdiffstats
path: root/lib/smtp.c
diff options
context:
space:
mode:
authorLucas Eckels <eckels@google.com>2012-08-06 15:07:02 -0700
committerLucas Eckels <eckels@google.com>2012-08-08 09:28:48 -0700
commit9bd90e6e25f1e55f50201c87a1b5837de7e5b64a (patch)
treed2061a00d7d0ee884170bc955fceeed2d0edf284 /lib/smtp.c
parente6f2b03027b5feb92b30f5d47801ec3fabe9fd95 (diff)
downloadandroid_external_curl-9bd90e6e25f1e55f50201c87a1b5837de7e5b64a.tar.gz
android_external_curl-9bd90e6e25f1e55f50201c87a1b5837de7e5b64a.tar.bz2
android_external_curl-9bd90e6e25f1e55f50201c87a1b5837de7e5b64a.zip
Add Music Manager's curl 7.21.2 source.
Change-Id: I259a43fa52d581524a5ce8ae1711467acb1d9d50
Diffstat (limited to 'lib/smtp.c')
-rw-r--r--lib/smtp.c493
1 files changed, 447 insertions, 46 deletions
diff --git a/lib/smtp.c b/lib/smtp.c
index 654f435..55e03d5 100644
--- a/lib/smtp.c
+++ b/lib/smtp.c
@@ -20,6 +20,9 @@
*
* RFC2821 SMTP protocol
* RFC3207 SMTP over TLS
+ * RFC4954 SMTP Authentication
+ * RFC2195 CRAM-MD5 authentication
+ * RFC4616 PLAIN authentication
*
***************************************************************************/
@@ -85,6 +88,10 @@
#include "url.h"
#include "rawstr.h"
#include "strtoofft.h"
+#include "curl_base64.h"
+#include "curl_md5.h"
+#include "curl_hmac.h"
+#include "curl_gethostname.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
@@ -202,26 +209,74 @@ static const struct Curl_handler Curl_handler_smtps_proxy = {
#endif
-/* fucntion that checks for an ending smtp status code at the start of the
- given string */
+/* Function that checks for an ending smtp status code at the start of the
+ given string.
+ As a side effect, it also flags allowed authentication mechanisms according
+ to EHLO AUTH response. */
static int smtp_endofresp(struct pingpong *pp, int *resp)
{
char *line = pp->linestart_resp;
size_t len = pp->nread_resp;
+ struct connectdata *conn = pp->conn;
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
+ int result;
+ size_t wordlen;
+
+ if(len < 4 || !ISDIGIT(line[0]) || !ISDIGIT(line[1]) || !ISDIGIT(line[2]))
+ return FALSE; /* Nothing for us. */
+
+ if((result = line[3] == ' '))
+ *resp = atoi(line);
+
+ line += 4;
+ len -= 4;
+
+ if(smtpc->state == SMTP_EHLO && len >= 5 && !memcmp(line, "AUTH ", 5)) {
+ line += 5;
+ len -= 5;
+
+ for (;;) {
+ while (len &&
+ (*line == ' ' || *line == '\t' ||
+ *line == '\r' || *line == '\n')) {
+ line++;
+ len--;
+ }
- if( (len >= 4) && (' ' == line[3]) &&
- ISDIGIT(line[0]) && ISDIGIT(line[1]) && ISDIGIT(line[2])) {
- *resp=atoi(line);
- return TRUE;
+ if(!len)
+ break;
+
+ for (wordlen = 0; wordlen < len && line[wordlen] != ' ' &&
+ line[wordlen] != '\t' && line[wordlen] != '\r' &&
+ line[wordlen] != '\n';)
+ wordlen++;
+
+ if(wordlen == 5 && !memcmp(line, "LOGIN", 5))
+ smtpc->authmechs |= SMTP_AUTH_LOGIN;
+ else if(wordlen == 5 && !memcmp(line, "PLAIN", 5))
+ smtpc->authmechs |= SMTP_AUTH_PLAIN;
+ else if(wordlen == 8 && !memcmp(line, "CRAM-MD5", 8))
+ smtpc->authmechs |= SMTP_AUTH_CRAM_MD5;
+ else if(wordlen == 10 && !memcmp(line, "DIGEST-MD5", 10))
+ smtpc->authmechs |= SMTP_AUTH_DIGEST_MD5;
+ else if(wordlen == 6 && !memcmp(line, "GSSAPI", 6))
+ smtpc->authmechs |= SMTP_AUTH_GSSAPI;
+ else if(wordlen == 8 && !memcmp(line, "EXTERNAL", 8))
+ smtpc->authmechs |= SMTP_AUTH_EXTERNAL;
+
+ line += wordlen;
+ len -= wordlen;
+ }
}
- return FALSE; /* nothing for us */
+ return result;
}
/* This is the ONLY way to change SMTP state! */
static void state(struct connectdata *conn,
smtpstate newstate)
{
+ struct smtp_conn *smtpc = &conn->proto.smtpc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* for debug purposes */
static const char * const names[]={
@@ -230,6 +285,11 @@ static void state(struct connectdata *conn,
"EHLO",
"HELO",
"STARTTLS",
+ "AUTHPLAIN",
+ "AUTHLOGIN",
+ "AUTHPASSWD",
+ "AUTHCRAM",
+ "AUTH",
"MAIL",
"RCPT",
"DATA",
@@ -237,9 +297,6 @@ static void state(struct connectdata *conn,
"QUIT",
/* LAST */
};
-#endif
- struct smtp_conn *smtpc = &conn->proto.smtpc;
-#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
if(smtpc->state != newstate)
infof(conn->data, "SMTP %p state change from %s to %s\n",
smtpc, names[smtpc->state], names[newstate]);
@@ -252,8 +309,10 @@ static CURLcode smtp_state_ehlo(struct connectdata *conn)
CURLcode result;
struct smtp_conn *smtpc = &conn->proto.smtpc;
+ smtpc->authmechs = 0; /* No known authentication mechanisms yet. */
+
/* send EHLO */
- result = Curl_pp_sendf(&conn->proto.smtpc.pp, "EHLO %s", smtpc->domain);
+ result = Curl_pp_sendf(&smtpc->pp, "EHLO %s", smtpc->domain);
if(result)
return result;
@@ -268,7 +327,7 @@ static CURLcode smtp_state_helo(struct connectdata *conn)
struct smtp_conn *smtpc = &conn->proto.smtpc;
/* send HELO */
- result = Curl_pp_sendf(&conn->proto.smtpc.pp, "HELO %s", smtpc->domain);
+ result = Curl_pp_sendf(&smtpc->pp, "HELO %s", smtpc->domain);
if(result)
return result;
@@ -277,6 +336,111 @@ static CURLcode smtp_state_helo(struct connectdata *conn)
return CURLE_OK;
}
+static size_t smtp_auth_plain_data(struct connectdata * conn, char * * outptr)
+{
+ char plainauth[2 * MAX_CURL_USER_LENGTH + MAX_CURL_PASSWORD_LENGTH];
+ size_t ulen;
+ size_t plen;
+
+ ulen = strlen(conn->user);
+ plen = strlen(conn->passwd);
+
+ if(2 * ulen + plen + 2 > sizeof plainauth)
+ return 0;
+
+ memcpy(plainauth, conn->user, ulen);
+ plainauth[ulen] = '\0';
+ memcpy(plainauth + ulen + 1, conn->user, ulen);
+ plainauth[2 * ulen + 1] = '\0';
+ memcpy(plainauth + 2 * ulen + 2, conn->passwd, plen);
+ return Curl_base64_encode(conn->data, plainauth, 2 * ulen + plen + 2, outptr);
+}
+
+static size_t smtp_auth_login_user(struct connectdata * conn, char * * outptr)
+{
+ size_t ulen;
+
+ ulen = strlen(conn->user);
+
+ if(!ulen) {
+ *outptr = strdup("=");
+ return *outptr? 1: 0;
+ }
+
+ return Curl_base64_encode(conn->data, conn->user, ulen, outptr);
+}
+
+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;
+}
+
/* For the SMTP "protocol connect" and "doing" phases only */
static int smtp_getsock(struct connectdata *conn,
curl_socket_t *socks,
@@ -295,12 +459,12 @@ static CURLcode smtp_state_starttls_resp(struct connectdata *conn,
(void)instate; /* no use for this yet */
if(smtpcode != 220) {
- if(data->set.ftp_ssl == CURLUSESSL_TRY)
- state(conn, SMTP_STOP);
- else {
+ 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 */
@@ -324,23 +488,23 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn,
(void)instate; /* no use for this yet */
if(smtpcode/100 != 2) {
- if(data->set.ftp_ssl <= CURLUSESSL_TRY)
+ if((data->set.ftp_ssl <= CURLUSESSL_TRY || conn->ssl[FIRSTSOCKET].use) &&
+ !conn->bits.user_passwd)
result = smtp_state_helo(conn);
else {
failf(data, "Access denied: %d", smtpcode);
result = CURLE_LOGIN_DENIED;
}
- }
+ }
else 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(&conn->proto.smtpc.pp, "STARTTLS", NULL);
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "STARTTLS");
state(conn, SMTP_STARTTLS);
}
- else {
- /* end the connect phase */
- state(conn, SMTP_STOP);
- }
+ else
+ result = smtp_authenticate(conn);
+
return result;
}
@@ -357,7 +521,7 @@ static CURLcode smtp_state_helo_resp(struct connectdata *conn,
if(smtpcode/100 != 2) {
failf(data, "Access denied: %d", smtpcode);
result = CURLE_LOGIN_DENIED;
- }
+ }
else {
/* end the connect phase */
state(conn, SMTP_STOP);
@@ -365,6 +529,223 @@ static CURLcode smtp_state_helo_resp(struct connectdata *conn,
return result;
}
+/* for AUTH PLAIN (without initial response) responses */
+static CURLcode smtp_state_authplain_resp(struct connectdata *conn,
+ int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ size_t l;
+ char * plainauth;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode != 334) {
+ failf(data, "Access denied: %d", smtpcode);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ l = smtp_auth_plain_data(conn, &plainauth);
+
+ if(!l)
+ result = CURLE_OUT_OF_MEMORY;
+ else {
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", plainauth);
+ free(plainauth);
+
+ if(!result)
+ state(conn, SMTP_AUTH);
+ }
+ }
+
+ return result;
+}
+
+/* for AUTH LOGIN (without initial response) responses */
+static CURLcode smtp_state_authlogin_resp(struct connectdata *conn,
+ int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ size_t l;
+ char * authuser;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode != 334) {
+ failf(data, "Access denied: %d", smtpcode);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ l = smtp_auth_login_user(conn, &authuser);
+
+ if(!l)
+ result = CURLE_OUT_OF_MEMORY;
+ else {
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", authuser);
+ free(authuser);
+
+ if(!result)
+ state(conn, SMTP_AUTHPASSWD);
+ }
+ }
+
+ return result;
+}
+
+/* for responses to user entry of AUTH LOGIN. */
+static CURLcode smtp_state_authpasswd_resp(struct connectdata *conn,
+ int smtpcode,
+ smtpstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ size_t plen;
+ size_t l;
+ char *authpasswd;
+
+ (void)instate; /* no use for this yet */
+
+ if(smtpcode != 334) {
+ failf(data, "Access denied: %d", smtpcode);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else {
+ plen = strlen(conn->passwd);
+
+ if(!plen)
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "=");
+ else {
+ l = Curl_base64_encode(data, conn->passwd, plen, &authpasswd);
+
+ if(!l)
+ result = CURLE_OUT_OF_MEMORY;
+ else {
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", authpasswd);
+ free(authpasswd);
+
+ if(!result)
+ state(conn, SMTP_AUTH);
+ }
+ }
+ }
+
+ return result;
+}
+
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+
+/* 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';
+
+ if(!(chlglen = Curl_base64_decode(chlg64, &chlg)))
+ 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;
+}
+
+#endif
+
+/* for final responses to AUTH sequences. */
+static CURLcode smtp_state_auth_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 != 235) {
+ failf(data, "Authentication failed: %d", smtpcode);
+ result = CURLE_LOGIN_DENIED;
+ }
+ else
+ state(conn, SMTP_STOP); /* End of connect phase. */
+
+ return result;
+}
+
/* start the DO phase */
static CURLcode smtp_mail(struct connectdata *conn)
{
@@ -451,7 +832,7 @@ static CURLcode smtp_state_rcpt_resp(struct connectdata *conn,
}
/* send DATA */
- result = Curl_pp_sendf(&conn->proto.smtpc.pp, "DATA", "");
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "DATA");
if(result)
return result;
@@ -465,7 +846,6 @@ static CURLcode smtp_state_data_resp(struct connectdata *conn,
int smtpcode,
smtpstate instate)
{
- CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct FTP *smtp = data->state.proto.smtp;
@@ -477,11 +857,11 @@ static CURLcode smtp_state_data_resp(struct connectdata *conn,
}
/* SMTP upload */
- result = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */
- FIRSTSOCKET, smtp->bytecountp);
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */
+ FIRSTSOCKET, smtp->bytecountp);
state(conn, SMTP_STOP);
- return result;
+ return CURLE_OK;
}
/* for the POSTDATA response, which is received after the entire DATA
@@ -542,6 +922,32 @@ static CURLcode smtp_statemach_act(struct connectdata *conn)
result = smtp_state_helo_resp(conn, smtpcode, smtpc->state);
break;
+ case SMTP_STARTTLS:
+ result = smtp_state_starttls_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_AUTHPLAIN:
+ result = smtp_state_authplain_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_AUTHLOGIN:
+ result = smtp_state_authlogin_resp(conn, smtpcode, smtpc->state);
+ break;
+
+ case SMTP_AUTHPASSWD:
+ result = smtp_state_authpasswd_resp(conn, smtpcode, smtpc->state);
+ break;
+
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+ case SMTP_AUTHCRAM:
+ result = smtp_state_authcram_resp(conn, smtpcode, smtpc->state);
+ break;
+#endif
+
+ case SMTP_AUTH:
+ result = smtp_state_auth_resp(conn, smtpcode, smtpc->state);
+ break;
+
case SMTP_MAIL:
result = smtp_state_mail_resp(conn, smtpcode, smtpc->state);
break;
@@ -550,10 +956,6 @@ static CURLcode smtp_statemach_act(struct connectdata *conn)
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;
@@ -644,10 +1046,7 @@ static CURLcode smtp_connect(struct connectdata *conn,
struct pingpong *pp=&smtpc->pp;
const char *path = conn->data->state.path;
int len;
-
-#ifdef HAVE_GETHOSTNAME
- char localhost[1024 + 1];
-#endif
+ char localhost[1024 + 1];
*done = FALSE; /* default to not done yet */
@@ -713,17 +1112,15 @@ static CURLcode smtp_connect(struct connectdata *conn,
pp->conn = conn;
if(!*path) {
-#ifdef HAVE_GETHOSTNAME
- if(!gethostname(localhost, sizeof localhost))
+ if(!Curl_gethostname(localhost, sizeof localhost))
path = localhost;
else
-#endif
- path = "localhost";
+ 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)
+ if(!smtpc->domain)
return CURLE_OUT_OF_MEMORY;
/* When we connect, we start in the state where we await the server greeting
@@ -894,7 +1291,7 @@ static CURLcode smtp_quit(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
- result = Curl_pp_sendf(&conn->proto.smtpc.pp, "QUIT", NULL);
+ result = Curl_pp_sendf(&conn->proto.smtpc.pp, "QUIT");
if(result)
return result;
state(conn, SMTP_QUIT);
@@ -922,11 +1319,15 @@ static CURLcode smtp_disconnect(struct connectdata *conn)
/* The SMTP session may or may not have been allocated/setup at this
point! */
- if (smtpc->pp.conn)
+ if(smtpc->pp.conn)
(void)smtp_quit(conn); /* ignore errors on the LOGOUT */
Curl_pp_disconnect(&smtpc->pp);
+ /* This won't already be freed in some error cases */
+ Curl_safefree(smtpc->domain);
+ smtpc->domain = NULL;
+
return CURLE_OK;
}
@@ -934,18 +1335,18 @@ static CURLcode smtp_disconnect(struct connectdata *conn)
static CURLcode smtp_dophase_done(struct connectdata *conn,
bool connected)
{
- CURLcode result = CURLE_OK;
struct FTP *smtp = conn->data->state.proto.smtp;
struct smtp_conn *smtpc= &conn->proto.smtpc;
(void)connected;
if(smtp->transfer != FTPTRANSFER_BODY)
/* no data to transfer */
- result=Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
free(smtpc->domain);
+ smtpc->domain = NULL;
- return result;
+ return CURLE_OK;
}
/* called from multi.c while DOing */