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
94static 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
114static 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
134void    tls_stream_start(VSTREAM *stream, TLS_SESS_STATE *context)
135{
136    vstream_control(stream,
137		    VSTREAM_CTL_READ_FN, tls_timed_read,
138		    VSTREAM_CTL_WRITE_FN, tls_timed_write,
139		    VSTREAM_CTL_CONTEXT, (void *) context,
140		    VSTREAM_CTL_END);
141}
142
143/* tls_stream_stop - stop VSTREAM over TLS */
144
145void    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		    VSTREAM_CTL_READ_FN, dummy_read,
155		    VSTREAM_CTL_WRITE_FN, dummy_write,
156		    VSTREAM_CTL_CONTEXT, (void *) 0,
157		    VSTREAM_CTL_END);
158}
159
160#endif
161