1 /*++
2 /* NAME
3 /*	tls_bio_ops 3
4 /* SUMMARY
5 /*	TLS network basic I/O management
6 /* SYNOPSIS
7 /*	#define TLS_INTERNAL
8 /*	#include <tls.h>
9 /*
10 /*	int tls_bio_connect(fd, timeout, context)
11 /*	int	fd;
12 /*	int	timeout;
13 /*	TLS_SESS_STATE *context;
14 /*
15 /*	int tls_bio_accept(fd, timeout, context)
16 /*	int	fd;
17 /*	int	timeout;
18 /*	TLS_SESS_STATE *context;
19 /*
20 /*	int tls_bio_shutdown(fd, timeout, context)
21 /*	int	fd;
22 /*	int	timeout;
23 /*	TLS_SESS_STATE *context;
24 /*
25 /*	int tls_bio_read(fd, buf, len, timeout, context)
26 /*	int	fd;
27 /*	void	*buf;
28 /*	int	len;
29 /*	int	timeout;
30 /*	TLS_SESS_STATE *context;
31 /*
32 /*	int tls_bio_write(fd, buf, len, timeout, context)
33 /*	int	fd;
34 /*	void	*buf;
35 /*	int	len;
36 /*	int	timeout;
37 /*	TLS_SESS_STATE *context;
38 /* DESCRIPTION
39 /*	This module enforces VSTREAM-style timeouts on non-blocking
40 /*	I/O while performing TLS handshake or input/output operations.
41 /*
42 /*	The Postfix VSTREAM read/write routines invoke the
43 /*	tls_bio_read/write routines to send and receive plain-text
44 /*	data.  In addition, this module provides tls_bio_connect/accept
45 /*	routines that trigger the initial TLS handshake.  The
46 /*	tls_bio_xxx routines invoke the corresponding SSL routines
47 /*	that translate the requests into TLS protocol messages.
48 /*
49 /*	Whenever an SSL operation indicates that network input (or
50 /*	output) needs to happen, the tls_bio_xxx routines wait for
51 /*	the network to become readable (or writable) within the
52 /*	timeout limit, then retry the SSL operation. This works
53 /*	because the network socket is in non-blocking mode.
54 /*
55 /*	tls_bio_connect() performs the SSL_connect() operation.
56 /*
57 /*	tls_bio_accept() performs the SSL_accept() operation.
58 /*
59 /*	tls_bio_shutdown() performs the SSL_shutdown() operation.
60 /*
61 /*	tls_bio_read() performs the SSL_read() operation.
62 /*
63 /*	tls_bio_write() performs the SSL_write() operation.
64 /*
65 /*	Arguments:
66 /* .IP fd
67 /*	Network socket.
68 /* .IP buf
69 /*	Read/write buffer.
70 /* .IP len
71 /*	Read/write request size.
72 /* .IP timeout
73 /*	Read/write timeout.
74 /* .IP TLScontext
75 /*	TLS session state.
76 /* DIAGNOSTICS
77 /*	A result value > 0 means successful completion.
78 /*
79 /*	A result value < 0 means that the requested operation did
80 /*	not complete due to TLS protocol failure, system call
81 /*	failure, or for any reason described under "in addition"
82 /*	below.
83 /*
84 /*	A result value of 0 from tls_bio_shutdown() means that the
85 /*	operation is in progress. A result value of 0 from other
86 /*	tls_bio_ops(3) operations means that the remote party either
87 /*	closed the network connection or that it sent a TLS shutdown
88 /*	request.
89 /*
90 /*	Upon return from the tls_bio_ops(3) routines the global
91 /*	errno value is non-zero when the requested operation did not
92 /*	complete due to system call failure.
93 /*
94 /*	In addition, the result value is set to -1, and the global
95 /*	errno value is set to ETIMEDOUT, when some network read/write
96 /*	operation did not complete within the time limit.
97 /* LICENSE
98 /* .ad
99 /* .fi
100 /*	This software is free. You can do with it whatever you want.
101 /*	The original author kindly requests that you acknowledge
102 /*	the use of his software.
103 /* AUTHOR(S)
104 /*	Originally written by:
105 /*	Lutz Jaenicke
106 /*	BTU Cottbus
107 /*	Allgemeine Elektrotechnik
108 /*	Universitaetsplatz 3-4
109 /*	D-03044 Cottbus, Germany
110 /*
111 /*	Updated by:
112 /*	Wietse Venema
113 /*	IBM T.J. Watson Research
114 /*	P.O. Box 704
115 /*	Yorktown Heights, NY 10598, USA
116 /*
117 /*	Victor Duchovni
118 /*	Morgan Stanley
119 /*--*/
120 
121 /* System library. */
122 
123 #include <sys_defs.h>
124 #include <sys/time.h>
125 
126 #ifndef timersub
127 /* res = a - b */
128 #define timersub(a, b, res) do { \
129 	(res)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
130 	(res)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
131 	if ((res)->tv_usec < 0) { \
132 		(res)->tv_sec--; \
133 		(res)->tv_usec += 1000000; \
134 	} \
135     } while (0)
136 #endif
137 
138 #ifdef USE_TLS
139 
140 /* Utility library. */
141 
142 #include <msg.h>
143 #include <iostuff.h>
144 
145 /* TLS library. */
146 
147 #define TLS_INTERNAL
148 #include <tls.h>
149 
150 /* tls_bio - perform SSL input/output operation with extreme prejudice */
151 
tls_bio(int fd,int timeout,TLS_SESS_STATE * TLScontext,int (* hsfunc)(SSL *),int (* rfunc)(SSL *,void *,int),int (* wfunc)(SSL *,const void *,int),void * buf,int num)152 int     tls_bio(int fd, int timeout, TLS_SESS_STATE *TLScontext,
153 		        int (*hsfunc) (SSL *),
154 		        int (*rfunc) (SSL *, void *, int),
155 		        int (*wfunc) (SSL *, const void *, int),
156 		        void *buf, int num)
157 {
158     const char *myname = "tls_bio";
159     int     status;
160     int     err;
161     int     enable_deadline;
162     struct timeval time_left;		/* amount of time left */
163     struct timeval time_deadline;	/* time of deadline */
164     struct timeval time_now;		/* time after SSL_mumble() call */
165 
166     /*
167      * Compensation for interface mis-match: With VSTREAMs, timeout <= 0
168      * means wait forever; with the read/write_wait() calls below, we need to
169      * specify timeout < 0 instead.
170      *
171      * Safety: no time limit means no deadline.
172      */
173     if (timeout <= 0) {
174 	timeout = -1;
175 	enable_deadline = 0;
176     }
177 
178     /*
179      * Deadline management is simpler than with VSTREAMs, because we don't
180      * need to decrement a per-stream time limit. We just work within the
181      * budget that is available for this tls_bio() call.
182      */
183     else {
184 	enable_deadline =
185 	    vstream_fstat(TLScontext->stream, VSTREAM_FLAG_DEADLINE);
186 	if (enable_deadline) {
187 	    GETTIMEOFDAY(&time_deadline);
188 	    time_deadline.tv_sec += timeout;
189 	}
190     }
191 
192     /*
193      * If necessary, retry the SSL handshake or read/write operation after
194      * handling any pending network I/O.
195      */
196     for (;;) {
197 
198 	/*
199 	 * Flush the per-thread SSL error queue. Otherwise, errors from other
200 	 * code that also uses TLS may confuse SSL_get_error(3).
201 	 */
202 	ERR_clear_error();
203 
204 	if (hsfunc)
205 	    status = hsfunc(TLScontext->con);
206 	else if (rfunc)
207 	    status = rfunc(TLScontext->con, buf, num);
208 	else if (wfunc)
209 	    status = wfunc(TLScontext->con, buf, num);
210 	else
211 	    msg_panic("%s: nothing to do here", myname);
212 	err = SSL_get_error(TLScontext->con, status);
213 
214 	/*
215 	 * Correspondence between SSL_ERROR_* error codes and tls_bio_(read,
216 	 * write, accept, connect, shutdown) return values (for brevity:
217 	 * retval).
218 	 *
219 	 * SSL_ERROR_NONE corresponds with retval > 0. With SSL_(read, write)
220 	 * this is the number of plaintext bytes sent or received. With
221 	 * SSL_(accept, connect, shutdown) this means that the operation was
222 	 * completed successfully.
223 	 *
224 	 * SSL_ERROR_WANT_(WRITE, READ) start a new loop iteration, or force
225 	 * (retval = -1, errno = ETIMEDOUT) when the time limit is exceeded.
226 	 *
227 	 * All other SSL_ERROR_* cases correspond with retval <= 0. With
228 	 * SSL_(read, write, accept, connect) retval == 0 means that the
229 	 * remote party either closed the network connection or that it
230 	 * requested TLS shutdown; with SSL_shutdown() retval == 0 means that
231 	 * our own shutdown request is in progress. With all operations
232 	 * retval < 0 means that there was an error. In the latter case,
233 	 * SSL_ERROR_SYSCALL means that error details are returned via the
234 	 * errno value.
235 	 *
236 	 * Find out if we must retry the operation and/or if there is pending
237 	 * network I/O.
238 	 *
239 	 * XXX If we're the first to invoke SSL_shutdown(), then the operation
240 	 * isn't really complete when the call returns. We could hide that
241 	 * anomaly here and repeat the call.
242 	 */
243 	switch (err) {
244 	case SSL_ERROR_WANT_WRITE:
245 	case SSL_ERROR_WANT_READ:
246 	    if (enable_deadline) {
247 		GETTIMEOFDAY(&time_now);
248 		timersub(&time_deadline, &time_now, &time_left);
249 		timeout = time_left.tv_sec + (time_left.tv_usec > 0);
250 		if (timeout <= 0) {
251 		    errno = ETIMEDOUT;
252 		    return (-1);
253 		}
254 	    }
255 	    if (err == SSL_ERROR_WANT_WRITE) {
256 		if (write_wait(fd, timeout) < 0)
257 		    return (-1);		/* timeout error */
258 	    } else {
259 		if (read_wait(fd, timeout) < 0)
260 		    return (-1);		/* timeout error */
261 	    }
262 	    break;
263 
264 	    /*
265 	     * Unhandled cases: SSL_ERROR_WANT_(ACCEPT, CONNECT, X509_LOOKUP)
266 	     * etc. Historically, Postfix silently treated these as ordinary
267 	     * I/O errors so we don't really know how common they are. For
268 	     * now, we just log a warning.
269 	     */
270 	default:
271 	    msg_warn("%s: unexpected SSL_ERROR code %d", myname, err);
272 	    /* FALLTHROUGH */
273 
274 	    /*
275 	     * With tls_timed_read() and tls_timed_write() the caller is the
276 	     * VSTREAM library module which is unaware of TLS, so we log the
277 	     * TLS error stack here. In a better world, each VSTREAM I/O
278 	     * object would provide an error reporting method in addition to
279 	     * the timed_read and timed_write methods, so that we would not
280 	     * need to have ad-hoc code like this.
281 	     */
282 	case SSL_ERROR_SSL:
283 	    if (rfunc || wfunc)
284 		tls_print_errors();
285 	    /* FALLTHROUGH */
286 	case SSL_ERROR_ZERO_RETURN:
287 	case SSL_ERROR_NONE:
288 	    errno = 0;				/* avoid bogus warnings */
289 	    /* FALLTHROUGH */
290 	case SSL_ERROR_SYSCALL:
291 	    return (status);
292 	}
293     }
294 }
295 
296 #endif
297