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