xref: /netbsd-src/external/ibm-public/postfix/dist/src/tls/tls_stream.c (revision e89934bbf778a6d6d6894877c4da59d0c7835b0f)
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