]> Pileus Git - ~andy/fetchmail/commitdiff
Abort verification if Subject CommonName/AltName contains NUL.
authorMatthias Andree <matthias.andree@gmx.de>
Tue, 4 Aug 2009 09:27:10 +0000 (09:27 -0000)
committerMatthias Andree <matthias.andree@gmx.de>
Tue, 4 Aug 2009 09:27:10 +0000 (09:27 -0000)
svn path=/branches/BRANCH_6-3/; revision=5389

NEWS
po/de.po
socket.c

diff --git a/NEWS b/NEWS
index edab25a3ee08396c0d7ce5aeab382dae456602b1..701339a21a19df059c2a2f21a5a9f4ef6acc9149 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -51,6 +51,11 @@ removed from a 6.4.0 or newer release.)
 
 fetchmail 6.3.11 (released XXXX-XX-XX - i. e. not yet):
 
 
 fetchmail 6.3.11 (released XXXX-XX-XX - i. e. not yet):
 
+# SECURITY BUGFIXES
+* Fetchmail checks the Subject CommonName and Subject AltName X.509 certificate
+  fields for embedded NUL characters and aborts certificate verification to
+  counter recent SSL certificate verification attacks. Untested.
+
 # BUGFIXES
 * Remove the spurious message "message delimiter found while scanning headers".
   RFC-5322 syntax states that the delimiter is part of the body, and the body is
 # BUGFIXES
 * Remove the spurious message "message delimiter found while scanning headers".
   RFC-5322 syntax states that the delimiter is part of the body, and the body is
index 9ce1ccc7c7bacdb05eb9d8cce573be46b892d13b..843e3c414584afb623541632ee0ef1527696d55d 100644 (file)
--- a/po/de.po
+++ b/po/de.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: fetchmail 6.3.10-beta1\n"
 "Report-Msgid-Bugs-To: fetchmail-devel@lists.berlios.de\n"
 msgstr ""
 "Project-Id-Version: fetchmail 6.3.10-beta1\n"
 "Report-Msgid-Bugs-To: fetchmail-devel@lists.berlios.de\n"
-"POT-Creation-Date: 2009-07-02 21:34+0200\n"
+"POT-Creation-Date: 2009-08-04 11:24+0200\n"
 "PO-Revision-Date: 2009-05-26 00:53+0200\n"
 "Last-Translator: Matthias Andree <matthias.andree@gmx.de>\n"
 "Language-Team: Deutsch <de@li.org>\n"
 "PO-Revision-Date: 2009-05-26 00:53+0200\n"
 "Last-Translator: Matthias Andree <matthias.andree@gmx.de>\n"
 "Language-Team: Deutsch <de@li.org>\n"
@@ -2935,79 +2935,93 @@ msgstr "Server-CommonName: %s\n"
 msgid "Bad certificate: Subject CommonName too long!\n"
 msgstr "Ungültiges Zertifikat: Server-CommonName zu lang!\n"
 
 msgid "Bad certificate: Subject CommonName too long!\n"
 msgstr "Ungültiges Zertifikat: Server-CommonName zu lang!\n"
 
-#: socket.c:678
+#: socket.c:638
+msgid "Bad certificate: Subject CommonName contains NUL, aborting!\n"
+msgstr "Ungültiges Zertifikat: Subject-CommonName enthält NUL, breche ab!\n"
+
+#: socket.c:661
+msgid "Bad certificate: Subject Alternative Name contains NUL, aborting!\n"
+msgstr ""
+"Ungültiges Zertifikat: Subject-Alternative-Name enthält NUL, breche ab!\n"
+
+#: socket.c:666
+#, c-format
+msgid "Subject Alternative Name: %s\n"
+msgstr "\"Subject Alternative Name\": %s\n"
+
+#: socket.c:691
 #, c-format
 msgid "Server CommonName mismatch: %s != %s\n"
 msgstr "Server-CommonName stimmt nicht überein: %s != %s\n"
 
 #, c-format
 msgid "Server CommonName mismatch: %s != %s\n"
 msgstr "Server-CommonName stimmt nicht überein: %s != %s\n"
 
-#: socket.c:684
+#: socket.c:697
 msgid "Server name not set, could not verify certificate!\n"
 msgstr "Server-Name nicht gesetzt, konnte Zertifikat nicht verifizieren!\n"
 
 msgid "Server name not set, could not verify certificate!\n"
 msgstr "Server-Name nicht gesetzt, konnte Zertifikat nicht verifizieren!\n"
 
-#: socket.c:689
+#: socket.c:702
 msgid "Unknown Server CommonName\n"
 msgstr "Unbekannter Server-CommonName\n"
 
 msgid "Unknown Server CommonName\n"
 msgstr "Unbekannter Server-CommonName\n"
 
-#: socket.c:691
+#: socket.c:704
 msgid "Server name not specified in certificate!\n"
 msgstr "Server-Name nicht in Zertifikat spezifiziert!\n"
 
 msgid "Server name not specified in certificate!\n"
 msgstr "Server-Name nicht in Zertifikat spezifiziert!\n"
 
-#: socket.c:703
+#: socket.c:716
 msgid "EVP_md5() failed!\n"
 msgstr "EVP_md5() fehlgeschlagen!\n"
 
 msgid "EVP_md5() failed!\n"
 msgstr "EVP_md5() fehlgeschlagen!\n"
 
-#: socket.c:707
+#: socket.c:720
 msgid "Out of memory!\n"
 msgstr "Kein Speicher mehr frei!\n"
 
 msgid "Out of memory!\n"
 msgstr "Kein Speicher mehr frei!\n"
 
-#: socket.c:715
+#: socket.c:728
 msgid "Digest text buffer too small!\n"
 msgstr "Textpuffer für Digest zu klein!\n"
 
 msgid "Digest text buffer too small!\n"
 msgstr "Textpuffer für Digest zu klein!\n"
 
-#: socket.c:721
+#: socket.c:734
 #, c-format
 msgid "%s key fingerprint: %s\n"
 msgstr "%s-Schlüssel-Fingerabdruck: %s\n"
 
 #, c-format
 msgid "%s key fingerprint: %s\n"
 msgstr "%s-Schlüssel-Fingerabdruck: %s\n"
 
-#: socket.c:725
+#: socket.c:738
 #, c-format
 msgid "%s fingerprints match.\n"
 msgstr "%s-Fingerabdrücke stimmen überein.\n"
 
 #, c-format
 msgid "%s fingerprints match.\n"
 msgstr "%s-Fingerabdrücke stimmen überein.\n"
 
-#: socket.c:727
+#: socket.c:740
 #, c-format
 msgid "%s fingerprints do not match!\n"
 msgstr "%s-Fingerabdrücke stimmen nicht überein!\n"
 
 #, c-format
 msgid "%s fingerprints do not match!\n"
 msgstr "%s-Fingerabdrücke stimmen nicht überein!\n"
 
-#: socket.c:736
+#: socket.c:749
 #, c-format
 msgid "Server certificate verification error: %s\n"
 msgstr "Fehler bei Server-Zertifikat-Überprüfung: %s\n"
 
 #, c-format
 msgid "Server certificate verification error: %s\n"
 msgstr "Fehler bei Server-Zertifikat-Überprüfung: %s\n"
 
-#: socket.c:742
+#: socket.c:755
 #, c-format
 msgid "unknown issuer (first %d characters): %s\n"
 msgstr "unbekannter Herausgeber (erste %d Zeichen): %s\n"
 
 #, c-format
 msgid "unknown issuer (first %d characters): %s\n"
 msgstr "unbekannter Herausgeber (erste %d Zeichen): %s\n"
 
-#: socket.c:829
+#: socket.c:842
 msgid "File descriptor out of range for SSL"
 msgstr "Datei-Deskriptor außerhalb des Bereichs für SSL"
 
 msgid "File descriptor out of range for SSL"
 msgstr "Datei-Deskriptor außerhalb des Bereichs für SSL"
 
-#: socket.c:845
+#: socket.c:858
 #, c-format
 msgid "Invalid SSL protocol '%s' specified, using default (SSLv23).\n"
 msgstr ""
 "Ungültiges SSL-Protokoll „%s“ angegeben, benutze Voreinstellung (SSLv23).\n"
 
 #, c-format
 msgid "Invalid SSL protocol '%s' specified, using default (SSLv23).\n"
 msgstr ""
 "Ungültiges SSL-Protokoll „%s“ angegeben, benutze Voreinstellung (SSLv23).\n"
 
-#: socket.c:921
+#: socket.c:934
 msgid "Certificate/fingerprint verification was somehow skipped!\n"
 msgstr "Zertifikat-/Fingerabdruck-Überprüfung wurde irgendwie übersprungen!\n"
 
 msgid "Certificate/fingerprint verification was somehow skipped!\n"
 msgstr "Zertifikat-/Fingerabdruck-Überprüfung wurde irgendwie übersprungen!\n"
 
-#: socket.c:999
+#: socket.c:1012
 msgid "Cygwin socket read retry\n"
 msgstr "Cygwin-Socket-Lese-Wiederholung\n"
 
 msgid "Cygwin socket read retry\n"
 msgstr "Cygwin-Socket-Lese-Wiederholung\n"
 
-#: socket.c:1002
+#: socket.c:1015
 msgid "Cygwin socket read retry failed!\n"
 msgstr "Cygwin-Socket-Lese-Wiederholung fehlgeschlagen!\n"
 
 msgid "Cygwin socket read retry failed!\n"
 msgstr "Cygwin-Socket-Lese-Wiederholung fehlgeschlagen!\n"
 
@@ -3054,50 +3068,46 @@ msgstr "keine „Received“-Adresse gefunden\n"
 msgid "found Received address `%s'\n"
 msgstr "„Received“-Adresse „%s“ gefunden\n"
 
 msgid "found Received address `%s'\n"
 msgstr "„Received“-Adresse „%s“ gefunden\n"
 
-#: transact.c:566
-msgid "message delimiter found while scanning headers\n"
-msgstr "Nachrichtentrenner gefunden beim Scannen der Kopfzeilen\n"
-
-#: transact.c:597
+#: transact.c:592
 msgid "incorrect header line found while scanning headers\n"
 msgstr "inkorrekte Kopfzeile gefunden beim Scannen der Kopfzeilen\n"
 
 msgid "incorrect header line found while scanning headers\n"
 msgstr "inkorrekte Kopfzeile gefunden beim Scannen der Kopfzeilen\n"
 
-#: transact.c:599
+#: transact.c:594
 #, c-format
 msgid "line: %s"
 msgstr "Zeile: %s"
 
 #, c-format
 msgid "line: %s"
 msgstr "Zeile: %s"
 
-#: transact.c:1138
+#: transact.c:1133
 #, c-format
 msgid "no local matches, forwarding to %s\n"
 msgstr "keine lokalen Übereinstimmungen, Weiterleitung an %s\n"
 
 #, c-format
 msgid "no local matches, forwarding to %s\n"
 msgstr "keine lokalen Übereinstimmungen, Weiterleitung an %s\n"
 
-#: transact.c:1153
+#: transact.c:1148
 msgid "forwarding and deletion suppressed due to DNS errors\n"
 msgstr "Weiterleiten und Löschen wegen DNS-Fehlern unterdrückt\n"
 
 msgid "forwarding and deletion suppressed due to DNS errors\n"
 msgstr "Weiterleiten und Löschen wegen DNS-Fehlern unterdrückt\n"
 
-#: transact.c:1263
+#: transact.c:1258
 msgid "writing RFC822 msgblk.headers\n"
 msgstr "schreibe RFC822 msgblk.headers\n"
 
 msgid "writing RFC822 msgblk.headers\n"
 msgstr "schreibe RFC822 msgblk.headers\n"
 
-#: transact.c:1282
+#: transact.c:1277
 msgid "no recipient addresses matched declared local names"
 msgstr "keine Empfängeradresse stimmt mit deklarierten lokalen Namen überein"
 
 msgid "no recipient addresses matched declared local names"
 msgstr "keine Empfängeradresse stimmt mit deklarierten lokalen Namen überein"
 
-#: transact.c:1289
+#: transact.c:1284
 #, c-format
 msgid "recipient address %s didn't match any local name"
 msgstr "Empfängeradresse %s stimmt mit keinem lokalen Namen überein"
 
 #, c-format
 msgid "recipient address %s didn't match any local name"
 msgstr "Empfängeradresse %s stimmt mit keinem lokalen Namen überein"
 
-#: transact.c:1298
+#: transact.c:1293
 msgid "message has embedded NULs"
 msgstr "Nachricht hat eingebettete NUL-Zeichen"
 
 msgid "message has embedded NULs"
 msgstr "Nachricht hat eingebettete NUL-Zeichen"
 
-#: transact.c:1306
+#: transact.c:1301
 msgid "SMTP listener rejected local recipient addresses: "
 msgstr "SMTP-Server lehnte Adressen mit lokalem Empfänger ab: "
 
 msgid "SMTP listener rejected local recipient addresses: "
 msgstr "SMTP-Server lehnte Adressen mit lokalem Empfänger ab: "
 
-#: transact.c:1445
+#: transact.c:1440
 msgid "error writing message text\n"
 msgstr "Fehler beim Schreiben des Nachrichtentextes\n"
 
 msgid "error writing message text\n"
 msgstr "Fehler beim Schreiben des Nachrichtentextes\n"
 
@@ -3172,3 +3182,6 @@ msgstr "malloc fehlgeschlagen\n"
 #: xmalloc.c:47
 msgid "realloc failed\n"
 msgstr "realloc fehlgeschlagen\n"
 #: xmalloc.c:47
 msgid "realloc failed\n"
 msgstr "realloc fehlgeschlagen\n"
+
+#~ msgid "message delimiter found while scanning headers\n"
+#~ msgstr "Nachrichtentrenner gefunden beim Scannen der Kopfzeilen\n"
index 474928d03ef7c764b33d5999df670b6986893e6c..45f03a6b83d733d7aa173e230829775081855108 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -608,7 +608,7 @@ static int SSL_verify_callback( int ok_return, X509_STORE_CTX *ctx, int strict )
 
        if (depth == 0 && !_depth0ck) {
                _depth0ck = 1;
 
        if (depth == 0 && !_depth0ck) {
                _depth0ck = 1;
-               
+
                if (outlevel >= O_VERBOSE) {
                        if ((i = X509_NAME_get_text_by_NID(issuer, NID_organizationName, buf, sizeof(buf))) != -1) {
                                report(stdout, GT_("Issuer Organization: %s\n"), buf);
                if (outlevel >= O_VERBOSE) {
                        if ((i = X509_NAME_get_text_by_NID(issuer, NID_organizationName, buf, sizeof(buf))) != -1) {
                                report(stdout, GT_("Issuer Organization: %s\n"), buf);
@@ -632,6 +632,12 @@ static int SSL_verify_callback( int ok_return, X509_STORE_CTX *ctx, int strict )
                                report(stderr, GT_("Bad certificate: Subject CommonName too long!\n"));
                                return (0);
                        }
                                report(stderr, GT_("Bad certificate: Subject CommonName too long!\n"));
                                return (0);
                        }
+                       if ((size_t)i > strlen(buf)) {
+                               /* Name contains embedded NUL characters, so we complain. This is likely
+                                * a certificate spoofing attack. */
+                               report(stderr, GT_("Bad certificate: Subject CommonName contains NUL, aborting!\n"));
+                               return 0;
+                       }
                        if (_ssl_server_cname != NULL) {
                                char *p1 = buf;
                                char *p2 = _ssl_server_cname;
                        if (_ssl_server_cname != NULL) {
                                char *p1 = buf;
                                char *p2 = _ssl_server_cname;
@@ -643,14 +649,21 @@ static int SSL_verify_callback( int ok_return, X509_STORE_CTX *ctx, int strict )
                                 * first find a match among alternative names */
                                gens = (STACK_OF(GENERAL_NAME) *)X509_get_ext_d2i(x509_cert, NID_subject_alt_name, NULL, NULL);
                                if (gens) {
                                 * first find a match among alternative names */
                                gens = (STACK_OF(GENERAL_NAME) *)X509_get_ext_d2i(x509_cert, NID_subject_alt_name, NULL, NULL);
                                if (gens) {
-                                       int i, r;
-                                       for (i = 0, r = sk_GENERAL_NAME_num(gens); i < r; ++i) {
-                                               const GENERAL_NAME *gn = sk_GENERAL_NAME_value(gens, i);
+                                       int j, r;
+                                       for (j = 0, r = sk_GENERAL_NAME_num(gens); j < r; ++j) {
+                                               const GENERAL_NAME *gn = sk_GENERAL_NAME_value(gens, j);
                                                if (gn->type == GEN_DNS) {
                                                        char *p1 = (char *)gn->d.ia5->data;
                                                        char *p2 = _ssl_server_cname;
                                                if (gn->type == GEN_DNS) {
                                                        char *p1 = (char *)gn->d.ia5->data;
                                                        char *p2 = _ssl_server_cname;
+                                                       /* Name contains embedded NUL characters, so we complain. This
+                                                        * is likely a certificate spoofing attack. */
+                                                       if ((size_t)gn->d.ia5->length != strlen(p1)) {
+                                                               report(stderr, GT_("Bad certificate: Subject Alternative Name contains NUL, aborting!\n"));
+                                                               sk_GENERAL_NAME_free(gens);
+                                                               return 0;
+                                                       }
                                                        if (outlevel >= O_VERBOSE)
                                                        if (outlevel >= O_VERBOSE)
-                                                               report(stderr, "Subject Alternative Name: %s\n", p1);
+                                                               report(stdout, GT_("Subject Alternative Name: %s\n"), p1);
                                                        if (*p1 == '*') {
                                                                ++p1;
                                                                n = strlen(p2) - strlen(p1);
                                                        if (*p1 == '*') {
                                                                ++p1;
                                                                n = strlen(p2) - strlen(p1);
@@ -669,9 +682,9 @@ static int SSL_verify_callback( int ok_return, X509_STORE_CTX *ctx, int strict )
                                        n = strlen(p2) - strlen(p1);
                                        if (n >= 0)
                                                p2 += n;
                                        n = strlen(p2) - strlen(p1);
                                        if (n >= 0)
                                                p2 += n;
-                               }       
+                               }
                                if (0 == strcasecmp(p1, p2)) {
                                if (0 == strcasecmp(p1, p2)) {
-                                 matched = 1;
+                                       matched = 1;
                                }
                                if (!matched) {
                                        report(stderr,
                                }
                                if (!matched) {
                                        report(stderr,