1 /* $NetBSD: tls_bio_ops.c,v 1.1.1.6 2020/05/25 23:40:34 christos 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 200 /* 201 * Flush the per-thread SSL error queue. Otherwise, errors from other 202 * code that also uses TLS may confuse SSL_get_error(3). 203 */ 204 ERR_clear_error(); 205 206 if (hsfunc) 207 status = hsfunc(TLScontext->con); 208 else if (rfunc) 209 status = rfunc(TLScontext->con, buf, num); 210 else if (wfunc) 211 status = wfunc(TLScontext->con, buf, num); 212 else 213 msg_panic("%s: nothing to do here", myname); 214 err = SSL_get_error(TLScontext->con, status); 215 216 /* 217 * Correspondence between SSL_ERROR_* error codes and tls_bio_(read, 218 * write, accept, connect, shutdown) return values (for brevity: 219 * retval). 220 * 221 * SSL_ERROR_NONE corresponds with retval > 0. With SSL_(read, write) 222 * this is the number of plaintext bytes sent or received. With 223 * SSL_(accept, connect, shutdown) this means that the operation was 224 * completed successfully. 225 * 226 * SSL_ERROR_WANT_(WRITE, READ) start a new loop iteration, or force 227 * (retval = -1, errno = ETIMEDOUT) when the time limit is exceeded. 228 * 229 * All other SSL_ERROR_* cases correspond with retval <= 0. With 230 * SSL_(read, write, accept, connect) retval == 0 means that the 231 * remote party either closed the network connection or that it 232 * requested TLS shutdown; with SSL_shutdown() retval == 0 means that 233 * our own shutdown request is in progress. With all operations 234 * retval < 0 means that there was an error. In the latter case, 235 * SSL_ERROR_SYSCALL means that error details are returned via the 236 * errno value. 237 * 238 * Find out if we must retry the operation and/or if there is pending 239 * network I/O. 240 * 241 * XXX If we're the first to invoke SSL_shutdown(), then the operation 242 * isn't really complete when the call returns. We could hide that 243 * anomaly here and repeat the call. 244 */ 245 switch (err) { 246 case SSL_ERROR_WANT_WRITE: 247 case SSL_ERROR_WANT_READ: 248 if (enable_deadline) { 249 GETTIMEOFDAY(&time_now); 250 timersub(&time_deadline, &time_now, &time_left); 251 timeout = time_left.tv_sec + (time_left.tv_usec > 0); 252 if (timeout <= 0) { 253 errno = ETIMEDOUT; 254 return (-1); 255 } 256 } 257 if (err == SSL_ERROR_WANT_WRITE) { 258 if (write_wait(fd, timeout) < 0) 259 return (-1); /* timeout error */ 260 } else { 261 if (read_wait(fd, timeout) < 0) 262 return (-1); /* timeout error */ 263 } 264 break; 265 266 /* 267 * Unhandled cases: SSL_ERROR_WANT_(ACCEPT, CONNECT, X509_LOOKUP) 268 * etc. Historically, Postfix silently treated these as ordinary 269 * I/O errors so we don't really know how common they are. For 270 * now, we just log a warning. 271 */ 272 default: 273 msg_warn("%s: unexpected SSL_ERROR code %d", myname, err); 274 /* FALLTHROUGH */ 275 276 /* 277 * With tls_timed_read() and tls_timed_write() the caller is the 278 * VSTREAM library module which is unaware of TLS, so we log the 279 * TLS error stack here. In a better world, each VSTREAM I/O 280 * object would provide an error reporting method in addition to 281 * the timed_read and timed_write methods, so that we would not 282 * need to have ad-hoc code like this. 283 */ 284 case SSL_ERROR_SSL: 285 if (rfunc || wfunc) 286 tls_print_errors(); 287 /* FALLTHROUGH */ 288 case SSL_ERROR_ZERO_RETURN: 289 case SSL_ERROR_NONE: 290 errno = 0; /* avoid bogus warnings */ 291 /* FALLTHROUGH */ 292 case SSL_ERROR_SYSCALL: 293 return (status); 294 } 295 } 296 } 297 298 #endif 299