summaryrefslogtreecommitdiffstats
path: root/src/tls/tls_session.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tls/tls_session.c')
-rw-r--r--src/tls/tls_session.c185
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