mirror of
https://github.com/curl/curl.git
synced 2026-08-24 13:33:33 +03:00
sasl: binary messages
Capabilities of sasl module are extended to exchange messages in binary as an alternative to base64. If http authentication flags have been set, those are used as sasl default preferred mechanisms. Closes #6930
This commit is contained in:
parent
e12dc2dd97
commit
3e2c1dcda8
6 changed files with 305 additions and 231 deletions
95
lib/smtp.c
95
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;
|
||||
|
||||
return Curl_pp_sendf(data, &smtpc->pp, "%s", resp);
|
||||
(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;
|
||||
|
||||
(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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue