Home | History | Annotate | Line # | Download | only in tls
      1 /*	$NetBSD: tls_session.c,v 1.3 2020/05/25 23:47:14 christos Exp $	*/
      2 
      3 /*++
      4 /* NAME
      5 /*	tls_session
      6 /* SUMMARY
      7 /*	TLS client and server session routines
      8 /* SYNOPSIS
      9 /*	#include <tls.h>
     10 /*
     11 /*	void	tls_session_stop(ctx, stream, timeout, failure, TLScontext)
     12 /*	TLS_APPL_STATE *ctx;
     13 /*	VSTREAM	*stream;
     14 /*	int	timeout;
     15 /*	int	failure;
     16 /*	TLS_SESS_STATE *TLScontext;
     17 /*
     18 /*	VSTRING	*tls_session_passivate(session)
     19 /*	SSL_SESSION *session;
     20 /*
     21 /*	SSL_SESSION *tls_session_activate(session_data, session_data_len)
     22 /*	char	*session_data;
     23 /*	int	session_data_len;
     24 /* DESCRIPTION
     25 /*	tls_session_stop() implements the tls_server_shutdown()
     26 /*	and the tls_client_shutdown() routines.
     27 /*
     28 /*	tls_session_passivate() converts an SSL_SESSION object to
     29 /*	VSTRING. The result is a null pointer in case of problems,
     30 /*	otherwise it should be disposed of with vstring_free().
     31 /*
     32 /*	tls_session_activate() reanimates a passivated SSL_SESSION object.
     33 /*	The result is a null pointer in case of problems,
     34 /*	otherwise it should be disposed of with SSL_SESSION_free().
     35 /* LICENSE
     36 /* .ad
     37 /* .fi
     38 /*	This software is free. You can do with it whatever you want.
     39 /*	The original author kindly requests that you acknowledge
     40 /*	the use of his software.
     41 /* AUTHOR(S)
     42 /*	Originally written by:
     43 /*	Lutz Jaenicke
     44 /*	BTU Cottbus
     45 /*	Allgemeine Elektrotechnik
     46 /*	Universitaetsplatz 3-4
     47 /*	D-03044 Cottbus, Germany
     48 /*
     49 /*	Updated by:
     50 /*	Wietse Venema
     51 /*	IBM T.J. Watson Research
     52 /*	P.O. Box 704
     53 /*	Yorktown Heights, NY 10598, USA
     54 /*
     55 /*	Wietse Venema
     56 /*	Google, Inc.
     57 /*	111 8th Avenue
     58 /*	New York, NY 10011, USA
     59 /*
     60 /*	Victor Duchovni
     61 /*	Morgan Stanley
     62 /*--*/
     63 
     64 /* System library. */
     65 
     66 #include <sys_defs.h>
     67 
     68 #ifdef USE_TLS
     69 
     70 /* Utility library. */
     71 
     72 #include <vstream.h>
     73 #include <msg.h>
     74 #include <mymalloc.h>
     75 
     76 /* Global library. */
     77 
     78 #include <mail_params.h>
     79 
     80 /* TLS library. */
     81 
     82 #define TLS_INTERNAL
     83 #include <tls.h>
     84 
     85 /* Application-specific. */
     86 
     87 #define STR	vstring_str
     88 
     89 /* tls_session_stop - shut down the TLS connection and reset state */
     90 
     91 void    tls_session_stop(TLS_APPL_STATE *unused_ctx, VSTREAM *stream, int timeout,
     92 			         int failure, TLS_SESS_STATE *TLScontext)
     93 {
     94     const char *myname = "tls_session_stop";
     95     int     retval;
     96 
     97     /*
     98      * Sanity check.
     99      */
    100     if (TLScontext == 0)
    101 	msg_panic("%s: stream has no active TLS context", myname);
    102 
    103     /*
    104      * According to RFC 2246 (TLS 1.0), there is no requirement to wait for
    105      * the peer's close-notify. If the application protocol provides
    106      * sufficient session termination signaling, then there's no need to
    107      * duplicate that at the TLS close-notify layer.
    108      *
    109      * https://tools.ietf.org/html/rfc2246#section-7.2.1
    110      * https://tools.ietf.org/html/rfc4346#section-7.2.1
    111      * https://tools.ietf.org/html/rfc5246#section-7.2.1
    112      *
    113      * Specify 'tls_fast_shutdown = no' to enable the historical behavior
    114      * described below.
    115      *
    116      * Perform SSL_shutdown() twice, as the first attempt will send out the
    117      * shutdown alert but it will not wait for the peer's shutdown alert.
    118      * Therefore, when we are the first party to send the alert, we must call
    119      * SSL_shutdown() again. On failure we don't want to resume the session,
    120      * so we will not perform SSL_shutdown() and the session will be removed
    121      * as being bad.
    122      */
    123     if (!failure && !SSL_in_init(TLScontext->con)) {
    124 	retval = tls_bio_shutdown(vstream_fileno(stream), timeout, TLScontext);
    125 	if (!var_tls_fast_shutdown && retval == 0)
    126 	    tls_bio_shutdown(vstream_fileno(stream), timeout, TLScontext);
    127     }
    128     tls_free_context(TLScontext);
    129     tls_stream_stop(stream);
    130 }
    131 
    132 /* tls_session_passivate - passivate SSL_SESSION object */
    133 
    134 VSTRING *tls_session_passivate(SSL_SESSION *session)
    135 {
    136     const char *myname = "tls_session_passivate";
    137     int     estimate;
    138     int     actual_size;
    139     VSTRING *session_data;
    140     unsigned char *ptr;
    141 
    142     /*
    143      * First, find out how much memory is needed for the passivated
    144      * SSL_SESSION object.
    145      */
    146     estimate = i2d_SSL_SESSION(session, (unsigned char **) 0);
    147     if (estimate <= 0) {
    148 	msg_warn("%s: i2d_SSL_SESSION failed: unable to cache session", myname);
    149 	return (0);
    150     }
    151 
    152     /*
    153      * Passivate the SSL_SESSION object. The use of a VSTRING is slightly
    154      * wasteful but is convenient to combine data and length.
    155      */
    156     session_data = vstring_alloc(estimate);
    157     ptr = (unsigned char *) STR(session_data);
    158     actual_size = i2d_SSL_SESSION(session, &ptr);
    159     if (actual_size != estimate) {
    160 	msg_warn("%s: i2d_SSL_SESSION failed: unable to cache session", myname);
    161 	vstring_free(session_data);
    162 	return (0);
    163     }
    164     vstring_set_payload_size(session_data, actual_size);
    165 
    166     return (session_data);
    167 }
    168 
    169 /* tls_session_activate - activate passivated session */
    170 
    171 SSL_SESSION *tls_session_activate(const char *session_data, int session_data_len)
    172 {
    173     SSL_SESSION *session;
    174     const unsigned char *ptr;
    175 
    176     /*
    177      * Activate the SSL_SESSION object.
    178      */
    179     ptr = (const unsigned char *) session_data;
    180     session = d2i_SSL_SESSION((SSL_SESSION **) 0, &ptr, session_data_len);
    181     if (!session)
    182 	tls_print_errors();
    183 
    184     return (session);
    185 }
    186 
    187 #endif
    188