]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.4-20180422-nonprod 20180422-nonprod
authorWietse Venema <wietse@porcupine.org>
Sun, 22 Apr 2018 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Mon, 23 Apr 2018 00:09:29 +0000 (20:09 -0400)
37 files changed:
postfix/HISTORY
postfix/makedefs
postfix/src/global/mail_proto.h
postfix/src/postscreen/postscreen_starttls.c
postfix/src/posttls-finger/posttls-finger.c
postfix/src/smtp/Makefile.in
postfix/src/smtp/lmtp_params.c
postfix/src/smtp/smtp.c
postfix/src/smtp/smtp.h
postfix/src/smtp/smtp_params.c
postfix/src/smtp/smtp_proto.c
postfix/src/smtp/smtp_session.c
postfix/src/smtpd/smtpd.c
postfix/src/tls/Makefile.in
postfix/src/tls/tls.h
postfix/src/tls/tls_client.c
postfix/src/tls/tls_proxy.h
postfix/src/tls/tls_proxy_client_init_print.c [new file with mode: 0644]
postfix/src/tls/tls_proxy_client_init_scan.c [new file with mode: 0644]
postfix/src/tls/tls_proxy_client_start_print.c [new file with mode: 0644]
postfix/src/tls/tls_proxy_client_start_scan.c [new file with mode: 0644]
postfix/src/tls/tls_proxy_clnt.c
postfix/src/tls/tls_proxy_context_print.c [moved from postfix/src/tls/tls_proxy_print.c with 63% similarity]
postfix/src/tls/tls_proxy_context_scan.c [new file with mode: 0644]
postfix/src/tls/tls_proxy_scan.c [deleted file]
postfix/src/tls/tls_proxy_server_init_print.c [new file with mode: 0644]
postfix/src/tls/tls_proxy_server_init_scan.c [new file with mode: 0644]
postfix/src/tls/tls_proxy_server_start_print.c [new file with mode: 0644]
postfix/src/tls/tls_proxy_server_start_scan.c [new file with mode: 0644]
postfix/src/tlsproxy/Makefile.in
postfix/src/tlsproxy/tlsproxy.c
postfix/src/tlsproxy/tlsproxy.h
postfix/src/tlsproxy/tlsproxy_state.c
postfix/src/util/Makefile.in
postfix/src/util/argv_attr.h [new file with mode: 0644]
postfix/src/util/argv_attr_print.c [new file with mode: 0644]
postfix/src/util/argv_attr_scan.c [new file with mode: 0644]

index 04e7f01fd1bcf1b109a53d3ae5adef62ca63ff7b..71ea22d3287081b4b70592733c9ce3a5cf58cbbb 100644 (file)
@@ -23396,3 +23396,35 @@ Apologies for any names omitted.
 
        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.
index 5449732b09a57c45c9a027bc08208cd05f39f26f..26e950d4b72eadc4d643c727e79a2aabe813616d 100644 (file)
@@ -878,7 +878,7 @@ CCARGS="$CCARGS -DSNAPSHOT"
 
 # 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"
index 363bc71ec84d0510ada614ea91217846ead322cc..9fc9ab68eaea59784d9db152439858ed68979961 100644 (file)
@@ -276,25 +276,6 @@ extern char *mail_pathname(const char *, const char *);
 #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.
   */
index a5d6906e695ca42049c524200cb67e15a9cce627..863ba8c23391881a37eb175ddd60b93d2119ea0e 100644 (file)
@@ -226,10 +226,10 @@ void    psc_starttls_open(PSC_STATE *smtp_state, EVENT_NOTIFY_FN resume_event)
     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);
index 5f559b4fd06d8bdc6510077b5b16864315d1e723..565e7ddb18a31c783e49a10a5c9339b6df815e1b 100644 (file)
@@ -747,6 +747,7 @@ static int starttls(STATE *state)
        TLS_CLIENT_START(&tls_props,
                         ctx = state->tls_ctx,
                         stream = stream,
+                        fd = -1,
                         timeout = smtp_tmout,
                         tls_level = state->level,
                         nexthop = state->nexthop,
index acd830264dc94290d858c1f2e49e7693b0ebcafb..7d455649699ff5f65d1be592e25524522874dda0 100644 (file)
@@ -101,8 +101,10 @@ smtp.o: ../../include/flush_clnt.h
 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
@@ -124,6 +126,7 @@ smtp.o: ../../include/string_list.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
@@ -168,6 +171,7 @@ smtp_addr.o: ../../include/string_list.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
@@ -217,6 +221,7 @@ smtp_chat.o: ../../include/string_list.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
@@ -266,6 +271,7 @@ smtp_connect.o: ../../include/stringops.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
@@ -305,6 +311,7 @@ smtp_key.o: ../../include/sock_addr.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
@@ -344,6 +351,7 @@ smtp_map11.o: ../../include/sock_addr.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
@@ -405,6 +413,7 @@ smtp_proto.o: ../../include/string_list.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
@@ -450,6 +459,7 @@ smtp_rcpt.o: ../../include/string_list.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
@@ -487,6 +497,7 @@ smtp_reuse.o: ../../include/string_list.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
@@ -527,6 +538,7 @@ smtp_sasl_auth_cache.o: ../../include/string_list.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
@@ -569,6 +581,7 @@ smtp_sasl_glue.o: ../../include/string_list.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
@@ -609,6 +622,7 @@ smtp_sasl_proto.o: ../../include/string_list.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
@@ -648,6 +662,7 @@ smtp_session.o: ../../include/string_list.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
@@ -685,6 +700,7 @@ smtp_state.o: ../../include/sock_addr.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
@@ -724,6 +740,7 @@ smtp_tls_policy.o: ../../include/string_list.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
@@ -768,6 +785,7 @@ smtp_trouble.o: ../../include/string_list.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
@@ -804,6 +822,7 @@ smtp_unalias.o: ../../include/sock_addr.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
index 68d611e265b77c2628b2cc8138bf077e2cbc63fa..5bbe9cbc04b1e8e1a5ef72e4b61b027e3d86adae 100644 (file)
@@ -61,6 +61,7 @@
        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[] = {
index ed27be96ae3771ef97cbbd6cf98bfda6647fc8c8..f5067e992edd84fdd458b358530c5999e6c81d2d 100644 (file)
 /* Global library. */
 
 #include <deliver_request.h>
+#include <mail_proto.h>
 #include <mail_params.h>
 #include <mail_version.h>
 #include <mail_conf.h>
@@ -895,6 +896,7 @@ bool    var_smtp_enforce_tls;
 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;
@@ -978,7 +980,10 @@ HBC_CHECKS *smtp_body_checks;              /* limited body checks */
  /*
   * OpenSSL client state (opaque handle)
   */
+#ifndef USE_TLSPROXY
 TLS_APPL_STATE *smtp_tls_ctx;
+
+#endif
 int     smtp_tls_insecure_mx_policy;
 
 #endif
@@ -1211,6 +1216,7 @@ static void pre_init(char *unused_name, char **unused_argv)
      */
     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;
 
        /*
@@ -1235,6 +1241,7 @@ static void pre_init(char *unused_name, char **unused_argv)
                            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");
index 11beb440683c97dc736d2f904e5413d4dc5f2e2b..dceb3f6c1aec2da847fef533158ba86438ee2964 100644 (file)
   */
 #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
@@ -288,8 +293,10 @@ extern int smtp_ext_prop_mask;             /* address externsion propagation */
 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
index ed5ea455ba7079e3c0e8b3aa498ada33dc7ee353..35a67470f35319df7b782c0491573b867fef0148 100644 (file)
@@ -62,6 +62,7 @@
        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[] = {
index 15a15db171e0c7311d029f54f75f0acc20bb6f39..74a2ecd95ecf39eaf8c1e3ee1fd275d9ebc18e9c 100644 (file)
@@ -757,7 +757,10 @@ int     smtp_helo(SMTP_STATE *state)
         * 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.
@@ -818,10 +821,12 @@ int     smtp_helo(SMTP_STATE *state)
                                       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);
@@ -848,10 +853,17 @@ static int smtp_start_tls(SMTP_STATE *state)
 {
     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
@@ -861,7 +873,9 @@ static int smtp_start_tls(SMTP_STATE *state)
      * 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:
@@ -894,6 +908,80 @@ static int smtp_start_tls(SMTP_STATE *state)
                    | 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
@@ -908,9 +996,10 @@ static int smtp_start_tls(SMTP_STATE *state)
      * 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,
@@ -925,6 +1014,7 @@ static int smtp_start_tls(SMTP_STATE *state)
                         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) {
index 806d8de060bd38214268c0d57d0728802fdf9b26..416a67d1cb512ba7711766add2d9b1cfa8378acb 100644 (file)
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
 /*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
+/*
 /*     Viktor Dukhovni
 /*--*/
 
@@ -176,9 +181,14 @@ void    smtp_session_free(SMTP_SESSION *session)
 #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)
index 20598992b7db35f94be471f65066fd21b61b1f72..5006e7449197770427ff0e98c80e282f32edec70 100644 (file)
@@ -1496,9 +1496,11 @@ static void tls_reset(SMTPD_STATE *);
  /*
   * TLS initialization status.
   */
+#ifndef USE_TLSPROXY
 static TLS_APPL_STATE *smtpd_tls_ctx;
 static int ask_client_cert;
 
+#endif                                 /* USE_TLSPROXY */
 #endif
 
  /*
@@ -4704,9 +4706,11 @@ static int starttls_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
 #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. */
@@ -4963,10 +4967,12 @@ static void smtpd_proto(SMTPD_STATE *state)
        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"
index 55dfd1ecce917733b3d2534f7f8d7d9be215c006..dea34b08cd2ae8d46dab5e9e7dbd7d4d9c379db2 100644 (file)
@@ -4,13 +4,21 @@ SRCS  = tls_prng_dev.c tls_prng_egd.c tls_prng_file.c tls_fprint.c \
        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)
@@ -294,6 +302,80 @@ tls_prng_file.o: ../../include/mymalloc.h
 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
@@ -318,46 +400,114 @@ tls_proxy_clnt.o: ../../include/vstring.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
index 79b8d73a3b10903f7ed422e16898b12af1bb5955..01419cb56253d3b3b2533db7fec6eb33833c34d1 100644 (file)
@@ -448,6 +448,7 @@ typedef struct {
 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 */
@@ -465,6 +466,8 @@ typedef struct {
 
 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))
@@ -477,11 +480,12 @@ extern TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *);
     ((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
index bbe18f9050fba1cd5aff8ce8842914567b6f919e..09e523364eaf77be648cf29b07921001e77e15d6 100644 (file)
 /*     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
@@ -837,8 +866,6 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
     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;
@@ -1018,7 +1045,8 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
     /*
      * 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);
@@ -1026,12 +1054,6 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
        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
@@ -1046,6 +1068,19 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
 
     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.
@@ -1069,8 +1104,19 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
        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);
 
     /*
@@ -1078,7 +1124,7 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
      * 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);
 
     /*
@@ -1125,7 +1171,8 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
      * 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.
@@ -1142,7 +1189,7 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
     /*
      * 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" :
index e677c67aba9d38e562198afb8832cd13c373a24d..921d3c76549b3e6bb6c00e08e96e9b1daffdfa5c 100644 (file)
 
 #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
diff --git a/postfix/src/tls/tls_proxy_client_init_print.c b/postfix/src/tls/tls_proxy_client_init_print.c
new file mode 100644 (file)
index 0000000..00157c2
--- /dev/null
@@ -0,0 +1,90 @@
+/*++
+/* 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
diff --git a/postfix/src/tls/tls_proxy_client_init_scan.c b/postfix/src/tls/tls_proxy_client_init_scan.c
new file mode 100644 (file)
index 0000000..a7dedec
--- /dev/null
@@ -0,0 +1,161 @@
+/*++
+/* 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
diff --git a/postfix/src/tls/tls_proxy_client_start_print.c b/postfix/src/tls/tls_proxy_client_start_print.c
new file mode 100644 (file)
index 0000000..a049595
--- /dev/null
@@ -0,0 +1,89 @@
+/*++
+/* 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
diff --git a/postfix/src/tls/tls_proxy_client_start_scan.c b/postfix/src/tls/tls_proxy_client_start_scan.c
new file mode 100644 (file)
index 0000000..04e5198
--- /dev/null
@@ -0,0 +1,138 @@
+/*++
+/* 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
index 97d096264c04b7deec4385d1fc129cac0ad9632f..e000b57ea634566b4ce9f0fb1c1ec7143d248259 100644 (file)
@@ -2,24 +2,36 @@
 /* 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
@@ -44,8 +56,8 @@
 /*
 /*     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
@@ -119,8 +142,12 @@ VSTREAM *tls_proxy_open(const char *service, int flags,
                                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;
@@ -146,19 +173,42 @@ VSTREAM *tls_proxy_open(const char *service, int flags,
     }
 
     /*
-     * 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));
@@ -170,7 +220,7 @@ VSTREAM *tls_proxy_open(const char *service, int flags,
      * 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,
@@ -191,7 +241,7 @@ VSTREAM *tls_proxy_open(const char *service, int flags,
     }
 
     /*
-     * 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) {
@@ -211,37 +261,17 @@ VSTREAM *tls_proxy_open(const char *service, int flags,
 
 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
similarity index 63%
rename from postfix/src/tls/tls_proxy_print.c
rename to postfix/src/tls/tls_proxy_context_print.c
index e30e8be88beea626dd26ef4e108f98ebed450354..a597024b2bbbf8440e2a0974ac0cb73c9ec7e626 100644 (file)
@@ -1,8 +1,8 @@
 /*++
 /* 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>
@@ -61,25 +62,26 @@ int     tls_proxy_context_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp,
 #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);
 }
 
diff --git a/postfix/src/tls/tls_proxy_context_scan.c b/postfix/src/tls/tls_proxy_context_scan.c
new file mode 100644 (file)
index 0000000..b2fe1d5
--- /dev/null
@@ -0,0 +1,128 @@
+/*++
+/* 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
diff --git a/postfix/src/tls/tls_proxy_scan.c b/postfix/src/tls/tls_proxy_scan.c
deleted file mode 100644 (file)
index 29a0cd9..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*++
-/* 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
diff --git a/postfix/src/tls/tls_proxy_server_init_print.c b/postfix/src/tls/tls_proxy_server_init_print.c
new file mode 100644 (file)
index 0000000..14a6587
--- /dev/null
@@ -0,0 +1,100 @@
+/*++
+/* 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
diff --git a/postfix/src/tls/tls_proxy_server_init_scan.c b/postfix/src/tls/tls_proxy_server_init_scan.c
new file mode 100644 (file)
index 0000000..57b12ba
--- /dev/null
@@ -0,0 +1,155 @@
+/*++
+/* 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
diff --git a/postfix/src/tls/tls_proxy_server_start_print.c b/postfix/src/tls/tls_proxy_server_start_print.c
new file mode 100644 (file)
index 0000000..73498ad
--- /dev/null
@@ -0,0 +1,77 @@
+/*++
+/* 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
diff --git a/postfix/src/tls/tls_proxy_server_start_scan.c b/postfix/src/tls/tls_proxy_server_start_scan.c
new file mode 100644 (file)
index 0000000..352776e
--- /dev/null
@@ -0,0 +1,114 @@
+/*++
+/* 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
index 087721bf7597e127bede771c857af5043ab085b2..e248f8501c22e6eba99126b0acf18ea3209b7d6c 100644 (file)
@@ -61,6 +61,7 @@ depend: $(MAKES)
        @$(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
@@ -90,9 +91,11 @@ tlsproxy.o: ../../include/vstring.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
@@ -101,9 +104,11 @@ tlsproxy_state.o: ../../include/mymalloc.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
index 2c855ffcc72077fb38a924f68c4de886d23c24ab..e4fc6aeb5dc4974afa1b7d51751c5bea0b5bcfeb 100644 (file)
@@ -309,6 +309,17 @@ int     var_tlsp_watchdog;
 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.
   */
@@ -406,7 +417,7 @@ static int tlsp_eval_tls_error(TLSP_STATE *state, int err)
                                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
@@ -422,7 +433,7 @@ static int tlsp_eval_tls_error(TLSP_STATE *state, int err)
        }
        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
@@ -438,7 +449,7 @@ static int tlsp_eval_tls_error(TLSP_STATE *state, int err)
        }
        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
@@ -450,7 +461,7 @@ static int tlsp_eval_tls_error(TLSP_STATE *state, int err)
        /* FALLTHROUGH */
     default:
        tlsp_state_free(state);
-       return (-1);
+       return (TLSP_STAT_ERR);
     }
 }
 
@@ -471,14 +482,22 @@ static void tlsp_strategy(TLSP_STATE *state)
      * 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;
        }
@@ -661,9 +680,46 @@ static void tlsp_ciphertext_event(int event, void *context)
     }
 }
 
-/* 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;
@@ -676,8 +732,8 @@ static int tlsp_start_tls(TLSP_STATE *state)
      */
 
     /*
-     * 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
@@ -716,7 +772,7 @@ static int tlsp_start_tls(TLSP_STATE *state)
 
     if (state->tls_context == 0) {
        tlsp_state_free(state);
-       return (-1);
+       return (TLSP_STAT_ERR);
     }
 
     /*
@@ -729,16 +785,17 @@ static int tlsp_start_tls(TLSP_STATE *state)
      * 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
@@ -751,6 +808,25 @@ static void tlsp_get_fd_event(int event, void *context)
     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
@@ -760,33 +836,32 @@ static void tlsp_get_fd_event(int event, void *context)
      * 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)
 {
@@ -798,7 +873,7 @@ 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.
@@ -825,10 +900,10 @@ static void tlsp_get_request_event(int event, void *context)
      */
     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);
@@ -836,38 +911,66 @@ static void tlsp_get_request_event(int event, void *context)
        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);
@@ -1033,7 +1136,7 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
 
 static void post_jail_init(char *unused_name, char **unused_argv)
 {
-     /* void */ ;
+    tlsp_client_app_cache = htable_create(10);
 }
 
 MAIL_VERSION_STAMP_DECLARE;
index e3e1d11fa38df2a8ed2b84c800799d369642eb8f..336c58c69aee1af41a691293128bc717a728cedb 100644 (file)
@@ -25,6 +25,7 @@
 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 */
@@ -33,8 +34,13 @@ typedef struct {
     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)
@@ -51,4 +57,9 @@ extern void tlsp_state_free(TLSP_STATE *);
 /*     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
 /*--*/
index e327649207fe1d189c65a7c34859c4dc2b688c5b..adc2f2282758275343e545b8a937930a44c8de66 100644 (file)
 /*     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
 /*--*/
 
  /*
@@ -85,6 +90,7 @@
 #ifdef USE_TLS
 #define TLS_INTERNAL                   /* XXX */
 #include <tls.h>
+#include <tls_proxy.h>
 
  /*
   * Application-specific.
@@ -108,6 +114,10 @@ TLSP_STATE *tlsp_state_create(const char *service,
     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);
 }
@@ -134,6 +144,14 @@ void    tlsp_state_free(TLSP_STATE *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);
 }
 
index 32cefbc0773ec74a02ff2fcd47b58ae2903593a6..fad103280584bb35b3915812d5d0e8d315680074 100644 (file)
@@ -40,7 +40,7 @@ SRCS  = alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \
        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 \
@@ -82,7 +82,7 @@ OBJS  = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.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.
@@ -111,7 +111,8 @@ HDRS        = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \
        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)
@@ -879,6 +880,31 @@ argv.o: argv.h
 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
@@ -1785,6 +1811,8 @@ load_file.o: vbuf.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
@@ -2363,6 +2391,7 @@ vbuf.o: vbuf.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
diff --git a/postfix/src/util/argv_attr.h b/postfix/src/util/argv_attr.h
new file mode 100644 (file)
index 0000000..65cfa55
--- /dev/null
@@ -0,0 +1,43 @@
+#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
diff --git a/postfix/src/util/argv_attr_print.c b/postfix/src/util/argv_attr_print.c
new file mode 100644 (file)
index 0000000..1d4c576
--- /dev/null
@@ -0,0 +1,73 @@
+/*++
+/* 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);
+}
diff --git a/postfix/src/util/argv_attr_scan.c b/postfix/src/util/argv_attr_scan.c
new file mode 100644 (file)
index 0000000..2373343
--- /dev/null
@@ -0,0 +1,92 @@
+/*++
+/* 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);
+}