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