xref: /netbsd-src/external/ibm-public/postfix/dist/src/tls/tls_bio_ops.c (revision a5847cc334d9a7029f6352b847e9e8d71a0f9e0c)
1 /*	$NetBSD: tls_bio_ops.c,v 1.1.1.3 2011/03/02 19:32:27 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 timeouts on non-blocking I/O while
42 /*	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 /*	The result value is -1 in case of a network read/write
80 /*	error, otherwise it is the result value of the TLS operation.
81 /* LICENSE
82 /* .ad
83 /* .fi
84 /*	This software is free. You can do with it whatever you want.
85 /*	The original author kindly requests that you acknowledge
86 /*	the use of his software.
87 /* AUTHOR(S)
88 /*	Originally written by:
89 /*	Lutz Jaenicke
90 /*	BTU Cottbus
91 /*	Allgemeine Elektrotechnik
92 /*	Universitaetsplatz 3-4
93 /*	D-03044 Cottbus, Germany
94 /*
95 /*	Updated by:
96 /*	Wietse Venema
97 /*	IBM T.J. Watson Research
98 /*	P.O. Box 704
99 /*	Yorktown Heights, NY 10598, USA
100 /*
101 /*	Victor Duchovni
102 /*	Morgan Stanley
103 /*--*/
104 
105 /* System library. */
106 
107 #include <sys_defs.h>
108 
109 #ifdef USE_TLS
110 
111 /* Utility library. */
112 
113 #include <msg.h>
114 #include <iostuff.h>
115 
116 /* TLS library. */
117 
118 #define TLS_INTERNAL
119 #include <tls.h>
120 
121 /* tls_bio - perform SSL input/output operation with extreme prejudice */
122 
123 int     tls_bio(int fd, int timeout, TLS_SESS_STATE *TLScontext,
124 		        int (*hsfunc) (SSL *),
125 		        int (*rfunc) (SSL *, void *, int),
126 		        int (*wfunc) (SSL *, const void *, int),
127 		        void *buf, int num)
128 {
129     const char *myname = "tls_bio";
130     int     status;
131     int     err;
132     int     retval = 0;
133     int     done;
134 
135     /*
136      * If necessary, retry the SSL handshake or read/write operation after
137      * handling any pending network I/O.
138      */
139     for (done = 0; done == 0; /* void */ ) {
140 	if (hsfunc)
141 	    status = hsfunc(TLScontext->con);
142 	else if (rfunc)
143 	    status = rfunc(TLScontext->con, buf, num);
144 	else if (wfunc)
145 	    status = wfunc(TLScontext->con, buf, num);
146 	else
147 	    msg_panic("%s: nothing to do here", myname);
148 	err = SSL_get_error(TLScontext->con, status);
149 
150 #if (OPENSSL_VERSION_NUMBER <= 0x0090581fL)
151 
152 	/*
153 	 * There is a bug up to and including OpenSSL-0.9.5a: if an error
154 	 * occurs while checking the peers certificate due to some
155 	 * certificate error (e.g. as happend with a RSA-padding error), the
156 	 * error is put onto the error stack. If verification is not
157 	 * enforced, this error should be ignored, but the error-queue is not
158 	 * cleared, so we can find this error here. The bug has been fixed on
159 	 * May 28, 2000.
160 	 *
161 	 * This bug so far has only manifested as 4800:error:0407006A:rsa
162 	 * routines:RSA_padding_check_PKCS1_type_1:block type is not
163 	 * 01:rsa_pk1.c:100: 4800:error:04067072:rsa
164 	 * routines:RSA_EAY_PUBLIC_DECRYPT:padding check
165 	 * failed:rsa_eay.c:396: 4800:error:0D079006:asn1 encoding
166 	 * routines:ASN1_verify:bad get asn1 object call:a_verify.c:109: so
167 	 * that we specifically test for this error. We print the errors to
168 	 * the logfile and automatically clear the error queue. Then we retry
169 	 * to get another error code. We cannot do better, since we can only
170 	 * retrieve the last entry of the error-queue without actually
171 	 * cleaning it on the way.
172 	 *
173 	 * This workaround is secure, as verify_result is set to "failed"
174 	 * anyway.
175 	 */
176 	if (err == SSL_ERROR_SSL) {
177 	    if (ERR_peek_error() == 0x0407006AL) {
178 		tls_print_errors();
179 		msg_info("OpenSSL <= 0.9.5a workaround called: certificate errors ignored");
180 		err = SSL_get_error(TLScontext->con, status);
181 	    }
182 	}
183 #endif
184 
185 	/*
186 	 * Find out if we must retry the operation and/or if there is pending
187 	 * network I/O.
188 	 *
189 	 * XXX If we're the first to invoke SSL_shutdown(), then the operation
190 	 * isn't really complete when the call returns. We could hide that
191 	 * anomaly here and repeat the call.
192 	 */
193 	switch (err) {
194 	case SSL_ERROR_NONE:			/* success */
195 	    retval = status;
196 	    done = 1;
197 	    break;
198 	case SSL_ERROR_WANT_WRITE:
199 	    if (write_wait(fd, timeout) < 0)
200 		return (-1);			/* timeout error */
201 	    break;
202 	case SSL_ERROR_WANT_READ:
203 	    if (read_wait(fd, timeout) < 0)
204 		return (-1);			/* timeout error */
205 	    break;
206 
207 	    /*
208 	     * With tls_timed_read() and tls_timed_write() the caller is the
209 	     * VSTREAM library module which is unaware of TLS, so we log the
210 	     * TLS error stack here. In a better world, each VSTREAM I/O
211 	     * object would provide an error reporting method in addition to
212 	     * the timed_read and timed_write methods, so that we would not
213 	     * need to have ad-hoc code like this.
214 	     */
215 	case SSL_ERROR_SSL:
216 	    if (rfunc || wfunc)
217 		tls_print_errors();
218 	    /* FALLTHROUGH */
219 	default:
220 	    retval = status;
221 	    done = 1;
222 	    break;
223 	}
224     }
225     return (retval);
226 }
227 
228 #endif
229