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