No empty .Rs/.Re
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / tls / tls_bio_ops.c
blob1890c18a4f34bdc571506f0984cbaf619330fb2a
1 /* $NetBSD$ */
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>
12 /* int tls_bio_connect(fd, timeout, context)
13 /* int fd;
14 /* int timeout;
15 /* TLS_SESS_STATE *context;
17 /* int tls_bio_accept(fd, timeout, context)
18 /* int fd;
19 /* int timeout;
20 /* TLS_SESS_STATE *context;
22 /* int tls_bio_shutdown(fd, timeout, context)
23 /* int fd;
24 /* int timeout;
25 /* TLS_SESS_STATE *context;
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;
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.
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.
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.
57 /* The TLS layer to network interface is realized with a BIO pair:
59 /* Postfix | 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 /* | /\ ||
70 /* | || \/
71 /* socket read/write <===> BIO read/write
72 /* /\ || |
73 /* || \/ |
74 /* network |
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.
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.
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.
97 /* tls_bio_connect() performs the SSL_connect() operation while
98 /* synchronizing the network_bio buffer with the network.
100 /* tls_bio_accept() performs the SSL_accept() operation while
101 /* synchronizing the network_bio buffer with the network.
103 /* tls_bio_shutdown() performs the SSL_shutdown() operation while
104 /* synchronizing the network_bio buffer with the network.
106 /* tls_bio_read() performs the SSL_read() operation while
107 /* synchronizing the network_bio buffer with the network.
109 /* tls_bio_write() performs the SSL_write() operation while
110 /* synchronizing the network_bio buffer with the network.
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
140 /* Updated by:
141 /* Wietse Venema
142 /* IBM T.J. Watson Research
143 /* P.O. Box 704
144 /* Yorktown Heights, NY 10598, USA
146 /* Victor Duchovni
147 /* Morgan Stanley
148 /*--*/
150 /* System library. */
152 #include <sys_defs.h>
154 #ifdef USE_TLS
156 /* Utility library. */
158 #include <msg.h>
159 #include <iostuff.h>
161 /* TLS library. */
163 #define TLS_INTERNAL
164 #include <tls.h>
166 /* Application-specific. */
168 #define NETLAYER_BUFFERSIZE 8192
170 /* network_biopair_interop - synchronize network with BIO pair */
172 static int network_biopair_interop(int fd, int timeout, BIO *network_bio)
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];
185 * To avoid deadlock, write all pending data to the network before
186 * attempting to read from the network.
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);
194 * Write the complete buffer contents to the network.
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);
210 } else {
211 write_pos += num_write;
217 * Read data from the network into the BIO pair.
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);
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);
244 return (0);
247 /* tls_bio - perform SSL input/output operation with extreme prejudice */
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)
255 const char *myname = "tls_bio";
256 int status;
257 int err;
258 int retval = 0;
259 int biop_retval;
260 int done;
263 * If necessary, retry the SSL handshake or read/write operation after
264 * handling any pending network I/O.
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);
277 #if (OPENSSL_VERSION_NUMBER <= 0x0090581fL)
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.
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.
300 * This workaround is secure, as verify_result is set to "failed"
301 * anyway.
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);
310 #endif
313 * Find out if we must retry the operation and/or if there is pending
314 * network I/O.
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.
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;
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.
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;
351 return (retval);
354 #endif