Bugfix: missing error tls_server_start() error handling in
tlsproxy(8). File: tlsproxy/tlsproxy.c.
+
+ Connection reuse for TLS-encrypted SMTP sessions. This is
+ work-in-progress, #ifdef USE_TLSPROXY, to avoid contamination
+ of existing code.
+
+ The idea is to have smtp(8) talk plaintext while tlsproxy(8)
+ converts between local plaintext and remote ciphertext.
+ Then, smtp(8) can save plaintext connections to the cache,
+ and scache(8) holds the handles to the tlsproxy(8) processes.
+
+ This preliminary implementation does not yet support proxying
+ of DANE attributes from smtp(8) to tlsproxy(8). tlsproxy(8)
+ does not have permissions to read private key files that
+ smtp(8) can read. And the name of a connection cache entry
+ does not yet depend on whether the cached connection uses
+ TLS, nor does it depend on DANE information.
+
+ Files: global/mail_proto.h, postscreen/postscreen_starttls.c,
+ posttls-finger/posttls-finger.c, smtp/smtp.c, smtp/smtp.h,
+ smtp/smtp_params.c, smtp/smtp_proto.c, smtp/smtp_session.c,
+ smtpd/smtpd.c, tls/tls.h, tls/tls_client.c, tls/tls_proxy.h,
+ tls/tls_proxy_client_init_print.c,
+ tls/tls_proxy_client_init_scan.c,
+ tls/tls_proxy_client_start_print.c,
+ tls/tls_proxy_client_start_scan.c, tls/tls_proxy_clnt.c,
+ tls/tls_proxy_context_print.c, tls/tls_proxy_context_scan.c,
+ tls/tls_proxy_server_init_print.c,
+ tls/tls_proxy_server_init_scan.c,
+ tls/tls_proxy_server_start_print.c,
+ tls/tls_proxy_server_start_scan.c, tlsproxy/tlsproxy.c,
+ tlsproxy/tlsproxy.h, tlsproxy/tlsproxy_state.c, util/argv_attr.h,
+ util/argv_attr_print.c, util/argv_attr_scan.c.
# Non-production: needs thorough testing, or major changes are still
# needed before the code stabilizes.
-#CCARGS="$CCARGS -DNONPROD"
+CCARGS="$CCARGS -DNONPROD"
# Workaround: prepend Postfix include files before other include files.
CCARGS="-I. -I../../include $CCARGS"
#define MAIL_ATTR_DSN_ORCPT "dsn_orig_rcpt" /* dsn original recipient */
#define MAIL_ATTR_SMTPUTF8 "smtputf8" /* RFC6531 support */
- /*
- * TLSPROXY support.
- */
-#define MAIL_ATTR_REMOTE_ENDPT "remote_endpoint" /* name[addr]:port */
-#define MAIL_ATTR_ROLE "role" /* requested role */
-#define MAIL_ATTR_ROLE_SERVER "server"
-#define MAIL_ATTR_ROLE_CLIENT "client"
-#define MAIL_ATTR_TIMEOUT "timeout"
-#define MAIL_ATTR_PEER_CN "peer_CN"
-#define MAIL_ATTR_ISSUER_CN "issuer_CN"
-#define MAIL_ATTR_PEER_CERT_FPT "peer_fingerprint"
-#define MAIL_ATTR_PEER_PKEY_FPT "peer_pubkey_fingerprint"
-#define MAIL_ATTR_PEER_STATUS "peer_status"
-#define MAIL_ATTR_CIPHER_PROTOCOL "cipher_protocol"
-#define MAIL_ATTR_CIPHER_NAME "cipher_name"
-#define MAIL_ATTR_CIPHER_USEBITS "cipher_usebits"
-#define MAIL_ATTR_CIPHER_ALGBITS "cipher_algbits"
-#define MAIL_ATTR_SERVER_ID "server_id"
-
/*
* SMTP reply footer support.
*/
vstring_sprintf(remote_endpt, "[%s]:%s", smtp_state->smtp_client_addr,
smtp_state->smtp_client_port);
attr_print(tlsproxy_stream, ATTR_FLAG_NONE,
- SEND_ATTR_STR(MAIL_ATTR_REMOTE_ENDPT, STR(remote_endpt)),
- SEND_ATTR_INT(MAIL_ATTR_FLAGS, TLS_PROXY_FLAG_ROLE_SERVER),
- SEND_ATTR_INT(MAIL_ATTR_TIMEOUT, psc_normal_cmd_time_limit),
- SEND_ATTR_STR(MAIL_ATTR_SERVER_ID, MAIL_SERVICE_SMTPD), /* XXX */
+ SEND_ATTR_STR(TLS_ATTR_REMOTE_ENDPT, STR(remote_endpt)),
+ SEND_ATTR_INT(TLS_ATTR_FLAGS, TLS_PROXY_FLAG_ROLE_SERVER),
+ SEND_ATTR_INT(TLS_ATTR_TIMEOUT, psc_normal_cmd_time_limit),
+ SEND_ATTR_STR(TLS_ATTR_SERVERID, MAIL_SERVICE_SMTPD), /* XXX */
ATTR_TYPE_END);
if (vstream_fflush(tlsproxy_stream) != 0) {
msg_warn("error sending request to %s service: %m", psc_tlsp_service);
TLS_CLIENT_START(&tls_props,
ctx = state->tls_ctx,
stream = stream,
+ fd = -1,
timeout = smtp_tmout,
tls_level = state->level,
nexthop = state->nexthop,
smtp.o: ../../include/header_body_checks.h
smtp.o: ../../include/header_opts.h
smtp.o: ../../include/htable.h
+smtp.o: ../../include/iostuff.h
smtp.o: ../../include/mail_conf.h
smtp.o: ../../include/mail_params.h
+smtp.o: ../../include/mail_proto.h
smtp.o: ../../include/mail_server.h
smtp.o: ../../include/mail_version.h
smtp.o: ../../include/maps.h
smtp.o: ../../include/stringops.h
smtp.o: ../../include/sys_defs.h
smtp.o: ../../include/tls.h
+smtp.o: ../../include/tls_proxy.h
smtp.o: ../../include/tok822.h
smtp.o: ../../include/vbuf.h
smtp.o: ../../include/vstream.h
smtp_addr.o: ../../include/stringops.h
smtp_addr.o: ../../include/sys_defs.h
smtp_addr.o: ../../include/tls.h
+smtp_addr.o: ../../include/tls_proxy.h
smtp_addr.o: ../../include/tok822.h
smtp_addr.o: ../../include/vbuf.h
smtp_addr.o: ../../include/vstream.h
smtp_chat.o: ../../include/stringops.h
smtp_chat.o: ../../include/sys_defs.h
smtp_chat.o: ../../include/tls.h
+smtp_chat.o: ../../include/tls_proxy.h
smtp_chat.o: ../../include/tok822.h
smtp_chat.o: ../../include/vbuf.h
smtp_chat.o: ../../include/vstream.h
smtp_connect.o: ../../include/sys_defs.h
smtp_connect.o: ../../include/timed_connect.h
smtp_connect.o: ../../include/tls.h
+smtp_connect.o: ../../include/tls_proxy.h
smtp_connect.o: ../../include/tok822.h
smtp_connect.o: ../../include/vbuf.h
smtp_connect.o: ../../include/vstream.h
smtp_key.o: ../../include/string_list.h
smtp_key.o: ../../include/sys_defs.h
smtp_key.o: ../../include/tls.h
+smtp_key.o: ../../include/tls_proxy.h
smtp_key.o: ../../include/tok822.h
smtp_key.o: ../../include/vbuf.h
smtp_key.o: ../../include/vstream.h
smtp_map11.o: ../../include/string_list.h
smtp_map11.o: ../../include/sys_defs.h
smtp_map11.o: ../../include/tls.h
+smtp_map11.o: ../../include/tls_proxy.h
smtp_map11.o: ../../include/tok822.h
smtp_map11.o: ../../include/vbuf.h
smtp_map11.o: ../../include/vstream.h
smtp_proto.o: ../../include/stringops.h
smtp_proto.o: ../../include/sys_defs.h
smtp_proto.o: ../../include/tls.h
+smtp_proto.o: ../../include/tls_proxy.h
smtp_proto.o: ../../include/tok822.h
smtp_proto.o: ../../include/uxtext.h
smtp_proto.o: ../../include/vbuf.h
smtp_rcpt.o: ../../include/stringops.h
smtp_rcpt.o: ../../include/sys_defs.h
smtp_rcpt.o: ../../include/tls.h
+smtp_rcpt.o: ../../include/tls_proxy.h
smtp_rcpt.o: ../../include/tok822.h
smtp_rcpt.o: ../../include/vbuf.h
smtp_rcpt.o: ../../include/vstream.h
smtp_reuse.o: ../../include/stringops.h
smtp_reuse.o: ../../include/sys_defs.h
smtp_reuse.o: ../../include/tls.h
+smtp_reuse.o: ../../include/tls_proxy.h
smtp_reuse.o: ../../include/tok822.h
smtp_reuse.o: ../../include/vbuf.h
smtp_reuse.o: ../../include/vstream.h
smtp_sasl_auth_cache.o: ../../include/stringops.h
smtp_sasl_auth_cache.o: ../../include/sys_defs.h
smtp_sasl_auth_cache.o: ../../include/tls.h
+smtp_sasl_auth_cache.o: ../../include/tls_proxy.h
smtp_sasl_auth_cache.o: ../../include/tok822.h
smtp_sasl_auth_cache.o: ../../include/vbuf.h
smtp_sasl_auth_cache.o: ../../include/vstream.h
smtp_sasl_glue.o: ../../include/stringops.h
smtp_sasl_glue.o: ../../include/sys_defs.h
smtp_sasl_glue.o: ../../include/tls.h
+smtp_sasl_glue.o: ../../include/tls_proxy.h
smtp_sasl_glue.o: ../../include/tok822.h
smtp_sasl_glue.o: ../../include/vbuf.h
smtp_sasl_glue.o: ../../include/vstream.h
smtp_sasl_proto.o: ../../include/stringops.h
smtp_sasl_proto.o: ../../include/sys_defs.h
smtp_sasl_proto.o: ../../include/tls.h
+smtp_sasl_proto.o: ../../include/tls_proxy.h
smtp_sasl_proto.o: ../../include/tok822.h
smtp_sasl_proto.o: ../../include/vbuf.h
smtp_sasl_proto.o: ../../include/vstream.h
smtp_session.o: ../../include/stringops.h
smtp_session.o: ../../include/sys_defs.h
smtp_session.o: ../../include/tls.h
+smtp_session.o: ../../include/tls_proxy.h
smtp_session.o: ../../include/tok822.h
smtp_session.o: ../../include/vbuf.h
smtp_session.o: ../../include/vstream.h
smtp_state.o: ../../include/string_list.h
smtp_state.o: ../../include/sys_defs.h
smtp_state.o: ../../include/tls.h
+smtp_state.o: ../../include/tls_proxy.h
smtp_state.o: ../../include/tok822.h
smtp_state.o: ../../include/vbuf.h
smtp_state.o: ../../include/vstream.h
smtp_tls_policy.o: ../../include/stringops.h
smtp_tls_policy.o: ../../include/sys_defs.h
smtp_tls_policy.o: ../../include/tls.h
+smtp_tls_policy.o: ../../include/tls_proxy.h
smtp_tls_policy.o: ../../include/tok822.h
smtp_tls_policy.o: ../../include/valid_hostname.h
smtp_tls_policy.o: ../../include/valid_utf8_hostname.h
smtp_trouble.o: ../../include/stringops.h
smtp_trouble.o: ../../include/sys_defs.h
smtp_trouble.o: ../../include/tls.h
+smtp_trouble.o: ../../include/tls_proxy.h
smtp_trouble.o: ../../include/tok822.h
smtp_trouble.o: ../../include/vbuf.h
smtp_trouble.o: ../../include/vstream.h
smtp_unalias.o: ../../include/string_list.h
smtp_unalias.o: ../../include/sys_defs.h
smtp_unalias.o: ../../include/tls.h
+smtp_unalias.o: ../../include/tls_proxy.h
smtp_unalias.o: ../../include/tok822.h
smtp_unalias.o: ../../include/vbuf.h
smtp_unalias.o: ../../include/vstream.h
VAR_LMTP_DNS_RES_OPT, DEF_LMTP_DNS_RES_OPT, &var_smtp_dns_res_opt, 0, 0,
VAR_LMTP_DSN_FILTER, DEF_LMTP_DSN_FILTER, &var_smtp_dsn_filter, 0, 0,
VAR_LMTP_DNS_RE_FILTER, DEF_LMTP_DNS_RE_FILTER, &var_smtp_dns_re_filter, 0, 0,
+ VAR_TLSPROXY_SERVICE, DEF_TLSPROXY_SERVICE, &var_tlsproxy_service, 1, 0,
0,
};
static const CONFIG_TIME_TABLE lmtp_time_table[] = {
/* Global library. */
#include <deliver_request.h>
+#include <mail_proto.h>
#include <mail_params.h>
#include <mail_version.h>
#include <mail_conf.h>
char *var_smtp_tls_per_site;
char *var_smtp_tls_policy;
bool var_smtp_tls_wrappermode;
+char *var_tlsproxy_service;
#ifdef USE_TLS
char *var_smtp_sasl_tls_opts;
/*
* OpenSSL client state (opaque handle)
*/
+#ifndef USE_TLSPROXY
TLS_APPL_STATE *smtp_tls_ctx;
+
+#endif
int smtp_tls_insecure_mx_policy;
#endif
*/
if (use_tls || var_smtp_tls_per_site[0] || var_smtp_tls_policy[0]) {
#ifdef USE_TLS
+#ifndef USE_TLSPROXY
TLS_CLIENT_INIT_PROPS props;
/*
CAfile = var_smtp_tls_CAfile,
CApath = var_smtp_tls_CApath,
mdalg = var_smtp_tls_fpt_dgst);
+#endif /* USE_TLSPROXY */
smtp_tls_list_init();
#else
msg_warn("TLS has been selected, but TLS support is not compiled in");
*/
#include <tls.h>
+ /*
+ * tlsproxy client.
+ */
+#include <tls_proxy.h>
+
/*
* Global iterator support. This is updated by the connection-management
* loop, and contains dynamic context that appears in lookup keys for SASL
extern unsigned smtp_dns_res_opt; /* DNS query flags */
#ifdef USE_TLS
-
+#ifndef USE_TLSPROXY
extern TLS_APPL_STATE *smtp_tls_ctx; /* client-side TLS engine */
+
+#endif
extern int smtp_tls_insecure_mx_policy; /* DANE post insecure MX? */
#endif
VAR_SMTP_DNS_RES_OPT, DEF_SMTP_DNS_RES_OPT, &var_smtp_dns_res_opt, 0, 0,
VAR_SMTP_DSN_FILTER, DEF_SMTP_DSN_FILTER, &var_smtp_dsn_filter, 0, 0,
VAR_SMTP_DNS_RE_FILTER, DEF_SMTP_DNS_RE_FILTER, &var_smtp_dns_re_filter, 0, 0,
+ VAR_TLSPROXY_SERVICE, DEF_TLSPROXY_SERVICE, &var_tlsproxy_service, 1, 0,
0,
};
static const CONFIG_TIME_TABLE smtp_time_table[] = {
* Decide whether or not to send STARTTLS.
*/
if ((session->features & SMTP_FEATURE_STARTTLS) != 0
- && smtp_tls_ctx != 0 && state->tls->level >= TLS_LEV_MAY) {
+#ifndef USE_TLSPROXY
+ && smtp_tls_ctx != 0
+#endif
+ && state->tls->level >= TLS_LEV_MAY) {
/*
* Prepare for disaster.
SMTP_RESP_FAKE(&fake, "4.7.4"),
"TLS is required, but was not offered by host %s",
session->namaddr));
+#ifndef USE_TLSPROXY
} else if (smtp_tls_ctx == 0) {
return (smtp_site_fail(state, DSN_BY_LOCAL_MTA,
SMTP_RESP_FAKE(&fake, "4.7.5"),
"TLS is required, but our TLS engine is unavailable"));
+#endif
} else {
msg_warn("%s: TLS is required but unavailable, don't know why",
myname);
{
SMTP_SESSION *session = state->session;
SMTP_ITERATOR *iter = state->iterator;
- TLS_CLIENT_START_PROPS tls_props;
+ TLS_CLIENT_START_PROPS start_props;
VSTRING *serverid;
SMTP_RESP fake;
+#ifdef USE_TLSPROXY
+ TLS_CLIENT_INIT_PROPS init_props;
+ VSTREAM *tlsproxy;
+
+#endif
+
+
/*
* Turn off SMTP connection caching. When the TLS handshake succeeds, we
* can't reuse the SMTP connection. Reason: we can't turn off TLS in one
* SMTP connection either, because the conversation is in an unknown
* state.
*/
+#ifndef USE_TLSPROXY
DONT_CACHE_THIS_SESSION;
+#endif
/*
* The following assumes sites that use TLS in a perverse configuration:
| SMTP_KEY_FLAG_HOSTNAME
| SMTP_KEY_FLAG_ADDR);
+#ifdef USE_TLSPROXY
+
+ /*
+ * Send all our wishes in one big request.
+ */
+ TLS_PROXY_CLIENT_INIT_PROPS(&init_props,
+ log_param = VAR_LMTP_SMTP(TLS_LOGLEVEL),
+ log_level = var_smtp_tls_loglevel,
+ verifydepth = var_smtp_tls_scert_vd,
+ cache_type = LMTP_SMTP_SUFFIX(TLS_MGR_SCACHE),
+ cert_file = var_smtp_tls_cert_file,
+ key_file = var_smtp_tls_key_file,
+ dcert_file = var_smtp_tls_dcert_file,
+ dkey_file = var_smtp_tls_dkey_file,
+ eccert_file = var_smtp_tls_eccert_file,
+ eckey_file = var_smtp_tls_eckey_file,
+ CAfile = var_smtp_tls_CAfile,
+ CApath = var_smtp_tls_CApath,
+ mdalg = var_smtp_tls_fpt_dgst);
+ TLS_PROXY_CLIENT_START_PROPS(&start_props,
+ timeout = var_smtp_starttls_tmout,
+ tls_level = state->tls->level,
+ nexthop = session->tls_nexthop,
+ host = STR(iter->host),
+ namaddr = session->namaddrport,
+ serverid = vstring_str(serverid),
+ helo = session->helo,
+ protocols = state->tls->protocols,
+ cipher_grade = state->tls->grade,
+ cipher_exclusions
+ = vstring_str(state->tls->exclusions),
+ matchargv = state->tls->matchargv,
+ mdalg = var_smtp_tls_fpt_dgst);
+
+#define PROXY_OPEN_FLAGS \
+ (TLS_PROXY_FLAG_ROLE_CLIENT | TLS_PROXY_FLAG_SEND_CONTEXT)
+
+ tlsproxy =
+ tls_proxy_open(var_tlsproxy_service, PROXY_OPEN_FLAGS,
+ session->stream, STR(iter->host),
+ "25" /* TODO */ , var_smtp_starttls_tmout,
+ "smtp" /* TODO */ , &init_props, &start_props);
+
+ /*
+ * To insert tlsproxy(8) between this process and the remote SMTP server,
+ * we swap the file descriptors between the tlsproxy and session->stream
+ * VSTREAMS, so that we don't lose all the user-configurable
+ * session->stream attributes (such as longjump buffers or timeouts).
+ *
+ * TODO: the tlsproxy RPCs should return more error detail than a "NO"
+ * result.
+ */
+ if (tlsproxy == 0) {
+ session->tls_context = 0;
+ } else {
+ vstream_control(tlsproxy,
+ CA_VSTREAM_CTL_DOUBLE,
+ CA_VSTREAM_CTL_END);
+ vstream_control(session->stream,
+ CA_VSTREAM_CTL_SWAP_FD(tlsproxy),
+ CA_VSTREAM_CTL_END);
+ (void) vstream_fclose(tlsproxy); /* direct-to-server stream! */
+
+ /*
+ * After plumbing the plaintext stream, receive the TLS context
+ * object. For this we must use the same VSTREAM buffer that we also
+ * use to receive subsequent SMTP commands. The attribute protocol is
+ * robust enough that an adversary cannot inject their own bogus TLS
+ * context attributes into the stream.
+ */
+ session->tls_context = tls_proxy_context_receive(session->stream);
+ }
+#else /* USE_TLS_PROXY */
+
/*
* As of Postfix 2.5, tls_client_start() tries hard to always complete
* the TLS handshake. It records the verification and match status in the
* that C does not have natively: named parameter lists.
*/
session->tls_context =
- TLS_CLIENT_START(&tls_props,
+ TLS_CLIENT_START(&start_props,
ctx = smtp_tls_ctx,
stream = session->stream,
+ fd = -1,
timeout = var_smtp_starttls_tmout,
tls_level = state->tls->level,
nexthop = session->tls_nexthop,
matchargv = state->tls->matchargv,
mdalg = var_smtp_tls_fpt_dgst,
dane = state->tls->dane);
+#endif /* USE_TLS_PROXY */
vstring_free(serverid);
if (session->tls_context == 0) {
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*
/* Viktor Dukhovni
/*--*/
#ifdef USE_TLS
if (session->stream) {
vstream_fflush(session->stream);
- if (session->tls_context)
- tls_client_stop(smtp_tls_ctx, session->stream,
- var_smtp_starttls_tmout, 0, session->tls_context);
+ }
+ if (session->tls_context) {
+#ifdef USE_TLSPROXY
+ tls_proxy_context_free(session->tls_context);
+#else /* USE_TLSPROXY */
+ tls_client_stop(smtp_tls_ctx, session->stream,
+ var_smtp_starttls_tmout, 0, session->tls_context);
+#endif /* USE_TLSPROXY */
}
#endif
if (session->stream)
/*
* TLS initialization status.
*/
+#ifndef USE_TLSPROXY
static TLS_APPL_STATE *smtpd_tls_ctx;
static int ask_client_cert;
+#endif /* USE_TLSPROXY */
#endif
/*
#define PROXY_OPEN_FLAGS \
(TLS_PROXY_FLAG_ROLE_SERVER | TLS_PROXY_FLAG_SEND_CONTEXT)
- state->tlsproxy = tls_proxy_open(var_tlsproxy_service, PROXY_OPEN_FLAGS,
- state->client, state->addr,
- state->port, var_smtpd_tmout);
+ state->tlsproxy =
+ tls_proxy_legacy_open(var_tlsproxy_service, PROXY_OPEN_FLAGS,
+ state->client, state->addr,
+ state->port, var_smtpd_tmout,
+ state->service);
if (state->tlsproxy == 0) {
state->error_mask |= MAIL_ERROR_SOFTWARE;
/* RFC 3207 Section 4. */
if (SMTPD_STAND_ALONE(state) == 0 && var_smtpd_tls_wrappermode) {
#ifdef USE_TLSPROXY
/* We garbage-collect the VSTREAM in smtpd_state_reset() */
- state->tlsproxy = tls_proxy_open(var_tlsproxy_service,
- PROXY_OPEN_FLAGS,
- state->client, state->addr,
- state->port, var_smtpd_tmout);
+ state->tlsproxy =
+ tls_proxy_legacy_open(var_tlsproxy_service,
+ PROXY_OPEN_FLAGS,
+ state->client, state->addr,
+ state->port, var_smtpd_tmout,
+ state->service);
if (state->tlsproxy == 0) {
msg_warn("Wrapper-mode request dropped from %s for service %s."
" TLS context initialization failed. For details see"
tls_rsa.c tls_verify.c tls_dane.c tls_certkey.c tls_session.c \
tls_client.c tls_server.c tls_scache.c tls_mgr.c tls_seed.c \
tls_level.c \
- tls_proxy_clnt.c tls_proxy_print.c tls_proxy_scan.c
+ tls_proxy_clnt.c tls_proxy_context_print.c tls_proxy_context_scan.c \
+ tls_proxy_client_init_print.c tls_proxy_client_init_scan.c \
+ tls_proxy_server_init_print.c tls_proxy_server_init_scan.c \
+ tls_proxy_client_start_print.c tls_proxy_client_start_scan.c \
+ tls_proxy_server_start_print.c tls_proxy_server_start_scan.c
OBJS = tls_prng_dev.o tls_prng_egd.o tls_prng_file.o tls_fprint.o \
tls_prng_exch.o tls_stream.o tls_bio_ops.o tls_misc.o tls_dh.o \
tls_rsa.o tls_verify.o tls_dane.o tls_certkey.o tls_session.o \
tls_client.o tls_server.o tls_scache.o tls_mgr.o tls_seed.o \
tls_level.o \
- tls_proxy_clnt.o tls_proxy_print.o tls_proxy_scan.o
+ tls_proxy_clnt.o tls_proxy_context_print.o tls_proxy_context_scan.o \
+ tls_proxy_client_init_print.o tls_proxy_client_init_scan.o \
+ tls_proxy_server_init_print.o tls_proxy_server_init_scan.o \
+ tls_proxy_client_start_print.o tls_proxy_client_start_scan.o \
+ tls_proxy_server_start_print.o tls_proxy_server_start_scan.o
HDRS = tls.h tls_prng.h tls_scache.h tls_mgr.h tls_proxy.h
TESTSRC =
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
tls_prng_file.o: ../../include/sys_defs.h
tls_prng_file.o: tls_prng.h
tls_prng_file.o: tls_prng_file.c
+tls_proxy_client_init_print.o: ../../include/argv.h
+tls_proxy_client_init_print.o: ../../include/attr.h
+tls_proxy_client_init_print.o: ../../include/check_arg.h
+tls_proxy_client_init_print.o: ../../include/dns.h
+tls_proxy_client_init_print.o: ../../include/htable.h
+tls_proxy_client_init_print.o: ../../include/myaddrinfo.h
+tls_proxy_client_init_print.o: ../../include/mymalloc.h
+tls_proxy_client_init_print.o: ../../include/name_code.h
+tls_proxy_client_init_print.o: ../../include/name_mask.h
+tls_proxy_client_init_print.o: ../../include/nvtable.h
+tls_proxy_client_init_print.o: ../../include/sock_addr.h
+tls_proxy_client_init_print.o: ../../include/sys_defs.h
+tls_proxy_client_init_print.o: ../../include/vbuf.h
+tls_proxy_client_init_print.o: ../../include/vstream.h
+tls_proxy_client_init_print.o: ../../include/vstring.h
+tls_proxy_client_init_print.o: tls.h
+tls_proxy_client_init_print.o: tls_proxy.h
+tls_proxy_client_init_print.o: tls_proxy_client_init_print.c
+tls_proxy_client_init_scan.o: ../../include/argv.h
+tls_proxy_client_init_scan.o: ../../include/attr.h
+tls_proxy_client_init_scan.o: ../../include/check_arg.h
+tls_proxy_client_init_scan.o: ../../include/dns.h
+tls_proxy_client_init_scan.o: ../../include/htable.h
+tls_proxy_client_init_scan.o: ../../include/myaddrinfo.h
+tls_proxy_client_init_scan.o: ../../include/mymalloc.h
+tls_proxy_client_init_scan.o: ../../include/name_code.h
+tls_proxy_client_init_scan.o: ../../include/name_mask.h
+tls_proxy_client_init_scan.o: ../../include/nvtable.h
+tls_proxy_client_init_scan.o: ../../include/sock_addr.h
+tls_proxy_client_init_scan.o: ../../include/sys_defs.h
+tls_proxy_client_init_scan.o: ../../include/vbuf.h
+tls_proxy_client_init_scan.o: ../../include/vstream.h
+tls_proxy_client_init_scan.o: ../../include/vstring.h
+tls_proxy_client_init_scan.o: tls.h
+tls_proxy_client_init_scan.o: tls_proxy.h
+tls_proxy_client_init_scan.o: tls_proxy_client_init_scan.c
+tls_proxy_client_start_print.o: ../../include/argv.h
+tls_proxy_client_start_print.o: ../../include/argv_attr.h
+tls_proxy_client_start_print.o: ../../include/attr.h
+tls_proxy_client_start_print.o: ../../include/check_arg.h
+tls_proxy_client_start_print.o: ../../include/dns.h
+tls_proxy_client_start_print.o: ../../include/htable.h
+tls_proxy_client_start_print.o: ../../include/myaddrinfo.h
+tls_proxy_client_start_print.o: ../../include/mymalloc.h
+tls_proxy_client_start_print.o: ../../include/name_code.h
+tls_proxy_client_start_print.o: ../../include/name_mask.h
+tls_proxy_client_start_print.o: ../../include/nvtable.h
+tls_proxy_client_start_print.o: ../../include/sock_addr.h
+tls_proxy_client_start_print.o: ../../include/sys_defs.h
+tls_proxy_client_start_print.o: ../../include/vbuf.h
+tls_proxy_client_start_print.o: ../../include/vstream.h
+tls_proxy_client_start_print.o: ../../include/vstring.h
+tls_proxy_client_start_print.o: tls.h
+tls_proxy_client_start_print.o: tls_proxy.h
+tls_proxy_client_start_print.o: tls_proxy_client_start_print.c
+tls_proxy_client_start_scan.o: ../../include/argv.h
+tls_proxy_client_start_scan.o: ../../include/argv_attr.h
+tls_proxy_client_start_scan.o: ../../include/attr.h
+tls_proxy_client_start_scan.o: ../../include/check_arg.h
+tls_proxy_client_start_scan.o: ../../include/dns.h
+tls_proxy_client_start_scan.o: ../../include/htable.h
+tls_proxy_client_start_scan.o: ../../include/myaddrinfo.h
+tls_proxy_client_start_scan.o: ../../include/mymalloc.h
+tls_proxy_client_start_scan.o: ../../include/name_code.h
+tls_proxy_client_start_scan.o: ../../include/name_mask.h
+tls_proxy_client_start_scan.o: ../../include/nvtable.h
+tls_proxy_client_start_scan.o: ../../include/sock_addr.h
+tls_proxy_client_start_scan.o: ../../include/sys_defs.h
+tls_proxy_client_start_scan.o: ../../include/vbuf.h
+tls_proxy_client_start_scan.o: ../../include/vstream.h
+tls_proxy_client_start_scan.o: ../../include/vstring.h
+tls_proxy_client_start_scan.o: tls.h
+tls_proxy_client_start_scan.o: tls_proxy.h
+tls_proxy_client_start_scan.o: tls_proxy_client_start_scan.c
tls_proxy_clnt.o: ../../include/argv.h
tls_proxy_clnt.o: ../../include/attr.h
tls_proxy_clnt.o: ../../include/check_arg.h
tls_proxy_clnt.o: tls.h
tls_proxy_clnt.o: tls_proxy.h
tls_proxy_clnt.o: tls_proxy_clnt.c
-tls_proxy_print.o: ../../include/argv.h
-tls_proxy_print.o: ../../include/attr.h
-tls_proxy_print.o: ../../include/check_arg.h
-tls_proxy_print.o: ../../include/dns.h
-tls_proxy_print.o: ../../include/htable.h
-tls_proxy_print.o: ../../include/iostuff.h
-tls_proxy_print.o: ../../include/mail_proto.h
-tls_proxy_print.o: ../../include/myaddrinfo.h
-tls_proxy_print.o: ../../include/mymalloc.h
-tls_proxy_print.o: ../../include/name_code.h
-tls_proxy_print.o: ../../include/name_mask.h
-tls_proxy_print.o: ../../include/nvtable.h
-tls_proxy_print.o: ../../include/sock_addr.h
-tls_proxy_print.o: ../../include/sys_defs.h
-tls_proxy_print.o: ../../include/vbuf.h
-tls_proxy_print.o: ../../include/vstream.h
-tls_proxy_print.o: ../../include/vstring.h
-tls_proxy_print.o: tls.h
-tls_proxy_print.o: tls_proxy.h
-tls_proxy_print.o: tls_proxy_print.c
-tls_proxy_scan.o: ../../include/argv.h
-tls_proxy_scan.o: ../../include/attr.h
-tls_proxy_scan.o: ../../include/check_arg.h
-tls_proxy_scan.o: ../../include/dns.h
-tls_proxy_scan.o: ../../include/htable.h
-tls_proxy_scan.o: ../../include/iostuff.h
-tls_proxy_scan.o: ../../include/mail_proto.h
-tls_proxy_scan.o: ../../include/myaddrinfo.h
-tls_proxy_scan.o: ../../include/mymalloc.h
-tls_proxy_scan.o: ../../include/name_code.h
-tls_proxy_scan.o: ../../include/name_mask.h
-tls_proxy_scan.o: ../../include/nvtable.h
-tls_proxy_scan.o: ../../include/sock_addr.h
-tls_proxy_scan.o: ../../include/sys_defs.h
-tls_proxy_scan.o: ../../include/vbuf.h
-tls_proxy_scan.o: ../../include/vstream.h
-tls_proxy_scan.o: ../../include/vstring.h
-tls_proxy_scan.o: tls.h
-tls_proxy_scan.o: tls_proxy.h
-tls_proxy_scan.o: tls_proxy_scan.c
+tls_proxy_context_print.o: ../../include/argv.h
+tls_proxy_context_print.o: ../../include/attr.h
+tls_proxy_context_print.o: ../../include/check_arg.h
+tls_proxy_context_print.o: ../../include/dns.h
+tls_proxy_context_print.o: ../../include/htable.h
+tls_proxy_context_print.o: ../../include/myaddrinfo.h
+tls_proxy_context_print.o: ../../include/mymalloc.h
+tls_proxy_context_print.o: ../../include/name_code.h
+tls_proxy_context_print.o: ../../include/name_mask.h
+tls_proxy_context_print.o: ../../include/nvtable.h
+tls_proxy_context_print.o: ../../include/sock_addr.h
+tls_proxy_context_print.o: ../../include/sys_defs.h
+tls_proxy_context_print.o: ../../include/vbuf.h
+tls_proxy_context_print.o: ../../include/vstream.h
+tls_proxy_context_print.o: ../../include/vstring.h
+tls_proxy_context_print.o: tls.h
+tls_proxy_context_print.o: tls_proxy.h
+tls_proxy_context_print.o: tls_proxy_context_print.c
+tls_proxy_context_scan.o: ../../include/argv.h
+tls_proxy_context_scan.o: ../../include/attr.h
+tls_proxy_context_scan.o: ../../include/check_arg.h
+tls_proxy_context_scan.o: ../../include/dns.h
+tls_proxy_context_scan.o: ../../include/htable.h
+tls_proxy_context_scan.o: ../../include/myaddrinfo.h
+tls_proxy_context_scan.o: ../../include/mymalloc.h
+tls_proxy_context_scan.o: ../../include/name_code.h
+tls_proxy_context_scan.o: ../../include/name_mask.h
+tls_proxy_context_scan.o: ../../include/nvtable.h
+tls_proxy_context_scan.o: ../../include/sock_addr.h
+tls_proxy_context_scan.o: ../../include/sys_defs.h
+tls_proxy_context_scan.o: ../../include/vbuf.h
+tls_proxy_context_scan.o: ../../include/vstream.h
+tls_proxy_context_scan.o: ../../include/vstring.h
+tls_proxy_context_scan.o: tls.h
+tls_proxy_context_scan.o: tls_proxy.h
+tls_proxy_context_scan.o: tls_proxy_context_scan.c
+tls_proxy_server_init_print.o: ../../include/argv.h
+tls_proxy_server_init_print.o: ../../include/attr.h
+tls_proxy_server_init_print.o: ../../include/check_arg.h
+tls_proxy_server_init_print.o: ../../include/dns.h
+tls_proxy_server_init_print.o: ../../include/htable.h
+tls_proxy_server_init_print.o: ../../include/myaddrinfo.h
+tls_proxy_server_init_print.o: ../../include/mymalloc.h
+tls_proxy_server_init_print.o: ../../include/name_code.h
+tls_proxy_server_init_print.o: ../../include/name_mask.h
+tls_proxy_server_init_print.o: ../../include/nvtable.h
+tls_proxy_server_init_print.o: ../../include/sock_addr.h
+tls_proxy_server_init_print.o: ../../include/sys_defs.h
+tls_proxy_server_init_print.o: ../../include/vbuf.h
+tls_proxy_server_init_print.o: ../../include/vstream.h
+tls_proxy_server_init_print.o: ../../include/vstring.h
+tls_proxy_server_init_print.o: tls.h
+tls_proxy_server_init_print.o: tls_proxy.h
+tls_proxy_server_init_print.o: tls_proxy_server_init_print.c
+tls_proxy_server_init_scan.o: ../../include/argv.h
+tls_proxy_server_init_scan.o: ../../include/attr.h
+tls_proxy_server_init_scan.o: ../../include/check_arg.h
+tls_proxy_server_init_scan.o: ../../include/dns.h
+tls_proxy_server_init_scan.o: ../../include/htable.h
+tls_proxy_server_init_scan.o: ../../include/myaddrinfo.h
+tls_proxy_server_init_scan.o: ../../include/mymalloc.h
+tls_proxy_server_init_scan.o: ../../include/name_code.h
+tls_proxy_server_init_scan.o: ../../include/name_mask.h
+tls_proxy_server_init_scan.o: ../../include/nvtable.h
+tls_proxy_server_init_scan.o: ../../include/sock_addr.h
+tls_proxy_server_init_scan.o: ../../include/sys_defs.h
+tls_proxy_server_init_scan.o: ../../include/vbuf.h
+tls_proxy_server_init_scan.o: ../../include/vstream.h
+tls_proxy_server_init_scan.o: ../../include/vstring.h
+tls_proxy_server_init_scan.o: tls.h
+tls_proxy_server_init_scan.o: tls_proxy.h
+tls_proxy_server_init_scan.o: tls_proxy_server_init_scan.c
+tls_proxy_server_start_print.o: ../../include/argv.h
+tls_proxy_server_start_print.o: ../../include/attr.h
+tls_proxy_server_start_print.o: ../../include/check_arg.h
+tls_proxy_server_start_print.o: ../../include/dns.h
+tls_proxy_server_start_print.o: ../../include/htable.h
+tls_proxy_server_start_print.o: ../../include/myaddrinfo.h
+tls_proxy_server_start_print.o: ../../include/mymalloc.h
+tls_proxy_server_start_print.o: ../../include/name_code.h
+tls_proxy_server_start_print.o: ../../include/name_mask.h
+tls_proxy_server_start_print.o: ../../include/nvtable.h
+tls_proxy_server_start_print.o: ../../include/sock_addr.h
+tls_proxy_server_start_print.o: ../../include/sys_defs.h
+tls_proxy_server_start_print.o: ../../include/vbuf.h
+tls_proxy_server_start_print.o: ../../include/vstream.h
+tls_proxy_server_start_print.o: ../../include/vstring.h
+tls_proxy_server_start_print.o: tls.h
+tls_proxy_server_start_print.o: tls_proxy.h
+tls_proxy_server_start_print.o: tls_proxy_server_start_print.c
+tls_proxy_server_start_scan.o: ../../include/argv.h
+tls_proxy_server_start_scan.o: ../../include/attr.h
+tls_proxy_server_start_scan.o: ../../include/check_arg.h
+tls_proxy_server_start_scan.o: ../../include/dns.h
+tls_proxy_server_start_scan.o: ../../include/htable.h
+tls_proxy_server_start_scan.o: ../../include/myaddrinfo.h
+tls_proxy_server_start_scan.o: ../../include/mymalloc.h
+tls_proxy_server_start_scan.o: ../../include/name_code.h
+tls_proxy_server_start_scan.o: ../../include/name_mask.h
+tls_proxy_server_start_scan.o: ../../include/nvtable.h
+tls_proxy_server_start_scan.o: ../../include/sock_addr.h
+tls_proxy_server_start_scan.o: ../../include/sys_defs.h
+tls_proxy_server_start_scan.o: ../../include/vbuf.h
+tls_proxy_server_start_scan.o: ../../include/vstream.h
+tls_proxy_server_start_scan.o: ../../include/vstring.h
+tls_proxy_server_start_scan.o: tls.h
+tls_proxy_server_start_scan.o: tls_proxy.h
+tls_proxy_server_start_scan.o: tls_proxy_server_start_scan.c
tls_rsa.o: ../../include/argv.h
tls_rsa.o: ../../include/check_arg.h
tls_rsa.o: ../../include/dns.h
typedef struct {
TLS_APPL_STATE *ctx;
VSTREAM *stream;
+ int fd; /* Event-driven file descriptor */
int timeout;
int tls_level; /* Security level */
const char *nexthop; /* destination domain */
extern TLS_APPL_STATE *tls_client_init(const TLS_CLIENT_INIT_PROPS *);
extern TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *);
+extern TLS_SESS_STATE *tls_client_post_connect(TLS_SESS_STATE *,
+ const TLS_CLIENT_START_PROPS *);
#define tls_client_stop(ctx, stream, timeout, failure, TLScontext) \
tls_session_stop(ctx, (stream), (timeout), (failure), (TLScontext))
((props)->a12), ((props)->a13), (props)))
#define TLS_CLIENT_START(props, a1, a2, a3, a4, a5, a6, a7, a8, a9, \
- a10, a11, a12, a13, a14, a15) \
+ a10, a11, a12, a13, a14, a15, a16) \
tls_client_start((((props)->a1), ((props)->a2), ((props)->a3), \
((props)->a4), ((props)->a5), ((props)->a6), ((props)->a7), \
((props)->a8), ((props)->a9), ((props)->a10), ((props)->a11), \
- ((props)->a12), ((props)->a13), ((props)->a14), ((props)->a15), (props)))
+ ((props)->a12), ((props)->a13), ((props)->a14), ((props)->a15), \
+ ((props)->a16), (props)))
/*
* tls_server.c
/* TLS_SESS_STATE *tls_client_start(start_props)
/* const TLS_CLIENT_START_PROPS *start_props;
/*
+/* TLS_SESS_STATE *tls_client_post_connect(TLScontext, start_props)
+/* TLS_SESS_STATE *TLScontext;
+/* const TLS_CLIENT_START_PROPS *start_props;
+/*
/* void tls_client_stop(app_ctx, stream, failure, TLScontext)
/* TLS_APPL_STATE *app_ctx;
/* VSTREAM *stream;
/* the fingerprint of the certificate.
/* .PP
/* If no peer certificate is presented the peer_status is set to 0.
+/* EVENT_DRIVEN APPLICATIONS
+/* .ad
+/* .fi
+/* Event-driven programs manage multiple I/O channels. Such
+/* programs cannot use the synchronous VSTREAM-over-TLS
+/* implementation that the current TLS library provides,
+/* including tls_client_stop() and the underlying tls_stream(3)
+/* and tls_bio_ops(3) routines.
+/*
+/* With the current TLS library implementation, this means
+/* that an event-driven application is responsible for calling
+/* and retrying SSL_connect(), SSL_read(), SSL_write() and
+/* SSL_shutdown().
+/*
+/* To maintain control over TLS I/O, an event-driven client
+/* invokes tls_client_start() with a null VSTREAM argument and
+/* with an fd argument that specifies the I/O file descriptor.
+/* Then, tls_client_start() performs all the necessary
+/* preparations before the TLS handshake and returns a partially
+/* populated TLS context. The event-driven application is then
+/* responsible for invoking SSL_connect(), and if successful,
+/* for invoking tls_client_post_connect() to finish the work
+/* that was started by tls_client_start(). In case of unrecoverable
+/* failure, tls_client_post_connect() destroys the TLS context
+/* and returns a null pointer value.
/* LICENSE
/* .ad
/* .fi
int protomask;
const char *cipher_list;
SSL_SESSION *session = 0;
- SSL_CIPHER_const SSL_CIPHER *cipher;
- X509 *peercert;
TLS_SESS_STATE *TLScontext;
TLS_APPL_STATE *app_ctx = props->ctx;
char *myserverid;
/*
* Connect the SSL connection with the network socket.
*/
- if (SSL_set_fd(TLScontext->con, vstream_fileno(props->stream)) != 1) {
+ if (SSL_set_fd(TLScontext->con, props->stream == 0 ? props->fd :
+ vstream_fileno(props->stream)) != 1) {
msg_info("SSL_set_fd error to %s", props->namaddr);
tls_print_errors();
uncache_session(app_ctx->ssl_ctx, TLScontext);
return (0);
}
- /*
- * Turn on non-blocking I/O so that we can enforce timeouts on network
- * I/O.
- */
- non_blocking(vstream_fileno(props->stream), NON_BLOCKING);
-
/*
* If the debug level selected is high enough, all of the data is dumped:
* TLS_LOG_TLSPKTS will dump the SSL negotiation, TLS_LOG_ALLPKTS will
tls_dane_set_callback(app_ctx->ssl_ctx, TLScontext);
+ /*
+ * If we don't trigger the handshake in the library, leave control over
+ * SSL_connect/read/write/etc with the application.
+ */
+ if (props->stream == 0)
+ return (TLScontext);
+
+ /*
+ * Turn on non-blocking I/O so that we can enforce timeouts on network
+ * I/O.
+ */
+ non_blocking(vstream_fileno(props->stream), NON_BLOCKING);
+
/*
* Start TLS negotiations. This process is a black box that invokes our
* call-backs for certificate verification.
tls_free_context(TLScontext);
return (0);
}
+ return (tls_client_post_connect(TLScontext, props));
+}
+
+/* tls_client_post_connect - post-handshake processing */
+
+TLS_SESS_STATE *tls_client_post_connect(TLS_SESS_STATE *TLScontext,
+ const TLS_CLIENT_START_PROPS *props)
+{
+ SSL_CIPHER_const SSL_CIPHER *cipher;
+ X509 *peercert;
+
/* Turn off packet dump if only dumping the handshake */
- if ((log_mask & TLS_LOG_ALLPKTS) == 0)
+ if ((TLScontext->log_mask & TLS_LOG_ALLPKTS) == 0)
BIO_set_callback(SSL_get_rbio(TLScontext->con), 0);
/*
* session was negotiated.
*/
TLScontext->session_reused = SSL_session_reused(TLScontext->con);
- if ((log_mask & TLS_LOG_CACHE) && TLScontext->session_reused)
+ if ((TLScontext->log_mask & TLS_LOG_CACHE) && TLScontext->session_reused)
msg_info("%s: Reusing old session", TLScontext->namaddr);
/*
* The TLS engine is active. Switch to the tls_timed_read/write()
* functions and make the TLScontext available to those functions.
*/
- tls_stream_start(props->stream, TLScontext);
+ if (TLScontext->stream != 0)
+ tls_stream_start(props->stream, TLScontext);
/*
* Fully secured only if trusted, matched and not insecure like halfdane.
/*
* All the key facts in a single log entry.
*/
- if (log_mask & TLS_LOG_SUMMARY)
+ if (TLScontext->log_mask & TLS_LOG_SUMMARY)
msg_info("%s TLS connection established to %s: %s with cipher %s "
"(%d/%d bits)",
!TLS_CERT_IS_PRESENT(TLScontext) ? "Anonymous" :
#ifdef USE_TLS
+#define tls_proxy_legacy_open(service, flags, peer_stream, peer_addr, \
+ peer_port, timeout, serverid) \
+ tls_proxy_open((service), (flags), (peer_stream), (peer_addr), \
+ (peer_port), (timeout), (serverid), (void *) 0, (void *) 0)
+
extern VSTREAM *tls_proxy_open(const char *, int, VSTREAM *, const char *,
- const char *, int);
+ const char *, int, const char *,
+ void *, void *);
+
+#define TLS_PROXY_CLIENT_INIT_PROPS(props, a1, a2, a3, a4, a5, a6, a7, a8, \
+ a9, a10, a11, a12, a13) \
+ (((props)->a1), ((props)->a2), ((props)->a3), \
+ ((props)->a4), ((props)->a5), ((props)->a6), ((props)->a7), \
+ ((props)->a8), ((props)->a9), ((props)->a10), ((props)->a11), \
+ ((props)->a12), ((props)->a13))
+
+#define TLS_PROXY_CLIENT_START_PROPS(props, a1, a2, a3, a4, a5, a6, a7, a8, \
+ a9, a10, a11, a12) \
+ (((props)->a1), ((props)->a2), ((props)->a3), \
+ ((props)->a4), ((props)->a5), ((props)->a6), ((props)->a7), \
+ ((props)->a8), ((props)->a9), ((props)->a10), ((props)->a11), \
+ ((props)->a12))
+
extern TLS_SESS_STATE *tls_proxy_context_receive(VSTREAM *);
extern void tls_proxy_context_free(TLS_SESS_STATE *);
extern int tls_proxy_context_print(ATTR_PRINT_MASTER_FN, VSTREAM *, int, void *);
extern int tls_proxy_context_scan(ATTR_SCAN_MASTER_FN, VSTREAM *, int, void *);
+extern int tls_proxy_client_init_print(ATTR_PRINT_MASTER_FN, VSTREAM *, int, void *);
+extern int tls_proxy_client_init_scan(ATTR_SCAN_MASTER_FN, VSTREAM *, int, void *);
+extern void tls_proxy_client_init_free(TLS_CLIENT_INIT_PROPS *);
+extern char *tls_proxy_client_init_to_string(VSTRING *, TLS_CLIENT_INIT_PROPS *);
+
+extern int tls_proxy_client_start_print(ATTR_PRINT_MASTER_FN, VSTREAM *, int, void *);
+extern int tls_proxy_client_start_scan(ATTR_SCAN_MASTER_FN, VSTREAM *, int, void *);
+extern void tls_proxy_client_start_free(TLS_CLIENT_START_PROPS *);
+
+extern int tls_proxy_server_init_print(ATTR_PRINT_MASTER_FN, VSTREAM *, int, void *);
+extern int tls_proxy_server_init_scan(ATTR_SCAN_MASTER_FN, VSTREAM *, int, void *);
+extern void tls_proxy_server_init_free(TLS_SERVER_INIT_PROPS *);
+
+extern int tls_proxy_server_start_print(ATTR_PRINT_MASTER_FN, VSTREAM *, int, void *);
+extern int tls_proxy_server_start_scan(ATTR_SCAN_MASTER_FN, VSTREAM *, int, void *);
+extern void tls_proxy_server_start_free(TLS_SERVER_START_PROPS *);
+
+ /*
+ * TLSPROXY attributes
+ */
+#define TLS_ATTR_REMOTE_ENDPT "remote_endpoint" /* name[addr]:port */
+#define TLS_ATTR_FLAGS "flags"
+#define TLS_ATTR_TIMEOUT "timeout"
+#define TLS_ATTR_SERVERID "serverid"
+
+ /*
+ * TLS_SESS_STATE attributes.
+ */
+#define TLS_ATTR_PEER_CN "peer_CN"
+#define TLS_ATTR_ISSUER_CN "issuer_CN"
+#define TLS_ATTR_PEER_CERT_FPT "peer_fingerprint"
+#define TLS_ATTR_PEER_PKEY_FPT "peer_pubkey_fingerprint"
+#define TLS_ATTR_PEER_STATUS "peer_status"
+#define TLS_ATTR_CIPHER_PROTOCOL "cipher_protocol"
+#define TLS_ATTR_CIPHER_NAME "cipher_name"
+#define TLS_ATTR_CIPHER_USEBITS "cipher_usebits"
+#define TLS_ATTR_CIPHER_ALGBITS "cipher_algbits"
+
+ /*
+ * TLS_SERVER_INIT_PROPS attributes.
+ */
+#define TLS_ATTR_LOG_PARAM "log_param"
+#define TLS_ATTR_LOG_LEVEL "log_level"
+#define TLS_ATTR_VERIFYDEPTH "verifydepth"
+#define TLS_ATTR_CACHE_TYPE "cache_type"
+#define TLS_ATTR_SET_SESSID "set_sessid"
+#define TLS_ATTR_CERT_FILE "cert_file"
+#define TLS_ATTR_KEY_FILE "key_file"
+#define TLS_ATTR_DCERT_FILE "dcert_file"
+#define TLS_ATTR_DKEY_FILE "dkey_file"
+#define TLS_ATTR_ECCERT_FILE "eccert_file"
+#define TLS_ATTR_ECKEY_FILE "eckey_file"
+#define TLS_ATTR_CAFILE "CAfile"
+#define TLS_ATTR_CAPATH "CApath"
+#define TLS_ATTR_PROTOCOLS "protocols"
+#define TLS_ATTR_EECDH_GRADE "eecdh_grade"
+#define TLS_ATTR_DH1K_PARAM_FILE "dh1024_param_file"
+#define TLS_ATTR_DH512_PARAM_FILE "dh512_param_file"
+#define TLS_ATTR_ASK_CCERT "ask_ccert"
+#define TLS_ATTR_MDALG "mdalg"
+
+ /*
+ * TLS_SERVER_START_PROPS attributes.
+ */
+#define TLS_ATTR_TIMEOUT "timeout"
+#define TLS_ATTR_REQUIRECERT "requirecert"
+#define TLS_ATTR_SERVERID "serverid"
+#define TLS_ATTR_NAMADDR "namaddr"
+#define TLS_ATTR_CIPHER_GRADE "cipher_grade"
+#define TLS_ATTR_CIPHER_EXCLUSIONS "cipher_exclusions"
+#define TLS_ATTR_MDALG "mdalg"
+
+ /*
+ * TLS_CLIENT_INIT_PROPS attributes.
+ */
+#define TLS_ATTR_LOG_PARAM "log_param"
+#define TLS_ATTR_LOG_LEVEL "log_level"
+#define TLS_ATTR_VERIFYDEPTH "verifydepth"
+#define TLS_ATTR_CACHE_TYPE "cache_type"
+#define TLS_ATTR_CERT_FILE "cert_file"
+#define TLS_ATTR_KEY_FILE "key_file"
+#define TLS_ATTR_DCERT_FILE "dcert_file"
+#define TLS_ATTR_DKEY_FILE "dkey_file"
+#define TLS_ATTR_ECCERT_FILE "eccert_file"
+#define TLS_ATTR_ECKEY_FILE "eckey_file"
+#define TLS_ATTR_CAFILE "CAfile"
+#define TLS_ATTR_CAPATH "CApath"
+#define TLS_ATTR_MDALG "mdalg"
+
+ /*
+ * TLS_CLIENT_START_PROPS attributes.
+ */
+#define TLS_ATTR_TIMEOUT "timeout"
+#define TLS_ATTR_TLS_LEVEL "tls_level"
+#define TLS_ATTR_NEXTHOP "nexthop"
+#define TLS_ATTR_HOST "host"
+#define TLS_ATTR_NAMADDR "namaddr"
+#define TLS_ATTR_SERVERID "serverid"
+#define TLS_ATTR_HELO "helo"
+#define TLS_ATTR_PROTOCOLS "protocols"
+#define TLS_ATTR_CIPHER_GRADE "cipher_grade"
+#define TLS_ATTR_CIPHER_EXCLUSIONS "cipher_exclusions"
+#define TLS_ATTR_MATCHARGV "matchargv"
+#define TLS_ATTR_MDALG "mdalg"
+
#endif
/* LICENSE
--- /dev/null
+/*++
+/* NAME
+/* tls_proxy_client_init_print.c
+/* SUMMARY
+/* write TLS_CLIENT_INIT_PROPS structure to stream
+/* SYNOPSIS
+/* #include <tls_proxy.h>
+/*
+/* int tls_proxy_client_init_print(print_fn, stream, flags, ptr)
+/* ATTR_PRINT_MASTER_FN print_fn;
+/* VSTREAM *stream;
+/* int flags;
+/* void *ptr;
+/* DESCRIPTION
+/* tls_proxy_client_init_print() writes a full TLS_CLIENT_INIT_PROPS
+/* structure to the named stream using the specified attribute
+/* print routine. tls_proxy_client_init_print() is meant to
+/* be passed as a call-back to attr_print(), thusly:
+/*
+/* SEND_ATTR_FUNC(tls_proxy_client_init_print, (void *) tls_context), ...
+/* DIAGNOSTICS
+/* Fatal: out of memory.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
+
+#ifdef USE_TLS
+
+/* System library. */
+
+#include <sys_defs.h>
+
+/* Utility library */
+
+#include <attr.h>
+
+/* TLS library. */
+
+#include <tls.h>
+#include <tls_proxy.h>
+
+/* tls_proxy_client_init_print - send TLS_CLIENT_INIT_PROPS over stream */
+
+int tls_proxy_client_init_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp,
+ int flags, void *ptr)
+{
+ TLS_CLIENT_INIT_PROPS *props = (TLS_CLIENT_INIT_PROPS *) ptr;
+ int ret;
+
+#define STRING_OR_EMPTY(s) ((s) ? (s) : "")
+
+ ret = print_fn(fp, flags | ATTR_FLAG_MORE,
+ SEND_ATTR_STR(TLS_ATTR_LOG_PARAM,
+ STRING_OR_EMPTY(props->log_param)),
+ SEND_ATTR_STR(TLS_ATTR_LOG_LEVEL,
+ STRING_OR_EMPTY(props->log_level)),
+ SEND_ATTR_INT(TLS_ATTR_VERIFYDEPTH, props->verifydepth),
+ SEND_ATTR_STR(TLS_ATTR_CACHE_TYPE,
+ STRING_OR_EMPTY(props->cache_type)),
+ SEND_ATTR_STR(TLS_ATTR_CERT_FILE,
+ STRING_OR_EMPTY(props->cert_file)),
+ SEND_ATTR_STR(TLS_ATTR_KEY_FILE,
+ STRING_OR_EMPTY(props->key_file)),
+ SEND_ATTR_STR(TLS_ATTR_DCERT_FILE,
+ STRING_OR_EMPTY(props->dcert_file)),
+ SEND_ATTR_STR(TLS_ATTR_DKEY_FILE,
+ STRING_OR_EMPTY(props->dkey_file)),
+ SEND_ATTR_STR(TLS_ATTR_ECCERT_FILE,
+ STRING_OR_EMPTY(props->eccert_file)),
+ SEND_ATTR_STR(TLS_ATTR_ECKEY_FILE,
+ STRING_OR_EMPTY(props->eckey_file)),
+ SEND_ATTR_STR(TLS_ATTR_CAFILE,
+ STRING_OR_EMPTY(props->CAfile)),
+ SEND_ATTR_STR(TLS_ATTR_CAPATH,
+ STRING_OR_EMPTY(props->CApath)),
+ SEND_ATTR_STR(TLS_ATTR_MDALG,
+ STRING_OR_EMPTY(props->mdalg)),
+ ATTR_TYPE_END);
+ /* Do not flush the stream. */
+ return (ret);
+}
+
+#endif
--- /dev/null
+/*++
+/* NAME
+/* tls_proxy_client_init_scan
+/* SUMMARY
+/* read TLS_CLIENT_INIT_PROPS from stream
+/* SYNOPSIS
+/* #include <tls_proxy.h>
+/*
+/* int tls_proxy_client_init_scan(scan_fn, stream, flags, ptr)
+/* ATTR_SCAN_MASTER_FN scan_fn;
+/* VSTREAM *stream;
+/* int flags;
+/* void *ptr;
+/*
+/* char *tls_proxy_client_init_to_string(buf, props)
+/* VSTRING *buf;
+/* TLS_CLIENT_INIT_PROPS *props;
+/*
+/* void tls_proxy_client_init_free(props)
+/* TLS_CLIENT_INIT_PROPS *props;
+/* DESCRIPTION
+/* tls_proxy_client_init_scan() reads a full TLS_CLIENT_INIT_PROPS
+/* structure from the named stream using the specified attribute
+/* scan routine. tls_proxy_client_init_scan() is meant to be passed
+/* as a call-back function to attr_scan(), as shown below.
+/*
+/* tls_proxy_client_init_to_string() produces a lookup key
+/* that is unique for the properties received by
+/* tls_proxy_client_init_scan().
+/*
+/* tls_proxy_client_init_free() destroys a TLS_CLIENT_INIT_PROPS
+/* structure that was created by tls_proxy_client_init_scan().
+/* This must be called even if the tls_proxy_client_init_scan()
+/* call returned an error.
+/*
+/* TLS_CLIENT_INIT_PROPS *props = 0;
+/* ...
+/* ... RECV_ATTR_FUNC(tls_proxy_client_init_scan, (void *) &props), ...
+/* ...
+/* if (props != 0)
+/* tls_proxy_client_init_free(props);
+/* DIAGNOSTICS
+/* Fatal: out of memory.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
+
+#ifdef USE_TLS
+
+/* System library. */
+
+#include <sys_defs.h>
+
+/* Utility library */
+
+#include <attr.h>
+#include <vstring.h>
+
+/* TLS library. */
+
+#include <tls.h>
+#include <tls_proxy.h>
+
+/* tls_proxy_client_init_scan - receive TLS_CLIENT_INIT_PROPS from stream */
+
+int tls_proxy_client_init_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp,
+ int flags, void *ptr)
+{
+ TLS_CLIENT_INIT_PROPS *props
+ = (TLS_CLIENT_INIT_PROPS *) mymalloc(sizeof(*props));
+ int ret;
+ VSTRING *log_param = vstring_alloc(25);
+ VSTRING *log_level = vstring_alloc(25);
+ VSTRING *cache_type = vstring_alloc(25);
+ VSTRING *cert_file = vstring_alloc(25);
+ VSTRING *key_file = vstring_alloc(25);
+ VSTRING *dcert_file = vstring_alloc(25);
+ VSTRING *dkey_file = vstring_alloc(25);
+ VSTRING *eccert_file = vstring_alloc(25);
+ VSTRING *eckey_file = vstring_alloc(25);
+ VSTRING *CAfile = vstring_alloc(25);
+ VSTRING *CApath = vstring_alloc(25);
+ VSTRING *mdalg = vstring_alloc(25);
+
+ /*
+ * Note: memset() is not a portable way to initialize non-integer types.
+ */
+ memset(props, 0, sizeof(*props));
+ ret = scan_fn(fp, flags | ATTR_FLAG_MORE,
+ RECV_ATTR_STR(TLS_ATTR_LOG_PARAM, log_param),
+ RECV_ATTR_STR(TLS_ATTR_LOG_LEVEL, log_level),
+ RECV_ATTR_INT(TLS_ATTR_VERIFYDEPTH, &props->verifydepth),
+ RECV_ATTR_STR(TLS_ATTR_CACHE_TYPE, cache_type),
+ RECV_ATTR_STR(TLS_ATTR_CERT_FILE, cert_file),
+ RECV_ATTR_STR(TLS_ATTR_KEY_FILE, key_file),
+ RECV_ATTR_STR(TLS_ATTR_DCERT_FILE, dcert_file),
+ RECV_ATTR_STR(TLS_ATTR_DKEY_FILE, dkey_file),
+ RECV_ATTR_STR(TLS_ATTR_ECCERT_FILE, eccert_file),
+ RECV_ATTR_STR(TLS_ATTR_ECKEY_FILE, eckey_file),
+ RECV_ATTR_STR(TLS_ATTR_CAFILE, CAfile),
+ RECV_ATTR_STR(TLS_ATTR_CAPATH, CApath),
+ RECV_ATTR_STR(TLS_ATTR_MDALG, mdalg),
+ ATTR_TYPE_END);
+ props->log_param = vstring_export(log_param);
+ props->log_level = vstring_export(log_level);
+ props->cache_type = vstring_export(cache_type);
+ props->cert_file = vstring_export(cert_file);
+ props->key_file = vstring_export(key_file);
+ props->dcert_file = vstring_export(dcert_file);
+ props->dkey_file = vstring_export(dkey_file);
+ props->eccert_file = vstring_export(eccert_file);
+ props->eckey_file = vstring_export(eckey_file);
+ props->CAfile = vstring_export(CAfile);
+ props->CApath = vstring_export(CApath);
+ props->mdalg = vstring_export(mdalg);
+ *(TLS_CLIENT_INIT_PROPS **) ptr = props;
+ return (ret == 13 ? 1 : -1);
+}
+
+/* tls_proxy_client_init_to_string - serialize to string */
+
+char *tls_proxy_client_init_to_string(VSTRING *buf,
+ TLS_CLIENT_INIT_PROPS *props)
+{
+ vstring_sprintf(buf, "%s\n%s\n%d\n%s\n%s\n%s\n%s\n%s\n"
+ "%s\n%s\n%s\n%s\n%s\n", props->log_param,
+ props->log_level, props->verifydepth,
+ props->cache_type, props->cert_file, props->key_file,
+ props->dcert_file, props->dkey_file,
+ props->eccert_file, props->eckey_file,
+ props->CAfile, props->CApath, props->mdalg);
+ return (vstring_str(buf));
+}
+
+/* tls_proxy_client_init_free - destroy TLS_CLIENT_INIT_PROPS structure */
+
+void tls_proxy_client_init_free(TLS_CLIENT_INIT_PROPS *props)
+{
+ myfree((void *) props->log_param);
+ myfree((void *) props->log_level);
+ myfree((void *) props->cache_type);
+ myfree((void *) props->cert_file);
+ myfree((void *) props->key_file);
+ myfree((void *) props->dcert_file);
+ myfree((void *) props->dkey_file);
+ myfree((void *) props->eccert_file);
+ myfree((void *) props->eckey_file);
+ myfree((void *) props->CAfile);
+ myfree((void *) props->CApath);
+ myfree((void *) props->mdalg);
+ myfree((void *) props);
+}
+
+#endif
--- /dev/null
+/*++
+/* NAME
+/* tls_proxy_client_start_print.c
+/* SUMMARY
+/* write TLS_CLIENT_START_PROPS structure to stream
+/* SYNOPSIS
+/* #include <tls_proxy.h>
+/*
+/* int tls_proxy_client_start_print(print_fn, stream, flags, ptr)
+/* ATTR_PRINT_MASTER_FN print_fn;
+/* VSTREAM *stream;
+/* int flags;
+/* void *ptr;
+/* DESCRIPTION
+/* tls_proxy_client_start_print() writes a TLS_CLIENT_START_PROPS
+/* structure, without stream or file descriptor members, to
+/* the named stream using the specified attribute print routine.
+/* tls_proxy_client_start_print() is meant to be passed as a
+/* call-back to attr_print(), thusly:
+/*
+/* SEND_ATTR_FUNC(tls_proxy_client_start_print, (void *) props), ...
+/* DIAGNOSTICS
+/* Fatal: out of memory.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
+
+#ifdef USE_TLS
+
+/* System library. */
+
+#include <sys_defs.h>
+
+/* Utility library */
+
+#include <argv_attr.h>
+#include <attr.h>
+
+/* TLS library. */
+
+#include <tls.h>
+#include <tls_proxy.h>
+
+/* tls_proxy_client_start_print - send TLS_CLIENT_START_PROPS over stream */
+
+int tls_proxy_client_start_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp,
+ int flags, void *ptr)
+{
+ TLS_CLIENT_START_PROPS *props = (TLS_CLIENT_START_PROPS *) ptr;
+ int ret;
+
+#define STRING_OR_EMPTY(s) ((s) ? (s) : "")
+
+ ret = print_fn(fp, flags | ATTR_FLAG_MORE,
+ SEND_ATTR_INT(TLS_ATTR_TIMEOUT, props->timeout),
+ SEND_ATTR_INT(TLS_ATTR_TLS_LEVEL, props->tls_level),
+ SEND_ATTR_STR(TLS_ATTR_NEXTHOP,
+ STRING_OR_EMPTY(props->nexthop)),
+ SEND_ATTR_STR(TLS_ATTR_HOST,
+ STRING_OR_EMPTY(props->host)),
+ SEND_ATTR_STR(TLS_ATTR_NAMADDR,
+ STRING_OR_EMPTY(props->namaddr)),
+ SEND_ATTR_STR(TLS_ATTR_SERVERID,
+ STRING_OR_EMPTY(props->serverid)),
+ SEND_ATTR_STR(TLS_ATTR_HELO,
+ STRING_OR_EMPTY(props->helo)),
+ SEND_ATTR_STR(TLS_ATTR_PROTOCOLS,
+ STRING_OR_EMPTY(props->protocols)),
+ SEND_ATTR_STR(TLS_ATTR_CIPHER_GRADE,
+ STRING_OR_EMPTY(props->cipher_grade)),
+ SEND_ATTR_STR(TLS_ATTR_CIPHER_EXCLUSIONS,
+ STRING_OR_EMPTY(props->cipher_exclusions)),
+ SEND_ATTR_FUNC(argv_attr_print, (void *) props->matchargv),
+ SEND_ATTR_STR(TLS_ATTR_MDALG,
+ STRING_OR_EMPTY(props->mdalg)),
+ /* TODO: DANE. */
+ ATTR_TYPE_END);
+ /* Do not flush the stream. */
+ return (ret);
+}
+
+#endif
--- /dev/null
+/*++
+/* NAME
+/* tls_proxy_client_start_scan
+/* SUMMARY
+/* read TLS_CLIENT_START_PROPS from stream
+/* SYNOPSIS
+/* #include <tls_proxy.h>
+/*
+/* int tls_proxy_client_start_scan(scan_fn, stream, flags, ptr)
+/* ATTR_SCAN_MASTER_FN scan_fn;
+/* VSTREAM *stream;
+/* int flags;
+/* void *ptr;
+/*
+/* void tls_proxy_client_start_free(props)
+/* TLS_CLIENT_START_PROPS *props;
+/* DESCRIPTION
+/* tls_proxy_client_start_scan() reads a TLS_CLIENT_START_PROPS
+/* structure, without the stream of file descriptor members,
+/* from the named stream using the specified attribute scan
+/* routine. tls_proxy_client_start_scan() is meant to be passed
+/* as a call-back function to attr_scan(), as shown below.
+/*
+/* tls_proxy_client_start_free() destroys a TLS_CLIENT_START_PROPS
+/* structure that was created by tls_proxy_client_start_scan().
+/* This must be called even if the tls_proxy_client_start_scan()
+/* call returned an error.
+/*
+/* TLS_CLIENT_START_PROPS *props = 0;
+/* ...
+/* ... RECV_ATTR_FUNC(tls_proxy_client_start_scan, (void *) &props), ...
+/* ...
+/* if (props != 0)
+/* tls_proxy_client_start_free(props);
+/* DIAGNOSTICS
+/* Fatal: out of memory.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
+
+#ifdef USE_TLS
+
+/* System library. */
+
+#include <sys_defs.h>
+
+/* Utility library */
+
+#include <argv_attr.h>
+#include <attr.h>
+
+/* TLS library. */
+
+#include <tls.h>
+#include <tls_proxy.h>
+
+/* tls_proxy_client_start_scan - receive TLS_CLIENT_START_PROPS from stream */
+
+int tls_proxy_client_start_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp,
+ int flags, void *ptr)
+{
+ TLS_CLIENT_START_PROPS *props
+ = (TLS_CLIENT_START_PROPS *) mymalloc(sizeof(*props));
+ int ret;
+ VSTRING *nexthop = vstring_alloc(25);
+ VSTRING *host = vstring_alloc(25);
+ VSTRING *namaddr = vstring_alloc(25);
+ VSTRING *serverid = vstring_alloc(25);
+ VSTRING *helo = vstring_alloc(25);
+ VSTRING *protocols = vstring_alloc(25);
+ VSTRING *cipher_grade = vstring_alloc(25);
+ VSTRING *cipher_exclusions = vstring_alloc(25);
+ VSTRING *mdalg = vstring_alloc(25);
+
+ /*
+ * Note: memset() is not a portable way to initialize non-integer types.
+ */
+ memset(props, 0, sizeof(*props));
+ props->ctx = 0;
+ props->stream = 0;
+ props->fd = -1;
+ props->dane = 0;
+ ret = scan_fn(fp, flags | ATTR_FLAG_MORE,
+ RECV_ATTR_INT(TLS_ATTR_TIMEOUT, &props->timeout),
+ RECV_ATTR_INT(TLS_ATTR_TLS_LEVEL, &props->tls_level),
+ RECV_ATTR_STR(TLS_ATTR_NEXTHOP, nexthop),
+ RECV_ATTR_STR(TLS_ATTR_HOST, host),
+ RECV_ATTR_STR(TLS_ATTR_NAMADDR, namaddr),
+ RECV_ATTR_STR(TLS_ATTR_SERVERID, serverid),
+ RECV_ATTR_STR(TLS_ATTR_HELO, helo),
+ RECV_ATTR_STR(TLS_ATTR_PROTOCOLS, protocols),
+ RECV_ATTR_STR(TLS_ATTR_CIPHER_GRADE, cipher_grade),
+ RECV_ATTR_STR(TLS_ATTR_CIPHER_EXCLUSIONS, cipher_exclusions),
+ RECV_ATTR_FUNC(argv_attr_scan, &props->matchargv),
+ RECV_ATTR_STR(TLS_ATTR_MDALG, mdalg),
+ /* TODO: DANE. */
+ ATTR_TYPE_END);
+ props->nexthop = vstring_export(nexthop);
+ props->host = vstring_export(host);
+ props->namaddr = vstring_export(namaddr);
+ props->serverid = vstring_export(serverid);
+ props->helo = vstring_export(helo);
+ props->protocols = vstring_export(protocols);
+ props->cipher_grade = vstring_export(cipher_grade);
+ props->cipher_exclusions = vstring_export(cipher_exclusions);
+ props->mdalg = vstring_export(mdalg);
+ *(TLS_CLIENT_START_PROPS **) ptr = props;
+ return (ret == 12 ? 1 : -1);
+}
+
+/* tls_proxy_client_start_free - destroy TLS_CLIENT_START_PROPS structure */
+
+void tls_proxy_client_start_free(TLS_CLIENT_START_PROPS *props)
+{
+ /* TODO: stream and file descriptor. */
+ myfree((void *) props->nexthop);
+ myfree((void *) props->host);
+ myfree((void *) props->namaddr);
+ myfree((void *) props->serverid);
+ myfree((void *) props->helo);
+ myfree((void *) props->protocols);
+ myfree((void *) props->cipher_grade);
+ myfree((void *) props->cipher_exclusions);
+ if (props->matchargv)
+ argv_free((ARGV *) props->matchargv);
+ myfree((void *) props->mdalg);
+ /* TODO: DANE. */
+ myfree((void *) props);
+}
+
+#endif
/* NAME
/* tlsproxy_clnt 3
/* SUMMARY
-/* postscreen TLS proxy support
+/* tlsproxy(8) client support
/* SYNOPSIS
/* #include <tlsproxy_clnt.h>
/*
/* VSTREAM *tls_proxy_open(service, flags, peer_stream, peer_addr,
-/* peer_port, timeout)
+/* peer_port, timeout, serverid, init_props,
+/* start_props)
/* const char *service;
/* int flags;
/* VSTREAM *peer_stream;
/* const char *peer_addr;
/* const char *peer_port;
/* int timeout;
+/* const char *serverid;
+/* void *init_props;
+/* void *start_props;
/*
/* TLS_SESS_STATE *tls_proxy_context_receive(proxy_stream)
/* VSTREAM *proxy_stream;
-/*
-/* void tls_proxy_context_free(tls_context)
-/* TLS_SESS_STATE *tls_context;
+/* AUXILIARY FUNCTIONS
+/* VSTREAM *tls_proxy_legacy_open(service, flags, peer_stream,
+/* peer_addr, peer_port,
+/* timeout, serverid)
+/* const char *service;
+/* int flags;
+/* VSTREAM *peer_stream;
+/* const char *peer_addr;
+/* const char *peer_port;
+/* int timeout;
+/* const char *serverid;
/* DESCRIPTION
/* tls_proxy_open() prepares for inserting the tlsproxy(8)
/* daemon between the current process and a remote peer (the
/*
/* After this, the proxy_stream is ready for plain-text I/O.
/*
-/* tls_proxy_context_free() destroys a TLS context object that
-/* was received with tls_proxy_context_receive().
+/* tls_proxy_legacy_open() is a backwards-compatibility feature
+/* that provides a historical interface.
/*
/* Arguments:
/* .IP service
/* Printable TCP port of the remote peer_stream endpoint.
/* .IP timeout
/* Time limit that the tlsproxy(8) daemon should use.
+/* .IP serverid
+/* Unique service identifier.
+/* .IP init_props
+/* Pointer to TLS_CLIENT_INIT_PROPS or TLS_SERVER_INIT_PROPS.
+/* .IP start_props
+/* Pointer to TLS_CLIENT_START_PROPS or TLS_SERVER_START_PROPS.
/* .IP proxy_stream
/* Stream from tls_proxy_open().
/* .IP tls_context
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
/*--*/
#ifdef USE_TLS
VSTREAM *peer_stream,
const char *peer_addr,
const char *peer_port,
- int timeout)
+ int timeout,
+ const char *serverid,
+ void *init_props,
+ void *start_props)
{
+ const char myname[] = "tls_proxy_open";
VSTREAM *tlsproxy_stream;
int status;
int fd;
}
/*
- * Initial handshake. Send the data attributes now, and send the client
- * file descriptor in a later transaction.
- *
- * XXX The formatted endpoint should be a state member. Then, we can
- * simplify all the format strings throughout the program.
+ * Initial handshake. Send common data attributes now, and send the
+ * remote peer file descriptor in a later transaction.
*/
tlsproxy_stream = vstream_fdopen(fd, O_RDWR);
vstring_sprintf(remote_endpt, "[%s]:%s", peer_addr, peer_port);
attr_print(tlsproxy_stream, ATTR_FLAG_NONE,
- SEND_ATTR_STR(MAIL_ATTR_REMOTE_ENDPT, STR(remote_endpt)),
- SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
- SEND_ATTR_INT(MAIL_ATTR_TIMEOUT, timeout),
+ SEND_ATTR_STR(TLS_ATTR_REMOTE_ENDPT, STR(remote_endpt)),
+ SEND_ATTR_INT(TLS_ATTR_FLAGS, flags),
+ SEND_ATTR_INT(TLS_ATTR_TIMEOUT, timeout),
+ SEND_ATTR_STR(TLS_ATTR_SERVERID, serverid),
ATTR_TYPE_END);
+ /* Do not flush the stream yet. */
+ if (vstream_ferror(tlsproxy_stream) != 0) {
+ msg_warn("error sending request to %s service: %m",
+ STR(tlsproxy_service));
+ vstream_fclose(tlsproxy_stream);
+ return (0);
+ }
+ switch (flags & (TLS_PROXY_FLAG_ROLE_CLIENT | TLS_PROXY_FLAG_ROLE_SERVER)) {
+ case TLS_PROXY_FLAG_ROLE_CLIENT:
+ attr_print(tlsproxy_stream, ATTR_FLAG_NONE,
+ SEND_ATTR_FUNC(tls_proxy_client_init_print, init_props),
+ SEND_ATTR_FUNC(tls_proxy_client_start_print, start_props),
+ ATTR_TYPE_END);
+ break;
+ case TLS_PROXY_FLAG_ROLE_SERVER:
+#if 0
+ attr_print(tlsproxy_stream, ATTR_FLAG_NONE,
+ SEND_ATTR_FUNC(tls_proxy_server_init_print, init_props),
+ SEND_ATTR_FUNC(tls_proxy_server_start_print, start_props),
+ ATTR_TYPE_END);
+#endif
+ break;
+ default:
+ msg_panic("%s: bad flags: 0x%x", myname, flags);
+ }
if (vstream_fflush(tlsproxy_stream) != 0) {
msg_warn("error sending request to %s service: %m",
STR(tlsproxy_service));
* Receive the "TLS is available" indication.
*
* This may seem out of order, but we must have a read transaction between
- * sending the request attributes and sending the SMTP client file
+ * sending the request attributes and sending the plaintext file
* descriptor. We can't assume UNIX-domain socket semantics here.
*/
if (attr_scan(tlsproxy_stream, ATTR_FLAG_STRICT,
}
/*
- * Send the remote SMTP client file descriptor.
+ * Send the remote peer file descriptor.
*/
if (LOCAL_SEND_FD(vstream_fileno(tlsproxy_stream),
vstream_fileno(peer_stream)) < 0) {
TLS_SESS_STATE *tls_proxy_context_receive(VSTREAM *proxy_stream)
{
- TLS_SESS_STATE *tls_context;
-
- tls_context = (TLS_SESS_STATE *) mymalloc(sizeof(*tls_context));
+ TLS_SESS_STATE *tls_context = 0;
if (attr_scan(proxy_stream, ATTR_FLAG_STRICT,
- RECV_ATTR_FUNC(tls_proxy_context_scan, (void *) tls_context),
+ RECV_ATTR_FUNC(tls_proxy_context_scan, (void *) &tls_context),
ATTR_TYPE_END) != 1) {
- tls_proxy_context_free(tls_context);
+ if (tls_context)
+ tls_proxy_context_free(tls_context);
return (0);
} else {
return (tls_context);
}
}
-/* tls_proxy_context_free - destroy object from tls_proxy_context_receive() */
-
-void tls_proxy_context_free(TLS_SESS_STATE *tls_context)
-{
- if (tls_context->peer_CN)
- myfree(tls_context->peer_CN);
- if (tls_context->issuer_CN)
- myfree(tls_context->issuer_CN);
- if (tls_context->peer_cert_fprint)
- myfree(tls_context->peer_cert_fprint);
- if (tls_context->peer_pkey_fprint)
- myfree(tls_context->peer_pkey_fprint);
- if (tls_context->protocol)
- myfree((void *) tls_context->protocol);
- if (tls_context->cipher_name)
- myfree((void *) tls_context->cipher_name);
- myfree((void *) tls_context);
-}
-
#endif
/*++
/* NAME
-/* tls_proxy_print
+/* tls_proxy_context_print
/* SUMMARY
-/* write DSN structure to stream
+/* write TLS_ATTR_STATE structure to stream
/* SYNOPSIS
/* #include <tls_proxy.h>
/*
/* int flags;
/* void *ptr;
/* DESCRIPTION
-/* tls_proxy_context_print() writes a TLS_SESS_STATE structure
-/* to the named stream using the specified attribute print
-/* routine. TLS_SESS_STATE() is meant to be passed as a call-back
-/* to attr_print(), thusly:
+/* tls_proxy_context_print() writes the public members of a
+/* TLS_ATTR_STATE structure to the named stream using the
+/* specified attribute print routine. tls_proxy_context_print()
+/* is meant to be passed as a call-back to attr_print(), thusly:
/*
/* ... SEND_ATTR_FUNC(tls_proxy_context_print, (void *) tls_context), ...
/* DIAGNOSTICS
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
/*--*/
#ifdef USE_TLS
#include <attr.h>
-/* Global library. */
-
-#include <mail_proto.h>
-
/* TLS library. */
#include <tls.h>
#define STRING_OR_EMPTY(s) ((s) ? (s) : "")
ret = print_fn(fp, flags | ATTR_FLAG_MORE,
- SEND_ATTR_STR(MAIL_ATTR_PEER_CN,
+ SEND_ATTR_STR(TLS_ATTR_PEER_CN,
STRING_OR_EMPTY(tp->peer_CN)),
- SEND_ATTR_STR(MAIL_ATTR_ISSUER_CN,
+ SEND_ATTR_STR(TLS_ATTR_ISSUER_CN,
STRING_OR_EMPTY(tp->issuer_CN)),
- SEND_ATTR_STR(MAIL_ATTR_PEER_CERT_FPT,
+ SEND_ATTR_STR(TLS_ATTR_PEER_CERT_FPT,
STRING_OR_EMPTY(tp->peer_cert_fprint)),
- SEND_ATTR_STR(MAIL_ATTR_PEER_PKEY_FPT,
+ SEND_ATTR_STR(TLS_ATTR_PEER_PKEY_FPT,
STRING_OR_EMPTY(tp->peer_pkey_fprint)),
- SEND_ATTR_INT(MAIL_ATTR_PEER_STATUS,
+ SEND_ATTR_INT(TLS_ATTR_PEER_STATUS,
tp->peer_status),
- SEND_ATTR_STR(MAIL_ATTR_CIPHER_PROTOCOL,
+ SEND_ATTR_STR(TLS_ATTR_CIPHER_PROTOCOL,
STRING_OR_EMPTY(tp->protocol)),
- SEND_ATTR_STR(MAIL_ATTR_CIPHER_NAME,
+ SEND_ATTR_STR(TLS_ATTR_CIPHER_NAME,
STRING_OR_EMPTY(tp->cipher_name)),
- SEND_ATTR_INT(MAIL_ATTR_CIPHER_USEBITS,
+ SEND_ATTR_INT(TLS_ATTR_CIPHER_USEBITS,
tp->cipher_usebits),
- SEND_ATTR_INT(MAIL_ATTR_CIPHER_ALGBITS,
+ SEND_ATTR_INT(TLS_ATTR_CIPHER_ALGBITS,
tp->cipher_algbits),
ATTR_TYPE_END);
+ /* Do not flush the stream. */
return (ret);
}
--- /dev/null
+/*++
+/* NAME
+/* tls_proxy_context_scan
+/* SUMMARY
+/* read TLS session state from stream
+/* SYNOPSIS
+/* #include <tls_proxy.h>
+/*
+/* int tls_proxy_context_scan(scan_fn, stream, flags, ptr)
+/* ATTR_SCAN_MASTER_FN scan_fn;
+/* VSTREAM *stream;
+/* int flags;
+/* void *ptr;
+/*
+/* void tls_proxy_context_free(tls_context)
+/* TLS_SESS_STATE *tls_context;
+/* DESCRIPTION
+/* tls_proxy_context_scan() reads the public members of a
+/* TLS_ATTR_STATE structure from the named stream using the
+/* specified attribute scan routine. tls_proxy_context_scan()
+/* is meant to be passed as a call-back to attr_scan() as shown
+/* below.
+/*
+/* tls_proxy_context_free() destroys a TLS context object that
+/* was received with tls_proxy_context_scan().
+/*
+/* TLS_ATTR_STATE *tls_context = 0;
+/* ...
+/* ... RECV_ATTR_FUNC(tls_proxy_context_scan, (void *) &tls_context), ...
+/* ...
+/* if (tls_context)
+/* tls_proxy_context_free(tls_context);
+/* DIAGNOSTICS
+/* Fatal: out of memory.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
+
+#ifdef USE_TLS
+
+/* System library. */
+
+#include <sys_defs.h>
+
+/* Utility library */
+
+#include <attr.h>
+
+/* TLS library. */
+
+#include <tls.h>
+#include <tls_proxy.h>
+
+/* tls_proxy_context_scan - receive TLS session state from stream */
+
+int tls_proxy_context_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp,
+ int flags, void *ptr)
+{
+ TLS_SESS_STATE *tls_context
+ = (TLS_SESS_STATE *) mymalloc(sizeof(*tls_context));;
+ int ret;
+ VSTRING *peer_CN = vstring_alloc(25);
+ VSTRING *issuer_CN = vstring_alloc(25);
+ VSTRING *peer_cert_fprint = vstring_alloc(60); /* 60 for SHA-1 */
+ VSTRING *peer_pkey_fprint = vstring_alloc(60); /* 60 for SHA-1 */
+ VSTRING *protocol = vstring_alloc(25);
+ VSTRING *cipher_name = vstring_alloc(25);
+
+ /*
+ * Note: memset() is not a portable way to initialize non-integer types.
+ */
+ memset(tls_context, 0, sizeof(*tls_context));
+ ret = scan_fn(fp, flags | ATTR_FLAG_MORE,
+ RECV_ATTR_STR(TLS_ATTR_PEER_CN, peer_CN),
+ RECV_ATTR_STR(TLS_ATTR_ISSUER_CN, issuer_CN),
+ RECV_ATTR_STR(TLS_ATTR_PEER_CERT_FPT, peer_cert_fprint),
+ RECV_ATTR_STR(TLS_ATTR_PEER_PKEY_FPT, peer_pkey_fprint),
+ RECV_ATTR_INT(TLS_ATTR_PEER_STATUS,
+ &tls_context->peer_status),
+ RECV_ATTR_STR(TLS_ATTR_CIPHER_PROTOCOL, protocol),
+ RECV_ATTR_STR(TLS_ATTR_CIPHER_NAME, cipher_name),
+ RECV_ATTR_INT(TLS_ATTR_CIPHER_USEBITS,
+ &tls_context->cipher_usebits),
+ RECV_ATTR_INT(TLS_ATTR_CIPHER_ALGBITS,
+ &tls_context->cipher_algbits),
+ ATTR_TYPE_END);
+ tls_context->peer_CN = vstring_export(peer_CN);
+ tls_context->issuer_CN = vstring_export(issuer_CN);
+ tls_context->peer_cert_fprint = vstring_export(peer_cert_fprint);
+ tls_context->peer_pkey_fprint = vstring_export(peer_pkey_fprint);
+ tls_context->protocol = vstring_export(protocol);
+ tls_context->cipher_name = vstring_export(cipher_name);
+ *(TLS_SESS_STATE **) ptr = tls_context;
+ return (ret == 9 ? 1 : -1);
+}
+
+/* tls_proxy_context_free - destroy object from tls_proxy_context_receive() */
+
+void tls_proxy_context_free(TLS_SESS_STATE *tls_context)
+{
+ if (tls_context->peer_CN)
+ myfree(tls_context->peer_CN);
+ if (tls_context->issuer_CN)
+ myfree(tls_context->issuer_CN);
+ if (tls_context->peer_cert_fprint)
+ myfree(tls_context->peer_cert_fprint);
+ if (tls_context->peer_pkey_fprint)
+ myfree(tls_context->peer_pkey_fprint);
+ if (tls_context->protocol)
+ myfree((void *) tls_context->protocol);
+ if (tls_context->cipher_name)
+ myfree((void *) tls_context->cipher_name);
+ myfree((void *) tls_context);
+}
+
+#endif
+++ /dev/null
-/*++
-/* NAME
-/* tls_proxy_scan
-/* SUMMARY
-/* read TLS session state from stream
-/* SYNOPSIS
-/* #include <tls_proxy.h>
-/*
-/* int tls_proxy_context_scan(scan_fn, stream, flags, ptr)
-/* ATTR_SCAN_MASTER_FN scan_fn;
-/* VSTREAM *stream;
-/* int flags;
-/* void *ptr;
-/* DESCRIPTION
-/* tls_proxy_context_scan() reads a TLS_SESS_STATE structure
-/* from the named stream using the specified attribute scan
-/* routine. tls_proxy_context_scan() is meant to be passed as
-/* a call-back to attr_scan(), thusly:
-/*
-/* ... RECV_ATTR_FUNC(tls_proxy_context_scan, (void *) tls_context), ...
-/* DIAGNOSTICS
-/* Fatal: out of memory.
-/* LICENSE
-/* .ad
-/* .fi
-/* The Secure Mailer license must be distributed with this software.
-/* AUTHOR(S)
-/* Wietse Venema
-/* IBM T.J. Watson Research
-/* P.O. Box 704
-/* Yorktown Heights, NY 10598, USA
-/*--*/
-
-#ifdef USE_TLS
-
-/* System library. */
-
-#include <sys_defs.h>
-
-/* Utility library */
-
-#include <attr.h>
-
-/* Global library. */
-
-#include <mail_proto.h>
-
-/* TLS library. */
-
-#include <tls.h>
-#include <tls_proxy.h>
-
-/* tls_proxy_context_scan - receive TLS session state from stream */
-
-int tls_proxy_context_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp,
- int flags, void *ptr)
-{
- TLS_SESS_STATE *tls_context = (TLS_SESS_STATE *) ptr;
- int ret;
- VSTRING *peer_CN = vstring_alloc(25);
- VSTRING *issuer_CN = vstring_alloc(25);
- VSTRING *peer_cert_fprint = vstring_alloc(60); /* 60 for SHA-1 */
- VSTRING *peer_pkey_fprint = vstring_alloc(60); /* 60 for SHA-1 */
- VSTRING *protocol = vstring_alloc(25);
- VSTRING *cipher_name = vstring_alloc(25);
-
- /*
- * Note: memset() is not a portable way to initialize non-integer types.
- */
- memset(ptr, 0, sizeof(TLS_SESS_STATE));
- ret = scan_fn(fp, flags | ATTR_FLAG_MORE,
- RECV_ATTR_STR(MAIL_ATTR_PEER_CN, peer_CN),
- RECV_ATTR_STR(MAIL_ATTR_ISSUER_CN, issuer_CN),
- RECV_ATTR_STR(MAIL_ATTR_PEER_CERT_FPT, peer_cert_fprint),
- RECV_ATTR_STR(MAIL_ATTR_PEER_PKEY_FPT, peer_pkey_fprint),
- RECV_ATTR_INT(MAIL_ATTR_PEER_STATUS,
- &tls_context->peer_status),
- RECV_ATTR_STR(MAIL_ATTR_CIPHER_PROTOCOL, protocol),
- RECV_ATTR_STR(MAIL_ATTR_CIPHER_NAME, cipher_name),
- RECV_ATTR_INT(MAIL_ATTR_CIPHER_USEBITS,
- &tls_context->cipher_usebits),
- RECV_ATTR_INT(MAIL_ATTR_CIPHER_ALGBITS,
- &tls_context->cipher_algbits),
- ATTR_TYPE_END);
- tls_context->peer_CN = vstring_export(peer_CN);
- tls_context->issuer_CN = vstring_export(issuer_CN);
- tls_context->peer_cert_fprint = vstring_export(peer_cert_fprint);
- tls_context->peer_pkey_fprint = vstring_export(peer_pkey_fprint);
- tls_context->protocol = vstring_export(protocol);
- tls_context->cipher_name = vstring_export(cipher_name);
- return (ret == 9 ? 1 : -1);
-}
-
-#endif
--- /dev/null
+/*++
+/* NAME
+/* tls_proxy_server_init_print
+/* SUMMARY
+/* write TLS_SERVER_INIT_PROPS structure to stream
+/* SYNOPSIS
+/* #include <tls_proxy.h>
+/*
+/* int tls_proxy_server_init_print(print_fn, stream, flags, ptr)
+/* ATTR_PRINT_MASTER_FN print_fn;
+/* VSTREAM *stream;
+/* int flags;
+/* void *ptr;
+/* DESCRIPTION
+/* tls_proxy_server_init_print() writes a TLS_SERVER_INIT_PROPS
+/* structure to the named stream using the specified attribute print
+/* routine. tls_proxy_server_init_print() is meant to be passed as
+/* a call-back to attr_print(), thusly:
+/*
+/* ... SEND_ATTR_FUNC(tls_proxy_server_init_print, (void *) props), ...
+/* DIAGNOSTICS
+/* Fatal: out of memory.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
+
+#ifdef USE_TLS
+
+/* System library. */
+
+#include <sys_defs.h>
+
+/* Utility library */
+
+#include <attr.h>
+
+/* TLS library. */
+
+#include <tls.h>
+#include <tls_proxy.h>
+
+/* tls_proxy_server_init_print - send TLS_SERVER_INIT_PROPS over stream */
+
+int tls_proxy_server_init_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp,
+ int flags, void *ptr)
+{
+ TLS_SERVER_INIT_PROPS *props = (TLS_SERVER_INIT_PROPS *) ptr;
+ int ret;
+
+#define STRING_OR_EMPTY(s) ((s) ? (s) : "")
+
+ ret = print_fn(fp, flags | ATTR_FLAG_MORE,
+ SEND_ATTR_STR(TLS_ATTR_LOG_PARAM,
+ STRING_OR_EMPTY(props->log_param)),
+ SEND_ATTR_STR(TLS_ATTR_LOG_LEVEL,
+ STRING_OR_EMPTY(props->log_level)),
+ SEND_ATTR_INT(TLS_ATTR_VERIFYDEPTH, props->verifydepth),
+ SEND_ATTR_STR(TLS_ATTR_CACHE_TYPE,
+ STRING_OR_EMPTY(props->cache_type)),
+ SEND_ATTR_INT(TLS_ATTR_SET_SESSID, props->set_sessid),
+ SEND_ATTR_STR(TLS_ATTR_CERT_FILE,
+ STRING_OR_EMPTY(props->cert_file)),
+ SEND_ATTR_STR(TLS_ATTR_KEY_FILE,
+ STRING_OR_EMPTY(props->key_file)),
+ SEND_ATTR_STR(TLS_ATTR_DCERT_FILE,
+ STRING_OR_EMPTY(props->dcert_file)),
+ SEND_ATTR_STR(TLS_ATTR_DKEY_FILE,
+ STRING_OR_EMPTY(props->dkey_file)),
+ SEND_ATTR_STR(TLS_ATTR_ECCERT_FILE,
+ STRING_OR_EMPTY(props->eccert_file)),
+ SEND_ATTR_STR(TLS_ATTR_ECKEY_FILE,
+ STRING_OR_EMPTY(props->eckey_file)),
+ SEND_ATTR_STR(TLS_ATTR_CAFILE,
+ STRING_OR_EMPTY(props->CAfile)),
+ SEND_ATTR_STR(TLS_ATTR_CAPATH,
+ STRING_OR_EMPTY(props->CApath)),
+ SEND_ATTR_STR(TLS_ATTR_PROTOCOLS,
+ STRING_OR_EMPTY(props->protocols)),
+ SEND_ATTR_STR(TLS_ATTR_EECDH_GRADE,
+ STRING_OR_EMPTY(props->eecdh_grade)),
+ SEND_ATTR_STR(TLS_ATTR_DH1K_PARAM_FILE,
+ STRING_OR_EMPTY(props->dh1024_param_file)),
+ SEND_ATTR_STR(TLS_ATTR_DH512_PARAM_FILE,
+ STRING_OR_EMPTY(props->dh512_param_file)),
+ SEND_ATTR_INT(TLS_ATTR_ASK_CCERT, props->ask_ccert),
+ SEND_ATTR_STR(TLS_ATTR_MDALG,
+ STRING_OR_EMPTY(props->mdalg)),
+ ATTR_TYPE_END);
+ /* Do not flush the stream. */
+ return (ret);
+}
+
+#endif
--- /dev/null
+/*++
+/* NAME
+/* tls_proxy_server_init_scan
+/* SUMMARY
+/* read TLS_SERVER_INIT_PROPS from stream
+/* SYNOPSIS
+/* #include <tls_proxy.h>
+/*
+/* int tls_proxy_server_init_scan(scan_fn, stream, flags, ptr)
+/* ATTR_SCAN_MASTER_FN scan_fn;
+/* VSTREAM *stream;
+/* int flags;
+/* void *ptr;
+/*
+/* tls_proxy_server_init_free(props)
+/* TLS_SERVER_INIT_PROPS *props;
+/* DESCRIPTION
+/* tls_proxy_server_init_scan() reads a TLS_SERVER_INIT_PROPS
+/* structure from the named stream using the specified attribute
+/* scan routine. tls_proxy_server_init_scan() is meant to be passed
+/* as a call-back function to attr_scan(), as shown below.
+/*
+/* tls_proxy_server_init_free() destroys a TLS_SERVER_INIT_PROPS
+/* structure that was created by tls_proxy_server_init_scan().
+/* This must be called even if the tls_proxy_server_init_scan()
+/* call returned an error.
+/*
+/* TLS_SERVER_INIT_PROPS *props = 0;
+/* ...
+/* ... RECV_ATTR_FUNC(tls_proxy_server_init_scan, (void *) &props), ...
+/* ...
+/* if (props)
+/* tls_proxy_client_init_free(props);
+/* DIAGNOSTICS
+/* Fatal: out of memory.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
+
+#ifdef USE_TLS
+
+/* System library. */
+
+#include <sys_defs.h>
+
+/* Utility library */
+
+#include <attr.h>
+
+/* TLS library. */
+
+#include <tls.h>
+#include <tls_proxy.h>
+
+/* tls_proxy_server_init_scan - receive TLS_SERVER_INIT_PROPS from stream */
+
+int tls_proxy_server_init_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp,
+ int flags, void *ptr)
+{
+ TLS_SERVER_INIT_PROPS *props
+ = (TLS_SERVER_INIT_PROPS *) mymalloc(sizeof(*props));
+ int ret;
+ VSTRING *log_param = vstring_alloc(25);
+ VSTRING *log_level = vstring_alloc(25);
+ VSTRING *cache_type = vstring_alloc(25);
+ VSTRING *cert_file = vstring_alloc(25);
+ VSTRING *key_file = vstring_alloc(25);
+ VSTRING *dcert_file = vstring_alloc(25);
+ VSTRING *dkey_file = vstring_alloc(25);
+ VSTRING *eccert_file = vstring_alloc(25);
+ VSTRING *eckey_file = vstring_alloc(25);
+ VSTRING *CAfile = vstring_alloc(25);
+ VSTRING *CApath = vstring_alloc(25);
+ VSTRING *protocols = vstring_alloc(25);
+ VSTRING *eecdh_grade = vstring_alloc(25);
+ VSTRING *dh1024_param_file = vstring_alloc(25);
+ VSTRING *dh512_param_file = vstring_alloc(25);
+ VSTRING *mdalg = vstring_alloc(25);
+
+ /*
+ * Note: memset() is not a portable way to initialize non-integer types.
+ */
+ memset(props, 0, sizeof(*props));
+ ret = scan_fn(fp, flags | ATTR_FLAG_MORE,
+ RECV_ATTR_STR(TLS_ATTR_LOG_PARAM, log_param),
+ RECV_ATTR_STR(TLS_ATTR_LOG_LEVEL, log_level),
+ RECV_ATTR_INT(TLS_ATTR_VERIFYDEPTH, &props->verifydepth),
+ RECV_ATTR_STR(TLS_ATTR_CACHE_TYPE, cache_type),
+ RECV_ATTR_INT(TLS_ATTR_SET_SESSID, &props->set_sessid),
+ RECV_ATTR_STR(TLS_ATTR_CERT_FILE, cert_file),
+ RECV_ATTR_STR(TLS_ATTR_KEY_FILE, key_file),
+ RECV_ATTR_STR(TLS_ATTR_DCERT_FILE, dcert_file),
+ RECV_ATTR_STR(TLS_ATTR_DKEY_FILE, dkey_file),
+ RECV_ATTR_STR(TLS_ATTR_ECCERT_FILE, eccert_file),
+ RECV_ATTR_STR(TLS_ATTR_ECKEY_FILE, eckey_file),
+ RECV_ATTR_STR(TLS_ATTR_CAFILE, CAfile),
+ RECV_ATTR_STR(TLS_ATTR_CAPATH, CApath),
+ RECV_ATTR_STR(TLS_ATTR_PROTOCOLS, protocols),
+ RECV_ATTR_STR(TLS_ATTR_EECDH_GRADE, eecdh_grade),
+ RECV_ATTR_STR(TLS_ATTR_DH1K_PARAM_FILE, dh1024_param_file),
+ RECV_ATTR_STR(TLS_ATTR_DH512_PARAM_FILE, dh512_param_file),
+ RECV_ATTR_INT(TLS_ATTR_ASK_CCERT, &props->ask_ccert),
+ RECV_ATTR_STR(TLS_ATTR_MDALG, mdalg),
+ ATTR_TYPE_END);
+ props->log_param = vstring_export(log_param);
+ props->log_level = vstring_export(log_level);
+ props->cache_type = vstring_export(cache_type);
+ props->cert_file = vstring_export(cert_file);
+ props->key_file = vstring_export(key_file);
+ props->dcert_file = vstring_export(dcert_file);
+ props->dkey_file = vstring_export(dkey_file);
+ props->eccert_file = vstring_export(eccert_file);
+ props->eckey_file = vstring_export(eckey_file);
+ props->CAfile = vstring_export(CAfile);
+ props->CApath = vstring_export(CApath);
+ props->protocols = vstring_export(protocols);
+ props->eecdh_grade = vstring_export(eecdh_grade);
+ props->dh1024_param_file = vstring_export(dh1024_param_file);
+ props->dh512_param_file = vstring_export(dh512_param_file);
+ props->mdalg = vstring_export(mdalg);
+ *(TLS_SERVER_INIT_PROPS **) ptr = props;
+ return (ret == 19 ? 1 : -1);
+}
+
+/* tls_proxy_server_init_free - destroy TLS_SERVER_INIT_PROPS structure */
+
+void tls_proxy_server_init_free(TLS_SERVER_INIT_PROPS *props)
+{
+ myfree((void *) props->log_param);
+ myfree((void *) props->log_level);
+ myfree((void *) props->cache_type);
+ myfree((void *) props->cert_file);
+ myfree((void *) props->key_file);
+ myfree((void *) props->dcert_file);
+ myfree((void *) props->dkey_file);
+ myfree((void *) props->eccert_file);
+ myfree((void *) props->eckey_file);
+ myfree((void *) props->CAfile);
+ myfree((void *) props->CApath);
+ myfree((void *) props->protocols);
+ myfree((void *) props->eecdh_grade);
+ myfree((void *) props->dh1024_param_file);
+ myfree((void *) props->dh512_param_file);
+ myfree((void *) props->mdalg);
+ myfree((void *) props);
+}
+
+#endif
--- /dev/null
+/*++
+/* NAME
+/* tls_proxy_server_start_print.c
+/* SUMMARY
+/* write TLS_SERVER_START_PROPS structure to stream
+/* SYNOPSIS
+/* #include <tls_proxy.h>
+/*
+/* int tls_proxy_server_start_print(print_fn, stream, flags, ptr)
+/* ATTR_PRINT_MASTER_FN print_fn;
+/* VSTREAM *stream;
+/* int flags;
+/* void *ptr;
+/* DESCRIPTION
+/* tls_proxy_server_start_print() writes a TLS_SERVER_START_PROPS
+/* structure to the named stream using the specified attribute print
+/* routine. tls_proxy_server_start_print() is meant to be passed as
+/* a call-back to attr_print(), thusly:
+/*
+/* ... SEND_ATTR_FUNC(tls_proxy_server_start_print, (void *) props), ...
+/* DIAGNOSTICS
+/* Fatal: out of memory.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
+
+#ifdef USE_TLS
+
+/* System library. */
+
+#include <sys_defs.h>
+
+/* Utility library */
+
+#include <attr.h>
+
+/* TLS library. */
+
+#include <tls.h>
+#include <tls_proxy.h>
+
+/* tls_proxy_server_start_print - send TLS_SERVER_START_PROPS over stream */
+
+int tls_proxy_server_start_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp,
+ int flags, void *ptr)
+{
+ TLS_SERVER_START_PROPS *props = (TLS_SERVER_START_PROPS *) ptr;
+ int ret;
+
+#define STRING_OR_EMPTY(s) ((s) ? (s) : "")
+
+ ret = print_fn(fp, flags | ATTR_FLAG_MORE,
+ SEND_ATTR_INT(TLS_ATTR_TIMEOUT, props->timeout),
+ SEND_ATTR_INT(TLS_ATTR_REQUIRECERT, props->requirecert),
+ SEND_ATTR_STR(TLS_ATTR_SERVERID,
+ STRING_OR_EMPTY(props->serverid)),
+ SEND_ATTR_STR(TLS_ATTR_NAMADDR,
+ STRING_OR_EMPTY(props->namaddr)),
+ SEND_ATTR_STR(TLS_ATTR_CIPHER_GRADE,
+ STRING_OR_EMPTY(props->cipher_grade)),
+ SEND_ATTR_STR(TLS_ATTR_CIPHER_EXCLUSIONS,
+ STRING_OR_EMPTY(props->cipher_exclusions)),
+ SEND_ATTR_STR(TLS_ATTR_MDALG,
+ STRING_OR_EMPTY(props->mdalg)),
+ ATTR_TYPE_END);
+ /* Do not flush the stream. */
+ return (ret);
+}
+
+#endif
--- /dev/null
+/*++
+/* NAME
+/* tls_proxy_server_start_scan
+/* SUMMARY
+/* read TLS_SERVER_START_PROPS from stream
+/* SYNOPSIS
+/* #include <tls_proxy.h>
+/*
+/* int tls_proxy_server_start_scan(scan_fn, stream, flags, ptr)
+/* ATTR_SCAN_MASTER_FN scan_fn;
+/* VSTREAM *stream;
+/* int flags;
+/* void *ptr;
+/*
+/* void tls_proxy_server_start_free(props)
+/* TLS_SERVER_START_PROPS *props;
+/* DESCRIPTION
+/* tls_proxy_server_start_scan() reads a TLS_SERVER_START_PROPS
+/* structure from the named stream using the specified attribute
+/* scan routine. tls_proxy_server_start_scan() is meant to be passed
+/* as a call-back function to attr_scan(), as shown below.
+/*
+/* tls_proxy_server_start_free() destroys a TLS_SERVER_START_PROPS
+/* structure that was created by tls_proxy_server_start_scan().
+/* This must be called even if the tls_proxy_server_start_scan()
+/* call returned an error.
+/*
+/* TLS_SERVER_START_PROPS *props = 0;
+/* ...
+/* ... RECV_ATTR_FUNC(tls_proxy_server_start_scan, (void *) &props), ...
+/* ...
+/* if (props)
+/* tls_proxy_server_start_free(props);
+/* DIAGNOSTICS
+/* Fatal: out of memory.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
+
+#ifdef USE_TLS
+
+/* System library. */
+
+#include <sys_defs.h>
+
+/* Utility library */
+
+#include <attr.h>
+
+/* TLS library. */
+
+#include <tls.h>
+#include <tls_proxy.h>
+
+/* tls_proxy_server_start_scan - receive TLS_SERVER_START_PROPS from stream */
+
+int tls_proxy_server_start_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp,
+ int flags, void *ptr)
+{
+ TLS_SERVER_START_PROPS *props
+ = (TLS_SERVER_START_PROPS *) mymalloc(sizeof(*props));
+ int ret;
+ VSTRING *serverid = vstring_alloc(25);
+ VSTRING *namaddr = vstring_alloc(25);
+ VSTRING *cipher_grade = vstring_alloc(25);
+ VSTRING *cipher_exclusions = vstring_alloc(25);
+ VSTRING *mdalg = vstring_alloc(25);
+
+ /*
+ * Note: memset() is not a portable way to initialize non-integer types.
+ */
+ memset(props, 0, sizeof(*props));
+ props->ctx = 0;
+ props->stream = 0;
+ /* XXX Caller sets fd. */
+ ret = scan_fn(fp, flags | ATTR_FLAG_MORE,
+ RECV_ATTR_INT(TLS_ATTR_TIMEOUT, &props->timeout),
+ RECV_ATTR_INT(TLS_ATTR_REQUIRECERT, &props->requirecert),
+ RECV_ATTR_STR(TLS_ATTR_SERVERID, serverid),
+ RECV_ATTR_STR(TLS_ATTR_NAMADDR, namaddr),
+ RECV_ATTR_STR(TLS_ATTR_CIPHER_GRADE, cipher_grade),
+ RECV_ATTR_STR(TLS_ATTR_CIPHER_EXCLUSIONS, cipher_exclusions),
+ RECV_ATTR_STR(TLS_ATTR_MDALG, mdalg),
+ ATTR_TYPE_END);
+ props->serverid = vstring_export(serverid);
+ props->namaddr = vstring_export(namaddr);
+ props->cipher_grade = vstring_export(cipher_grade);
+ props->cipher_exclusions = vstring_export(cipher_exclusions);
+ props->mdalg = vstring_export(mdalg);
+ *(TLS_SERVER_START_PROPS **) ptr = props;
+ return (ret == 7 ? 1 : -1);
+}
+
+/* tls_proxy_server_start_free - destroy TLS_SERVER_START_PROPS structure */
+
+void tls_proxy_server_start_free(TLS_SERVER_START_PROPS *props)
+{
+ /* XXX Caller closes fd. */
+ myfree((void *) props->serverid);
+ myfree((void *) props->namaddr);
+ myfree((void *) props->cipher_grade);
+ myfree((void *) props->cipher_exclusions);
+ myfree((void *) props->mdalg);
+ myfree((void *) props);
+}
+
+#endif
@$(EXPORT) make -f Makefile.in Makefile 1>&2
# do not edit below this line - it is generated by 'make depend'
+tls_client.o: tls_client.c
tlsproxy.o: ../../include/argv.h
tlsproxy.o: ../../include/attr.h
tlsproxy.o: ../../include/check_arg.h
tlsproxy.o: tlsproxy.c
tlsproxy.o: tlsproxy.h
tlsproxy_state.o: ../../include/argv.h
+tlsproxy_state.o: ../../include/attr.h
tlsproxy_state.o: ../../include/check_arg.h
tlsproxy_state.o: ../../include/dns.h
tlsproxy_state.o: ../../include/events.h
+tlsproxy_state.o: ../../include/htable.h
tlsproxy_state.o: ../../include/mail_conf.h
tlsproxy_state.o: ../../include/mail_server.h
tlsproxy_state.o: ../../include/msg.h
tlsproxy_state.o: ../../include/name_code.h
tlsproxy_state.o: ../../include/name_mask.h
tlsproxy_state.o: ../../include/nbbio.h
+tlsproxy_state.o: ../../include/nvtable.h
tlsproxy_state.o: ../../include/sock_addr.h
tlsproxy_state.o: ../../include/sys_defs.h
tlsproxy_state.o: ../../include/tls.h
+tlsproxy_state.o: ../../include/tls_proxy.h
tlsproxy_state.o: ../../include/vbuf.h
tlsproxy_state.o: ../../include/vstream.h
tlsproxy_state.o: ../../include/vstring.h
static TLS_APPL_STATE *tlsp_server_ctx;
static int ask_client_cert;
+ /*
+ * TLS per-client status.
+ */
+static HTABLE *tlsp_client_app_cache;
+
+ /*
+ * Internal status API.
+ */
+#define TLSP_STAT_OK 0
+#define TLSP_STAT_ERR (-1)
+
/*
* SLMs.
*/
state->timeout);
state->ssl_last_err = SSL_ERROR_NONE;
}
- return (0);
+ return (TLSP_STAT_OK);
/*
* The TLS engine wants to write to the network. Turn on
}
event_request_timer(tlsp_ciphertext_event, (void *) state,
state->timeout);
- return (0);
+ return (TLSP_STAT_OK);
/*
* The TLS engine wants to read from the network. Turn on
}
event_request_timer(tlsp_ciphertext_event, (void *) state,
state->timeout);
- return (0);
+ return (TLSP_STAT_OK);
/*
* Some error. Self-destruct. This automagically cleans up all
/* FALLTHROUGH */
default:
tlsp_state_free(state);
- return (-1);
+ return (TLSP_STAT_ERR);
}
}
* pending read/write and timeout event requests.
*/
if (state->flags & TLSP_FLAG_DO_HANDSHAKE) {
- ssl_stat = SSL_accept(tls_context->con);
+ if (state->is_server_role)
+ ssl_stat = SSL_accept(tls_context->con);
+ else
+ ssl_stat = SSL_connect(tls_context->con);
if (ssl_stat != 1) {
handshake_err = SSL_get_error(tls_context->con, ssl_stat);
tlsp_eval_tls_error(state, handshake_err);
/* At this point, state could be a dangling pointer. */
return;
}
- if ((state->tls_context = tls_server_post_accept(tls_context)) == 0) {
+ if (state->is_server_role)
+ state->tls_context = tls_server_post_accept(tls_context);
+ else
+ state->tls_context = tls_client_post_connect(tls_context,
+ state->client_start_props);
+ if (state->tls_context == 0) {
tlsp_state_free(state);
return;
}
}
}
-/* tlsp_start_tls - turn on TLS or force disconnect */
+/* tlsp_start_client_pre_handshake - turn on TLS or force disconnect */
+
+static int tlsp_start_client_pre_handshake(TLSP_STATE *state)
+{
+ VSTRING *buf;
+ char *key;
+
+ /*
+ * Share a TLS_APPL_STATE object among multiple requests that specify the
+ * same TLS_CLIENT_INIT_PROPS. TLS_APPL_STATE owns an SSL_CTX which is
+ * expensive.
+ */
+ buf = vstring_alloc(100);
+ key = tls_proxy_client_init_to_string(buf, state->client_init_props);
+ if ((state->appl_state = (TLS_APPL_STATE *)
+ htable_find(tlsp_client_app_cache, key)) == 0
+ && (state->appl_state =
+ tls_client_init(state->client_init_props)) != 0)
+ (void) htable_enter(tlsp_client_app_cache, key,
+ (void *) state->appl_state);
+ vstring_free(buf);
+
+ if (state->appl_state != 0) {
+ state->client_start_props->ctx = state->appl_state;
+ state->client_start_props->fd = state->ciphertext_fd;
+ state->tls_context = tls_client_start(state->client_start_props);
+ if (state->tls_context != 0)
+ return (TLSP_STAT_OK);
+ }
+
+ /*
+ * TLS client initialization failed.
+ */
+ tlsp_state_free(state);
+ return (TLSP_STAT_ERR);
+}
+
+/* tlsp_start_server_pre_handshake - turn on TLS or force disconnect */
-static int tlsp_start_tls(TLSP_STATE *state)
+static int tlsp_start_server_pre_handshake(TLSP_STATE *state)
{
TLS_SERVER_START_PROPS props;
static char *cipher_grade;
*/
/*
- * Perform the before-handshake portion of the per-session initialization.
- * Pass a null VSTREAM to indicate that this program, will do the
+ * Perform the before-handshake portion of per-session initialization.
+ * Pass a null VSTREAM to indicate that this program will do the
* ciphertext I/O, not libtls.
*
* The cipher grade and exclusions don't change between sessions. Compute
if (state->tls_context == 0) {
tlsp_state_free(state);
- return (-1);
+ return (TLSP_STAT_ERR);
}
/*
* XXX Do we care about certificate verification results? Not as long as
* postscreen(8) doesn't actually receive email.
*/
- return (0);
+ return (TLSP_STAT_OK);
}
-/* tlsp_get_fd_event - receive final postscreen(8) hand-off information */
+/* tlsp_get_fd_event - receive final connection hand-off information */
static void tlsp_get_fd_event(int event, void *context)
{
const char *myname = "tlsp_get_fd_event";
TLSP_STATE *state = (TLSP_STATE *) context;
int plaintext_fd = vstream_fileno(state->plaintext_stream);
+ int status;
/*
* At this point we still manually manage plaintext read/write/timeout
else
errno = ETIMEDOUT;
+ if (event != EVENT_READ
+ || (state->ciphertext_fd = LOCAL_RECV_FD(plaintext_fd)) < 0) {
+ msg_warn("%s: receive remote SMTP peer file descriptor: %m", myname);
+ tlsp_state_free(state);
+ return;
+ }
+
+ /*
+ * Perform the TLS layer before-handshake initialization. We perform the
+ * remainder after the actual TLS handshake completes. If this fails then
+ * state is a dangling pointer.
+ */
+ if (state->is_server_role)
+ status = tlsp_start_server_pre_handshake(state);
+ else
+ status = tlsp_start_client_pre_handshake(state);
+ if (status != TLSP_STAT_OK)
+ return;
+
/*
* Initialize plaintext-related session state. Once we have this behind
* us, the TLSP_STATE destructor will automagically clean up requests for
* destructor. Insert the NBBIO event-driven I/O layer between the
* postscreen(8) server and the TLS engine.
*/
- if (event != EVENT_READ
- || (state->ciphertext_fd = LOCAL_RECV_FD(plaintext_fd)) < 0) {
- msg_warn("%s: receive SMTP client file descriptor: %m", myname);
- tlsp_state_free(state);
- return;
- }
non_blocking(state->ciphertext_fd, NON_BLOCKING);
state->ciphertext_timer = tlsp_ciphertext_event;
state->plaintext_buf = nbbio_create(plaintext_fd,
- VSTREAM_BUFSIZE, "postscreen",
+ VSTREAM_BUFSIZE, state->server_id,
tlsp_plaintext_event,
(void *) state);
- /*
- * Perform the TLS layer before-handshake initialization. We perform the
- * remainder after the TLS handshake completes.
- */
- if (tlsp_start_tls(state) < 0)
- return;
-
/*
* Trigger the initial proxy server I/Os.
*/
tlsp_strategy(state);
}
-/* tlsp_get_request_event - receive initial postscreen(8) hand-off info */
+/* tlsp_close_event - handle plaintext-client close event */
+
+static void tlsp_close_event(int event, void *context)
+{
+ TLSP_STATE *state = (TLSP_STATE *) context;
+ int plaintext_fd = vstream_fileno(state->plaintext_stream);
+
+ event_cancel_timer(tlsp_close_event, (void *) state);
+ event_disable_readwrite(plaintext_fd);
+ tlsp_state_free(state);
+}
+
+/* tlsp_get_request_event - receive initial hand-off info */
static void tlsp_get_request_event(int event, void *context)
{
static VSTRING *server_id;
int req_flags;
int timeout;
- int ready;
+ int ready = 0;
/*
* One-time initialization.
*/
if (event != EVENT_READ
|| attr_scan(plaintext_stream, ATTR_FLAG_STRICT,
- RECV_ATTR_STR(MAIL_ATTR_REMOTE_ENDPT, remote_endpt),
- RECV_ATTR_INT(MAIL_ATTR_FLAGS, &req_flags),
- RECV_ATTR_INT(MAIL_ATTR_TIMEOUT, &timeout),
- RECV_ATTR_STR(MAIL_ATTR_SERVER_ID, server_id),
+ RECV_ATTR_STR(TLS_ATTR_REMOTE_ENDPT, remote_endpt),
+ RECV_ATTR_INT(TLS_ATTR_FLAGS, &req_flags),
+ RECV_ATTR_INT(TLS_ATTR_TIMEOUT, &timeout),
+ RECV_ATTR_STR(TLS_ATTR_SERVERID, server_id),
ATTR_TYPE_END) != 4) {
msg_warn("%s: receive request attributes: %m", myname);
event_disable_readwrite(plaintext_fd);
return;
}
+ /*
+ * XXX We use the same fixed timeout throughout the entire session for
+ * both plaintext and ciphertext communication. This timeout is just a
+ * safety feature; the real timeout will be enforced by our plaintext
+ * peer.
+ */
+ state->remote_endpt = mystrdup(STR(remote_endpt));
+ state->server_id = mystrdup(STR(server_id));
+ msg_info("CONNECT %s %s",
+ (req_flags & TLS_PROXY_FLAG_ROLE_SERVER) ? "from" :
+ (req_flags & TLS_PROXY_FLAG_ROLE_CLIENT) ? "to" :
+ "(bogus_direction)", state->remote_endpt);
+ state->req_flags = req_flags;
+ /* state->is_server_role is set below. */
+ state->timeout = timeout + 10; /* XXX */
+
+ /*
+ * Receive the TLS preferences now, to reduce the number of protocol
+ * roundtrips. To call the pre-handshake tls_*_start() before receiving
+ * the ciphertext FD, pass in the FD through some other interface.
+ */
+ switch (req_flags & (TLS_PROXY_FLAG_ROLE_CLIENT | TLS_PROXY_FLAG_ROLE_SERVER)) {
+ case TLS_PROXY_FLAG_ROLE_CLIENT:
+ state->is_server_role = 0;
+ if (attr_scan(plaintext_stream, ATTR_FLAG_STRICT,
+ RECV_ATTR_FUNC(tls_proxy_client_init_scan,
+ (void *) &state->client_init_props),
+ RECV_ATTR_FUNC(tls_proxy_client_start_scan,
+ (void *) &state->client_start_props),
+ ATTR_TYPE_END) != 2) {
+ msg_warn("%s: receive client TLS settings: %m", myname);
+ event_disable_readwrite(plaintext_fd);
+ tlsp_state_free(state);
+ return;
+ }
+ ready = 1;
+ break;
+ case TLS_PROXY_FLAG_ROLE_SERVER:
+ state->is_server_role = 1;
+ ready = (tlsp_server_ctx != 0);
+ break;
+ default:
+ state->is_server_role = 0;
+ msg_warn("%s: bad request flags: 0x%x", myname, req_flags);
+ ready = 0;
+ }
+
/*
* If the requested TLS engine is unavailable, hang up after making sure
* that the plaintext peer has received our "sorry" indication.
*/
- ready = ((req_flags & TLS_PROXY_FLAG_ROLE_SERVER) != 0
- && tlsp_server_ctx != 0);
if (attr_print(plaintext_stream, ATTR_FLAG_NONE,
SEND_ATTR_INT(MAIL_ATTR_STATUS, ready),
ATTR_TYPE_END) != 0
|| vstream_fflush(plaintext_stream) != 0
|| ready == 0) {
- read_wait(plaintext_fd, TLSP_INIT_TIMEOUT); /* XXX */
- event_disable_readwrite(plaintext_fd);
- tlsp_state_free(state);
+ event_enable_read(plaintext_fd, tlsp_close_event, (void *) state);
+ event_request_timer(tlsp_close_event, (void *) state, TLSP_INIT_TIMEOUT);
return;
- }
-
- /*
- * XXX We use the same fixed timeout throughout the entire session for
- * both plaintext and ciphertext communication. This timeout is just a
- * safety feature; the real timeout will be enforced by our plaintext
- * peer.
- */
- else {
- state->remote_endpt = mystrdup(STR(remote_endpt));
- state->server_id = mystrdup(STR(server_id));
- msg_info("CONNECT %s %s",
- (req_flags & TLS_PROXY_FLAG_ROLE_SERVER) ? "from" :
- (req_flags & TLS_PROXY_FLAG_ROLE_CLIENT) ? "to" :
- "(bogus_direction)", state->remote_endpt);
- state->req_flags = req_flags;
- state->timeout = timeout + 10; /* XXX */
+ } else {
event_enable_read(plaintext_fd, tlsp_get_fd_event, (void *) state);
event_request_timer(tlsp_get_fd_event, (void *) state,
TLSP_INIT_TIMEOUT);
static void post_jail_init(char *unused_name, char **unused_argv)
{
- /* void */ ;
+ tlsp_client_app_cache = htable_create(10);
}
MAIL_VERSION_STAMP_DECLARE;
typedef struct {
int flags; /* see below */
int req_flags; /* request flags, see tls_proxy.h */
+ int is_server_role; /* avoid clumsy handler code */
char *service; /* argv[0] */
VSTREAM *plaintext_stream; /* local peer: postscreen(8), etc. */
NBBIO *plaintext_buf; /* plaintext buffer */
int timeout; /* read/write time limit */
char *remote_endpt; /* printable remote endpoint */
char *server_id; /* cache management */
- TLS_SESS_STATE *tls_context; /* llibtls state */
+ TLS_APPL_STATE *appl_state; /* libtls state */
+ TLS_SESS_STATE *tls_context; /* libtls state */
int ssl_last_err; /* TLS I/O state */
+ TLS_SERVER_INIT_PROPS *server_init_props;
+ TLS_SERVER_START_PROPS *server_start_props;
+ TLS_CLIENT_INIT_PROPS *client_init_props;
+ TLS_CLIENT_START_PROPS *client_start_props;
} TLSP_STATE;
#define TLSP_FLAG_DO_HANDSHAKE (1<<0)
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
/*--*/
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
/*--*/
/*
#ifdef USE_TLS
#define TLS_INTERNAL /* XXX */
#include <tls.h>
+#include <tls_proxy.h>
/*
* Application-specific.
state->remote_endpt = 0;
state->server_id = 0;
state->tls_context = 0;
+ state->server_init_props = 0;
+ state->server_start_props = 0;
+ state->client_init_props = 0;
+ state->client_start_props = 0;
return (state);
}
myfree(state->server_id);
if (state->tls_context)
tls_free_context(state->tls_context);
+ if (state->server_init_props)
+ tls_proxy_server_init_free(state->server_init_props);
+ if (state->server_start_props)
+ tls_proxy_server_start_free(state->server_start_props);
+ if (state->client_init_props)
+ tls_proxy_client_init_free(state->client_init_props);
+ if (state->client_start_props)
+ tls_proxy_client_start_free(state->client_start_props);
myfree((void *) state);
}
poll_fd.c timecmp.c slmdb.c dict_pipe.c dict_random.c \
valid_utf8_hostname.c midna_domain.c argv_splitq.c balpar.c dict_union.c \
extpar.c dict_inline.c casefold.c dict_utf8.c strcasecmp_utf8.c \
- split_qnameval.c
+ split_qnameval.c argv_attr_print.c argv_attr_scan.c
OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \
attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \
poll_fd.o timecmp.o $(NON_PLUGIN_MAP_OBJ) dict_pipe.o dict_random.o \
valid_utf8_hostname.o midna_domain.o argv_splitq.o balpar.o dict_union.o \
extpar.o dict_inline.o casefold.o dict_utf8.o strcasecmp_utf8.o \
- split_qnameval.o
+ split_qnameval.o argv_attr_print.o argv_attr_scan.o
# MAP_OBJ is for maps that may be dynamically loaded with dynamicmaps.cf.
# When hard-linking these, makedefs sets NON_PLUGIN_MAP_OBJ=$(MAP_OBJ),
# otherwise it sets the PLUGIN_* macros.
edit_file.h dict_cache.h dict_thash.h ip_match.h nbbio.h base32_code.h \
dict_fail.h warn_stat.h dict_sockmap.h line_number.h timecmp.h \
slmdb.h compat_va_copy.h dict_pipe.h dict_random.h \
- valid_utf8_hostname.h midna_domain.h dict_union.h dict_inline.h check_arg.h
+ valid_utf8_hostname.h midna_domain.h dict_union.h dict_inline.h \
+ check_arg.h argv_attr.h
TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
stream_test.c dup2_pass_on_exec.c
DEFS = -I. -D$(SYSTYPE)
argv.o: msg.h
argv.o: mymalloc.h
argv.o: sys_defs.h
+argv_attr_print.o: argv.h
+argv_attr_print.o: argv_attr.h
+argv_attr_print.o: argv_attr_print.c
+argv_attr_print.o: attr.h
+argv_attr_print.o: check_arg.h
+argv_attr_print.o: htable.h
+argv_attr_print.o: mymalloc.h
+argv_attr_print.o: nvtable.h
+argv_attr_print.o: sys_defs.h
+argv_attr_print.o: vbuf.h
+argv_attr_print.o: vstream.h
+argv_attr_print.o: vstring.h
+argv_attr_scan.o: argv.h
+argv_attr_scan.o: argv_attr.h
+argv_attr_scan.o: argv_attr_scan.c
+argv_attr_scan.o: attr.h
+argv_attr_scan.o: check_arg.h
+argv_attr_scan.o: htable.h
+argv_attr_scan.o: msg.h
+argv_attr_scan.o: mymalloc.h
+argv_attr_scan.o: nvtable.h
+argv_attr_scan.o: sys_defs.h
+argv_attr_scan.o: vbuf.h
+argv_attr_scan.o: vstream.h
+argv_attr_scan.o: vstring.h
argv_split.o: argv.h
argv_split.o: argv_split.c
argv_split.o: check_arg.h
load_file.o: vstream.h
load_file.o: warn_stat.h
load_lib.o: load_lib.c
+load_lib.o: load_lib.h
+load_lib.o: msg.h
load_lib.o: sys_defs.h
lowercase.o: check_arg.h
lowercase.o: lowercase.c
vbuf.o: vbuf.h
vbuf_print.o: check_arg.h
vbuf_print.o: msg.h
+vbuf_print.o: mymalloc.h
vbuf_print.o: sys_defs.h
vbuf_print.o: vbuf.h
vbuf_print.o: vbuf_print.c
--- /dev/null
+#ifndef _ARGV_ATTR_H_INCLUDED_
+#define _ARGV_ATTR_H_INCLUDED_
+
+/*++
+/* NAME
+/* argv_attr 3h
+/* SUMMARY
+/* argv serialization/deserialization
+/* SYNOPSIS
+/* #include <argv_attr.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * Utility library.
+ */
+#include <argv.h>
+#include <attr.h>
+#include <check_arg.h>
+#include <vstream.h>
+
+ /*
+ * External API.
+ */
+#define ARGV_ATTR_SIZE "argv_size"
+#define ARGV_ATTR_VALUE "argv_value"
+#define ARGV_ATTR_MAX 1024
+
+extern int argv_attr_print(ATTR_PRINT_MASTER_FN, VSTREAM *, int, void *);
+extern int argv_attr_scan(ATTR_SCAN_MASTER_FN, VSTREAM *, int, void *);
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
+
+#endif
--- /dev/null
+/*++
+/* NAME
+/* argv_attr_print
+/* SUMMARY
+/* write ARGV to stream
+/* SYNOPSIS
+/* #include <argv_attr.h>
+/*
+/* int argv_attr_print(print_fn, stream, flags, ptr)
+/* ATTR_PRINT_MASTER_FN print_fn;
+/* VSTREAM *stream;
+/* int flags;
+/* void *ptr;
+/* DESCRIPTION
+/* argv_attr_print() writes an ARGV to the named stream using
+/* the specified attribute print routine. argv_attr_print() is meant
+/* to be passed as a call-back to attr_print(), thusly:
+/*
+/* ... SEND_ATTR_FUNC(argv_attr_print, (void *) argv), ...
+/* DIAGNOSTICS
+/* Fatal: out of memory.
+/*
+/* The result value is zero in case of success, non-zero
+/* otherwise.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+
+ /*
+ * Utility library.
+ */
+#include <argv.h>
+#include <argv_attr.h>
+#include <attr.h>
+#include <vstream.h>
+
+/* argv_attr_print - write ARGV to stream */
+
+int argv_attr_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp,
+ int flags, void *ptr)
+{
+ ARGV *argv = (ARGV *) ptr;
+ char **cpp;
+ int n;
+ int ret;
+ int argc = argv ? argv->argc : 0;
+
+ if ((ret = print_fn(fp, flags | ATTR_FLAG_MORE,
+ SEND_ATTR_INT(ARGV_ATTR_SIZE, argc),
+ ATTR_TYPE_END)) != 0)
+ return (ret);
+ if (argc > 0) {
+ for (n = 0, cpp = argv->argv; n < argc; n++, cpp++) {
+ if ((ret = print_fn(fp, flags | ATTR_FLAG_MORE,
+ SEND_ATTR_STR(ARGV_ATTR_VALUE, *cpp),
+ ATTR_TYPE_END)) != 0)
+ break;
+ }
+ }
+ return (ret);
+}
--- /dev/null
+/*++
+/* NAME
+/* argv_attr_scan
+/* SUMMARY
+/* read ARGV from stream
+/* SYNOPSIS
+/* #include <argv_attr.h>
+/*
+/* int argv_attr_scan(scan_fn, stream, flags, ptr)
+/* ATTR_SCAN_MASTER_FN scan_fn;
+/* VSTREAM *stream;
+/* int flags;
+/* void *ptr;
+/* DESCRIPTION
+/* argv_attr_scan() creates an ARGV and reads its contents
+/* from the named stream using the specified attribute scan
+/* routine. argv_attr_scan() is meant to be passed as a call-back
+/* to attr_scan(), thusly:
+/*
+/* ARGV *argv = 0;
+/* ...
+/* ... RECV_ATTR_FUNC(argv_attr_scan, (void *) &argv), ...
+/* ...
+/* if (argv)
+/* argv_free(argv);
+/* DIAGNOSTICS
+/* Fatal: out of memory.
+/*
+/* In case of error, this function returns non-zero and creates
+/* an ARGV null pointer.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+
+ /*
+ * Utility library.
+ */
+#include <argv.h>
+#include <argv_attr.h>
+#include <attr.h>
+#include <msg.h>
+#include <vstream.h>
+#include <vstring.h>
+
+/* argv_attr_scan - write ARGV to stream */
+
+int argv_attr_scan(ATTR_PRINT_MASTER_FN scan_fn, VSTREAM *fp,
+ int flags, void *ptr)
+{
+ ARGV *argv;
+ int size;
+ int ret;
+
+ if ((ret = scan_fn(fp, flags | ATTR_FLAG_MORE,
+ RECV_ATTR_INT(ARGV_ATTR_SIZE, &size),
+ ATTR_TYPE_END)) != 0) {
+ argv = 0;
+ } else if (size < 0 || size > ARGV_ATTR_MAX) {
+ msg_warn("invalid size %d from %s while reading ARGV",
+ size, VSTREAM_PATH(fp));
+ argv = 0;
+ } else if (size == 0) {
+ argv = 0;
+ } else {
+ VSTRING *buffer = vstring_alloc(100);
+
+ argv = argv_alloc(size);
+ while (size-- > 0) {
+ if ((ret = scan_fn(fp, flags | ATTR_FLAG_MORE,
+ RECV_ATTR_STR(ARGV_ATTR_VALUE, buffer),
+ ATTR_TYPE_END)) != 0)
+ break;
+ argv_add(argv, vstring_str(buffer), ARGV_END);
+ }
+ argv_terminate(argv);
+ vstring_free(buffer);
+ }
+ *(ARGV **) ptr = argv;
+ return (ret);
+}