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