1 /* $NetBSD: tls_stream.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ 2 3 /*++ 4 /* NAME 5 /* tls_stream 6 /* SUMMARY 7 /* VSTREAM over TLS 8 /* SYNOPSIS 9 /* #define TLS_INTERNAL 10 /* #include <tls.h> 11 /* 12 /* void tls_stream_start(stream, context) 13 /* VSTREAM *stream; 14 /* TLS_SESS_STATE *context; 15 /* 16 /* void tls_stream_stop(stream) 17 /* VSTREAM *stream; 18 /* DESCRIPTION 19 /* This module implements the VSTREAM over TLS support user interface. 20 /* The hard work is done elsewhere. 21 /* 22 /* tls_stream_start() enables TLS on the named stream. All read 23 /* and write operations are directed through the TLS library, 24 /* using the state information specified with the context argument. 25 /* 26 /* tls_stream_stop() replaces the VSTREAM read/write routines 27 /* by dummies that have no side effects, and deletes the 28 /* VSTREAM's reference to the TLS context. 29 /* DIAGNOSTICS 30 /* The tls_stream(3) read/write routines return the non-zero 31 /* number of plaintext bytes read/written if successful; -1 32 /* after TLS protocol failure, system-call failure, or for any 33 /* reason described under "in addition" below; and zero when 34 /* the remote party closed the connection or sent a TLS shutdown 35 /* request. 36 /* 37 /* Upon return from the tls_stream(3) read/write routines the 38 /* global errno value is non-zero when the requested operation 39 /* did not complete due to system call failure. 40 /* 41 /* In addition, the result value is set to -1, and the global 42 /* errno value is set to ETIMEDOUT, when a network read/write 43 /* request did not complete within the time limit. 44 /* SEE ALSO 45 /* dummy_read(3), placebo read routine 46 /* dummy_write(3), placebo write routine 47 /* LICENSE 48 /* .ad 49 /* .fi 50 /* This software is free. You can do with it whatever you want. 51 /* The original author kindly requests that you acknowledge 52 /* the use of his software. 53 /* AUTHOR(S) 54 /* Based on code that was originally written by: 55 /* Lutz Jaenicke 56 /* BTU Cottbus 57 /* Allgemeine Elektrotechnik 58 /* Universitaetsplatz 3-4 59 /* D-03044 Cottbus, Germany 60 /* 61 /* Updated by: 62 /* Wietse Venema 63 /* IBM T.J. Watson Research 64 /* P.O. Box 704 65 /* Yorktown Heights, NY 10598, USA 66 /*--*/ 67 68 /* System library. */ 69 70 #include <sys_defs.h> 71 72 #ifdef USE_TLS 73 74 /* Utility library. */ 75 76 #include <iostuff.h> 77 #include <vstream.h> 78 #include <msg.h> 79 80 /* TLS library. */ 81 82 #define TLS_INTERNAL 83 #include <tls.h> 84 85 /* 86 * Interface mis-match compensation. The OpenSSL read/write routines return 87 * unspecified negative values when an operation fails, while the vstream(3) 88 * plaintext timed_read/write() functions follow the convention of UNIX 89 * system calls, and return -1 upon error. The macro below makes OpenSSL 90 * read/write results consistent with the UNIX system-call convention. 91 */ 92 #define NORMALIZED_VSTREAM_RETURN(retval) ((retval) < 0 ? -1 : (retval)) 93 94 /* tls_timed_read - read content from stream, then TLS decapsulate */ 95 96 static ssize_t tls_timed_read(int fd, void *buf, size_t len, int timeout, 97 void *context) 98 { 99 const char *myname = "tls_timed_read"; 100 ssize_t ret; 101 TLS_SESS_STATE *TLScontext; 102 103 TLScontext = (TLS_SESS_STATE *) context; 104 if (!TLScontext) 105 msg_panic("%s: no context", myname); 106 107 ret = tls_bio_read(fd, buf, len, timeout, TLScontext); 108 if (ret > 0 && (TLScontext->log_mask & TLS_LOG_ALLPKTS)) 109 msg_info("Read %ld chars: %.*s", 110 (long) ret, (int) (ret > 40 ? 40 : ret), (char *) buf); 111 return (NORMALIZED_VSTREAM_RETURN(ret)); 112 } 113 114 /* tls_timed_write - TLS encapsulate content, then write to stream */ 115 116 static ssize_t tls_timed_write(int fd, void *buf, size_t len, int timeout, 117 void *context) 118 { 119 const char *myname = "tls_timed_write"; 120 ssize_t ret; 121 TLS_SESS_STATE *TLScontext; 122 123 TLScontext = (TLS_SESS_STATE *) context; 124 if (!TLScontext) 125 msg_panic("%s: no context", myname); 126 127 if (TLScontext->log_mask & TLS_LOG_ALLPKTS) 128 msg_info("Write %ld chars: %.*s", 129 (long) len, (int) (len > 40 ? 40 : len), (char *) buf); 130 ret = tls_bio_write(fd, buf, len, timeout, TLScontext); 131 return (NORMALIZED_VSTREAM_RETURN(ret)); 132 } 133 134 /* tls_stream_start - start VSTREAM over TLS */ 135 136 void tls_stream_start(VSTREAM *stream, TLS_SESS_STATE *context) 137 { 138 vstream_control(stream, 139 CA_VSTREAM_CTL_READ_FN(tls_timed_read), 140 CA_VSTREAM_CTL_WRITE_FN(tls_timed_write), 141 CA_VSTREAM_CTL_CONTEXT(context), 142 CA_VSTREAM_CTL_END); 143 } 144 145 /* tls_stream_stop - stop VSTREAM over TLS */ 146 147 void tls_stream_stop(VSTREAM *stream) 148 { 149 150 /* 151 * Prevent data leakage after TLS is turned off. The Postfix/TLS patch 152 * provided null function pointers; we use dummy routines that make less 153 * noise when used. 154 */ 155 vstream_control(stream, 156 CA_VSTREAM_CTL_READ_FN(dummy_read), 157 CA_VSTREAM_CTL_WRITE_FN(dummy_write), 158 CA_VSTREAM_CTL_CONTEXT((void *) 0), 159 CA_VSTREAM_CTL_END); 160 } 161 162 #endif 163