X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/cd53031b83b4ee584378c581ed50fa7fb12b9e4e..303e8387acecca26329e939f228f78ca805b7a15:/mts/smtp/smtp.c?ds=sidebyside diff --git a/mts/smtp/smtp.c b/mts/smtp/smtp.c index 75ac2f21..79c1e79b 100644 --- a/mts/smtp/smtp.c +++ b/mts/smtp/smtp.c @@ -11,6 +11,7 @@ #include #include #include +#include #ifdef CYRUS_SASL #include @@ -174,7 +175,7 @@ static int sm_fputs(char *); static int sm_fputc(int); static void sm_fflush(void); static int sm_fgets(char *, int, FILE *); -static int sm_auth_xoauth2(const char *); +static int sm_auth_xoauth2(const char *, const char *, int); #ifdef CYRUS_SASL /* @@ -187,12 +188,12 @@ static int sm_auth_sasl(char *, int, char *, char *); int sm_init (char *client, char *server, char *port, int watch, int verbose, int debug, int sasl, int saslssf, char *saslmech, char *user, - const char *xoauth_client_res, int tls) + const char *oauth_svc, int tls) { if (sm_mts == MTS_SMTP) return smtp_init (client, server, port, watch, verbose, debug, sasl, saslssf, saslmech, user, - xoauth_client_res, tls); + oauth_svc, tls); else return sendmail_init (client, server, watch, verbose, debug, sasl, saslssf, saslmech, user); @@ -202,7 +203,7 @@ static int smtp_init (char *client, char *server, char *port, int watch, int verbose, int debug, int sasl, int saslssf, char *saslmech, char *user, - const char *xoauth_client_res, int tls) + const char *oauth_svc, int tls) { int result, sd1, sd2; #ifndef CYRUS_SASL @@ -380,7 +381,7 @@ smtp_init (char *client, char *server, char *port, int watch, int verbose, /* Don't call sm_auth_sasl() for XAUTH2 with -sasl. Instead, call sm_auth_xoauth2() below. */ - if (xoauth_client_res == NULL && + if (oauth_svc == NULL && sm_auth_sasl(user, saslssf, saslmech ? saslmech : server_mechs, server) != RP_OK) { sm_end(NOTOK); @@ -389,14 +390,14 @@ smtp_init (char *client, char *server, char *port, int watch, int verbose, } #endif /* CYRUS_SASL */ - if (xoauth_client_res != NULL) { + if (oauth_svc != NULL) { char *server_mechs; if ((server_mechs = EHLOset("AUTH")) == NULL || stringdex("XOAUTH2", server_mechs) == -1) { sm_end(NOTOK); return sm_ierror("SMTP server does not support SASL XOAUTH2"); } - if (sm_auth_xoauth2(xoauth_client_res) != RP_OK) { + if (sm_auth_xoauth2(user, oauth_svc, debug) != RP_OK) { sm_end(NOTOK); return NOTOK; } @@ -1154,9 +1155,26 @@ sm_get_pass(sasl_conn_t *conn, void *context, int id, /* https://developers.google.com/gmail/xoauth2_protocol */ static int -sm_auth_xoauth2(const char *client_res) +sm_auth_xoauth2(const char *user, const char *oauth_svc, int snoop) { - int status = smtalk(SM_AUTH, "AUTH XOAUTH2 %s", client_res); + const char *xoauth_client_res; + int status; + +#ifdef OAUTH_SUPPORT + xoauth_client_res = mh_oauth_do_xoauth(user, oauth_svc, + snoop ? stderr : NULL); + + if (xoauth_client_res == NULL) { + return sm_ierror("Internal error: mh_oauth_do_xoauth() returned NULL"); + } +#else + NMH_UNUSED(user); + NMH_UNUSED(snoop); + adios(NULL, "sendfrom built without OAUTH_SUPPORT, " + "so oauth_svc %s is not supported", oauth_svc); +#endif /* OAUTH_SUPPORT */ + + status = smtalk(SM_AUTH, "AUTH XOAUTH2 %s", xoauth_client_res); if (status == 235) { /* It worked! */ return RP_OK; @@ -1925,23 +1943,14 @@ prepare_for_display (const char *string, int *next_line_encoded) { size_t decoded_len; int prefix_len = -1; - if (strncmp (string, "AUTH XOAUTH2 ", 13) == 0) { - /* Entire XOAUTH2 line. */ - prefix_len = 13; - *next_line_encoded = 0; - } else if (strncmp (string, "AUTH LOGIN ", 11) == 0) { - /* AUTH LOGIN followed by login name. - For AUTH LOGIN not followed by the name, the response to the 334 - server request will be handled by the code below. */ - prefix_len = 11; - *next_line_encoded = 0; - } else if (strncmp (string, "AUTH PLAIN ", 11) == 0) { - /* AUTH PLAIN followed by authorization/authentication string, e.g., - the display output will be: - AUTH PLAIN b64 - For AUTH PLAIN not followed by the string, the response to the 334 - will be handled by the code below. */ - prefix_len = 11; + if (strncmp (string, "AUTH ", 5) == 0) { + /* AUTH line: the mechanism isn't encoded. If there's an initial + response, it must be base64 encoded.. */ + char *mechanism = strchr (string + 5, ' '); + + if (mechanism != NULL) { + prefix_len = (int) (mechanism - string + 1); + } /* else no space following the mechanism, so no initial response */ *next_line_encoded = 0; } else if (strncmp (string, "334 ", 4) == 0) { /* 334 is the server's request for user or password. */ @@ -1957,7 +1966,10 @@ prepare_for_display (const char *string, int *next_line_encoded) { *next_line_encoded = 0; } - if (prefix_len > -1) { + /* Don't attempt to decoded unencoded initial response ('=') or cancel + response ('*'). */ + if (prefix_len > -1 && + string[prefix_len] != '=' && string[prefix_len] != '*') { start = string + prefix_len; }