]> Pileus Git - ~andy/fetchmail/blobdiff - socket.c
Put 6.3.12 on front page.
[~andy/fetchmail] / socket.c
index 3a03a6eb0227609f67a4c2442b768f86373f0673..c245b3d4c55c12a7291feaafecae050b8a94b202 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -52,6 +52,7 @@
 #include "fetchmail.h"
 #include "getaddrinfo.h"
 #include "i18n.h"
+#include "sdump.h"
 
 /* Defines to allow BeOS and Cygwin to play nice... */
 #ifdef __BEOS__
@@ -276,6 +277,9 @@ int SockOpen(const char *host, const char *service,
 
     memset(&req, 0, sizeof(struct addrinfo));
     req.ai_socktype = SOCK_STREAM;
+#ifdef AI_ADDRCONFIG
+    req.ai_flags = AI_ADDRCONFIG;
+#endif
 
     i = fm_getaddrinfo(host, service, &req, ai0);
     if (i) {
@@ -595,6 +599,7 @@ static int SSL_verify_callback( int ok_return, X509_STORE_CTX *ctx, int strict )
        const EVP_MD *digest_tp;
        unsigned int dsz, esz;
        X509_NAME *subj, *issuer;
+       char *tt;
 
        x509_cert = X509_STORE_CTX_get_current_cert(ctx);
        err = X509_STORE_CTX_get_error(ctx);
@@ -605,30 +610,40 @@ static int SSL_verify_callback( int ok_return, X509_STORE_CTX *ctx, int strict )
 
        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);
+                               report(stdout, GT_("Issuer Organization: %s\n"), (tt = sdump(buf, i)));
+                               xfree(tt);
                                if ((size_t)i >= sizeof(buf) - 1)
                                        report(stdout, GT_("Warning: Issuer Organization Name too long (possibly truncated).\n"));
                        } else
                                report(stdout, GT_("Unknown Organization\n"));
                        if ((i = X509_NAME_get_text_by_NID(issuer, NID_commonName, buf, sizeof(buf))) != -1) {
-                               report(stdout, GT_("Issuer CommonName: %s\n"), buf);
+                               report(stdout, GT_("Issuer CommonName: %s\n"), (tt = sdump(buf, i)));
+                               xfree(tt);
                                if ((size_t)i >= sizeof(buf) - 1)
                                        report(stdout, GT_("Warning: Issuer CommonName too long (possibly truncated).\n"));
                        } else
                                report(stdout, GT_("Unknown Issuer CommonName\n"));
                }
                if ((i = X509_NAME_get_text_by_NID(subj, NID_commonName, buf, sizeof(buf))) != -1) {
-                       if (outlevel >= O_VERBOSE)
-                               report(stdout, GT_("Server CommonName: %s\n"), buf);
+                       if (outlevel >= O_VERBOSE) {
+                               report(stdout, GT_("Server CommonName: %s\n"), (tt = sdump(buf, i)));
+                               xfree(tt);
+                       }
                        if ((size_t)i >= sizeof(buf) - 1) {
                                /* Possible truncation. In this case, this is a DNS name, so this
                                 * is really bad. We do not tolerate this even in the non-strict case. */
                                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;
@@ -640,14 +655,23 @@ 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) {
-                                       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 (outlevel >= O_VERBOSE)
-                                                               report(stderr, "Subject Alternative Name: %s\n", p1);
+                                                       if (outlevel >= O_VERBOSE) {
+                                                               report(stdout, GT_("Subject Alternative Name: %s\n"), (tt = sdump(p1, (size_t)gn->d.ia5->length)));
+                                                               xfree(tt);
+                                                       }
+                                                       /* 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 (*p1 == '*') {
                                                                ++p1;
                                                                n = strlen(p2) - strlen(p1);
@@ -666,14 +690,15 @@ static int SSL_verify_callback( int ok_return, X509_STORE_CTX *ctx, int strict )
                                        n = strlen(p2) - strlen(p1);
                                        if (n >= 0)
                                                p2 += n;
-                               }       
+                               }
                                if (0 == strcasecmp(p1, p2)) {
-                                 matched = 1;
+                                       matched = 1;
                                }
                                if (!matched) {
                                        report(stderr,
                                            GT_("Server CommonName mismatch: %s != %s\n"),
-                                           buf, _ssl_server_cname );
+                                           (tt = sdump(buf, i)), _ssl_server_cname );
+                                       xfree(tt);
                                        if (ok_return && strict)
                                                return (0);
                                }
@@ -717,7 +742,7 @@ static int SSL_verify_callback( int ok_return, X509_STORE_CTX *ctx, int strict )
                        if (outlevel > O_NORMAL)
                            report(stdout, GT_("%s key fingerprint: %s\n"), _server_label, text);
                        if (_check_digest != NULL) {
-                               if (strcmp(text, _check_digest) == 0) {
+                               if (strcasecmp(text, _check_digest) == 0) {
                                    if (outlevel > O_NORMAL)
                                        report(stdout, GT_("%s fingerprints match.\n"), _server_label);
                                } else {