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
tls_timed_read(int fd,void * buf,size_t len,int timeout,void * context)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
tls_timed_write(int fd,void * buf,size_t len,int timeout,void * context)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
tls_stream_start(VSTREAM * stream,TLS_SESS_STATE * context)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
tls_stream_stop(VSTREAM * stream)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