X-Git-Url: http://git.marmaro.de/?a=blobdiff_plain;f=mts%2Fsmtp%2Fsmtp.c;h=df1dbbf4e3d11a30194f6e0f2b99a2a19e86976f;hb=3a84d814004fd4557bf4f44952648e9e69bd22a8;hp=20fdce523cd9bb77ac81ebabd4f8a726616dbac4;hpb=bd7d13ad3cdf433d73849b3bb847eaec2f1396ba;p=mmh diff --git a/mts/smtp/smtp.c b/mts/smtp/smtp.c index 20fdce5..df1dbbf 100644 --- a/mts/smtp/smtp.c +++ b/mts/smtp/smtp.c @@ -1,8 +1,6 @@ /* * smtp.c -- nmh SMTP interface * - * $Id$ - * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. @@ -118,6 +116,7 @@ static SSL_CTX *sslctx = NULL; static SSL *ssl = NULL; static BIO *sbior = NULL; static BIO *sbiow = NULL; +static BIO *io = NULL; #endif /* TLS_SUPPORT */ #if defined(CYRUS_SASL) || defined(TLS_SUPPORT) @@ -159,7 +158,7 @@ static int sm_werror (void); static int smhear (void); static int sm_rrecord (char *, int *); static int sm_rerror (int); -static RETSIGTYPE alrmser (int); +static void alrmser (int); static char *EHLOset (char *); static int sm_fwrite(char *, int); static int sm_fputs(char *); @@ -288,6 +287,8 @@ smtp_init (char *client, char *server, char *port, int watch, int verbose, */ if (tls) { + BIO *ssl_bio; + if (! EHLOset("STARTTLS")) { sm_end(NOTOK); return sm_ierror("SMTP server does not support TLS"); @@ -340,8 +341,36 @@ smtp_init (char *client, char *server, char *port, int watch, int verbose, } SSL_set_bio(ssl, sbior, sbiow); + SSL_set_connect_state(ssl); + + /* + * Set up a BIO to handle buffering for us + */ - if (SSL_connect(ssl) < 1) { + io = BIO_new(BIO_f_buffer()); + + if (! io) { + sm_end(NOTOK); + return sm_ierror("Unable to create a buffer BIO: %s", + ERR_error_string(ERR_get_error(), NULL)); + } + + ssl_bio = BIO_new(BIO_f_ssl()); + + if (! ssl_bio) { + sm_end(NOTOK); + return sm_ierror("Unable to create a SSL BIO: %s", + ERR_error_string(ERR_get_error(), NULL)); + } + + BIO_set_ssl(ssl_bio, ssl, BIO_CLOSE); + BIO_push(io, ssl_bio); + + /* + * Try doing the handshake now + */ + + if (BIO_do_handshake(io) < 1) { sm_end(NOTOK); return sm_ierror("Unable to negotiate SSL connection: %s", ERR_error_string(ERR_get_error(), NULL)); @@ -367,6 +396,8 @@ smtp_init (char *client, char *server, char *port, int watch, int verbose, return RP_RPLY; } } +#else /* TLS_SUPPORT */ + NMH_UNUSED (tls); #endif /* TLS_SUPPORT */ #ifdef CYRUS_SASL @@ -417,7 +448,7 @@ sendmail_init (char *client, char *server, int watch, int verbose, #ifdef CYRUS_SASL char *server_mechs; #endif /* CYRUS_SASL */ - int i, result, vecp; + unsigned int i, result, vecp; int pdi[2], pdo[2]; char *vec[15]; @@ -443,12 +474,12 @@ sendmail_init (char *client, char *server, int watch, int verbose, if (client == NULL || *client == '\0') client = "localhost"; -#ifdef CYRUS_SASL +#if defined(CYRUS_SASL) || defined(TLS_SUPPORT) sasl_inbuffer = malloc(SASL_MAXRECVBUF); if (!sasl_inbuffer) return sm_ierror("Unable to allocate %d bytes for read buffer", SASL_MAXRECVBUF); -#endif /* CYRUS_SASL */ +#endif /* CYRUS_SASL || TLS_SUPPORT */ if (pipe (pdi) == NOTOK) return sm_ierror ("no pipes"); @@ -789,8 +820,8 @@ sm_end (int type) #ifdef TLS_SUPPORT if (tls_active) { - SSL_shutdown(ssl); - SSL_free(ssl); + BIO_ssl_shutdown(io); + BIO_free_all(io); } #endif /* TLS_SUPPORT */ @@ -1092,6 +1123,8 @@ static int sm_get_pass(sasl_conn_t *conn, void *context, int id, sasl_secret_t **psecret) { + NMH_UNUSED (conn); + char **pw_context = (char **) context; char *pass = NULL; int len; @@ -1237,9 +1270,9 @@ sm_fwrite(char *buffer, int len) if (tls_active) { int ret; - ret = SSL_write(ssl, buffer, len); + ret = BIO_write(io, buffer, len); - if (SSL_get_error(ssl, ret) != SSL_ERROR_NONE) { + if (ret <= 0) { sm_ierror("TLS error during write: %s", ERR_error_string(ERR_get_error(), NULL)); return NOTOK; @@ -1318,6 +1351,12 @@ sm_fflush(void) } #endif /* CYRUS_SASL */ +#ifdef TLS_SUPPORT + if (tls_active) { + (void) BIO_flush(io); + } +#endif /* TLS_SUPPORT */ + fflush(sm_wfp); } @@ -1574,6 +1613,7 @@ sm_fgetc(FILE *f) * encryption working */ +#ifdef CYRUS_SASL if (sasl_complete == 0 || sasl_ssf == 0) { retbuf = tmpbuf; retbufsize = cc; @@ -1587,6 +1627,10 @@ sm_fgetc(FILE *f) return -2; } } +#else /* ! CYRUS_SASL */ + retbuf = tmpbuf; + retbufsize = cc; +#endif /* CYRUS_SASL */ } if (retbufsize > SASL_MAXRECVBUF) { @@ -1623,9 +1667,11 @@ sm_rerror (int rc) } -static RETSIGTYPE +static void alrmser (int i) { + NMH_UNUSED (i); + #ifndef RELIABLE_SIGNALS SIGNAL (SIGALRM, alrmser); #endif