diff options
Diffstat (limited to 'src/tls/tls_session.c')
-rw-r--r-- | src/tls/tls_session.c | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/src/tls/tls_session.c b/src/tls/tls_session.c new file mode 100644 index 0000000..a4b7a8f --- /dev/null +++ b/src/tls/tls_session.c @@ -0,0 +1,185 @@ +/*++ +/* NAME +/* tls_session +/* SUMMARY +/* TLS client and server session routines +/* SYNOPSIS +/* #include <tls.h> +/* +/* void tls_session_stop(ctx, stream, timeout, failure, TLScontext) +/* TLS_APPL_STATE *ctx; +/* VSTREAM *stream; +/* int timeout; +/* int failure; +/* TLS_SESS_STATE *TLScontext; +/* +/* VSTRING *tls_session_passivate(session) +/* SSL_SESSION *session; +/* +/* SSL_SESSION *tls_session_activate(session_data, session_data_len) +/* char *session_data; +/* int session_data_len; +/* DESCRIPTION +/* tls_session_stop() implements the tls_server_shutdown() +/* and the tls_client_shutdown() routines. +/* +/* tls_session_passivate() converts an SSL_SESSION object to +/* VSTRING. The result is a null pointer in case of problems, +/* otherwise it should be disposed of with vstring_free(). +/* +/* tls_session_activate() reanimates a passivated SSL_SESSION object. +/* The result is a null pointer in case of problems, +/* otherwise it should be disposed of with SSL_SESSION_free(). +/* LICENSE +/* .ad +/* .fi +/* This software is free. You can do with it whatever you want. +/* The original author kindly requests that you acknowledge +/* the use of his software. +/* AUTHOR(S) +/* Originally written by: +/* Lutz Jaenicke +/* BTU Cottbus +/* Allgemeine Elektrotechnik +/* Universitaetsplatz 3-4 +/* D-03044 Cottbus, Germany +/* +/* Updated by: +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/* +/* Victor Duchovni +/* Morgan Stanley +/*--*/ + +/* System library. */ + +#include <sys_defs.h> + +#ifdef USE_TLS + +/* Utility library. */ + +#include <vstream.h> +#include <msg.h> +#include <mymalloc.h> + +/* Global library. */ + +#include <mail_params.h> + +/* TLS library. */ + +#define TLS_INTERNAL +#include <tls.h> + +/* Application-specific. */ + +#define STR vstring_str + +/* tls_session_stop - shut down the TLS connection and reset state */ + +void tls_session_stop(TLS_APPL_STATE *unused_ctx, VSTREAM *stream, int timeout, + int failure, TLS_SESS_STATE *TLScontext) +{ + const char *myname = "tls_session_stop"; + int retval; + + /* + * Sanity check. + */ + if (TLScontext == 0) + msg_panic("%s: stream has no active TLS context", myname); + + /* + * According to RFC 2246 (TLS 1.0), there is no requirement to wait for + * the peer's close-notify. If the application protocol provides + * sufficient session termination signaling, then there's no need to + * duplicate that at the TLS close-notify layer. + * + * https://tools.ietf.org/html/rfc2246#section-7.2.1 + * https://tools.ietf.org/html/rfc4346#section-7.2.1 + * https://tools.ietf.org/html/rfc5246#section-7.2.1 + * + * Specify 'tls_fast_shutdown = no' to enable the historical behavior + * described below. + * + * Perform SSL_shutdown() twice, as the first attempt will send out the + * shutdown alert but it will not wait for the peer's shutdown alert. + * Therefore, when we are the first party to send the alert, we must call + * SSL_shutdown() again. On failure we don't want to resume the session, + * so we will not perform SSL_shutdown() and the session will be removed + * as being bad. + */ + if (!failure && !SSL_in_init(TLScontext->con)) { + retval = tls_bio_shutdown(vstream_fileno(stream), timeout, TLScontext); + if (!var_tls_fast_shutdown && retval == 0) + tls_bio_shutdown(vstream_fileno(stream), timeout, TLScontext); + } + tls_free_context(TLScontext); + tls_stream_stop(stream); +} + +/* tls_session_passivate - passivate SSL_SESSION object */ + +VSTRING *tls_session_passivate(SSL_SESSION *session) +{ + const char *myname = "tls_session_passivate"; + int estimate; + int actual_size; + VSTRING *session_data; + unsigned char *ptr; + + /* + * First, find out how much memory is needed for the passivated + * SSL_SESSION object. + */ + estimate = i2d_SSL_SESSION(session, (unsigned char **) 0); + if (estimate <= 0) { + msg_warn("%s: i2d_SSL_SESSION failed: unable to cache session", myname); + return (0); + } + + /* + * Passivate the SSL_SESSION object. The use of a VSTRING is slightly + * wasteful but is convenient to combine data and length. + */ + session_data = vstring_alloc(estimate); + ptr = (unsigned char *) STR(session_data); + actual_size = i2d_SSL_SESSION(session, &ptr); + if (actual_size != estimate) { + msg_warn("%s: i2d_SSL_SESSION failed: unable to cache session", myname); + vstring_free(session_data); + return (0); + } + vstring_set_payload_size(session_data, actual_size); + + return (session_data); +} + +/* tls_session_activate - activate passivated session */ + +SSL_SESSION *tls_session_activate(const char *session_data, int session_data_len) +{ + SSL_SESSION *session; + const unsigned char *ptr; + + /* + * Activate the SSL_SESSION object. + */ + ptr = (const unsigned char *) session_data; + session = d2i_SSL_SESSION((SSL_SESSION **) 0, &ptr, session_data_len); + if (!session) + tls_print_errors(); + + return (session); +} + +#endif |