diff options
Diffstat (limited to '')
-rw-r--r-- | src/tls/tls_stream.c | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/src/tls/tls_stream.c b/src/tls/tls_stream.c new file mode 100644 index 0000000..4cc53a7 --- /dev/null +++ b/src/tls/tls_stream.c @@ -0,0 +1,160 @@ +/*++ +/* NAME +/* tls_stream +/* SUMMARY +/* VSTREAM over TLS +/* SYNOPSIS +/* #define TLS_INTERNAL +/* #include <tls.h> +/* +/* void tls_stream_start(stream, context) +/* VSTREAM *stream; +/* TLS_SESS_STATE *context; +/* +/* void tls_stream_stop(stream) +/* VSTREAM *stream; +/* DESCRIPTION +/* This module implements the VSTREAM over TLS support user interface. +/* The hard work is done elsewhere. +/* +/* tls_stream_start() enables TLS on the named stream. All read +/* and write operations are directed through the TLS library, +/* using the state information specified with the context argument. +/* +/* tls_stream_stop() replaces the VSTREAM read/write routines +/* by dummies that have no side effects, and deletes the +/* VSTREAM's reference to the TLS context. +/* DIAGNOSTICS +/* The tls_stream(3) read/write routines return the non-zero +/* number of plaintext bytes read/written if successful; -1 +/* after TLS protocol failure, system-call failure, or for any +/* reason described under "in addition" below; and zero when +/* the remote party closed the connection or sent a TLS shutdown +/* request. +/* +/* Upon return from the tls_stream(3) read/write routines the +/* global errno value is non-zero when the requested operation +/* did not complete due to system call failure. +/* +/* In addition, the result value is set to -1, and the global +/* errno value is set to ETIMEDOUT, when a network read/write +/* request did not complete within the time limit. +/* SEE ALSO +/* dummy_read(3), placebo read routine +/* dummy_write(3), placebo write routine +/* LICENSE +/* .ad +/* .fi +/* This software is free. You can do with it whatever you want. +/* The original author kindly requests that you acknowledge +/* the use of his software. +/* AUTHOR(S) +/* Based on code that was originally written by: +/* Lutz Jaenicke +/* BTU Cottbus +/* Allgemeine Elektrotechnik +/* Universitaetsplatz 3-4 +/* D-03044 Cottbus, Germany +/* +/* Updated by: +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +/* System library. */ + +#include <sys_defs.h> + +#ifdef USE_TLS + +/* Utility library. */ + +#include <iostuff.h> +#include <vstream.h> +#include <msg.h> + +/* TLS library. */ + +#define TLS_INTERNAL +#include <tls.h> + + /* + * Interface mis-match compensation. The OpenSSL read/write routines return + * unspecified negative values when an operation fails, while the vstream(3) + * plaintext timed_read/write() functions follow the convention of UNIX + * system calls, and return -1 upon error. The macro below makes OpenSSL + * read/write results consistent with the UNIX system-call convention. + */ +#define NORMALIZED_VSTREAM_RETURN(retval) ((retval) < 0 ? -1 : (retval)) + +/* tls_timed_read - read content from stream, then TLS decapsulate */ + +static ssize_t tls_timed_read(int fd, void *buf, size_t len, int timeout, + void *context) +{ + const char *myname = "tls_timed_read"; + ssize_t ret; + TLS_SESS_STATE *TLScontext; + + TLScontext = (TLS_SESS_STATE *) context; + if (!TLScontext) + msg_panic("%s: no context", myname); + + ret = tls_bio_read(fd, buf, len, timeout, TLScontext); + if (ret > 0 && (TLScontext->log_mask & TLS_LOG_ALLPKTS)) + msg_info("Read %ld chars: %.*s", + (long) ret, (int) (ret > 40 ? 40 : ret), (char *) buf); + return (NORMALIZED_VSTREAM_RETURN(ret)); +} + +/* tls_timed_write - TLS encapsulate content, then write to stream */ + +static ssize_t tls_timed_write(int fd, void *buf, size_t len, int timeout, + void *context) +{ + const char *myname = "tls_timed_write"; + ssize_t ret; + TLS_SESS_STATE *TLScontext; + + TLScontext = (TLS_SESS_STATE *) context; + if (!TLScontext) + msg_panic("%s: no context", myname); + + if (TLScontext->log_mask & TLS_LOG_ALLPKTS) + msg_info("Write %ld chars: %.*s", + (long) len, (int) (len > 40 ? 40 : len), (char *) buf); + ret = tls_bio_write(fd, buf, len, timeout, TLScontext); + return (NORMALIZED_VSTREAM_RETURN(ret)); +} + +/* tls_stream_start - start VSTREAM over TLS */ + +void tls_stream_start(VSTREAM *stream, TLS_SESS_STATE *context) +{ + vstream_control(stream, + CA_VSTREAM_CTL_READ_FN(tls_timed_read), + CA_VSTREAM_CTL_WRITE_FN(tls_timed_write), + CA_VSTREAM_CTL_CONTEXT(context), + CA_VSTREAM_CTL_END); +} + +/* tls_stream_stop - stop VSTREAM over TLS */ + +void tls_stream_stop(VSTREAM *stream) +{ + + /* + * Prevent data leakage after TLS is turned off. The Postfix/TLS patch + * provided null function pointers; we use dummy routines that make less + * noise when used. + */ + vstream_control(stream, + CA_VSTREAM_CTL_READ_FN(dummy_read), + CA_VSTREAM_CTL_WRITE_FN(dummy_write), + CA_VSTREAM_CTL_CONTEXT((void *) 0), + CA_VSTREAM_CTL_END); +} + +#endif |