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 
tls_session_stop(TLS_APPL_STATE * unused_ctx,VSTREAM * stream,int timeout,int failure,TLS_SESS_STATE * TLScontext)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 
tls_session_passivate(SSL_SESSION * session)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 
tls_session_activate(const char * session_data,int session_data_len)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