]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.3-20050920
authorWietse Venema <wietse@porcupine.org>
Tue, 20 Sep 2005 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:31:28 +0000 (06:31 +0000)
30 files changed:
postfix/.indent.pro
postfix/HISTORY
postfix/README_FILES/IPV6_README
postfix/README_FILES/SASL_README
postfix/README_FILES/TLS_README
postfix/html/IPV6_README.html
postfix/html/SASL_README.html
postfix/html/TLS_README.html
postfix/html/ldap_table.5.html
postfix/man/man5/ldap_table.5
postfix/proto/IPV6_README.html
postfix/proto/SASL_README.html
postfix/proto/TLS_README.html
postfix/proto/ldap_table
postfix/src/global/mail_version.h
postfix/src/smtp/smtp.h
postfix/src/smtp/smtp_proto.c
postfix/src/smtp/smtp_session.c
postfix/src/smtpd/smtpd.c
postfix/src/smtpd/smtpd.h
postfix/src/smtpd/smtpd_check.c
postfix/src/smtpd/smtpd_state.c
postfix/src/tls/Makefile.in
postfix/src/tls/tls.h
postfix/src/tls/tls_client.c
postfix/src/tls/tls_misc.c
postfix/src/tls/tls_server.c
postfix/src/tls/tls_session.c
postfix/src/tls/tls_temp.c [deleted file]
postfix/src/tls/tls_verify.c

index 5a3608b54bb6af140eed2ec6391e8ecb0471a1cc..2a8c443b764c9e581d8d0eea36befb65c4725559 100644 (file)
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-TX509
+-TX509_NAME
 -TX509_STORE_CTX
 -Tregex_t
 -Tregmatch_t
index afeb334602a92aec31d6d788a526f0b3affca737..8c9da4bb88509f85d7384100842f75181ad665f1 100644 (file)
@@ -11115,6 +11115,15 @@ Apologies for any names omitted.
        needed before cleanup_bounce() can seek to the start of the
        queue file after a file size error. File: util/vstream.c.
 
+20050920
+
+       Cleanup: removed the legacy "tls_info" structure, factored
+       out common code for peer_CN and issuer_CN lookup, and added
+       sanity check to not verify subject common names that contain
+       nulls or that are execessively long. Patch by Victor Duchovni.
+       Files: tls_client.c, tls_server.c, tls_session.c, tls_misc.c,
+       tls_verify.c.
+       
 Open problems:
 
        Look for systems with XPG basename() declared in <libgen.h>,
index 742941c9786069b5856b6b35cf75c805116ad3c0..ee49675b79ac636b8de1213368cb5d673f1f2592 100644 (file)
@@ -13,7 +13,7 @@ The main feature of interest is that IPv6 uses 128-bit IP addresses instead of
 the 32-bit addresses used by IPv4. It can therefore accommodate a much larger
 number of hosts and networks without ugly kluges such as NAT. A side benefit of
 the much larger address space is that it makes random network scanning
-unpractical.
+impractical.
 
 Postfix uses the same SMTP protocol over IPv6 as it already uses over the older
 IPv4 network, and does AAAA record lookups in the DNS in addition to the older
index 54c65bfcbb97b60d2bc9ee8e6b9f74012820618a..2cc7da6af350efccd4290a195f95984e86bd22bf 100644 (file)
@@ -20,6 +20,10 @@ When receiving mail, Postfix logs the client-provided username, authentication
 method, and sender address to the maillog file, and optionally grants mail
 access via the permit_sasl_authenticated UCE restriction.
 
+When sending mail, Postfix can look up the server hostname or destination
+domain (the address right-hand part) in a table, and if a username/password is
+found, it will use that username and password to authenticate to the server.
+
 This document covers the following topics:
 
   * What SASL versions are supported
@@ -31,10 +35,6 @@ This document covers the following topics:
   * Enabling SASL authentication in the Postfix SMTP client
   * Credits
 
-When sending mail, Postfix can look up the server hostname or destination
-domain (the address right-hand part) in a table, and if a username/password is
-found, it will use that username and password to authenticate to the server.
-
 W\bWh\bha\bat\bt S\bSA\bAS\bSL\bL v\bve\ber\brs\bsi\bio\bon\bns\bs a\bar\bre\be s\bsu\bup\bpp\bpo\bor\brt\bte\bed\bd
 
 Postfix+SASL 1.5.5 was seen working on RedHat 6.1 (pwcheck_method set to shadow
index 1e1a753834a4334382ac99e0395bdd53a0e8c2c9..3c8fbb41ba48cc1b95d29c6ee431e325bd8adc4b 100644 (file)
@@ -422,7 +422,7 @@ Example:
             ...
 
 The Postfix list manipulation routines give special treatment to whitespace and
-some other characters, making the use of certificate names unpractical. Instead
+some other characters, making the use of certificate names impractical. Instead
 we use the certificate fingerprints as they are difficult to fake but easy to
 use for lookup. Postfix lookup tables are in the form of (key, value) pairs.
 Since we only need the key, the value can be chosen freely, e.g. the name of
index 4b7463630c7a6a8848999959dc07c5cf8ffee3fa..cce966534d70cbe67226d73e0ad1175b6af02fae 100644 (file)
@@ -30,7 +30,7 @@ between these implementations. </p>
 addresses instead of the 32-bit addresses used by IPv4. It can
 therefore accommodate a much larger number of hosts and networks
 without ugly kluges such as NAT. A side benefit of the much larger
-address space is that it makes random network scanning unpractical.
+address space is that it makes random network scanning impractical.
 </p>
 
 <p> Postfix uses the same SMTP protocol over IPv6 as it already
index e9f45f25b4d399d84a3c14fb3be725d3f5139ff4..f3e53efaddd97584df5b31a50397b4ac983d9fd9 100644 (file)
@@ -37,6 +37,11 @@ authentication method, and sender address to the maillog file, and
 optionally grants mail access via the <a href="postconf.5.html#permit_sasl_authenticated">permit_sasl_authenticated</a>
 UCE restriction. </p>
 
+<p> When sending mail, Postfix can look up the server hostname or
+destination domain (the address right-hand part) in a table, and if a
+username/password is found, it will use that username and password
+to authenticate to the server. </p>
+
 <p>This document covers the following topics: </p>
 
 <ul>
@@ -63,11 +68,6 @@ Postfix SMTP client</a></li>
 
 </ul>
 
-<p> When sending mail, Postfix can look up the server hostname or
-destination domain (the address right-hand part) in a table, and if a
-username/password is found, it will use that username and password
-to authenticate to the server. </p>
-
 <h2><a name="versions">What SASL versions are supported</a></h2>
 
 <p> Postfix+SASL 1.5.5 was seen working on RedHat 6.1 (pwcheck_method
index 054bb40b2f4cb91814287911d41a9a3e1b36c7ad..307f4074177effc1d95e11a58931e64bd66ecfed 100644 (file)
@@ -591,7 +591,7 @@ Postfix SMTP server access control:  </p>
 <dt> <a href="postconf.5.html#permit_tls_clientcerts">permit_tls_clientcerts</a> </dt> <dd> <p> Allow the remote SMTP
 client SMTP request if the client certificate passes verification,
 and if its fingerprint is listed in the list of client certificates
-(see relay_clientcerts discussion below). </p> </dd>
+(see <a href="postconf.5.html#relay_clientcerts">relay_clientcerts</a> discussion below). </p> </dd>
 
 <dt> <a href="postconf.5.html#permit_tls_all_clientcerts">permit_tls_all_clientcerts</a> </dt> <dd> <p> Allow the remote
 client SMTP request if the client certificate passes verification.
@@ -614,7 +614,7 @@ The <a href="postconf.5.html#permit_tls_all_clientcerts">permit_tls_all_clientce
 specially created email relay server.  </p>
 
 <p> It is however recommended to stay with the <a href="postconf.5.html#permit_tls_clientcerts">permit_tls_clientcerts</a>
-feature and list all certificates via $relay_clientcerts, as
+feature and list all certificates via $<a href="postconf.5.html#relay_clientcerts">relay_clientcerts</a>, as
 <a href="postconf.5.html#permit_tls_all_clientcerts">permit_tls_all_clientcerts</a> does not permit any control when a
 certificate must no longer be used (e.g. an employee leaving). </p>
 
@@ -633,7 +633,7 @@ certificate must no longer be used (e.g. an employee leaving). </p>
 
 <p> The Postfix list manipulation routines give special treatment
 to whitespace and some other characters, making the use of certificate
-names unpractical.  Instead we use the certificate fingerprints as
+names impractical.  Instead we use the certificate fingerprints as
 they are difficult to fake but easy to use for lookup.  Postfix
 lookup tables are in the form of (key, value) pairs.  Since we only
 need the key, the value can be chosen freely, e.g.  the name of
@@ -644,7 +644,7 @@ the user or host.</p>
 <blockquote>
 <pre>
 /etc/postfix/main.cf:
-    relay_clientcerts = hash:/etc/postfix/relay_clientcerts
+    <a href="postconf.5.html#relay_clientcerts">relay_clientcerts</a> = hash:/etc/postfix/relay_clientcerts
 
 /etc/postfix/relay_clientcerts:
     D7:04:2F:A7:0B:8C:A5:21:FA:31:77:E1:41:8A:EE:80 lutzpc.at.home
index e03a2ef5716e293397d7d8e80067d3d3c50b858d..254f5d0d15cccdd0d3b813a215120f4f88746dd9 100644 (file)
@@ -324,7 +324,7 @@ LDAP_TABLE(5)                                                    LDAP_TABLE(5)
               NOTE:  DO  NOT  define  this parameter for <a href="local.8.html">local(8)</a>
               aliases.
 
-              This feature is available in Postfix 2.1 and later.
+              This feature is available in Postfix 1.0 and later.
 
        <b>result_attribute (default: maildrop)</b>
               The  attribute(s) Postfix will read from any direc-
index 43654be47d81cee1444c4235e15c798001eb52ab..9a0c79f9ac7c5cd595382c36111543ef1d46e32a 100644 (file)
@@ -305,7 +305,7 @@ for LDAP lookups.
 
 NOTE: DO NOT define this parameter for local(8) aliases.
 
-This feature is available in Postfix 2.1 and later.
+This feature is available in Postfix 1.0 and later.
 .IP "\fBresult_attribute (default: maildrop)\fR"
 The attribute(s) Postfix will read from any directory
 entries returned by the lookup, to be resolved to an email
index 10e5424b1810de8d4173101410b59f19be9e0503..f5a8a9006c2ab52735d8db66ffa0cce80ad62660 100644 (file)
@@ -30,7 +30,7 @@ between these implementations. </p>
 addresses instead of the 32-bit addresses used by IPv4. It can
 therefore accommodate a much larger number of hosts and networks
 without ugly kluges such as NAT. A side benefit of the much larger
-address space is that it makes random network scanning unpractical.
+address space is that it makes random network scanning impractical.
 </p>
 
 <p> Postfix uses the same SMTP protocol over IPv6 as it already
index 9b019129f5ce6e944adf43939dee6d746648d1f7..8a6aa49c6e4f99703f7ea62a41b962a38bcb5d25 100644 (file)
@@ -37,6 +37,11 @@ authentication method, and sender address to the maillog file, and
 optionally grants mail access via the permit_sasl_authenticated
 UCE restriction. </p>
 
+<p> When sending mail, Postfix can look up the server hostname or
+destination domain (the address right-hand part) in a table, and if a
+username/password is found, it will use that username and password
+to authenticate to the server. </p>
+
 <p>This document covers the following topics: </p>
 
 <ul>
@@ -63,11 +68,6 @@ Postfix SMTP client</a></li>
 
 </ul>
 
-<p> When sending mail, Postfix can look up the server hostname or
-destination domain (the address right-hand part) in a table, and if a
-username/password is found, it will use that username and password
-to authenticate to the server. </p>
-
 <h2><a name="versions">What SASL versions are supported</a></h2>
 
 <p> Postfix+SASL 1.5.5 was seen working on RedHat 6.1 (pwcheck_method
index 23f51d28b77ec6a0b353fceb727198ea522fc01f..5e3243b0d78780ebff9b96a167c3611c3043faac 100644 (file)
@@ -633,7 +633,7 @@ certificate must no longer be used (e.g. an employee leaving). </p>
 
 <p> The Postfix list manipulation routines give special treatment
 to whitespace and some other characters, making the use of certificate
-names unpractical.  Instead we use the certificate fingerprints as
+names impractical.  Instead we use the certificate fingerprints as
 they are difficult to fake but easy to use for lookup.  Postfix
 lookup tables are in the form of (key, value) pairs.  Since we only
 need the key, the value can be chosen freely, e.g.  the name of
index 8faec658373bb47122d1e6a33af559b3eaf86d0a..ec26743637421f245765cfc4635acd2e2aedb268 100644 (file)
 #
 #      NOTE: DO NOT define this parameter for local(8) aliases.
 #
-#      This feature is available in Postfix 2.1 and later.
+#      This feature is available in Postfix 1.0 and later.
 # .IP "\fBresult_attribute (default: maildrop)\fR"
 #      The attribute(s) Postfix will read from any directory
 #      entries returned by the lookup, to be resolved to an email
index 6c87a3a040e12095f7c18a2a5555ce0c080a1ba2..72a3f5a0121e44a9c0374b70805ae5d0034587b6 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20050829"
+#define MAIL_RELEASE_DATE      "20050920"
 #define MAIL_VERSION_NUMBER    "2.3"
 
 #ifdef SNAPSHOT
index d924ce3434d7810e39b721ece1e188c8213edc56..919cc81322cec34a92fd40cbc0a0ee7e5ce9ae84 100644 (file)
@@ -217,7 +217,6 @@ typedef struct SMTP_SESSION {
     int     tls_enforce_tls;           /* must do TLS */
     int     tls_enforce_peername;      /* cert must match */
     TLScontext_t *tls_context;         /* TLS session state */
-    tls_info_t tls_info;               /* legacy */
 #endif
 
 } SMTP_SESSION;
index b9da58558ca8c7bce2840e22dc8b7d80c581aad1..a52fd61063225dddf16935fdddd5fc01a61ae768 100644 (file)
@@ -626,8 +626,7 @@ static int smtp_start_tls(SMTP_STATE *state, int misc_flags)
                         var_smtp_starttls_tmout,
                         session->tls_enforce_peername,
                         session->host,
-                        lowercase(vstring_str(serverid)),
-                        &(session->tls_info));
+                        lowercase(vstring_str(serverid)));
     vstring_free(serverid);
     if (session->tls_context == 0)
        return (smtp_site_fail(state, DSN_BY_LOCAL_MTA,
@@ -815,6 +814,7 @@ static void smtp_header_rewrite(void *context, int header_class,
        }
     }
 }
+
 /* smtp_mime_fail - MIME problem */
 
 static void smtp_mime_fail(SMTP_STATE *state, int mime_errs)
index f9d338708a9f24f613fe19117b902724987f59a1..e71defd9d498f63c2278af66e990dc5ada406ce7 100644 (file)
@@ -233,7 +233,6 @@ SMTP_SESSION *smtp_session_alloc(VSTREAM *stream, const char *dest,
     session->tls_use_tls = session->tls_enforce_tls = 0;
     session->tls_enforce_peername = 0;
     session->tls_context = 0;
-    session->tls_info = tls_info_zero;
 
     /*
      * Override the main.cf TLS policy with an optional per-site policy.
@@ -282,8 +281,7 @@ void    smtp_session_free(SMTP_SESSION *session)
        vstream_fflush(session->stream);
        if (session->tls_context)
            tls_client_stop(smtp_tls_ctx, session->stream,
-                           var_smtp_starttls_tmout, 0,
-                           &(session->tls_info));
+                         var_smtp_starttls_tmout, 0, session->tls_context);
     }
 #endif
     if (session->stream)
index c25b592d40764fe0ae6be89ff4903622493e103d..b9a4d1aab72b3d1a6878eb9e965b4e15c36552b4 100644 (file)
@@ -2142,15 +2142,17 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
        if (var_smtpd_tls_received_header && state->tls_context) {
            out_fprintf(out_stream, REC_TYPE_NORM,
                        "\t(using %s with cipher %s (%d/%d bits))",
-                     state->tls_info.protocol, state->tls_info.cipher_name,
-                       state->tls_info.cipher_usebits,
-                       state->tls_info.cipher_algbits);
-           if (state->tls_info.peer_CN) {
-               peer_CN = VSTRING_STRDUP(state->tls_info.peer_CN);
+                       state->tls_context->protocol,
+                       state->tls_context->cipher_name,
+                       state->tls_context->cipher_usebits,
+                       state->tls_context->cipher_algbits);
+           if (state->tls_context->peer_CN) {
+               peer_CN = VSTRING_STRDUP(state->tls_context->peer_CN);
                comment_sanitize(peer_CN);
-               issuer_CN = VSTRING_STRDUP(state->tls_info.issuer_CN);
+               issuer_CN = VSTRING_STRDUP(state->tls_context->issuer_CN ?
+                                       state->tls_context->issuer_CN : "");
                comment_sanitize(issuer_CN);
-               if (state->tls_info.peer_verified)
+               if (state->tls_context->peer_verified)
                    out_fprintf(out_stream, REC_TYPE_NORM,
                        "\t(Client CN \"%s\", Issuer \"%s\" (verified OK))",
                                STR(peer_CN), STR(issuer_CN));
@@ -3036,8 +3038,7 @@ static void smtpd_start_tls(SMTPD_STATE *state)
      */
     state->tls_context =
     tls_server_start(smtpd_tls_ctx, state->client,
-                    var_smtpd_starttls_tmout,
-                    state->name, state->addr, &(state->tls_info),
+                    var_smtpd_starttls_tmout, state->name, state->addr,
                     (var_smtpd_tls_req_ccert && state->tls_enforce_tls));
 
     /*
@@ -3121,7 +3122,7 @@ static void tls_reset(SMTPD_STATE *state)
            failure = 1;
        vstream_fflush(state->client);          /* NOT: smtp_flush() */
        tls_server_stop(smtpd_tls_ctx, state->client, var_smtpd_starttls_tmout,
-                       failure, &(state->tls_info));
+                       failure, state->tls_context);
        state->tls_context = 0;
     }
 }
index 6c38008950fac68dcaad69dd985ce5ad3b73d6f0..80a0a5de4a9345f414135c1fcac77e50f4f7f0b7 100644 (file)
@@ -175,7 +175,6 @@ typedef struct SMTPD_STATE {
     int     tls_enforce_tls;           /* must use TLS */
     int     tls_auth_only;             /* use SASL over TLS only */
     TLScontext_t *tls_context;         /* TLS session state */
-    tls_info_t tls_info;               /* legacy */
 #endif
 
 } SMTPD_STATE;
index 00e0dd60a6455a9b746a77388343180ce1b115ec..660e4efebbd0311964475f6bc230bdfcc899ad33 100644 (file)
@@ -1216,13 +1216,17 @@ static int permit_tls_clientcerts(SMTPD_STATE *state, int permit_all_certs)
     char   *low_name;
     const char *found;
 
-    if (state->tls_info.peer_verified && permit_all_certs) {
+    if (!state->tls_context)
+       return SMTPD_CHECK_DUNNO;
+
+    if (state->tls_context->peer_verified && permit_all_certs) {
        if (msg_verbose)
            msg_info("Relaying allowed for all verified client certificates");
        return (SMTPD_CHECK_OK);
     }
-    if (state->tls_info.peer_verified && state->tls_info.peer_fingerprint) {
-       low_name = lowercase(mystrdup(state->tls_info.peer_fingerprint));
+    if (state->tls_context->peer_verified
+       && state->tls_context->peer_fingerprint) {
+       low_name = lowercase(mystrdup(state->tls_context->peer_fingerprint));
        found = maps_find(relay_ccerts, low_name, DICT_FLAG_FIXED);
        myfree(low_name);
        if (found) {
@@ -1231,7 +1235,7 @@ static int permit_tls_clientcerts(SMTPD_STATE *state, int permit_all_certs)
            return (SMTPD_CHECK_OK);
        } else if (msg_verbose)
            msg_info("relay_clientcerts: No match for fingerprint '%s'",
-                    state->tls_info.peer_fingerprint);
+                    state->tls_context->peer_fingerprint);
     }
     return (SMTPD_CHECK_DUNNO);
 }
@@ -2496,9 +2500,13 @@ static int check_ccert_access(SMTPD_STATE *state, const char *table,
     char   *myname = "check_ccert_access";
     int     found;
 
-    if (state->tls_info.peer_verified && state->tls_info.peer_fingerprint) {
+    if (!state->tls_context)
+       return SMTPD_CHECK_DUNNO;
+
+    if (state->tls_context->peer_verified
+       && state->tls_context->peer_fingerprint) {
        if (msg_verbose)
-           msg_info("%s: %s", myname, state->tls_info.peer_fingerprint);
+           msg_info("%s: %s", myname, state->tls_context->peer_fingerprint);
 
        /*
         * Regexp tables don't make sense for certificate fingerprints. That
@@ -2510,8 +2518,10 @@ static int check_ccert_access(SMTPD_STATE *state, const char *table,
         * client name and address are always syslogged as part of a "reject"
         * event.
         */
-       return (check_access(state, table, state->tls_info.peer_fingerprint,
-                            DICT_FLAG_NONE, &found, state->tls_info.peer_CN,
+       return (check_access(state, table,
+                            state->tls_context->peer_fingerprint,
+                            DICT_FLAG_NONE, &found,
+                            state->tls_context->peer_CN,
                             SMTPD_NAME_CCERT, def_acl));
     }
     return (SMTPD_CHECK_DUNNO);
@@ -3228,15 +3238,15 @@ static int check_policy_service(SMTPD_STATE *state, const char *server,
                          state->sasl_sender : "",
 #endif
 #ifdef USE_TLS
+#define IF_VERIFIED(x) \
+    ((state->tls_context && \
+      state->tls_context->peer_verified && ((x) != 0)) ? (x) : "")
                          ATTR_TYPE_STR, MAIL_ATTR_CCERT_SUBJECT,
-                         state->tls_info.peer_verified ?
-                         state->tls_info.peer_CN : "",
+                         IF_VERIFIED(state->tls_context->peer_CN),
                          ATTR_TYPE_STR, MAIL_ATTR_CCERT_ISSSUER,
-                         state->tls_info.peer_verified ?
-                         state->tls_info.issuer_CN : "",
+                         IF_VERIFIED(state->tls_context->issuer_CN),
                          ATTR_TYPE_STR, MAIL_ATTR_CCERT_FINGERPRINT,
-                         state->tls_info.peer_verified ?
-                         state->tls_info.peer_fingerprint : "",
+                         IF_VERIFIED(state->tls_context->peer_fingerprint),
 #endif
                          ATTR_TYPE_END,
                          ATTR_FLAG_MISSING,    /* Reply attributes. */
index d46716da4adadcd88fb5b8c85a734ac96c074524..bd443f0bd4dfd167ac37927dbd2ad1742ef62f87 100644 (file)
@@ -138,7 +138,6 @@ void    smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream,
     state->tls_enforce_tls = 0;
     state->tls_auth_only = 0;
     state->tls_context = 0;
-    state->tls_info = tls_info_zero;
 #endif
 
 #ifdef USE_SASL_AUTH
index 92d15c7556c0edb8deb3cdfced6a26db4cd068c8..fb50f316ad5a45206fe0a8a0a0b26789251b7c71 100644 (file)
@@ -1,11 +1,11 @@
 SHELL  = /bin/sh
 SRCS   = tls_prng_dev.c tls_prng_egd.c tls_prng_file.c \
        tls_prng_exch.c tls_stream.c tls_bio_ops.c tls_misc.c tls_dh.c \
-       tls_rsa.c tls_verify.c tls_certkey.c tls_session.c tls_temp.c \
+       tls_rsa.c tls_verify.c tls_certkey.c tls_session.c \
        tls_client.c tls_server.c tls_scache.c tls_mgr.c tls_seed.c
 OBJS   = tls_prng_dev.o tls_prng_egd.o tls_prng_file.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_certkey.o tls_session.o tls_temp.o \
+       tls_rsa.o tls_verify.o tls_certkey.o tls_session.o \
        tls_client.o tls_server.o tls_scache.o tls_mgr.o tls_seed.o
 HDRS   = tls.h tls_prng.h tls_scache.h tls_mgr.h
 TESTSRC        = 
@@ -222,12 +222,6 @@ tls_stream.o: ../../include/vstream.h
 tls_stream.o: ../../include/vstring.h
 tls_stream.o: tls.h
 tls_stream.o: tls_stream.c
-tls_temp.o: ../../include/sys_defs.h
-tls_temp.o: ../../include/vbuf.h
-tls_temp.o: ../../include/vstream.h
-tls_temp.o: ../../include/vstring.h
-tls_temp.o: tls.h
-tls_temp.o: tls_temp.c
 tls_verify.o: ../../include/msg.h
 tls_verify.o: ../../include/sys_defs.h
 tls_verify.o: ../../include/vbuf.h
index 8674d0c3fa476d5776a654b94b805b06f1db1d3f..2fed1254b776b37aad6084a1f88fdd0012e9dee3 100644 (file)
  /*
   * TLS session context, also used by the VSTREAM call-back routines for SMTP
   * input/output, and by OpenSSL call-back routines for key verification.
-  * 
-  * XXX Eliminate fixed-length buffers where possible.
-  * 
-  * XXX Eliminate the tls_info structure; it is no longer needed now that the
-  * TLScontext structure is exposed to the caller. If the caller's TLScontext
-  * pointer is null, there is no TLS session. This change (plus other
-  * changes) eliminated global variables that were shared between TLS client
-  * and server code. Multiple clients and/or servers can now co-exist in the
-  * same process.
   */
 #define CCERT_BUFSIZ   256
 #define HOST_BUFSIZ  255               /* RFC 1035 */
@@ -53,63 +44,48 @@ typedef struct {
     BIO    *internal_bio;              /* postfix/TLS side of pair */
     BIO    *network_bio;               /* network side of pair */
     char   *serverid;                  /* unique server identifier */
-    char    peer_subject[CCERT_BUFSIZ];
-    char    peer_issuer[CCERT_BUFSIZ];
-    char    peer_CN[CCERT_BUFSIZ];
-    char    issuer_CN[CCERT_BUFSIZ];
-    unsigned char md[EVP_MAX_MD_SIZE];
-    char    fingerprint[EVP_MAX_MD_SIZE * 3];
+    char   *peer_CN;                   /* Peer Common Name */
+    char   *issuer_CN;                 /* Issuer Common Name */
+    char   *peer_fingerprint;          /* ASCII fingerprint */
     char   *peername;
     int     enforce_verify_errors;
     int     enforce_CN;
     int     hostname_matched;
-    int     log_level;
-} TLScontext_t;
-
-#define TLS_BIO_BUFSIZE        8192
-
-typedef struct {
     int     peer_verified;
-    int     hostname_matched;
-    char   *peer_subject;
-    char   *peer_issuer;
-    char   *peer_fingerprint;
-    char   *peer_CN;
-    char   *issuer_CN;
     const char *protocol;
     const char *cipher_name;
     int     cipher_usebits;
     int     cipher_algbits;
-} tls_info_t;
+    int     log_level;
+} TLScontext_t;
 
-extern const tls_info_t tls_info_zero;
+#define TLS_BIO_BUFSIZE        8192
 
  /*
   * tls_client.c
   */
 extern SSL_CTX *tls_client_init(int);
 extern TLScontext_t *tls_client_start(SSL_CTX *, VSTREAM *, int, int,
-                                             const char *, const char *,
-                                             tls_info_t *);
+                                             const char *, const char *);
 
-#define tls_client_stop(ctx , stream, timeout, failure, tls_info) \
-       tls_session_stop((ctx), (stream), (timeout), (failure), (tls_info))
+#define tls_client_stop(ctx , stream, timeout, failure, TLScontext) \
+       tls_session_stop((ctx), (stream), (timeout), (failure), (TLScontext))
 
  /*
   * tls_server.c
   */
 extern SSL_CTX *tls_server_init(int, int);
 extern TLScontext_t *tls_server_start(SSL_CTX *, VSTREAM *, int,
-                                             const char *, const char *,
-                                             tls_info_t *, int);
+                                          const char *, const char *, int);
 
-#define tls_server_stop(ctx , stream, timeout, failure, tls_info) \
-       tls_session_stop((ctx), (stream), (timeout), (failure), (tls_info))
+#define tls_server_stop(ctx , stream, timeout, failure, TLScontext) \
+       tls_session_stop((ctx), (stream), (timeout), (failure), (TLScontext))
 
  /*
   * tls_session.c
   */
-extern void tls_session_stop(SSL_CTX *, VSTREAM *, int, int, tls_info_t *);
+extern void tls_session_stop(SSL_CTX *, VSTREAM *, int, int,
+                                             TLScontext_t *);
 
 #ifdef TLS_INTERNAL
 
@@ -167,6 +143,8 @@ extern RSA *tls_tmp_rsa_cb(SSL *, int, int);
  /*
   * tls_verify.c
   */
+extern char *tls_peer_CN(X509 *);
+extern char *tls_issuer_CN(X509 *);
 extern int tls_verify_certificate_callback(int, X509_STORE_CTX *);
 
  /*
index 263837129131d16008b6ac5a718bdf53ae5ae0ea..979f4e8e2261c298d01dcf82a47a551840b18972 100644 (file)
 /*
 /*     TLScontext_t *tls_client_start(client_ctx, stream, timeout,
 /*                                     enforce_peername, peername,
-/*                                     serverid, tls_info)
+/*                                     serverid)
 /*     SSL_CTX *client_ctx;
 /*     VSTREAM *stream;
 /*     int     timeout;
 /*     int     enforce_peername;
 /*     const char *peername;
 /*     const char *serverid;
-/*     tls_info_t *tls_info;
 /*
-/*     void    tls_client_stop(client_ctx, stream, failure, tls_info)
+/*     void    tls_client_stop(client_ctx, stream, failure, TLScontext)
 /*     SSL_CTX *client_ctx;
 /*     VSTREAM *stream;
 /*     int     failure;
-/*     tls_info_t *tls_info;
+/*     TLScontext_t *TLScontext;
 /* DESCRIPTION
-/*      This module is the interface between Postfix TLS clients
-/*     and the OpenSSL library and TLS entropy and cache manager.
+/*     This module is the interface between Postfix TLS clients,
+/*     the OpenSSL library and the TLS entropy and cache manager.
+/*
+/*     The SMTP client will attempt to verify the server hostname
+/*     against the names listed in the server certificate. When
+/*     a hostname match is required, the verification fails
+/*     on certificate verification or hostname mis-match errors.
+/*     When no hostname match is required, hostname verification
+/*     failures are logged but they do not affect the TLS handshake
+/*     or the SMTP session.
+/*
+/*     The rules for peer name wild-card matching differ between
+/*     RFC 2818 (HTTP over TLS) and RFC 2830 (LDAP over TLS), while
+/*     RFC RFC3207 (SMTP over TLS) does not specify a rule at all.
+/*     Postfix uses a restrictive match algorithm. One asterisk
+/*     ('*') is allowed as the left-most component of a wild-card
+/*     certificate name; it matches the left-most component of
+/*     the peer hostname.
+/*
+/*     Another area where RFCs aren't always explicit is the
+/*     handling of dNSNames in peer certificates. RFC 3207 (SMTP
+/*     over TLS) does not mention dNSNames. Postfix follows the
+/*     strict rules in RFC 2818 (HTTP over TLS), section 3.1: The
+/*     Subject Alternative Name/dNSName has precedence over
+/*     CommonName.  If at least one dNSName is provided, Postfix
+/*     verifies those against the peer hostname and ignores the
+/*     CommonName, otherwise Postfix verifies the CommonName
+/*     against the peer hostname.
 /*
 /*     tls_client_init() is called once when the SMTP client
 /*     initializes.
 /*     so that peer-specific behavior is not possible.
 /*
 /*     tls_client_start() activates the TLS feature for the VSTREAM
-/*     passed as argument. We expect that network buffers are flushed and the
-/*     TLS handshake can begin immediately. Information about the peer
-/*     is stored into the tls_info structure passed as argument.
-/*     The serverid argument specifies a string that hopefully
-/*     uniquely identifies a server. It is used as the client
-/*     session cache lookup key.
+/*     passed as argument. We expect that network buffers are flushed and
+/*     the TLS handshake can begin immediately. The serverid argument
+/*     specifies a string that hopefully uniquely identifies a server.
+/*     It is used as the client session cache lookup key.
 /*
 /*     tls_client_stop() sends the "close notify" alert via
 /*     SSL_shutdown() to the peer and resets all connection specific
 /*     If the failure flag is set, no SSL_shutdown() handshake is performed.
 /*
 /*     Once the TLS connection is initiated, information about the TLS
-/*     state is available via the tls_info structure:
-/* .IP tls_info->protocol
+/*     state is available via the TLScontext structure:
+/* .IP TLScontext->protocol
 /*     the protocol name (SSLv2, SSLv3, TLSv1),
-/* .IP tls_info->cipher_name
+/* .IP TLScontext->cipher_name
 /*     the cipher name (e.g. RC4/MD5),
-/* .IP tls_info->cipher_usebits
+/* .IP TLScontext->cipher_usebits
 /*     the number of bits actually used (e.g. 40),
-/* .IP tls_info->cipher_algbits
+/* .IP TLScontext->cipher_algbits
 /*     the number of bits the algorithm is based on (e.g. 128).
 /* .PP
 /*     The last two values may differ from each other when export-strength
 /*     encryption is used.
 /*
 /*     The status of the peer certificate verification is available in
-/*     tls_info->peer_verified. It is set to 1 when the certificate could
+/*     TLScontext->peer_verified. It is set to 1 when the certificate could
 /*     be verified.
 /*     If the peer offered a certificate, part of the certificate data are
 /*     available as:
-/* .IP tls_info->peer_subject
-/*     X509v3-oneline with the DN of the peer
-/* .IP tls_info->peer_CN
-/*     extracted CommonName of the peer
-/* .IP tls_info->peer_issuer
-/*     X509v3-oneline with the DN of the issuer
-/* .IP tls_info->issuer_CN
-/*     extracted CommonName of the issuer
-/* .IP tls_info->peer_fingerprint
-/*     fingerprint of the certificate
+/* .IP TLScontext->peer_CN
+/*     Extracted CommonName of the peer, or zero-length string if the
+/*     information could not be extracted.
+/* .IP TLScontext->issuer_CN
+/*     extracted CommonName of the issuer, or zero-length string if the
+/*     information could not be extracted.
+/* .PP
+/*     Otherwise these fields are set to null pointers.
 /* LICENSE
 /* .ad
 /* .fi
 #define STR    vstring_str
 #define LEN    VSTRING_LEN
 
- /*
-  * To convert binary to fingerprint.
-  */
-static const char hexcodes[] = "0123456789ABCDEF";
-
  /*
   * Do or don't we cache client sessions?
   */
@@ -438,28 +454,28 @@ static int match_hostname(const char *pattern, const char *hostname)
 /* verify_extract_peer - verify peer name and extract peer information */
 
 static void verify_extract_peer(const char *peername, X509 * peercert,
-                            TLScontext_t *TLScontext, tls_info_t *tls_info)
+                                       TLScontext_t *TLScontext)
 {
-    char    buf[1024];
     int     i;
     int     r;
-    int     hostname_matched;
-    int     dNSName_found;
+    int     hostname_matched = 0;
+    int     dNSName_found = 0;
+    int     verify_peername;
 
     STACK_OF(GENERAL_NAME) * gens;
 
-    tls_info->peer_verified =
+    TLScontext->peer_verified =
        (SSL_get_verify_result(TLScontext->con) == X509_V_OK);
 
-    if (TLScontext->enforce_CN != 0 && tls_info->peer_verified != 0) {
+    verify_peername =
+       (TLScontext->enforce_CN != 0 && TLScontext->peer_verified != 0);
+
+    if (verify_peername) {
 
        /*
-        * Verify the name(s) in the peer certificate against the peer
-        * hostname. Log peer hostname/certificate mis-matches. If a match is
-        * required but fails, bail out with a verification error.
+        * Verify the dNSName(s) in the peer certificate against the
+        * peername.
         */
-       hostname_matched = dNSName_found = 0;
-
        gens = X509_get_ext_d2i(peercert, NID_subject_alt_name, 0, 0);
        if (gens) {
            for (i = 0, r = sk_GENERAL_NAME_num(gens); i < r; ++i) {
@@ -474,61 +490,37 @@ static void verify_extract_peer(const char *peername, X509 * peercert,
            }
            sk_GENERAL_NAME_free(gens);
        }
-       if (dNSName_found) {
-           if (!hostname_matched)
-               msg_info("certificate peer name verification failed for "
-                        "%s: %d dNSNames in certificate found, "
-                        "but none matches", peername, dNSName_found);
-       } else {
-           buf[0] = '\0';
-           if (!X509_NAME_get_text_by_NID(X509_get_subject_name(peercert),
-                                          NID_commonName, buf,
-                                          sizeof(buf))) {
-               msg_info("certificate peer name verification failed for"
-                        " %s: cannot parse subject CommonName", peername);
-               tls_print_errors();
-           } else {
-               hostname_matched = match_hostname(buf, peername);
-               if (!hostname_matched)
-                   msg_info("certificate peer name verification failed "
-                            "for %s: CommonName mis-match: %s",
-                            peername, buf);
-           }
-       }
-
-       TLScontext->hostname_matched = hostname_matched;
     }
-    tls_info->hostname_matched = TLScontext->hostname_matched;
-
-    TLScontext->peer_CN[0] = '\0';
-    if (!X509_NAME_get_text_by_NID(X509_get_subject_name(peercert),
-                                  NID_commonName, TLScontext->peer_CN,
-                                  sizeof(TLScontext->peer_CN))) {
-       msg_info("Could not parse server's subject CN");
-       tls_print_errors();
+    if (dNSName_found) {
+       if (!hostname_matched)
+           msg_info("certificate peer name verification failed for "
+                    "%s: %d dNSNames in certificate found, "
+                    "but none match", peername, dNSName_found);
     }
-    tls_info->peer_CN = TLScontext->peer_CN;
+    if ((TLScontext->peer_CN = tls_peer_CN(peercert)) == 0)
+       TLScontext->peer_CN = mystrdup("");
 
-    TLScontext->issuer_CN[0] = '\0';
-    if (!X509_NAME_get_text_by_NID(X509_get_issuer_name(peercert),
-                                  NID_commonName, TLScontext->issuer_CN,
-                                  sizeof(TLScontext->issuer_CN))) {
-       msg_info("Could not parse server's issuer CN");
-       tls_print_errors();
-    }
-    if (!TLScontext->issuer_CN[0]) {
-       /* No issuer CN field, use Organization instead */
-       if (!X509_NAME_get_text_by_NID(X509_get_issuer_name(peercert),
-                               NID_organizationName, TLScontext->issuer_CN,
-                                      sizeof(TLScontext->issuer_CN))) {
-           msg_info("Could not parse server's issuer Organization");
-           tls_print_errors();
+    if ((TLScontext->issuer_CN = tls_issuer_CN(peercert)) == 0)
+       TLScontext->issuer_CN = mystrdup("");
+
+    if (!dNSName_found && verify_peername) {
+
+       /*
+        * Verify the CommonName in the peer certificate against the
+        * peername.
+        */
+       if (TLScontext->peer_CN[0] != '\0') {
+           hostname_matched = match_hostname(TLScontext->peer_CN, peername);
+           if (!hostname_matched)
+               msg_info("certificate peer name verification failed "
+                        "for %s: CommonName mis-match: %s",
+                        peername, TLScontext->peer_CN);
        }
     }
-    tls_info->issuer_CN = TLScontext->issuer_CN;
+    TLScontext->hostname_matched = hostname_matched;
 
     if (var_smtp_tls_loglevel >= 1) {
-       if (tls_info->peer_verified
+       if (TLScontext->peer_verified
            && (!TLScontext->enforce_CN || TLScontext->hostname_matched))
            msg_info("Verified: subject_CN=%s, issuer=%s",
                     TLScontext->peer_CN, TLScontext->issuer_CN);
@@ -547,8 +539,7 @@ TLScontext_t *tls_client_start(SSL_CTX *client_ctx, VSTREAM *stream,
                                       int timeout,
                                       int enforce_peername,
                                       const char *peername,
-                                      const char *serverid,
-                                      tls_info_t *tls_info)
+                                      const char *serverid)
 {
     int     sts;
     SSL_SESSION *session;
@@ -707,30 +698,30 @@ TLScontext_t *tls_client_start(SSL_CTX *client_ctx, VSTREAM *stream,
      * from the certificate for later use.
      */
     if ((peercert = SSL_get_peer_certificate(TLScontext->con)) != 0) {
-       verify_extract_peer(peername, peercert, TLScontext, tls_info);
+       verify_extract_peer(peername, peercert, TLScontext);
        X509_free(peercert);
     }
     if (enforce_peername && !TLScontext->hostname_matched) {
        msg_info("Server certificate could not be verified for %s:"
                 " hostname mismatch", peername);
-       tls_client_stop(client_ctx, stream, timeout, 0, tls_info);
+       tls_client_stop(client_ctx, stream, timeout, 0, TLScontext);
        return (0);
     }
 
     /*
      * Finally, collect information about protocol and cipher for logging
      */
-    tls_info->protocol = SSL_get_version(TLScontext->con);
+    TLScontext->protocol = SSL_get_version(TLScontext->con);
     cipher = SSL_get_current_cipher(TLScontext->con);
-    tls_info->cipher_name = SSL_CIPHER_get_name(cipher);
-    tls_info->cipher_usebits = SSL_CIPHER_get_bits(cipher,
-                                              &(tls_info->cipher_algbits));
+    TLScontext->cipher_name = SSL_CIPHER_get_name(cipher);
+    TLScontext->cipher_usebits = SSL_CIPHER_get_bits(cipher,
+                                            &(TLScontext->cipher_algbits));
 
     if (var_smtp_tls_loglevel >= 1)
        msg_info("TLS connection established to %s: %s with cipher %s"
                 " (%d/%d bits)", peername,
-                tls_info->protocol, tls_info->cipher_name,
-                tls_info->cipher_usebits, tls_info->cipher_algbits);
+                TLScontext->protocol, TLScontext->cipher_name,
+                TLScontext->cipher_usebits, TLScontext->cipher_algbits);
 
     tls_int_seed();
 
index 7db5b4db98b57865fc8efae984f3f7f46b217a3c..b8d5980391ca2957d6b65eb472718545c763b47f 100644 (file)
@@ -110,6 +110,8 @@ TLScontext_t *tls_alloc_context(int log_level, const char *peername)
      * 
      * See the C language FAQ item 5.17, or if you have time to burn,
      * http://www.google.com/search?q=zero+bit+null+pointer
+     * 
+     * However, it's OK to use memset() to zero integer values.
      */
     TLScontext = (TLScontext_t *) mymalloc(sizeof(TLScontext_t));
     memset((char *) TLScontext, 0, sizeof(*TLScontext));
@@ -117,6 +119,11 @@ TLScontext_t *tls_alloc_context(int log_level, const char *peername)
     TLScontext->internal_bio = 0;
     TLScontext->network_bio = 0;
     TLScontext->serverid = 0;
+    TLScontext->peer_CN = 0;
+    TLScontext->issuer_CN = 0;
+    TLScontext->peer_fingerprint = 0;
+    TLScontext->protocol = 0;
+    TLScontext->cipher_name = 0;
     TLScontext->log_level = log_level;
     TLScontext->peername = lowercase(mystrdup(peername));
 
@@ -137,10 +144,19 @@ void    tls_free_context(TLScontext_t *TLScontext)
        SSL_free(TLScontext->con);
     if (TLScontext->network_bio)
        BIO_free(TLScontext->network_bio);
+
     if (TLScontext->peername)
        myfree(TLScontext->peername);
     if (TLScontext->serverid)
        myfree(TLScontext->serverid);
+
+    if (TLScontext->peer_CN)
+       myfree(TLScontext->peer_CN);
+    if (TLScontext->issuer_CN)
+       myfree(TLScontext->issuer_CN);
+    if (TLScontext->peer_fingerprint)
+       myfree(TLScontext->peer_fingerprint);
+
     myfree((char *) TLScontext);
 }
 
index 2df0edcb1c846ebba7eb2144762d538dde9bf7ce..6bfb6cd8497171ebf78572367523ee6bf5023411 100644 (file)
 /*     int     askcert;
 /*
 /*     TLScontext_t *tls_server_start(server_ctx, stream, timeout,
-/*                                     peername, peeraddr,
-/*                                     tls_info, requirecert)
+/*                                     peername, peeraddr, requirecert)
 /*     SSL_CTX *server_ctx;
 /*     VSTREAM *stream;
 /*     int     timeout;
 /*     const char *peername;
 /*     const char *peeraddr;
-/*     tls_info_t *tls_info;
 /*     int     requirecert;
 /*
-/*     void    tls_server_stop(server_ctx, stream, failure, tls_info)
+/*     void    tls_server_stop(server_ctx, stream, failure, TLScontext)
 /*     SSL_CTX *server_ctx;
 /*     VSTREAM *stream;
 /*     int     failure;
-/*     tls_info_t *tls_info;
+/*     TLScontext_t *TLScontext;
 /* DESCRIPTION
-/*     This module is the interface between Postfix TLS servers
-/*     and the OpenSSL library and TLS entropy and cache manager.
+/*     This module is the interface between Postfix TLS servers,
+/*     the OpenSSL library, and the TLS entropy and cache manager.
 /*
 /*     tls_server_init() is called once when the SMTP server
 /*     initializes.
@@ -36,9 +34,8 @@
 /*     so that peer-specific behavior is not possible.
 /*
 /*     tls_server_start() activates the TLS feature for the VSTREAM
-/*     passed as argument. We assume that network buffers are flushed and the
-/*     TLS handshake can begin immediately. Information about the peer
-/*     is stored into the tls_info structure passed as argument.
+/*     passed as argument. We assume that network buffers are flushed
+/*     and the TLS handshake can begin immediately.
 /*
 /*     tls_server_stop() sends the "close notify" alert via
 /*     SSL_shutdown() to the peer and resets all connection specific
 /*     If the failure flag is set, no SSL_shutdown() handshake is performed.
 /*
 /*     Once the TLS connection is initiated, information about the TLS
-/*     state is available via the tls_info structure:
-/* .IP tls_info->protocol
+/*     state is available via the TLScontext structure:
+/* .IP TLScontext->protocol
 /*     the protocol name (SSLv2, SSLv3, TLSv1),
-/* .IP tls_info->cipher_name
+/* .IP TLScontext->cipher_name
 /*     the cipher name (e.g. RC4/MD5),
-/* .IP tls_info->cipher_usebits
+/* .IP TLScontext->cipher_usebits
 /*     the number of bits actually used (e.g. 40),
-/* .IP tls_info->cipher_algbits
+/* .IP TLScontext->cipher_algbits
 /*     the number of bits the algorithm is based on (e.g. 128).
 /* .PP
 /*     The last two values may differ from each other when export-strength
 /*     encryption is used.
 /*
 /*     The status of the peer certificate verification is available in
-/*     tls_info->peer_verified. It is set to 1 when the certificate could
+/*     TLScontext->peer_verified. It is set to 1 when the certificate could
 /*     be verified.
 /*     If the peer offered a certificate, part of the certificate data are
 /*     available as:
-/* .IP tls_info->peer_subject
-/*     X509v3-oneline with the DN of the peer
-/* .IP tls_info->peer_CN
-/*     extracted CommonName of the peer
-/* .IP tls_info->peer_issuer
-/*     X509v3-oneline with the DN of the issuer
-/* .IP tls_info->issuer_CN
-/*     extracted CommonName of the issuer
-/* .IP tls_info->peer_fingerprint
-/*     fingerprint of the certificate
+/* .IP TLScontext->peer_CN
+/*     Extracted CommonName of the peer, or zero-length string
+/*     when information could not be extracted.
+/* .IP TLScontext->issuer_CN
+/*     Extracted CommonName of the issuer, or zero-length string
+/*     when information could not be extracted.
+/* .IP TLScontext->peer_fingerprint
+/*     Fingerprint of the certificate, or null pointer when no
+/*     certificate digest is available.
+/* .PP
+/*     Otherwise these fields are set to null pointers.
 /* LICENSE
 /* .ad
 /* .fi
@@ -450,9 +448,7 @@ SSL_CTX *tls_server_init(int unused_verifydepth, int askcert)
   */
 TLScontext_t *tls_server_start(SSL_CTX *server_ctx, VSTREAM *stream,
                                       int timeout, const char *peername,
-                                      const char *peeraddr,
-                                      tls_info_t *tls_info,
-                                      int requirecert)
+                                      const char *peeraddr, int requirecert)
 {
     int     sts;
     int     j;
@@ -461,6 +457,8 @@ TLScontext_t *tls_server_start(SSL_CTX *server_ctx, VSTREAM *stream,
     TLScontext_t *TLScontext;
     SSL_CIPHER *cipher;
     X509   *peer;
+    unsigned char md[EVP_MAX_MD_SIZE];
+    char    buf[CCERT_BUFSIZ];
 
     if (var_smtpd_tls_loglevel >= 1)
        msg_info("setting up TLS connection from %s[%s]", peername, peeraddr);
@@ -573,66 +571,38 @@ TLScontext_t *tls_server_start(SSL_CTX *server_ctx, VSTREAM *stream,
     peer = SSL_get_peer_certificate(TLScontext->con);
     if (peer != NULL) {
        if (SSL_get_verify_result(TLScontext->con) == X509_V_OK)
-           tls_info->peer_verified = 1;
-
-       X509_NAME_oneline(X509_get_subject_name(peer),
-                         TLScontext->peer_subject,
-                         sizeof(TLScontext->peer_subject));
-       if (var_smtpd_tls_loglevel >= 2)
-           msg_info("subject=%s", TLScontext->peer_subject);
-       tls_info->peer_subject = TLScontext->peer_subject;
-
-       X509_NAME_oneline(X509_get_issuer_name(peer),
-                         TLScontext->peer_issuer,
-                         sizeof(TLScontext->peer_issuer));
-       if (var_smtpd_tls_loglevel >= 2)
-           msg_info("issuer=%s", TLScontext->peer_issuer);
-       tls_info->peer_issuer = TLScontext->peer_issuer;
-
-       if (X509_digest(peer, EVP_md5(), TLScontext->md, &n)) {
+           TLScontext->peer_verified = 1;
+
+       if (var_smtpd_tls_loglevel >= 2) {
+           X509_NAME_oneline(X509_get_subject_name(peer),
+                             buf, sizeof(buf));
+           msg_info("subject=%s", buf);
+           X509_NAME_oneline(X509_get_issuer_name(peer),
+                             buf, sizeof(buf));
+           msg_info("issuer=%s", buf);
+       }
+       if (X509_digest(peer, EVP_md5(), md, &n) && n > 0) {
+           TLScontext->peer_fingerprint = mymalloc(n * 3);
            for (j = 0; j < (int) n; j++) {
-               TLScontext->fingerprint[j * 3] =
-                   hexcodes[(TLScontext->md[j] & 0xf0) >> 4U];
-               TLScontext->fingerprint[(j * 3) + 1] =
-                   hexcodes[(TLScontext->md[j] & 0x0f)];
+               TLScontext->peer_fingerprint[j * 3] =
+                   hexcodes[(md[j] & 0xf0) >> 4U];
+               TLScontext->peer_fingerprint[(j * 3) + 1] =
+                   hexcodes[(md[j] & 0x0f)];
                if (j + 1 != (int) n)
-                   TLScontext->fingerprint[(j * 3) + 2] = ':';
+                   TLScontext->peer_fingerprint[(j * 3) + 2] = ':';
                else
-                   TLScontext->fingerprint[(j * 3) + 2] = '\0';
+                   TLScontext->peer_fingerprint[(j * 3) + 2] = '\0';
            }
            if (var_smtpd_tls_loglevel >= 1)
-               msg_info("fingerprint=%s", TLScontext->fingerprint);
-           tls_info->peer_fingerprint = TLScontext->fingerprint;
-       }
-       TLScontext->peer_CN[0] = '\0';
-       if (!X509_NAME_get_text_by_NID(X509_get_subject_name(peer),
-                                      NID_commonName, TLScontext->peer_CN,
-                                      sizeof(TLScontext->peer_CN))) {
-           msg_info("Could not parse client's subject CN");
-           tls_print_errors();
-       }
-       tls_info->peer_CN = TLScontext->peer_CN;
-
-       TLScontext->issuer_CN[0] = '\0';
-       if (!X509_NAME_get_text_by_NID(X509_get_issuer_name(peer),
-                                      NID_commonName, TLScontext->issuer_CN,
-                                      sizeof(TLScontext->issuer_CN))) {
-           msg_info("Could not parse client's issuer CN");
-           tls_print_errors();
-       }
-       if (!TLScontext->issuer_CN[0]) {
-           /* No issuer CN field, use Organization instead */
-           if (!X509_NAME_get_text_by_NID(X509_get_issuer_name(peer),
-                               NID_organizationName, TLScontext->issuer_CN,
-                                          sizeof(TLScontext->issuer_CN))) {
-               msg_info("Could not parse client's issuer Organization");
-               tls_print_errors();
-           }
+               msg_info("fingerprint=%s", TLScontext->peer_fingerprint);
        }
-       tls_info->issuer_CN = TLScontext->issuer_CN;
+       if ((TLScontext->peer_CN = tls_peer_CN(peer)) == 0)
+           TLScontext->peer_CN = mystrdup("");
+       if ((TLScontext->issuer_CN = tls_issuer_CN(peer)) == 0)
+           TLScontext->issuer_CN = mystrdup("");
 
        if (var_smtpd_tls_loglevel >= 1) {
-           if (tls_info->peer_verified)
+           if (TLScontext->peer_verified)
                msg_info("Verified: subject_CN=%s, issuer=%s",
                         TLScontext->peer_CN, TLScontext->issuer_CN);
            else
@@ -647,7 +617,7 @@ TLScontext_t *tls_server_start(SSL_CTX *server_ctx, VSTREAM *stream,
      * session peer was verified.
      */
     if (requirecert) {
-       if (!tls_info->peer_verified || !tls_info->peer_CN) {
+       if (!TLScontext->peer_verified || !TLScontext->peer_CN) {
            msg_info("Re-used session without peer certificate removed");
            uncache_session(server_ctx, TLScontext);
            tls_free_context(TLScontext);
@@ -658,11 +628,11 @@ TLScontext_t *tls_server_start(SSL_CTX *server_ctx, VSTREAM *stream,
     /*
      * Finally, collect information about protocol and cipher for logging
      */
-    tls_info->protocol = SSL_get_version(TLScontext->con);
+    TLScontext->protocol = SSL_get_version(TLScontext->con);
     cipher = SSL_get_current_cipher(TLScontext->con);
-    tls_info->cipher_name = SSL_CIPHER_get_name(cipher);
-    tls_info->cipher_usebits = SSL_CIPHER_get_bits(cipher,
-                                              &(tls_info->cipher_algbits));
+    TLScontext->cipher_name = SSL_CIPHER_get_name(cipher);
+    TLScontext->cipher_usebits = SSL_CIPHER_get_bits(cipher,
+                                            &(TLScontext->cipher_algbits));
 
     /*
      * The TLS engine is active. Switch to the tls_timed_read/write()
@@ -673,8 +643,8 @@ TLScontext_t *tls_server_start(SSL_CTX *server_ctx, VSTREAM *stream,
     if (var_smtpd_tls_loglevel >= 1)
        msg_info("TLS connection established from %s[%s]: %s with cipher %s (%d/%d bits)",
                 peername, peeraddr,
-                tls_info->protocol, tls_info->cipher_name,
-                tls_info->cipher_usebits, tls_info->cipher_algbits);
+                TLScontext->protocol, TLScontext->cipher_name,
+                TLScontext->cipher_usebits, TLScontext->cipher_algbits);
     tls_int_seed();
 
     return (TLScontext);
index 21d939ee09ea1b3fa15542ad7ed0303e2140341c..b30b72761d4d219b9581db4b08190a55c1f1c3f4 100644 (file)
@@ -6,12 +6,12 @@
 /* SYNOPSIS
 /*     #include <tls.h>
 /*
-/*     int     tls_session_stop(ctx, stream, timeout, failure, tls_info)
+/*     void    tls_session_stop(ctx, stream, timeout, failure, TLScontext)
 /*     SSL_CTX *ctx;
 /*     VSTREAM *stream;
 /*     int     timeout;
 /*     int     failure;
-/*     tls_info_t *tls_info;
+/*     TLScontext_t *TLScontext;
 /*
 /*     VSTRING *tls_session_passivate(session)
 /*     SSL_SESSION *session;
 /* tls_session_stop - shut down the TLS connection and reset state */
 
 void    tls_session_stop(SSL_CTX *ctx, VSTREAM *stream, int timeout,
-                                int failure, tls_info_t *tls_info)
+                                int failure, TLScontext_t *TLScontext)
 {
     const char *myname = "tls_session_stop";
-    TLScontext_t *TLScontext;
     int     retval;
 
     /*
      * Sanity check.
      */
-    TLScontext = (TLScontext_t *) vstream_context(stream);
     if (TLScontext == 0)
        msg_panic("%s: stream has no active TLS context", myname);
 
@@ -103,7 +101,6 @@ void    tls_session_stop(SSL_CTX *ctx, VSTREAM *stream, int timeout,
     }
     tls_free_context(TLScontext);
     tls_stream_stop(stream);
-    *tls_info = tls_info_zero;
 }
 
 /* tls_session_passivate - passivate SSL_SESSION object */
diff --git a/postfix/src/tls/tls_temp.c b/postfix/src/tls/tls_temp.c
deleted file mode 100644 (file)
index a75d8ef..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*++
-/* NAME
-/*     tls_temp 3
-/* SUMMARY
-/*     code that is to be replaced
-/* SYNOPSIS
-/*     #define TLS_INTERNAL
-/*     #include <tls.h>
-/* DESCRIPTION
-/*     As the summary says.
-/* LICENSE
-/* .ad
-/* .fi
-/*     This software is free. You can do with it whatever you want.
-/*     The original author kindly requests that you acknowledge
-/*     the use of his software.
-/* AUTHOR(S)
-/*     Originally written by:
-/*     Lutz Jaenicke
-/*     BTU Cottbus
-/*     Allgemeine Elektrotechnik
-/*     Universitaetsplatz 3-4
-/*     D-03044 Cottbus, Germany
-/*
-/*     Updated by:
-/*     Wietse Venema
-/*     IBM T.J. Watson Research
-/*     P.O. Box 704
-/*     Yorktown Heights, NY 10598, USA
-/*--*/
-
-/* System library. */
-
-#include <sys_defs.h>
-
-#ifdef USE_TLS
-
-/* TLS library. */
-
-#define TLS_INTERNAL
-#include <tls.h>
-
-/* Application-specific. */
-
-const tls_info_t tls_info_zero = {
-    0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0
-};
-
-#endif
index 508ba7f3cd75444960995742980a57003f17ba3e..2580ff21ca232d9859b58c24ed53121f972ce7e1 100644 (file)
@@ -7,10 +7,26 @@
 /*     #define TLS_INTERNAL
 /*     #include <tls.h>
 /*
+/*     char *tls_peer_CN(peercert)
+/*     X509   *peercert;
+/*
+/*     char *tls_issuer_CN(peercert)
+/*     X509   *peercert;
+/*
 /*     int     tls_verify_certificate_callback(ok, ctx)
 /*     int     ok;
 /*     X509_STORE_CTX *ctx;
 /* DESCRIPTION
+/*     tls_peer_CN() returns the text CommonName for the peer
+/*     certificate subject, or a null pointer if no CommonName was
+/*     found. The result is allocated with mymalloc() and must be
+/*     freed by the caller.
+/*
+/*     tls_issuer_CN() returns the text CommonName for the peer
+/*     certificate issuer, or a null pointer if no CommonName was
+/*     found. The result is allocated with mymalloc() and must be
+/*     freed by the caller.
+/*
 /*     tls_verify_callback() is called several times (directly or
 /*     indirectly) from crypto/x509/x509_vfy.c. It is called as
 /*     a final check, and if it returns "0", the handshake is
 /*      certificate verification failure will result in immediate
 /*     termination (return 0).
 /*
-/*     The SMTP client will attempt to verify the server hostname
-/*     against the names listed in the server certificate. When
-/*     a hostname match is required, the verification fails
-/*     on certificate verification or hostname mis-match errors.
-/*     When no hostname match is required, hostname verification
-/*     failures are logged but they do not affect the TLS handshake
-/*     or the SMTP session.
-/*
-/*     The rules for peer name wild-card matching differ between
-/*     RFC 2818 (HTTP over TLS) and RFC 2830 (LDAP over TLS), while
-/*     RFC RFC3207 (SMTP over TLS) does not specify a rule at all.
-/*     Postfix uses a restrictive match algorithm. One asterisk
-/*     ('*') is allowed as the left-most component of a wild-card
-/*     certificate name; it matches the left-most component of
-/*     the peer hostname.
-/*
-/*     Another area where RFCs aren't always explicit is the
-/*     handling of dNSNames in peer certificates. RFC 3207 (SMTP
-/*     over TLS) does not mention dNSNames. Postfix follows the
-/*     strict rules in RFC 2818 (HTTP over TLS), section 3.1: The
-/*     Subject Alternative Name/dNSName has precedence over
-/*     CommonName.  If at least one dNSName is provided, Postfix
-/*     verifies those against the peer hostname and ignores the
-/*     CommonName, otherwise Postfix verifies the CommonName
-/*     against the peer hostname.
-/*
 /*     The only error condition not handled inside the OpenSSL
 /*     library is the case of a too-long certificate chain. We
 /*     test for this condition only if "ok = 1", that is, if
 /* .IP ctx
 /*     TLS client or server context. This also specifies the
 /*     TLScontext with enforcement options.
+/* DIAGNOSTICS
+/*     tls_peer_CN() and tls_issuer_CN() log a warning and return
+/*     a null pointer when 1) the requested information is not
+/*     available in the specified certificate, 2) the result
+/*     exceeds a fixed limit, or 3) the result contains null
+/*     characters.
 /* LICENSE
 /* .ad
 /* .fi
 /* Utility library. */
 
 #include <msg.h>
+#include <mymalloc.h>
 
 /* TLS library. */
 
@@ -196,4 +193,72 @@ int     tls_verify_certificate_callback(int ok, X509_STORE_CTX *ctx)
        return (1);
 }
 
+#ifndef DONT_GRIPE
+#define DONT_GRIPE 0
+#define DO_GRIPE 1
+#endif
+
+/* tls_text_name - extract certificate property value by name */
+
+static char *tls_text_name(X509_NAME *name, int nid, char *label, int gripe)
+{
+    int     len;
+    char   *text;
+
+    if ((len = X509_NAME_get_text_by_NID(name, nid, 0, 0)) < 0) {
+       if (gripe != DONT_GRIPE) {
+           msg_warn("peer certificate has no %s", label);
+           tls_print_errors();
+       }
+       return (0);
+    }
+
+    /*
+     * Since the peer CN is used in peer verification, take care to detect
+     * truncation due to excessive length or internal NULs.
+     */
+    if (len >= CCERT_BUFSIZ) {
+       msg_warn("peer %s too long: %d", label, (int) len);
+       return (0);
+    }
+    text = mymalloc(len + 1);
+    X509_NAME_get_text_by_NID(name, nid, text, len + 1);
+    if (strlen(text) != len) {
+       msg_warn("internal NUL in peer %s", label);
+       myfree(text);
+       text = 0;
+    }
+    return (text);
+}
+
+/* tls_peer_CN - extract peer common name from certificate */
+
+char   *tls_peer_CN(X509 *peercert)
+{
+    char   *cn;
+
+    cn = tls_text_name(X509_get_subject_name(peercert),
+                      NID_commonName, "CN", DO_GRIPE);
+    return (cn);
+}
+
+/* tls_text_name - extract issuer common name from certificate */
+
+char   *tls_issuer_CN(X509 *peer)
+{
+    X509_NAME *name;
+    char   *cn;
+
+    name = X509_get_issuer_name(peer);
+
+    /*
+     * If no issuer CN field, use Organization instead. CA certs without a CN
+     * are common, so we only complain if the organization is also missing.
+     */
+    if (!(cn = tls_text_name(name, NID_commonName, "issuer CN", DONT_GRIPE)))
+       cn = tls_text_name(name, NID_organizationName,
+                          "issuer Organization", DO_GRIPE);
+    return (cn);
+}
+
 #endif