X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/a5b2adde414330e1661db05d1ee5b1daeaa2476d..b54c3cca7632b31faf33e57f35631e9589551e1a:/mts/smtp/smtp.c?ds=sidebyside diff --git a/mts/smtp/smtp.c b/mts/smtp/smtp.c index c7d95073..8270b343 100644 --- a/mts/smtp/smtp.c +++ b/mts/smtp/smtp.c @@ -5,12 +5,15 @@ * complete copyright information. */ -#include +#include "h/mh.h" +#include "sbr/r1bindex.h" +#include "sbr/client.h" +#include "sbr/error.h" #include "smtp.h" -#include -#include -#include -#include +#include "h/mts.h" +#include "h/signals.h" +#include "h/utils.h" +#include "h/netsec.h" #include #include "sbr/base64.h" @@ -68,7 +71,7 @@ static int smhear (void); static char *EHLOset (char *) PURE; static int sm_sasl_callback(enum sasl_message_type, unsigned const char *, unsigned int, unsigned char **, unsigned int *, - char **); + void *, char **); int sm_init (char *client, char *server, char *port, int watch, int verbose, @@ -133,7 +136,7 @@ smtp_init (char *client, char *server, char *port, int watch, int verbose, if (sasl) { if (netsec_set_sasl_params(nsc, "smtp", saslmech, sm_sasl_callback, - &errstr) != OK) + NULL, &errstr) != OK) return sm_nerror(errstr); } @@ -295,7 +298,7 @@ sendmail_init (char *client, int watch, int verbose, int debug, int sasl, if (sasl) { if (netsec_set_sasl_params(nsc, "smtp", saslmech, sm_sasl_callback, - &errstr) != OK) + NULL, &errstr) != OK) return sm_nerror(errstr); } @@ -529,10 +532,14 @@ sm_waend (void) int sm_wtxt (char *buffer, int len) { - int result; + int result, snoopstate; + + if ((snoopstate = netsec_get_snoop(nsc))) + netsec_set_snoop(nsc, 0); result = sm_wstream (buffer, len); + netsec_set_snoop(nsc, snoopstate); return result == NOTOK ? RP_BHST : RP_OK; } @@ -540,9 +547,30 @@ sm_wtxt (char *buffer, int len) int sm_wtend (void) { + int snoopstate; + + if ((snoopstate = netsec_get_snoop(nsc))) + netsec_set_snoop(nsc, 0); + if (sm_wstream(NULL, 0) == NOTOK) return RP_BHST; + /* + * Because snoop output now happens at flush time, if we are using snoop + * we force an extra flush here. While this introduces some extra network + * traffic, we're only doing it when snoop is in effect so I think it's + * reasonable. + */ + + if (snoopstate) { + char *errstr; + if (netsec_flush(nsc, &errstr) != OK) { + sm_nerror(errstr); + return RP_BHST; + } + netsec_set_snoop(nsc, snoopstate); + } + switch (smtalk (SM_DOT + 3 * sm_addrs, ".")) { case 250: case 251: @@ -760,7 +788,7 @@ smhear (void) char **ehlo = EHLOkeys, *buffer; if (doingEHLO) { - static int at_least_once = 0; + static bool at_least_once; if (at_least_once) { char *ep; @@ -770,7 +798,7 @@ smhear (void) free (ep); } } else { - at_least_once = 1; + at_least_once = true; } ehlo = EHLOkeys; @@ -947,11 +975,12 @@ EHLOset (char *s) static int sm_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata, unsigned int indatalen, unsigned char **outdata, - unsigned int *outdatalen, char **errstr) + unsigned int *outdatalen, void *context, char **errstr) { int rc, snoopoffset; char *mech, *line; size_t len; + NMH_UNUSED(context); switch (mtype) { case NETSEC_SASL_START: @@ -974,15 +1003,19 @@ sm_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata, snoopoffset = 6 + strlen(mech); rc = netsec_printf(nsc, errstr, "AUTH %s %s\r\n", mech, b64data); free(b64data); - netsec_set_snoop_callback(nsc, NULL, NULL); } else { rc = netsec_printf(nsc, errstr, "AUTH %s\r\n", mech); } - if (rc != OK) + if (rc != OK) { + netsec_set_snoop_callback(nsc, NULL, NULL); return NOTOK; + } + + rc = netsec_flush(nsc, errstr); + netsec_set_snoop_callback(nsc, NULL, NULL); - if (netsec_flush(nsc, errstr) != OK) + if (rc != OK) return NOTOK; break; @@ -1036,14 +1069,16 @@ sm_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata, writeBase64raw(indata, indatalen, b64data); netsec_set_snoop_callback(nsc, netsec_b64_snoop_decoder, NULL); rc = netsec_printf(nsc, errstr, "%s\r\n", b64data); - netsec_set_snoop_callback(nsc, NULL, NULL); free(b64data); } if (rc != OK) return NOTOK; - if (netsec_flush(nsc, errstr) != OK) + rc = netsec_flush(nsc, errstr); + netsec_set_snoop_callback(nsc, NULL, NULL); + + if (rc != OK) return NOTOK; break;