xref: /netbsd-src/external/ibm-public/postfix/dist/src/tls/tls_bio_ops.c (revision c2f76ff004a2cb67efe5b12d97bd3ef7fe89e18d)
1 /*	$NetBSD: tls_bio_ops.c,v 1.1.1.2 2010/06/17 18:07:08 tron Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	tls_bio_ops 3
6 /* SUMMARY
7 /*	TLS network BIO 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 layer synchronizes the TLS network buffers with the network
42 /*	while performing TLS handshake or input/output operations.
43 /*
44 /*	When the TLS layer is active, it converts plain-text
45 /*	data from Postfix into encrypted network data and vice versa.
46 /*	However, to handle network timeout conditions, Postfix
47 /*	needs to maintain control over network input/output. This
48 /*	rules out the usual approach of placing the TLS layer
49 /*	between the application and the network socket.
50 /*
51 /*	As shown below, Postfix reads/writes plain-text data from/to
52 /*	the TLS layer. The TLS layer informs Postfix when it needs
53 /*	to read/write encrypted data from/to the network; Postfix
54 /*	then reads/writes encrypted data from/to the TLS layer and
55 /*	takes care of the network socket I/O.
56 /*
57 /*	The TLS layer to network interface is realized with a BIO pair:
58 /*
59 /*	Postfix SMTP layer   |   TLS layer
60 /*	                     |
61 /*	smtp/smtpd           |
62 /*	 /\    ||            |
63 /*	 ||    \/            |
64 /*	vstream read/write <===> TLS read/write/etc
65 /*	                     |     /\    ||
66 /*	                     |     ||    \/
67 /*	                     |   BIO pair (internal_bio)
68 /*	                     |   BIO pair (network_bio)
69 /*	Postfix socket layer |     /\    ||
70 /*	                     |     ||    \/
71 /*	socket read/write  <===> BIO read/write
72 /*	 /\    ||            |
73 /*	 ||    \/            |
74 /*	 network             |
75 /*
76 /*	The Postfix VSTREAM read/write operations invoke the SSL
77 /*	read/write operations to send and retrieve plain-text data. Inside
78 /*	the TLS layer the data are converted to/from TLS protocol.
79 /*
80 /*	Whenever an SSL operation reports success, or whenever it
81 /*	indicates that network input/output needs to happen, Postfix
82 /*	uses the BIO read/write routines to synchronize the
83 /*	network_bio buffer with the network.  Writing data to the
84 /*	network has precedence over reading from the network. This
85 /*	is necessary to avoid deadlock.
86 /*
87 /*	The BIO pair buffer size is set to 8192 bytes. This is much
88 /*	larger than the typical Path MTU, and avoids sending tiny TCP
89 /*	segments.  It is also larger than the default VSTREAM_BUFSIZE
90 /*	(4096, see vstream.h), so that large write operations can
91 /*	be handled within one request.  The internal buffer in the
92 /*	network/network_bio handling layer is set to the same
93 /*	value, since this seems to be reasonable. The code is
94 /*	however able to handle arbitrary values smaller or larger
95 /*	than the buffer size in the BIO pair.
96 /*
97 /*	tls_bio_connect() performs the SSL_connect() operation while
98 /*	synchronizing the network_bio buffer with the network.
99 /*
100 /*	tls_bio_accept() performs the SSL_accept() operation while
101 /*	synchronizing the network_bio buffer with the network.
102 /*
103 /*	tls_bio_shutdown() performs the SSL_shutdown() operation while
104 /*	synchronizing the network_bio buffer with the network.
105 /*
106 /*	tls_bio_read() performs the SSL_read() operation while
107 /*	synchronizing the network_bio buffer with the network.
108 /*
109 /*	tls_bio_write() performs the SSL_write() operation while
110 /*	synchronizing the network_bio buffer with the network.
111 /*
112 /*	Arguments:
113 /* .IP fd
114 /*	Network socket.
115 /* .IP buf
116 /*	Read/write buffer.
117 /* .IP len
118 /*	Read/write request size.
119 /* .IP timeout
120 /*	Read/write timeout.
121 /* .IP TLScontext
122 /*	TLS session state.
123 /* DIAGNOSTICS
124 /*	The result value is -1 in case of a network read/write
125 /*	error, otherwise it is the result value of the TLS operation.
126 /* LICENSE
127 /* .ad
128 /* .fi
129 /*	This software is free. You can do with it whatever you want.
130 /*	The original author kindly requests that you acknowledge
131 /*	the use of his software.
132 /* AUTHOR(S)
133 /*	Originally written by:
134 /*	Lutz Jaenicke
135 /*	BTU Cottbus
136 /*	Allgemeine Elektrotechnik
137 /*	Universitaetsplatz 3-4
138 /*	D-03044 Cottbus, Germany
139 /*
140 /*	Updated by:
141 /*	Wietse Venema
142 /*	IBM T.J. Watson Research
143 /*	P.O. Box 704
144 /*	Yorktown Heights, NY 10598, USA
145 /*
146 /*	Victor Duchovni
147 /*	Morgan Stanley
148 /*--*/
149 
150 /* System library. */
151 
152 #include <sys_defs.h>
153 
154 #ifdef USE_TLS
155 
156 /* Utility library. */
157 
158 #include <msg.h>
159 #include <iostuff.h>
160 
161 /* TLS library. */
162 
163 #define TLS_INTERNAL
164 #include <tls.h>
165 
166 /* Application-specific. */
167 
168 #define NETLAYER_BUFFERSIZE 8192
169 
170 /* network_biopair_interop - synchronize network with BIO pair */
171 
172 static int network_biopair_interop(int fd, int timeout, BIO *network_bio)
173 {
174     const char *myname = "network_biopair_interop";
175     int     want_write;
176     int     num_write;
177     int     write_pos;
178     int     from_bio;
179     int     want_read;
180     int     num_read;
181     int     to_bio;
182     char    buffer[NETLAYER_BUFFERSIZE];
183 
184     /*
185      * To avoid deadlock, write all pending data to the network before
186      * attempting to read from the network.
187      */
188     while ((want_write = BIO_ctrl_pending(network_bio)) > 0) {
189 	if (want_write > sizeof(buffer))
190 	    want_write = sizeof(buffer);
191 	from_bio = BIO_read(network_bio, buffer, want_write);
192 
193 	/*
194 	 * Write the complete buffer contents to the network.
195 	 */
196 	for (write_pos = 0; write_pos < from_bio; /* see below */ ) {
197 	    if (timeout > 0 && write_wait(fd, timeout) < 0)
198 		return (-1);
199 	    num_write = write(fd, buffer + write_pos, from_bio - write_pos);
200 	    if (num_write <= 0) {
201 		if ((num_write < 0) && (timeout > 0) && (errno == EAGAIN)) {
202 		    msg_warn("write() returns EAGAIN on a writable file descriptor!");
203 		    msg_warn("pausing to avoid going into a tight select/write loop!");
204 		    sleep(1);
205 		} else {
206 		    msg_warn("%s: error writing %d bytes to the network: %m",
207 			     myname, from_bio - write_pos);
208 		    return (-1);
209 		}
210 	    } else {
211 		write_pos += num_write;
212 	    }
213 	}
214     }
215 
216     /*
217      * Read data from the network into the BIO pair.
218      */
219     while ((want_read = BIO_ctrl_get_read_request(network_bio)) > 0) {
220 	if (want_read > sizeof(buffer))
221 	    want_read = sizeof(buffer);
222 	if (timeout > 0 && read_wait(fd, timeout) < 0)
223 	    return (-1);
224 	num_read = read(fd, buffer, want_read);
225 	if (num_read == 0)
226 	    /* FIX 200412 Cannot return a zero read count. */
227 	    return (-1);
228 	if (num_read < 0) {
229 	    if ((num_read < 0) && (timeout > 0) && (errno == EAGAIN)) {
230 		msg_warn("read() returns EAGAIN on a readable file descriptor!");
231 		msg_warn("pausing to avoid going into a tight select/write loop!");
232 		sleep(1);
233 	    } else {
234 		msg_warn("%s: error reading %d bytes from the network: %m",
235 			 myname, want_read);
236 		return (-1);
237 	    }
238 	} else {
239 	    to_bio = BIO_write(network_bio, buffer, num_read);
240 	    if (to_bio != num_read)
241 		msg_panic("%s: BIO_write error: to_bio != num_read", myname);
242 	}
243     }
244     return (0);
245 }
246 
247 /* tls_bio - perform SSL input/output operation with extreme prejudice */
248 
249 int     tls_bio(int fd, int timeout, TLS_SESS_STATE *TLScontext,
250 		        int (*hsfunc) (SSL *),
251 		        int (*rfunc) (SSL *, void *, int),
252 		        int (*wfunc) (SSL *, const void *, int),
253 		        void *buf, int num)
254 {
255     const char *myname = "tls_bio";
256     int     status;
257     int     err;
258     int     retval = 0;
259     int     biop_retval;
260     int     done;
261 
262     /*
263      * If necessary, retry the SSL handshake or read/write operation after
264      * handling any pending network I/O.
265      */
266     for (done = 0; done == 0; /* void */ ) {
267 	if (hsfunc)
268 	    status = hsfunc(TLScontext->con);
269 	else if (rfunc)
270 	    status = rfunc(TLScontext->con, buf, num);
271 	else if (wfunc)
272 	    status = wfunc(TLScontext->con, buf, num);
273 	else
274 	    msg_panic("%s: nothing to do here", myname);
275 	err = SSL_get_error(TLScontext->con, status);
276 
277 #if (OPENSSL_VERSION_NUMBER <= 0x0090581fL)
278 
279 	/*
280 	 * There is a bug up to and including OpenSSL-0.9.5a: if an error
281 	 * occurs while checking the peers certificate due to some
282 	 * certificate error (e.g. as happend with a RSA-padding error), the
283 	 * error is put onto the error stack. If verification is not
284 	 * enforced, this error should be ignored, but the error-queue is not
285 	 * cleared, so we can find this error here. The bug has been fixed on
286 	 * May 28, 2000.
287 	 *
288 	 * This bug so far has only manifested as 4800:error:0407006A:rsa
289 	 * routines:RSA_padding_check_PKCS1_type_1:block type is not
290 	 * 01:rsa_pk1.c:100: 4800:error:04067072:rsa
291 	 * routines:RSA_EAY_PUBLIC_DECRYPT:padding check
292 	 * failed:rsa_eay.c:396: 4800:error:0D079006:asn1 encoding
293 	 * routines:ASN1_verify:bad get asn1 object call:a_verify.c:109: so
294 	 * that we specifically test for this error. We print the errors to
295 	 * the logfile and automatically clear the error queue. Then we retry
296 	 * to get another error code. We cannot do better, since we can only
297 	 * retrieve the last entry of the error-queue without actually
298 	 * cleaning it on the way.
299 	 *
300 	 * This workaround is secure, as verify_result is set to "failed"
301 	 * anyway.
302 	 */
303 	if (err == SSL_ERROR_SSL) {
304 	    if (ERR_peek_error() == 0x0407006AL) {
305 		tls_print_errors();
306 		msg_info("OpenSSL <= 0.9.5a workaround called: certificate errors ignored");
307 		err = SSL_get_error(TLScontext->con, status);
308 	    }
309 	}
310 #endif
311 
312 	/*
313 	 * Find out if we must retry the operation and/or if there is pending
314 	 * network I/O.
315 	 *
316 	 * XXX If we're the first to invoke SSL_shutdown(), then the operation
317 	 * isn't really complete when the call returns. We could hide that
318 	 * anomaly here and repeat the call.
319 	 */
320 	switch (err) {
321 	case SSL_ERROR_NONE:			/* success */
322 	    retval = status;
323 	    done = 1;
324 	    /* FALLTHROUGH */
325 	case SSL_ERROR_WANT_WRITE:		/* flush/update buffers */
326 	case SSL_ERROR_WANT_READ:
327 	    biop_retval =
328 		network_biopair_interop(fd, timeout, TLScontext->network_bio);
329 	    if (biop_retval < 0)
330 		return (-1);			/* network read/write error */
331 	    break;
332 
333 	    /*
334 	     * With tls_timed_read() and tls_timed_write() the caller is the
335 	     * VSTREAM library module which is unaware of TLS, so we log the
336 	     * TLS error stack here. In a better world, each VSTREAM I/O
337 	     * object would provide an error reporting method in addition to
338 	     * the timed_read and timed_write methods, so that we would not
339 	     * need to have ad-hoc code like this.
340 	     */
341 	case SSL_ERROR_SSL:
342 	    if (rfunc || wfunc)
343 		tls_print_errors();
344 	    /* FALLTHROUGH */
345 	default:
346 	    retval = status;
347 	    done = 1;
348 	    break;
349 	}
350     }
351     return (retval);
352 }
353 
354 #endif
355