1*68e5c67bSchristos /*	$NetBSD: tls_stream.c,v 1.2 2017/02/14 01:16:48 christos Exp $	*/
241fbaed0Stron 
341fbaed0Stron /*++
441fbaed0Stron /* NAME
541fbaed0Stron /*	tls_stream
641fbaed0Stron /* SUMMARY
741fbaed0Stron /*	VSTREAM over TLS
841fbaed0Stron /* SYNOPSIS
941fbaed0Stron /*	#define TLS_INTERNAL
1041fbaed0Stron /*	#include <tls.h>
1141fbaed0Stron /*
1241fbaed0Stron /*	void	tls_stream_start(stream, context)
1341fbaed0Stron /*	VSTREAM	*stream;
1441fbaed0Stron /*	TLS_SESS_STATE *context;
1541fbaed0Stron /*
1641fbaed0Stron /*	void	tls_stream_stop(stream)
1741fbaed0Stron /*	VSTREAM	*stream;
1841fbaed0Stron /* DESCRIPTION
1941fbaed0Stron /*	This module implements the VSTREAM over TLS support user interface.
2041fbaed0Stron /*	The hard work is done elsewhere.
2141fbaed0Stron /*
2241fbaed0Stron /*	tls_stream_start() enables TLS on the named stream. All read
2341fbaed0Stron /*	and write operations are directed through the TLS library,
2441fbaed0Stron /*	using the state information specified with the context argument.
2541fbaed0Stron /*
2641fbaed0Stron /*	tls_stream_stop() replaces the VSTREAM read/write routines
2741fbaed0Stron /*	by dummies that have no side effects, and deletes the
2841fbaed0Stron /*	VSTREAM's reference to the TLS context.
29e694ac3bStron /* DIAGNOSTICS
30e694ac3bStron /*	The tls_stream(3) read/write routines return the non-zero
31e694ac3bStron /*	number of plaintext bytes read/written if successful; -1
32e694ac3bStron /*	after TLS protocol failure, system-call failure, or for any
33e694ac3bStron /*	reason described under "in addition" below; and zero when
34e694ac3bStron /*	the remote party closed the connection or sent a TLS shutdown
35e694ac3bStron /*	request.
36e694ac3bStron /*
37e694ac3bStron /*	Upon return from the tls_stream(3) read/write routines the
38e694ac3bStron /*	global errno value is non-zero when the requested operation
39e694ac3bStron /*	did not complete due to system call failure.
40e694ac3bStron /*
41e694ac3bStron /*	In addition, the result value is set to -1, and the global
42e694ac3bStron /*	errno value is set to ETIMEDOUT, when a network read/write
43e694ac3bStron /*	request did not complete within the time limit.
4441fbaed0Stron /* SEE ALSO
4541fbaed0Stron /*	dummy_read(3), placebo read routine
4641fbaed0Stron /*	dummy_write(3), placebo write routine
4741fbaed0Stron /* LICENSE
4841fbaed0Stron /* .ad
4941fbaed0Stron /* .fi
5041fbaed0Stron /*	This software is free. You can do with it whatever you want.
5141fbaed0Stron /*	The original author kindly requests that you acknowledge
5241fbaed0Stron /*	the use of his software.
5341fbaed0Stron /* AUTHOR(S)
5441fbaed0Stron /*	Based on code that was originally written by:
5541fbaed0Stron /*	Lutz Jaenicke
5641fbaed0Stron /*	BTU Cottbus
5741fbaed0Stron /*	Allgemeine Elektrotechnik
5841fbaed0Stron /*	Universitaetsplatz 3-4
5941fbaed0Stron /*	D-03044 Cottbus, Germany
6041fbaed0Stron /*
6141fbaed0Stron /*	Updated by:
6241fbaed0Stron /*	Wietse Venema
6341fbaed0Stron /*	IBM T.J. Watson Research
6441fbaed0Stron /*	P.O. Box 704
6541fbaed0Stron /*	Yorktown Heights, NY 10598, USA
6641fbaed0Stron /*--*/
6741fbaed0Stron 
6841fbaed0Stron /* System library. */
6941fbaed0Stron 
7041fbaed0Stron #include <sys_defs.h>
7141fbaed0Stron 
7241fbaed0Stron #ifdef USE_TLS
7341fbaed0Stron 
7441fbaed0Stron /* Utility library. */
7541fbaed0Stron 
7641fbaed0Stron #include <iostuff.h>
7741fbaed0Stron #include <vstream.h>
7841fbaed0Stron #include <msg.h>
7941fbaed0Stron 
8041fbaed0Stron /* TLS library. */
8141fbaed0Stron 
8241fbaed0Stron #define TLS_INTERNAL
8341fbaed0Stron #include <tls.h>
8441fbaed0Stron 
85e694ac3bStron  /*
86e694ac3bStron   * Interface mis-match compensation. The OpenSSL read/write routines return
87e694ac3bStron   * unspecified negative values when an operation fails, while the vstream(3)
88e694ac3bStron   * plaintext timed_read/write() functions follow the convention of UNIX
89e694ac3bStron   * system calls, and return -1 upon error. The macro below makes OpenSSL
90e694ac3bStron   * read/write results consistent with the UNIX system-call convention.
91e694ac3bStron   */
92e694ac3bStron #define NORMALIZED_VSTREAM_RETURN(retval) ((retval) < 0 ? -1 : (retval))
93e694ac3bStron 
9441fbaed0Stron /* tls_timed_read - read content from stream, then TLS decapsulate */
9541fbaed0Stron 
tls_timed_read(int fd,void * buf,size_t len,int timeout,void * context)9641fbaed0Stron static ssize_t tls_timed_read(int fd, void *buf, size_t len, int timeout,
9741fbaed0Stron 			              void *context)
9841fbaed0Stron {
9941fbaed0Stron     const char *myname = "tls_timed_read";
10041fbaed0Stron     ssize_t ret;
10141fbaed0Stron     TLS_SESS_STATE *TLScontext;
10241fbaed0Stron 
10341fbaed0Stron     TLScontext = (TLS_SESS_STATE *) context;
10441fbaed0Stron     if (!TLScontext)
10541fbaed0Stron 	msg_panic("%s: no context", myname);
10641fbaed0Stron 
10741fbaed0Stron     ret = tls_bio_read(fd, buf, len, timeout, TLScontext);
108e694ac3bStron     if (ret > 0 && (TLScontext->log_mask & TLS_LOG_ALLPKTS))
10941fbaed0Stron 	msg_info("Read %ld chars: %.*s",
11041fbaed0Stron 		 (long) ret, (int) (ret > 40 ? 40 : ret), (char *) buf);
111e694ac3bStron     return (NORMALIZED_VSTREAM_RETURN(ret));
11241fbaed0Stron }
11341fbaed0Stron 
11441fbaed0Stron /* tls_timed_write - TLS encapsulate content, then write to stream */
11541fbaed0Stron 
tls_timed_write(int fd,void * buf,size_t len,int timeout,void * context)11641fbaed0Stron static ssize_t tls_timed_write(int fd, void *buf, size_t len, int timeout,
11741fbaed0Stron 			               void *context)
11841fbaed0Stron {
11941fbaed0Stron     const char *myname = "tls_timed_write";
120e694ac3bStron     ssize_t ret;
12141fbaed0Stron     TLS_SESS_STATE *TLScontext;
12241fbaed0Stron 
12341fbaed0Stron     TLScontext = (TLS_SESS_STATE *) context;
12441fbaed0Stron     if (!TLScontext)
12541fbaed0Stron 	msg_panic("%s: no context", myname);
12641fbaed0Stron 
127e694ac3bStron     if (TLScontext->log_mask & TLS_LOG_ALLPKTS)
12841fbaed0Stron 	msg_info("Write %ld chars: %.*s",
12941fbaed0Stron 		 (long) len, (int) (len > 40 ? 40 : len), (char *) buf);
130e694ac3bStron     ret = tls_bio_write(fd, buf, len, timeout, TLScontext);
131e694ac3bStron     return (NORMALIZED_VSTREAM_RETURN(ret));
13241fbaed0Stron }
13341fbaed0Stron 
13441fbaed0Stron /* tls_stream_start - start VSTREAM over TLS */
13541fbaed0Stron 
tls_stream_start(VSTREAM * stream,TLS_SESS_STATE * context)13641fbaed0Stron void    tls_stream_start(VSTREAM *stream, TLS_SESS_STATE *context)
13741fbaed0Stron {
13841fbaed0Stron     vstream_control(stream,
139837e7c1aSchristos 		    CA_VSTREAM_CTL_READ_FN(tls_timed_read),
140837e7c1aSchristos 		    CA_VSTREAM_CTL_WRITE_FN(tls_timed_write),
141837e7c1aSchristos 		    CA_VSTREAM_CTL_CONTEXT(context),
142837e7c1aSchristos 		    CA_VSTREAM_CTL_END);
14341fbaed0Stron }
14441fbaed0Stron 
14541fbaed0Stron /* tls_stream_stop - stop VSTREAM over TLS */
14641fbaed0Stron 
tls_stream_stop(VSTREAM * stream)14741fbaed0Stron void    tls_stream_stop(VSTREAM *stream)
14841fbaed0Stron {
14941fbaed0Stron 
15041fbaed0Stron     /*
15141fbaed0Stron      * Prevent data leakage after TLS is turned off. The Postfix/TLS patch
15241fbaed0Stron      * provided null function pointers; we use dummy routines that make less
15341fbaed0Stron      * noise when used.
15441fbaed0Stron      */
15541fbaed0Stron     vstream_control(stream,
156837e7c1aSchristos 		    CA_VSTREAM_CTL_READ_FN(dummy_read),
157837e7c1aSchristos 		    CA_VSTREAM_CTL_WRITE_FN(dummy_write),
158837e7c1aSchristos 		    CA_VSTREAM_CTL_CONTEXT((void *) 0),
159837e7c1aSchristos 		    CA_VSTREAM_CTL_END);
16041fbaed0Stron }
16141fbaed0Stron 
16241fbaed0Stron #endif
163