summaryrefslogtreecommitdiffstats
path: root/src/tls/tls_stream.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tls/tls_stream.c')
-rw-r--r--src/tls/tls_stream.c160
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