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