summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/TODO5
-rw-r--r--lib/curl_sasl.c117
-rw-r--r--lib/curl_sasl.h67
-rw-r--r--lib/imap.c154
-rw-r--r--lib/pop3.c96
-rw-r--r--lib/smtp.c95
6 files changed, 304 insertions, 230 deletions
diff --git a/docs/TODO b/docs/TODO
index 35f3331d3..eb7f75b47 100644
--- a/docs/TODO
+++ b/docs/TODO
@@ -133,7 +133,6 @@
16. SASL
16.1 Other authentication mechanisms
16.2 Add QOP support to GSSAPI authentication
- 16.3 Support binary messages (i.e.: non-base64)
17. SSH protocols
17.1 Multiplexing
@@ -902,10 +901,6 @@
with integrity protection) and auth-conf (Authentication with integrity and
privacy protection).
-16.3 Support binary messages (i.e.: non-base64)
-
- Mandatory to support LDAP SASL authentication.
-
17. SSH protocols
diff --git a/lib/curl_sasl.c b/lib/curl_sasl.c
index a5ee8bbe2..8d39e4f81 100644
--- a/lib/curl_sasl.c
+++ b/lib/curl_sasl.c
@@ -56,8 +56,8 @@
/* Supported mechanisms */
static const struct {
- const char *name; /* Name */
- size_t len; /* Name length */
+ const char *name; /* Name */
+ size_t len; /* Name length */
unsigned short bit; /* Flag bit */
} mechtable[] = {
{ "LOGIN", 5, SASL_MECH_LOGIN },
@@ -85,8 +85,11 @@ static const struct {
* conn [in] - The connection data.
* authused [in] - The authentication mechanism used.
*/
-void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused)
+void Curl_sasl_cleanup(struct connectdata *conn, unsigned short authused)
{
+ (void)conn;
+ (void)authused;
+
#if defined(USE_KERBEROS5)
/* Cleanup the gssapi structure */
if(authused == SASL_MECH_GSSAPI) {
@@ -107,12 +110,6 @@ void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused)
Curl_auth_cleanup_ntlm(&conn->ntlm);
}
#endif
-
-#if !defined(USE_KERBEROS5) && !defined(USE_NTLM)
- /* Reserved for future use */
- (void)conn;
- (void)authused;
-#endif
}
/*
@@ -189,16 +186,35 @@ CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl,
*
* Initializes the SASL structure.
*/
-void Curl_sasl_init(struct SASL *sasl, const struct SASLproto *params)
+void Curl_sasl_init(struct SASL *sasl, struct Curl_easy *data,
+ const struct SASLproto *params)
{
+ unsigned long auth = data->set.httpauth;
+
sasl->params = params; /* Set protocol dependent parameters */
sasl->state = SASL_STOP; /* Not yet running */
+ sasl->curmech = NULL; /* No mechanism yet. */
sasl->authmechs = SASL_AUTH_NONE; /* No known authentication mechanism yet */
- sasl->prefmech = SASL_AUTH_DEFAULT; /* Prefer all mechanisms */
- sasl->authused = SASL_AUTH_NONE; /* No the authentication mechanism used */
+ sasl->prefmech = params->defmechs; /* Default preferred mechanisms */
+ sasl->authused = SASL_AUTH_NONE; /* The authentication mechanism used */
sasl->resetprefs = TRUE; /* Reset prefmech upon AUTH parsing. */
sasl->mutual_auth = FALSE; /* No mutual authentication (GSSAPI only) */
sasl->force_ir = FALSE; /* Respect external option */
+
+ if(auth != CURLAUTH_BASIC) {
+ sasl->resetprefs = FALSE;
+ sasl->prefmech = SASL_AUTH_NONE;
+ if(auth & CURLAUTH_BASIC)
+ sasl->prefmech |= SASL_MECH_PLAIN | SASL_MECH_LOGIN;
+ if(auth & CURLAUTH_DIGEST)
+ sasl->prefmech |= SASL_MECH_DIGEST_MD5;
+ if(auth & CURLAUTH_NTLM)
+ sasl->prefmech |= SASL_MECH_NTLM;
+ if(auth & CURLAUTH_BEARER)
+ sasl->prefmech |= SASL_MECH_OAUTHBEARER | SASL_MECH_XOAUTH2;
+ if(auth & CURLAUTH_GSSAPI)
+ sasl->prefmech |= SASL_MECH_GSSAPI;
+ }
}
/*
@@ -247,40 +263,45 @@ static void state(struct SASL *sasl, struct Curl_easy *data,
static CURLcode get_server_message(struct SASL *sasl, struct Curl_easy *data,
struct bufref *out)
{
- unsigned char *msg;
- size_t msglen;
- char *serverdata = NULL;
CURLcode result = CURLE_OK;
- sasl->params->getmessage(data->state.buffer, &serverdata);
- if(!serverdata)
- result = CURLE_BAD_CONTENT_ENCODING;
- else if(!*serverdata || *serverdata == '=')
- Curl_bufref_set(out, NULL, 0, NULL);
- else {
- result = Curl_base64_decode(serverdata, &msg, &msglen);
- if(!result)
- Curl_bufref_set(out, msg, msglen, curl_free);
+ result = sasl->params->getmessage(data, out);
+ if(!result && (sasl->params->flags & SASL_FLAG_BASE64)) {
+ unsigned char *msg;
+ size_t msglen;
+ const char *serverdata = (const char *) Curl_bufref_ptr(out);
+
+ if(!*serverdata || *serverdata == '=')
+ Curl_bufref_set(out, NULL, 0, NULL);
+ else {
+ result = Curl_base64_decode(serverdata, &msg, &msglen);
+ if(!result)
+ Curl_bufref_set(out, msg, msglen, curl_free);
+ }
}
return result;
}
/* Encode the outgoing SASL message. */
-static CURLcode build_message(struct Curl_easy *data, struct bufref *msg)
+static CURLcode build_message(struct SASL *sasl, struct Curl_easy *data,
+ struct bufref *msg)
{
CURLcode result = CURLE_OK;
- char *base64;
- size_t base64len;
- if(!Curl_bufref_ptr(msg)) /* Empty message. */
- Curl_bufref_set(msg, "", 0, NULL);
- else if(!Curl_bufref_len(msg)) /* Explicit empty response. */
- Curl_bufref_set(msg, "=", 1, NULL);
- else {
- result = Curl_base64_encode(data, (const char *) Curl_bufref_ptr(msg),
- Curl_bufref_len(msg), &base64, &base64len);
- if(!result)
- Curl_bufref_set(msg, base64, base64len, curl_free);
+ if(sasl->params->flags & SASL_FLAG_BASE64) {
+ if(!Curl_bufref_ptr(msg)) /* Empty message. */
+ Curl_bufref_set(msg, "", 0, NULL);
+ else if(!Curl_bufref_len(msg)) /* Explicit empty response. */
+ Curl_bufref_set(msg, "=", 1, NULL);
+ else {
+ char *base64;
+ size_t base64len;
+
+ result = Curl_base64_encode(data, (const char *) Curl_bufref_ptr(msg),
+ Curl_bufref_len(msg), &base64, &base64len);
+ if(!result)
+ Curl_bufref_set(msg, base64, base64len, curl_free);
+ }
}
return result;
@@ -310,11 +331,11 @@ bool Curl_sasl_can_authenticate(struct SASL *sasl, struct connectdata *conn)
* Calculate the required login details for SASL authentication.
*/
CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
- struct connectdata *conn,
bool force_ir, saslprogress *progress)
{
CURLcode result = CURLE_OK;
- unsigned int enabledmechs;
+ struct connectdata *conn = data->conn;
+ unsigned short enabledmechs;
const char *mech = NULL;
struct bufref resp;
saslstate state1 = SASL_STOP;
@@ -471,16 +492,16 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
}
if(!result && mech) {
+ sasl->curmech = mech;
if(Curl_bufref_ptr(&resp))
- result = build_message(data, &resp);
+ result = build_message(sasl, data, &resp);
if(sasl->params->maxirlen &&
strlen(mech) + Curl_bufref_len(&resp) > sasl->params->maxirlen)
Curl_bufref_free(&resp);
if(!result)
- result = sasl->params->sendauth(data, conn, mech,
- (const char *) Curl_bufref_ptr(&resp));
+ result = sasl->params->sendauth(data, mech, &resp);
if(!result) {
*progress = SASL_INPROGRESS;
@@ -498,10 +519,10 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
* Continue the authentication.
*/
CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
- struct connectdata *conn,
int code, saslprogress *progress)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
saslstate newstate = SASL_FINAL;
struct bufref resp;
const char * const hostname = SSL_HOST_NAME();
@@ -574,7 +595,8 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
result = Curl_auth_create_digest_md5_message(data, &serverdata,
conn->user, conn->passwd,
service, &resp);
- newstate = SASL_DIGESTMD5_RESP;
+ if(!result && (sasl->params->flags & SASL_FLAG_BASE64))
+ newstate = SASL_DIGESTMD5_RESP;
break;
case SASL_DIGESTMD5_RESP:
/* Keep response NULL to output an empty line. */
@@ -691,7 +713,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
sasl->authmechs ^= sasl->authused;
/* Start an alternative SASL authentication */
- return Curl_sasl_start(sasl, data, conn, sasl->force_ir, progress);
+ return Curl_sasl_start(sasl, data, sasl->force_ir, progress);
default:
failf(data, "Unsupported SASL authentication mechanism");
result = CURLE_UNSUPPORTED_PROTOCOL; /* Should not happen */
@@ -703,14 +725,13 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
switch(result) {
case CURLE_BAD_CONTENT_ENCODING:
/* Cancel dialog */
- result = sasl->params->sendcont(data, conn, "*");
+ result = sasl->params->cancelauth(data, sasl->curmech);
newstate = SASL_CANCEL;
break;
case CURLE_OK:
- result = build_message(data, &resp);
+ result = build_message(sasl, data, &resp);
if(!result)
- result = sasl->params->sendcont(data, conn,
- (const char *) Curl_bufref_ptr(&resp));
+ result = sasl->params->contauth(data, sasl->curmech, &resp);
break;
default:
newstate = SASL_STOP; /* Stop on error */
diff --git a/lib/curl_sasl.h b/lib/curl_sasl.h
index e17d323eb..91458c74a 100644
--- a/lib/curl_sasl.h
+++ b/lib/curl_sasl.h
@@ -24,6 +24,8 @@
#include <curl/curl.h>
+#include "bufref.h"
+
struct Curl_easy;
struct connectdata;
@@ -46,17 +48,20 @@ struct connectdata;
#define SASL_AUTH_DEFAULT (SASL_AUTH_ANY & ~SASL_MECH_EXTERNAL)
/* Authentication mechanism strings */
-#define SASL_MECH_STRING_LOGIN "LOGIN"
-#define SASL_MECH_STRING_PLAIN "PLAIN"
-#define SASL_MECH_STRING_CRAM_MD5 "CRAM-MD5"
-#define SASL_MECH_STRING_DIGEST_MD5 "DIGEST-MD5"
-#define SASL_MECH_STRING_GSSAPI "GSSAPI"
-#define SASL_MECH_STRING_EXTERNAL "EXTERNAL"
-#define SASL_MECH_STRING_NTLM "NTLM"
-#define SASL_MECH_STRING_XOAUTH2 "XOAUTH2"
-#define SASL_MECH_STRING_OAUTHBEARER "OAUTHBEARER"
-#define SASL_MECH_STRING_SCRAM_SHA_1 "SCRAM-SHA-1"
-#define SASL_MECH_STRING_SCRAM_SHA_256 "SCRAM-SHA-256"
+#define SASL_MECH_STRING_LOGIN "LOGIN"
+#define SASL_MECH_STRING_PLAIN "PLAIN"
+#define SASL_MECH_STRING_CRAM_MD5 "CRAM-MD5"
+#define SASL_MECH_STRING_DIGEST_MD5 "DIGEST-MD5"
+#define SASL_MECH_STRING_GSSAPI "GSSAPI"
+#define SASL_MECH_STRING_EXTERNAL "EXTERNAL"
+#define SASL_MECH_STRING_NTLM "NTLM"
+#define SASL_MECH_STRING_XOAUTH2 "XOAUTH2"
+#define SASL_MECH_STRING_OAUTHBEARER "OAUTHBEARER"
+#define SASL_MECH_STRING_SCRAM_SHA_1 "SCRAM-SHA-1"
+#define SASL_MECH_STRING_SCRAM_SHA_256 "SCRAM-SHA-256"
+
+/* SASL flags */
+#define SASL_FLAG_BASE64 0x0001 /* Messages are base64-encoded */
/* SASL machine states */
typedef enum {
@@ -90,30 +95,37 @@ typedef enum {
/* Protocol dependent SASL parameters */
struct SASLproto {
const char *service; /* The service name */
- int contcode; /* Code to receive when continuation is expected */
- int finalcode; /* Code to receive upon authentication success */
- size_t maxirlen; /* Maximum initial response length */
- CURLcode (*sendauth)(struct Curl_easy *data,
- struct connectdata *conn,
- const char *mech, const char *ir);
+ CURLcode (*sendauth)(struct Curl_easy *data, const char *mech,
+ const struct bufref *ir);
/* Send authentication command */
- CURLcode (*sendcont)(struct Curl_easy *data,
- struct connectdata *conn, const char *contauth);
+ CURLcode (*contauth)(struct Curl_easy *data, const char *mech,
+ const struct bufref *contauth);
/* Send authentication continuation */
- void (*getmessage)(char *buffer, char **outptr);
+ CURLcode (*cancelauth)(struct Curl_easy *data, const char *mech);
+ /* Cancel authentication. */
+ CURLcode (*getmessage)(struct Curl_easy *data, struct bufref *out);
/* Get SASL response message */
+ size_t maxirlen; /* Maximum initial response + mechanism length,
+ or zero if no max. This is normally the max
+ command length - other characters count.
+ This has to be zero for non-base64 protocols. */
+ int contcode; /* Code to receive when continuation is expected */
+ int finalcode; /* Code to receive upon authentication success */
+ unsigned short defmechs; /* Mechanisms enabled by default */
+ unsigned short flags; /* Configuration flags. */
};
/* Per-connection parameters */
struct SASL {
const struct SASLproto *params; /* Protocol dependent parameters */
- saslstate state; /* Current machine state */
+ saslstate state; /* Current machine state */
+ const char *curmech; /* Current mechanism id. */
unsigned short authmechs; /* Accepted authentication mechanisms */
unsigned short prefmech; /* Preferred authentication mechanism */
unsigned short authused; /* Auth mechanism used for the connection */
- bool resetprefs; /* For URL auth option parsing. */
- bool mutual_auth; /* Mutual authentication enabled (GSSAPI only) */
- bool force_ir; /* Protocol always supports initial response */
+ bool resetprefs; /* For URL auth option parsing. */
+ bool mutual_auth; /* Mutual authentication enabled (GSSAPI only) */
+ bool force_ir; /* Protocol always supports initial response */
};
/* This is used to test whether the line starts with the given mechanism */
@@ -123,7 +135,7 @@ struct SASL {
/* This is used to cleanup any libraries or curl modules used by the sasl
functions */
-void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused);
+void Curl_sasl_cleanup(struct connectdata *conn, unsigned short authused);
/* Convert a mechanism name to a token */
unsigned short Curl_sasl_decode_mech(const char *ptr,
@@ -134,19 +146,18 @@ CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl,
const char *value, size_t len);
/* Initializes an SASL structure */
-void Curl_sasl_init(struct SASL *sasl, const struct SASLproto *params);
+void Curl_sasl_init(struct SASL *sasl, struct Curl_easy *data,
+ const struct SASLproto *params);
/* Check if we have enough auth data and capabilities to authenticate */
bool Curl_sasl_can_authenticate(struct SASL *sasl, struct connectdata *conn);
/* Calculate the required login details for SASL authentication */
CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
- struct connectdata *conn,
bool force_ir, saslprogress *progress);
/* Continue an SASL authentication */
CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
- struct connectdata *conn,
int code, saslprogress *progress);
#endif /* HEADER_CURL_SASL_H */
diff --git a/lib/imap.c b/lib/imap.c
index 6163899bb..e1704b299 100644
--- a/lib/imap.c
+++ b/lib/imap.c
@@ -78,6 +78,7 @@
#include "multiif.h"
#include "url.h"
#include "strcase.h"
+#include "bufref.h"
#include "curl_sasl.h"
#include "warnless.h"
@@ -101,19 +102,19 @@ static CURLcode imap_doing(struct Curl_easy *data, bool *dophase_done);
static CURLcode imap_setup_connection(struct Curl_easy *data,
struct connectdata *conn);
static char *imap_atom(const char *str, bool escape_only);
-static CURLcode imap_sendf(struct Curl_easy *data,
- struct connectdata *conn, const char *fmt, ...);
+static CURLcode imap_sendf(struct Curl_easy *data, const char *fmt, ...);
static CURLcode imap_parse_url_options(struct connectdata *conn);
static CURLcode imap_parse_url_path(struct Curl_easy *data);
static CURLcode imap_parse_custom_request(struct Curl_easy *data);
static CURLcode imap_perform_authenticate(struct Curl_easy *data,
- struct connectdata *conn,
const char *mech,
- const char *initresp);
+ const struct bufref *initresp);
static CURLcode imap_continue_authenticate(struct Curl_easy *data,
- struct connectdata *conn,
- const char *resp);
-static void imap_get_message(char *buffer, char **outptr);
+ const char *mech,
+ const struct bufref *resp);
+static CURLcode imap_cancel_authenticate(struct Curl_easy *data,
+ const char *mech);
+static CURLcode imap_get_message(struct Curl_easy *data, struct bufref *out);
/*
* IMAP protocol handler.
@@ -180,12 +181,15 @@ const struct Curl_handler Curl_handler_imaps = {
/* SASL parameters for the imap protocol */
static const struct SASLproto saslimap = {
"imap", /* The service name */
- '+', /* Code received when continuation is expected */
- IMAP_RESP_OK, /* Code to receive upon authentication success */
- 0, /* Maximum initial response length (no max) */
imap_perform_authenticate, /* Send authentication command */
imap_continue_authenticate, /* Send authentication continuation */
- imap_get_message /* Get SASL response message */
+ imap_cancel_authenticate, /* Send authentication cancellation */
+ imap_get_message, /* Get SASL response message */
+ 0, /* No maximum initial response length */
+ '+', /* Code received when continuation is expected */
+ IMAP_RESP_OK, /* Code to receive upon authentication success */
+ SASL_AUTH_DEFAULT, /* Default mechanisms */
+ SASL_FLAG_BASE64 /* Configuration flags */
};
@@ -352,34 +356,32 @@ static bool imap_endofresp(struct Curl_easy *data, struct connectdata *conn,
*
* Gets the authentication message from the response buffer.
*/
-static void imap_get_message(char *buffer, char **outptr)
+static CURLcode imap_get_message(struct Curl_easy *data, struct bufref *out)
{
- size_t len = strlen(buffer);
- char *message = NULL;
+ char *message = data->state.buffer;
+ size_t len = strlen(message);
if(len > 2) {
/* Find the start of the message */
len -= 2;
- for(message = buffer + 2; *message == ' ' || *message == '\t';
- message++, len--)
+ for(message += 2; *message == ' ' || *message == '\t'; message++, len--)
;
/* Find the end of the message */
- for(; len--;)
+ while(len--)
if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' &&
message[len] != '\t')
break;
/* Terminate the message */
- if(++len) {
- message[len] = '\0';
- }
+ message[++len] = '\0';
+ Curl_bufref_set(out, message, len, NULL);
}
else
/* junk input => zero length output */
- message = &buffer[len];
+ Curl_bufref_set(out, "", 0, NULL);
- *outptr = message;
+ return CURLE_OK;
}
/***********************************************************************
@@ -437,7 +439,7 @@ static CURLcode imap_perform_capability(struct Curl_easy *data,
imapc->tls_supported = FALSE; /* Clear the TLS capability */
/* Send the CAPABILITY command */
- result = imap_sendf(data, conn, "CAPABILITY");
+ result = imap_sendf(data, "CAPABILITY");
if(!result)
state(data, IMAP_CAPABILITY);
@@ -451,11 +453,10 @@ static CURLcode imap_perform_capability(struct Curl_easy *data,
*
* Sends the STARTTLS command to start the upgrade to TLS.
*/
-static CURLcode imap_perform_starttls(struct Curl_easy *data,
- struct connectdata *conn)
+static CURLcode imap_perform_starttls(struct Curl_easy *data)
{
/* Send the STARTTLS command */
- CURLcode result = imap_sendf(data, conn, "STARTTLS");
+ CURLcode result = imap_sendf(data, "STARTTLS");
if(!result)
state(data, IMAP_STARTTLS);
@@ -516,7 +517,7 @@ static CURLcode imap_perform_login(struct Curl_easy *data,
passwd = imap_atom(conn->passwd, false);
/* Send the LOGIN command */
- result = imap_sendf(data, conn, "LOGIN %s %s", user ? user : "",
+ result = imap_sendf(data, "LOGIN %s %s", user ? user : "",
passwd ? passwd : "");
free(user);
@@ -536,20 +537,19 @@ static CURLcode imap_perform_login(struct Curl_easy *data,
* SASL authentication mechanism.
*/
static CURLcode imap_perform_authenticate(struct Curl_easy *data,
- struct connectdata *conn,
const char *mech,
- const char *initresp)
+ const struct bufref *initresp)
{
CURLcode result = CURLE_OK;
- (void)data;
+ const char *ir = (const char *) Curl_bufref_ptr(initresp);
- if(initresp) {
+ if(ir) {
/* Send the AUTHENTICATE command with the initial response */
- result = imap_sendf(data, conn, "AUTHENTICATE %s %s", mech, initresp);
+ result = imap_sendf(data, "AUTHENTICATE %s %s", mech, ir);
}
else {
/* Send the AUTHENTICATE command */
- result = imap_sendf(data, conn, "AUTHENTICATE %s", mech);
+ result = imap_sendf(data, "AUTHENTICATE %s", mech);
}
return result;
@@ -559,15 +559,34 @@ static CURLcode imap_perform_authenticate(struct Curl_easy *data,
*
* imap_continue_authenticate()
*
- * Sends SASL continuation data or cancellation.
+ * Sends SASL continuation data.
*/
static CURLcode imap_continue_authenticate(struct Curl_easy *data,
- struct connectdata *conn,
- const char *resp)
+ const char *mech,
+ const struct bufref *resp)
{
- struct imap_conn *imapc = &conn->proto.imapc;
+ struct imap_conn *imapc = &data->conn->proto.imapc;
+
+ (void)mech;
- return Curl_pp_sendf(data, &imapc->pp, "%s", resp);
+ return Curl_pp_sendf(data, &imapc->pp,
+ "%s", (const char *) Curl_bufref_ptr(resp));
+}
+
+/***********************************************************************
+ *
+ * imap_cancel_authenticate()
+ *
+ * Sends SASL cancellation.
+ */
+static CURLcode imap_cancel_authenticate(struct Curl_easy *data,
+ const char *mech)
+{
+ struct imap_conn *imapc = &data->conn->proto.imapc;
+
+ (void)mech;
+
+ return Curl_pp_sendf(data, &imapc->pp, "*");
}
/***********************************************************************
@@ -594,8 +613,7 @@ static CURLcode imap_perform_authentication(struct Curl_easy *data,
}
/* Calculate the SASL login details */
- result = Curl_sasl_start(&imapc->sasl, data, conn,
- imapc->ir_supported, &progress);
+ result = Curl_sasl_start(&imapc->sasl, data, imapc->ir_supported, &progress);
if(!result) {
if(progress == SASL_INPROGRESS)
@@ -622,12 +640,11 @@ static CURLcode imap_perform_authentication(struct Curl_easy *data,
static CURLcode imap_perform_list(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
struct IMAP *imap = data->req.p.imap;
if(imap->custom)
/* Send the custom request */
- result = imap_sendf(data, conn, "%s%s", imap->custom,
+ result = imap_sendf(data, "%s%s", imap->custom,
imap->custom_params ? imap->custom_params : "");
else {
/* Make sure the mailbox is in the correct atom format if necessary */
@@ -637,7 +654,7 @@ static CURLcode imap_perform_list(struct Curl_easy *data)
return CURLE_OUT_OF_MEMORY;
/* Send the LIST command */
- result = imap_sendf(data, conn, "LIST \"%s\" *", mailbox);
+ result = imap_sendf(data, "LIST \"%s\" *", mailbox);
free(mailbox);
}
@@ -678,7 +695,7 @@ static CURLcode imap_perform_select(struct Curl_easy *data)
return CURLE_OUT_OF_MEMORY;
/* Send the SELECT command */
- result = imap_sendf(data, conn, "SELECT %s", mailbox);
+ result = imap_sendf(data, "SELECT %s", mailbox);
free(mailbox);
@@ -694,8 +711,7 @@ static CURLcode imap_perform_select(struct Curl_easy *data)
*
* Sends a FETCH command to initiate the download of a message.
*/
-static CURLcode imap_perform_fetch(struct Curl_easy *data,
- struct connectdata *conn)
+static CURLcode imap_perform_fetch(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
struct IMAP *imap = data->req.p.imap;
@@ -704,21 +720,21 @@ static CURLcode imap_perform_fetch(struct Curl_easy *data,
/* Send the FETCH command */
if(imap->partial)
- result = imap_sendf(data, conn, "UID FETCH %s BODY[%s]<%s>",
+ result = imap_sendf(data, "UID FETCH %s BODY[%s]<%s>",
imap->uid, imap->section ? imap->section : "",
imap->partial);
else
- result = imap_sendf(data, conn, "UID FETCH %s BODY[%s]",
+ result = imap_sendf(data, "UID FETCH %s BODY[%s]",
imap->uid, imap->section ? imap->section : "");
}
else if(imap->mindex) {
/* Send the FETCH command */
if(imap->partial)
- result = imap_sendf(data, conn, "FETCH %s BODY[%s]<%s>",
+ result = imap_sendf(data, "FETCH %s BODY[%s]<%s>",
imap->mindex, imap->section ? imap->section : "",
imap->partial);
else
- result = imap_sendf(data, conn, "FETCH %s BODY[%s]",
+ result = imap_sendf(data, "FETCH %s BODY[%s]",
imap->mindex, imap->section ? imap->section : "");
}
else {
@@ -740,7 +756,6 @@ static CURLcode imap_perform_fetch(struct Curl_easy *data,
static CURLcode imap_perform_append(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
struct IMAP *imap = data->req.p.imap;
char *mailbox;
@@ -791,7 +806,7 @@ static CURLcode imap_perform_append(struct Curl_easy *data)
return CURLE_OUT_OF_MEMORY;
/* Send the APPEND command */
- result = imap_sendf(data, conn,
+ result = imap_sendf(data,
"APPEND %s (\\Seen) {%" CURL_FORMAT_CURL_OFF_T "}",
mailbox, data->state.infilesize);
@@ -809,8 +824,7 @@ static CURLcode imap_perform_append(struct Curl_easy *data)
*
* Sends a SEARCH command.
*/
-static CURLcode imap_perform_search(struct Curl_easy *data,
- struct connectdata *conn)
+static CURLcode imap_perform_search(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
struct IMAP *imap = data->req.p.imap;
@@ -822,7 +836,7 @@ static CURLcode imap_perform_search(struct Curl_easy *data,
}
/* Send the SEARCH command */
- result = imap_sendf(data, conn, "SEARCH %s", imap->query);
+ result = imap_sendf(data, "SEARCH %s", imap->query);
if(!result)
state(data, IMAP_SEARCH);
@@ -836,11 +850,10 @@ static CURLcode imap_perform_search(struct Curl_easy *data,
*
* Performs the logout action prior to sclose() being called.
*/
-static CURLcode imap_perform_logout(struct Curl_easy *data,
- struct connectdata *conn)
+static CURLcode imap_perform_logout(struct Curl_easy *data)
{
/* Send the LOGOUT command */
- CURLcode result = imap_sendf(data, conn, "LOGOUT");
+ CURLcode result = imap_sendf(data, "LOGOUT");
if(!result)
state(data, IMAP_LOGOUT);
@@ -938,7 +951,7 @@ static CURLcode imap_state_capability_resp(struct Curl_easy *data,
/* PREAUTH is not compatible with STARTTLS. */
if(imapcode == IMAP_RESP_OK && imapc->tls_supported && !imapc->preauth) {
/* Switch to TLS connection now */
- result = imap_perform_starttls(data, conn);
+ result = imap_perform_starttls(data);
}
else if(data->set.use_ssl <= CURLUSESSL_TRY)
result = imap_perform_authentication(data, conn);
@@ -993,7 +1006,7 @@ static CURLcode imap_state_auth_resp(struct Curl_easy *data,
(void)instate; /* no use for this yet */
- result = Curl_sasl_continue(&imapc->sasl, data, conn, imapcode, &progress);
+ result = Curl_sasl_continue(&imapc->sasl, data, imapcode, &progress);
if(!result)
switch(progress) {
case SASL_DONE:
@@ -1094,9 +1107,9 @@ static CURLcode imap_state_select_resp(struct Curl_easy *data, int imapcode,
if(imap->custom)
result = imap_perform_list(data);
else if(imap->query)
- result = imap_perform_search(data, conn);
+ result = imap_perform_search(data);
else
- result = imap_perform_fetch(data, conn);
+ result = imap_perform_fetch(data);
}
}
else {
@@ -1441,7 +1454,7 @@ static CURLcode imap_connect(struct Curl_easy *data, bool *done)
/* Set the default preferred authentication type and mechanism */
imapc->preftype = IMAP_TYPE_ANY;
- Curl_sasl_init(&imapc->sasl, &saslimap);
+ Curl_sasl_init(&imapc->sasl, data, &saslimap);
Curl_dyn_init(&imapc->dyn, DYN_IMAP_CMD);
/* Initialise the pingpong layer */
@@ -1568,10 +1581,10 @@ static CURLcode imap_perform(struct Curl_easy *data, bool *connected,
result = imap_perform_list(data);
else if(!imap->custom && selected && (imap->uid || imap->mindex))
/* FETCH from the same mailbox */
- result = imap_perform_fetch(data, conn);
+ result = imap_perform_fetch(data);
else if(!imap->custom && selected && imap->query)
/* SEARCH the current mailbox */
- result = imap_perform_search(data, conn);
+ result = imap_perform_search(data);
else if(imap->mailbox && !selected &&
(imap->custom || imap->uid || imap->mindex || imap->query))
/* SELECT the mailbox */
@@ -1643,7 +1656,7 @@ static CURLcode imap_disconnect(struct Curl_easy *data,
/* The IMAP session may or may not have been allocated/setup at this
point! */
if(!dead_connection && conn->bits.protoconnstart) {
- if(!imap_perform_logout(data, conn))
+ if(!imap_perform_logout(data))
(void)imap_block_statemach(data, conn, TRUE); /* ignore errors */
}
@@ -1747,17 +1760,16 @@ static CURLcode imap_setup_connection(struct Curl_easy *data,
*
* Designed to never block.
*/
-static CURLcode imap_sendf(struct Curl_easy *data,
- struct connectdata *conn, const char *fmt, ...)
+static CURLcode imap_sendf(struct Curl_easy *data, const char *fmt, ...)
{
CURLcode result = CURLE_OK;
- struct imap_conn *imapc = &conn->proto.imapc;
+ struct imap_conn *imapc = &data->conn->proto.imapc;
DEBUGASSERT(fmt);
/* Calculate the tag based on the connection ID and command ID */
msnprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d",
- 'A' + curlx_sltosi(conn->connection_id % 26),
+ 'A' + curlx_sltosi(data->conn->connection_id % 26),
(++imapc->cmdid)%1000);
/* start with a blank buffer */
@@ -1911,8 +1923,6 @@ static CURLcode imap_parse_url_options(struct connectdata *conn)
struct imap_conn *imapc = &conn->proto.imapc;
const char *ptr = conn->options;
- imapc->sasl.resetprefs = TRUE;
-
while(!result && ptr && *ptr) {
const char *key = ptr;
const char *value;
diff --git a/lib/pop3.c b/lib/pop3.c
index 57296cf9b..d4ca67877 100644
--- a/lib/pop3.c
+++ b/lib/pop3.c
@@ -78,6 +78,7 @@
#include "select.h"
#include "multiif.h"
#include "url.h"
+#include "bufref.h"
#include "curl_sasl.h"
#include "curl_md5.h"
#include "warnless.h"
@@ -103,12 +104,12 @@ static CURLcode pop3_setup_connection(struct Curl_easy *data,
static CURLcode pop3_parse_url_options(struct connectdata *conn);
static CURLcode pop3_parse_url_path(struct Curl_easy *data);
static CURLcode pop3_parse_custom_request(struct Curl_easy *data);
-static CURLcode pop3_perform_auth(struct Curl_easy *data,
- struct connectdata *conn, const char *mech,
- const char *initresp);
-static CURLcode pop3_continue_auth(struct Curl_easy *data,
- struct connectdata *conn, const char *resp);
-static void pop3_get_message(char *buffer, char **outptr);
+static CURLcode pop3_perform_auth(struct Curl_easy *data, const char *mech,
+ const struct bufref *initresp);
+static CURLcode pop3_continue_auth(struct Curl_easy *data, const char *mech,
+ const struct bufref *resp);
+static CURLcode pop3_cancel_auth(struct Curl_easy *data, const char *mech);
+static CURLcode pop3_get_message(struct Curl_easy *data, struct bufref *out);
/*
* POP3 protocol handler.
@@ -170,13 +171,16 @@ const struct Curl_handler Curl_handler_pop3s = {
/* SASL parameters for the pop3 protocol */
static const struct SASLproto saslpop3 = {
- "pop", /* The service name */
- '*', /* Code received when continuation is expected */
- '+', /* Code to receive upon authentication success */
- 255 - 8, /* Maximum initial response length (no max) */
- pop3_perform_auth, /* Send authentication command */
- pop3_continue_auth, /* Send authentication continuation */
- pop3_get_message /* Get SASL response message */
+ "pop", /* The service name */
+ pop3_perform_auth, /* Send authentication command */
+ pop3_continue_auth, /* Send authentication continuation */
+ pop3_cancel_auth, /* Send authentication cancellation */
+ pop3_get_message, /* Get SASL response message */
+ 255 - 8, /* Max line len - strlen("AUTH ") - 1 space - crlf */
+ '*', /* Code received when continuation is expected */
+ '+', /* Code to receive upon authentication success */
+ SASL_AUTH_DEFAULT, /* Default mechanisms */
+ SASL_FLAG_BASE64 /* Configuration flags */
};
#ifdef USE_SSL
@@ -250,34 +254,32 @@ static bool pop3_endofresp(struct Curl_easy *data, struct connectdata *conn,
*
* Gets the authentication message from the response buffer.
*/
-static void pop3_get_message(char *buffer, char **outptr)
+static CURLcode pop3_get_message(struct Curl_easy *data, struct bufref *out)
{
- size_t len = strlen(buffer);
- char *message = NULL;
+ char *message = data->state.buffer;
+ size_t len = strlen(message);
if(len > 2) {
/* Find the start of the message */
len -= 2;
- for(message = buffer + 2; *message == ' ' || *message == '\t';
- message++, len--)
+ for(message += 2; *message == ' ' || *message == '\t'; message++, len--)
;
/* Find the end of the message */
- for(; len--;)
+ while(len--)
if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' &&
message[len] != '\t')
break;
/* Terminate the message */
- if(++len) {
- message[len] = '\0';
- }
+ message[++len] = '\0';
+ Curl_bufref_set(out, message, len, NULL);
}
else
/* junk input => zero length output */
- message = &buffer[len];
+ Curl_bufref_set(out, "", 0, NULL);
- *outptr = message;
+ return CURLE_OK;
}
/***********************************************************************
@@ -474,16 +476,16 @@ static CURLcode pop3_perform_apop(struct Curl_easy *data,
* authentication mechanism.
*/
static CURLcode pop3_perform_auth(struct Curl_easy *data,
- struct connectdata *conn,
const char *mech,
- const char *initresp)
+ const struct bufref *initresp)
{
CURLcode result = CURLE_OK;
- struct pop3_conn *pop3c = &conn->proto.pop3c;
+ struct pop3_conn *pop3c = &data->conn->proto.pop3c;
+ const char *ir = (const char *) Curl_bufref_ptr(initresp);
- if(initresp) { /* AUTH <mech> ...<crlf> */
+ if(ir) { /* AUTH <mech> ...<crlf> */
/* Send the AUTH command with the initial response */
- result = Curl_pp_sendf(data, &pop3c->pp, "AUTH %s %s", mech, initresp);
+ result = Curl_pp_sendf(data, &pop3c->pp, "AUTH %s %s", mech, ir);
}
else {
/* Send the AUTH command */
@@ -497,15 +499,33 @@ static CURLcode pop3_perform_auth(struct Curl_easy *data,
*
* pop3_continue_auth()
*
- * Sends SASL continuation data or cancellation.
+ * Sends SASL continuation data.
*/
static CURLcode pop3_continue_auth(struct Curl_easy *data,
- struct connectdata *conn,
- const char *resp)
+ const char *mech,
+ const struct bufref *resp)
{
- struct pop3_conn *pop3c = &conn->proto.pop3c;
+ struct pop3_conn *pop3c = &data->conn->proto.pop3c;
+
+ (void)mech;
+
+ return Curl_pp_sendf(data, &pop3c->pp,
+ "%s", (const char *) Curl_bufref_ptr(resp));
+}
+
+/***********************************************************************
+ *
+ * pop3_cancel_auth()
+ *
+ * Sends SASL cancellation.
+ */
+static CURLcode pop3_cancel_auth(struct Curl_easy *data, const char *mech)
+{
+ struct pop3_conn *pop3c = &data->conn->proto.pop3c;
- return Curl_pp_sendf(data, &pop3c->pp, "%s", resp);
+ (void)mech;
+
+ return Curl_pp_sendf(data, &pop3c->pp, "*");
}
/***********************************************************************
@@ -532,7 +552,7 @@ static CURLcode pop3_perform_authentication(struct Curl_easy *data,
if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_SASL) {
/* Calculate the SASL login details */
- result = Curl_sasl_start(&pop3c->sasl, data, conn, FALSE, &progress);
+ result = Curl_sasl_start(&pop3c->sasl, data, FALSE, &progress);
if(!result)
if(progress == SASL_INPROGRESS)
@@ -801,7 +821,7 @@ static CURLcode pop3_state_auth_resp(struct Curl_easy *data,
(void)instate; /* no use for this yet */
- result = Curl_sasl_continue(&pop3c->sasl, data, conn, pop3code, &progress);
+ result = Curl_sasl_continue(&pop3c->sasl, data, pop3code, &progress);
if(!result)
switch(progress) {
case SASL_DONE:
@@ -1104,7 +1124,7 @@ static CURLcode pop3_connect(struct Curl_easy *data, bool *done)
/* Set the default preferred authentication type and mechanism */
pop3c->preftype = POP3_TYPE_ANY;
- Curl_sasl_init(&pop3c->sasl, &saslpop3);
+ Curl_sasl_init(&pop3c->sasl, data, &saslpop3);
/* Initialise the pingpong layer */
Curl_pp_setup(pp);
@@ -1345,8 +1365,6 @@ static CURLcode pop3_parse_url_options(struct connectdata *conn)
struct pop3_conn *pop3c = &conn->proto.pop3c;
const char *ptr = conn->options;
- pop3c->sasl.resetprefs = TRUE;
-
while(!result && ptr && *ptr) {
const char *key = ptr;
const char *value;
diff --git a/lib/smtp.c b/lib/smtp.c
index 02ddaca0a..fdacefe55 100644
--- a/lib/smtp.c
+++ b/lib/smtp.c
@@ -82,6 +82,7 @@
#include "multiif.h"
#include "url.h"
#include "curl_gethostname.h"
+#include "bufref.h"
#include "curl_sasl.h"
#include "warnless.h"
/* The last 3 #include files should be in this order */
@@ -108,12 +109,12 @@ static CURLcode smtp_parse_url_path(struct Curl_easy *data);
static CURLcode smtp_parse_custom_request(struct Curl_easy *data);
static CURLcode smtp_parse_address(struct Curl_easy *data, const char *fqma,
char **address, struct hostname *host);
-static CURLcode smtp_perform_auth(struct Curl_easy *data,
- struct connectdata *conn, const char *mech,
- const char *initresp);
-static CURLcode smtp_continue_auth(struct Curl_easy *data,
- struct connectdata *conn, const char *resp);
-static void smtp_get_message(char *buffer, char **outptr);
+static CURLcode smtp_perform_auth(struct Curl_easy *data, const char *mech,
+ const struct bufref *initresp);
+static CURLcode smtp_continue_auth(struct Curl_easy *data, const char *mech,
+ const struct bufref *resp);
+static CURLcode smtp_cancel_auth(struct Curl_easy *data, const char *mech);
+static CURLcode smtp_get_message(struct Curl_easy *data, struct bufref *out);
/*
* SMTP protocol handler.
@@ -175,13 +176,16 @@ const struct Curl_handler Curl_handler_smtps = {
/* SASL parameters for the smtp protocol */
static const struct SASLproto saslsmtp = {
- "smtp", /* The service name */
- 334, /* Code received when continuation is expected */
- 235, /* Code to receive upon authentication success */
- 512 - 8, /* Maximum initial response length (no max) */
- smtp_perform_auth, /* Send authentication command */
- smtp_continue_auth, /* Send authentication continuation */
- smtp_get_message /* Get SASL response message */
+ "smtp", /* The service name */
+ smtp_perform_auth, /* Send authentication command */
+ smtp_continue_auth, /* Send authentication continuation */
+ smtp_cancel_auth, /* Cancel authentication */
+ smtp_get_message, /* Get SASL response message */
+ 512 - 8, /* Max line len - strlen("AUTH ") - 1 space - crlf */
+ 334, /* Code received when continuation is expected */
+ 235, /* Code to receive upon authentication success */
+ SASL_AUTH_DEFAULT, /* Default mechanisms */
+ SASL_FLAG_BASE64 /* Configuration flags */
};
#ifdef USE_SSL
@@ -248,34 +252,32 @@ static bool smtp_endofresp(struct Curl_easy *data, struct connectdata *conn,
*
* Gets the authentication message from the response buffer.
*/
-static void smtp_get_message(char *buffer, char **outptr)
+static CURLcode smtp_get_message(struct Curl_easy *data, struct bufref *out)
{
- size_t len = strlen(buffer);
- char *message = NULL;
+ char *message = data->state.buffer;
+ size_t len = strlen(message);
if(len > 4) {
/* Find the start of the message */
len -= 4;
- for(message = buffer + 4; *message == ' ' || *message == '\t';
- message++, len--)
+ for(message += 4; *message == ' ' || *message == '\t'; message++, len--)
;
/* Find the end of the message */
- for(; len--;)
+ while(len--)
if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' &&
message[len] != '\t')
break;
/* Terminate the message */
- if(++len) {
- message[len] = '\0';
- }
+ message[++len] = '\0';
+ Curl_bufref_set(out, message, len, NULL);
}
else
/* junk input => zero length output */
- message = &buffer[len];
+ Curl_bufref_set(out, "", 0, NULL);
- *outptr = message;
+ return CURLE_OK;
}
/***********************************************************************
@@ -421,16 +423,16 @@ static CURLcode smtp_perform_upgrade_tls(struct Curl_easy *data)
* authentication mechanism.
*/
static CURLcode smtp_perform_auth(struct Curl_easy *data,
- struct connectdata *conn,
const char *mech,
- const char *initresp)
+ const struct bufref *initresp)
{
CURLcode result = CURLE_OK;
- struct smtp_conn *smtpc = &conn->proto.smtpc;
+ struct smtp_conn *smtpc = &data->conn->proto.smtpc;
+ const char *ir = (const char *) Curl_bufref_ptr(initresp);
- if(initresp) { /* AUTH <mech> ...<crlf> */
+ if(ir) { /* AUTH <mech> ...<crlf> */
/* Send the AUTH command with the initial response */
- result = Curl_pp_sendf(data, &smtpc->pp, "AUTH %s %s", mech, initresp);
+ result = Curl_pp_sendf(data, &smtpc->pp, "AUTH %s %s", mech, ir);
}
else {
/* Send the AUTH command */
@@ -444,14 +446,33 @@ static CURLcode smtp_perform_auth(struct Curl_easy *data,
*
* smtp_continue_auth()
*
- * Sends SASL continuation data or cancellation.
+ * Sends SASL continuation data.
*/
static CURLcode smtp_continue_auth(struct Curl_easy *data,
- struct connectdata *conn, const char *resp)
+ const char *mech,
+ const struct bufref *resp)
{
- struct smtp_conn *smtpc = &conn->proto.smtpc;
+ struct smtp_conn *smtpc = &data->conn->proto.smtpc;
+
+ (void)mech;
+
+ return Curl_pp_sendf(data, &smtpc->pp,
+ "%s", (const char *) Curl_bufref_ptr(resp));
+}
+
+/***********************************************************************
+ *
+ * smtp_cancel_auth()
+ *
+ * Sends SASL cancellation.
+ */
+static CURLcode smtp_cancel_auth(struct Curl_easy *data, const char *mech)
+{
+ struct smtp_conn *smtpc = &data->conn->proto.smtpc;
- return Curl_pp_sendf(data, &smtpc->pp, "%s", resp);
+ (void)mech;
+
+ return Curl_pp_sendf(data, &smtpc->pp, "*");
}
/***********************************************************************
@@ -477,7 +498,7 @@ static CURLcode smtp_perform_authentication(struct Curl_easy *data)
}
/* Calculate the SASL login details */
- result = Curl_sasl_start(&smtpc->sasl, data, conn, FALSE, &progress);
+ result = Curl_sasl_start(&smtpc->sasl, data, FALSE, &progress);
if(!result) {
if(progress == SASL_INPROGRESS)
@@ -985,7 +1006,7 @@ static CURLcode smtp_state_auth_resp(struct Curl_easy *data,
(void)instate; /* no use for this yet */
- result = Curl_sasl_continue(&smtpc->sasl, data, conn, smtpcode, &progress);
+ result = Curl_sasl_continue(&smtpc->sasl, data, smtpcode, &progress);
if(!result)
switch(progress) {
case SASL_DONE:
@@ -1333,7 +1354,7 @@ static CURLcode smtp_connect(struct Curl_easy *data, bool *done)
PINGPONG_SETUP(pp, smtp_statemachine, smtp_endofresp);
/* Initialize the SASL storage */
- Curl_sasl_init(&smtpc->sasl, &saslsmtp);
+ Curl_sasl_init(&smtpc->sasl, data, &saslsmtp);
/* Initialise the pingpong layer */
Curl_pp_setup(pp);
@@ -1655,8 +1676,6 @@ static CURLcode smtp_parse_url_options(struct connectdata *conn)
struct smtp_conn *smtpc = &conn->proto.smtpc;
const char *ptr = conn->options;
- smtpc->sasl.resetprefs = TRUE;
-
while(!result && ptr && *ptr) {
const char *key = ptr;
const char *value;