]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.6-20080511
authorWietse Venema <wietse@porcupine.org>
Sun, 11 May 2008 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:34:02 +0000 (06:34 +0000)
postfix/HISTORY
postfix/README_FILES/SMTPD_POLICY_README
postfix/RELEASE_NOTES
postfix/html/SMTPD_POLICY_README.html
postfix/proto/SMTPD_POLICY_README.html
postfix/src/global/mail_version.h
postfix/src/smtpd/smtpd.c
postfix/src/tls/tls_verify.c

index 51750adaab01b60a436841507ec742ff2da12041..1cfc7c5269af368e2577bc4823aadd4d72f28956 100644 (file)
@@ -14457,8 +14457,18 @@ Apologies for any names omitted.
 
 20080510
 
-       Cleanup: when extracting common name and issuer name from
+       Cleanup: when extracting peer and issuer common name from
        TLS certificates, convert the result into UTF-8, and use
        RFC 2047 encoding when logging these as Received: header
        comment fields. Based remotely on code by Victor Duchovni.
        Files: smtpd/smtpd.c, tls/tls_verify.c.
+
+20080511
+
+       Cleanup: the RFC 2047 encoding of RFC*822 comments is too
+       problematic.  The text that explains the problems is as
+       long as the code itself.  That is usually a good indication
+       that code is not ready for use.  File: smtpd/smtpd.c.
+
+       Cleanup: block non-printable ASCII text in UTF8 encoded TLS
+       peer and issuer common names.  File: tls/tls_verify.c.
index 80e2edbe98b910388b000e88b1c2f6680294531c..7ba1838da169827edcb50b7a6405c05d628218a7 100644 (file)
@@ -127,9 +127,8 @@ Notes:
     case of no certificate authentication. As of Postfix 2.2.11 these attribute
     values are encoded as xtext: some characters are represented by +XX, where
     XX is the two-digit hexadecimal representation of the character value. With
-    Postfix 2.5 and later, the decoded string may contain non-ASCII characters.
-    If so, this is a UTF-8 string; xtext encoding works with the bytes of the
-    UTF-8 string, not the characters.
+    Postfix 2.6 and later, the decoded string is an UTF-8 string without non-
+    printable ASCII characters.
 
   * The "encryption_*" attributes (Postfix 2.3 and later) specify information
     about how the connection is encrypted. With plaintext connections the
index fb605fea68da477b0a7123f854e4c1cdadf55a90..ca72d68c3adab02520c9dc3683ee5cc8a66e1a7f 100644 (file)
@@ -22,7 +22,7 @@ Incompatibility with snapshot 20080510
 
 In the policy delegation protocol, certificate common name attributes
 are now xtext encoded UTF-8. The xtext decoded attributes may contain
-any UTF-8 value including control characters.
+any UTF-8 value except non-printable ASCII characters.
 
 Incompatibility with snapshot 20080428
 ======================================
index 4471aaf1600c0114c607d47397be7274c23f3e7c..fef97a1acceee6fdd9f25035ff27a7053b18881a 100644 (file)
@@ -174,10 +174,8 @@ stress=
     As of Postfix 2.2.11 these attribute values are encoded as
     xtext: some characters are represented by +XX, where XX is the
     two-digit hexadecimal representation of the character value. With
-    Postfix 2.5 and later, the decoded string may contain non-ASCII
-    characters. If so, this is a UTF-8 string; xtext encoding works
-    with the bytes of the UTF-8 string, not the characters.
-    </p>
+    Postfix 2.6 and later, the decoded string is an UTF-8 string
+    without non-printable ASCII characters.  </p>
 
     <li> <p> The "encryption_*" attributes (Postfix 2.3 and later)
     specify information about how the connection is encrypted. With
index d3e6f005f960e7ad09aec310a18a5d2ea15197cc..549a9d6e334d219352f542aa7bb2ae85d62fe01f 100644 (file)
@@ -174,10 +174,8 @@ stress=
     As of Postfix 2.2.11 these attribute values are encoded as
     xtext: some characters are represented by +XX, where XX is the
     two-digit hexadecimal representation of the character value. With
-    Postfix 2.5 and later, the decoded string may contain non-ASCII
-    characters. If so, this is a UTF-8 string; xtext encoding works
-    with the bytes of the UTF-8 string, not the characters.
-    </p>
+    Postfix 2.6 and later, the decoded string is an UTF-8 string
+    without non-printable ASCII characters.  </p>
 
     <li> <p> The "encryption_*" attributes (Postfix 2.3 and later)
     specify information about how the connection is encrypted. With
index c3fdb6d8d25c83662c75aa1c68ca60aa929bc889..9e80dff98cfbb25fb4ff78a44f54dfe8ed9d7dc0 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      "20080510"
+#define MAIL_RELEASE_DATE      "20080511"
 #define MAIL_VERSION_NUMBER    "2.6"
 
 #ifdef SNAPSHOT
index c1c3b8710b6fc5c87eafaf6915dd53e0f45e2503..dca5bd87e113d1f719ed0005f22e9ec44f5b5eff 100644 (file)
@@ -2496,6 +2496,8 @@ static void rcpt_reset(SMTPD_STATE *state)
     state->rcpt_overshoot = 0;
 }
 
+#if 0
+
 /* rfc2047_comment_encode - encode comment string */
 
 static VSTRING *rfc2047_comment_encode(const char *str, const char *charset)
@@ -2505,22 +2507,29 @@ static VSTRING *rfc2047_comment_encode(const char *str, const char *charset)
     int     ch;
 
     /*
-     * XXX Most of the RFC 2047 "especials" are not special in RFC*822
-     * comments, but we encode them anyway to avoid complaints.
+     * XXX This is problematic code.
+     * 
+     * XXX Most of the RFC 2047 "especials" are not special in RFC*822 comments,
+     * but we encode them anyway to avoid complaints.
      * 
      * XXX In Received: header comments we enclose peer and issuer common names
-     * with "" quotes. This is the cause of several quirks.
+     * with "" quotes (inherited from the Lutz Jaenicke patch). This is the
+     * cause of several quirks.
      * 
      * 1) We encode text that contains the " character, even though that
-     * character is not special for RFC*822.
+     * character is not special for RFC*822 comments.
      * 
-     * 2) Long comments look ugly when folded in-between quotes, so we ignore
-     * the recommended limit of 75 characters per encoded word.
+     * 2) We ignore the recommended limit of 75 characters per encoded word,
+     * because long comments look ugly when folded in-between quotes.
      * 
-     * 3) We must encode the the enclosing quotes, to avoid producing invalid
-     * encoded words.
+     * 3) We encode the enclosing quotes, to avoid producing invalid encoded
+     * words. Microsoft abuses RFC 2047 encoding with attachment names, but
+     * we have no information on what decoders do with malformed encoding in
+     * comments. This means the comments are Jaenicke-compatible only after
+     * decoding.
      */
 #define ESPECIALS "()<>@,;:\"/[]?.="           /* Special in RFC 2047 */
+#define QSPECIALS "_" ESPECIALS                        /* Special in RFC 2047 'Q' */
 #define CSPECIALS "\\\"()"                     /* Special in our comments */
 
     /* Don't encode if not needed. */
@@ -2538,7 +2547,7 @@ static VSTRING *rfc2047_comment_encode(const char *str, const char *charset)
      */
     vstring_sprintf(buf, "=?%s?Q?=%02X", charset, '"');
     for (cp = (unsigned char *) str; (ch = *cp) != 0; ++cp) {
-       if (!ISPRINT(ch) || strchr(ESPECIALS CSPECIALS, ch)) {
+       if (!ISPRINT(ch) || strchr(QSPECIALS CSPECIALS, ch)) {
            vstring_sprintf_append(buf, "=%02X", ch);
        } else if (ch == ' ') {
            VSTRING_ADDCH(buf, '_');
@@ -2550,6 +2559,8 @@ static VSTRING *rfc2047_comment_encode(const char *str, const char *charset)
     return (buf);
 }
 
+#endif
+
 /* comment_sanitize - clean up comment string */
 
 static void comment_sanitize(VSTRING *comment_string)
@@ -2709,10 +2720,6 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
 
 #define VSTRING_STRDUP(s) vstring_strcpy(vstring_alloc(strlen(s) + 1), (s))
 
-       /*
-        * Certificate CN information is arbitrary content in the UTF-8
-        * character set.
-        */
 #ifdef USE_TLS
        if (var_smtpd_tls_received_header && state->tls_context) {
            out_fprintf(out_stream, REC_TYPE_NORM,
@@ -2722,14 +2729,13 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
                        state->tls_context->cipher_usebits,
                        state->tls_context->cipher_algbits);
            if (TLS_CERT_IS_PRESENT(state->tls_context)) {
-               peer_CN =
-                   rfc2047_comment_encode(state->tls_context->peer_CN,
-                                          "utf-8");
-               issuer_CN =
-                   rfc2047_comment_encode(state->tls_context->issuer_CN,
-                                          "utf-8");
+               peer_CN = VSTRING_STRDUP(state->tls_context->peer_CN);
+               comment_sanitize(peer_CN);
+               issuer_CN = VSTRING_STRDUP(state->tls_context->issuer_CN ?
+                                       state->tls_context->issuer_CN : "");
+               comment_sanitize(issuer_CN);
                out_fprintf(out_stream, REC_TYPE_NORM,
-                           "\t(Client CN %s, Issuer %s (%s))",
+                           "\t(Client CN \"%s\", Issuer \"%s\" (%s))",
                            STR(peer_CN), STR(issuer_CN),
                            TLS_CERT_IS_TRUSTED(state->tls_context) ?
                            "verified OK" : "not verified");
index 5a5e0766890f29bf1d325275ab24615f9459d03b..d6da9b14e57c158ce02b5f0cd05b7f7dcfc6a9ab 100644 (file)
 /*     tls_peer_CN() returns the text CommonName for the peer
 /*     certificate subject, or an empty string if no CommonName was
 /*     found. The result is allocated with mymalloc() and must be
-/*     freed by the caller; it is arbitrary UTF-8 content.
+/*     freed by the caller; it contains UTF-8 without non-printable
+/*     ASCII characters.
 /*
 /*     tls_issuer_CN() returns the text CommonName for the peer
 /*     certificate issuer, or an empty string if no CommonName was
 /*     found. The result is allocated with mymalloc() and must be
-/*     freed by the caller; it is arbitrary UTF-8 content.
+/*     freed by the caller; it contains UTF-8 without non-printable
+/*     ASCII characters.
 /*
 /*     tls_dns_name() returns the string value of a GENERAL_NAME
 /*     from a DNS subjectAltName extension. If non-printable characters
@@ -281,6 +283,8 @@ static char *tls_text_name(X509_NAME *name, int nid, const char *label,
     int     asn1_type;
     int     utf8_length;
     unsigned char *utf8_value;
+    int     ch;
+    unsigned char *cp;
 
     if (name == 0 || (pos = X509_NAME_get_index_by_NID(name, nid, -1)) < 0) {
        if (gripe != DONT_GRIPE) {
@@ -347,16 +351,6 @@ static char *tls_text_name(X509_NAME *name, int nid, const char *label,
        return (__tls_text_name_temp); \
     } while (0)
 
-#if 0
-    for (cp = utf8_value; (ch = *cp) != 0; cp++) {
-       if (ISASCII(ch) && !ISPRINT(ch)) {
-           msg_warn("%s: %s: non-printable content in peer %s",
-                    myname, TLScontext->namaddr, label);
-           TLS_TEXT_NAME_RETURN(0);
-       }
-    }
-#endif
-
     /*
      * Remove trailing null characters. They would give false alarms with the
      * length check and with the embedded null check.
@@ -376,14 +370,29 @@ static char *tls_text_name(X509_NAME *name, int nid, const char *label,
     }
 
     /*
-     * Don't allow embedded nulls in ASCII or UTF-8 names. OpenSSL is
-     * responsible for producing properly-formatted UTF-8.
+     * Reject embedded nulls in ASCII or UTF-8 names. OpenSSL is responsible
+     * for producing properly-formatted UTF-8.
      */
     if (utf8_length != strlen((char *) utf8_value)) {
        msg_warn("%s: %s: NULL character in peer %s",
                 myname, TLScontext->namaddr, label);
        TLS_TEXT_NAME_RETURN(0);
     }
+
+    /*
+     * Reject non-printable ASCII characters from UTF-8 content.
+     * 
+     * Note: the code below does not find control characters in illegal UTF-8
+     * sequences. It's OpenSSL's job to produce valid UTF-8, and reportedly,
+     * it does validation.
+     */
+    for (cp = utf8_value; (ch = *cp) != 0; cp++) {
+       if (ISASCII(ch) && !ISPRINT(ch)) {
+           msg_warn("%s: %s: non-printable content in peer %s",
+                    myname, TLScontext->namaddr, label);
+           TLS_TEXT_NAME_RETURN(0);
+       }
+    }
     TLS_TEXT_NAME_RETURN(mystrdup((char *) utf8_value));
 }