2006-12-06 [colin] 2.6.1cvs8
authorColin Leroy <colin@colino.net>
Wed, 6 Dec 2006 07:24:40 +0000 (07:24 +0000)
committerColin Leroy <colin@colino.net>
Wed, 6 Dec 2006 07:24:40 +0000 (07:24 +0000)
* src/ssl_manager.c
* src/common/ssl_certificate.c
* src/common/ssl_certificate.h
Handle multiple certificates per host/port

ChangeLog
PATCHSETS
configure.ac
src/common/ssl_certificate.c
src/common/ssl_certificate.h
src/ssl_manager.c

index 39d1b508be3d17809072c4741da8582bb1511fbc..e0adf0ef80a6e5946a6f236ca4ad76dc573d101e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2006-12-06 [colin]     2.6.1cvs8
+
+       * src/ssl_manager.c
+       * src/common/ssl_certificate.c
+       * src/common/ssl_certificate.h
+               Handle multiple certificates per host/port
+
 2006-12-06 [colin]     2.6.1cvs7
 
        * src/etpan/imap-thread.c
index a4dcdfd41ca10c051e6f455e60b030072d5d0b9b..56fb65d1aad1a2d24e47cfd51985791ffe029b41 100644 (file)
--- a/PATCHSETS
+++ b/PATCHSETS
 ( cvs diff -u -r 1.3.12.20 -r 1.3.12.21 src/message_search.c;  cvs diff -u -r 1.15.2.38 -r 1.15.2.39 src/summary_search.c;  cvs diff -u -r 1.1.2.3 -r 1.1.2.4 src/gtk/combobox.c;  cvs diff -u -r 1.1.2.3 -r 1.1.2.4 src/gtk/combobox.h;  cvs diff -u -r 1.5.2.45 -r 1.5.2.46 src/gtk/gtkutils.c;  cvs diff -u -r 1.4.2.27 -r 1.4.2.28 src/gtk/gtkutils.h;  ) > 2.6.1cvs5.patchset
 ( cvs diff -u -r 1.207.2.136 -r 1.207.2.137 src/folderview.c;  ) > 2.6.1cvs6.patchset
 ( cvs diff -u -r 1.1.4.58 -r 1.1.4.59 src/etpan/imap-thread.c;  ) > 2.6.1cvs7.patchset
+( cvs diff -u -r 1.3.2.23 -r 1.3.2.24 src/ssl_manager.c;  cvs diff -u -r 1.4.2.13 -r 1.4.2.14 src/common/ssl_certificate.c;  cvs diff -u -r 1.1.4.5 -r 1.1.4.6 src/common/ssl_certificate.h;  ) > 2.6.1cvs8.patchset
index 96799c425d535fa7d9ad8ee00167824f75133323..2b8848ce86d787764daa80d145ac14c6560048e1 100644 (file)
@@ -11,7 +11,7 @@ MINOR_VERSION=6
 MICRO_VERSION=1
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=7
+EXTRA_VERSION=8
 EXTRA_RELEASE=
 EXTRA_GTK2_VERSION=
 
index 1b57accf96760c98082a143b26037dc0883f53ab..d715ad484eb37ce9a30bdb793e58f56f82037471 100644 (file)
@@ -128,6 +128,8 @@ SSLCertificate *ssl_certificate_new(X509 *x509_cert, gchar *host, gushort port)
 static SSLCertificate *ssl_certificate_new_lookup(X509 *x509_cert, gchar *host, gushort port, gboolean lookup)
 {
        SSLCertificate *cert = g_new0(SSLCertificate, 1);
+       unsigned int n;
+       unsigned char md[EVP_MAX_MD_SIZE];      
        
        if (host == NULL || x509_cert == NULL) {
                ssl_certificate_destroy(cert);
@@ -139,6 +141,11 @@ static SSLCertificate *ssl_certificate_new_lookup(X509 *x509_cert, gchar *host,
        else
                cert->host = g_strdup(host);
        cert->port = port;
+       
+       /* fingerprint */
+       X509_digest(cert->x509_cert, EVP_md5(), md, &n);
+       cert->fingerprint = readable_fingerprint(md, (int)n);
+
        return cert;
 }
 
@@ -157,7 +164,7 @@ static void ssl_certificate_save (SSLCertificate *cert)
        port = g_strdup_printf("%d", cert->port);
        file = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, 
                          "certs", G_DIR_SEPARATOR_S,
-                         cert->host, ".", port, ".cert", NULL);
+                         cert->host, ".", port, ".", cert->fingerprint, ".cert", NULL);
 
        g_free(port);
        fp = g_fopen(file, "wb");
@@ -261,6 +268,7 @@ void ssl_certificate_destroy(SSLCertificate *cert)
        if (cert->x509_cert)
                X509_free(cert->x509_cert);
        g_free(cert->host);
+       g_free(cert->fingerprint);
        g_free(cert);
        cert = NULL;
 }
@@ -272,25 +280,26 @@ void ssl_certificate_delete_from_disk(SSLCertificate *cert)
        buf = g_strdup_printf("%d", cert->port);
        file = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, 
                          "certs", G_DIR_SEPARATOR_S,
-                         cert->host, ".", buf, ".cert", NULL);
+                         cert->host, ".", buf, ".", cert->fingerprint, ".cert", NULL);
        g_unlink (file);
-       g_free(buf);
        g_free(file);
+       g_free(buf);
 }
 
-SSLCertificate *ssl_certificate_find (gchar *host, gushort port)
+SSLCertificate *ssl_certificate_find (gchar *host, gushort port, const gchar *fingerprint)
 {
-       return ssl_certificate_find_lookup (host, port, TRUE);
+       return ssl_certificate_find_lookup (host, port, fingerprint, TRUE);
 }
 
-SSLCertificate *ssl_certificate_find_lookup (gchar *host, gushort port, gboolean lookup)
+SSLCertificate *ssl_certificate_find_lookup (gchar *host, gushort port, const gchar *fingerprint, gboolean lookup)
 {
-       gchar *file;
+       gchar *file = NULL;
        gchar *buf;
        gchar *fqdn_host;
        SSLCertificate *cert = NULL;
        X509 *tmp_x509;
-       FILE *fp;
+       FILE *fp = NULL;
+       gboolean must_rename = FALSE;
 
        if (lookup)
                fqdn_host = get_fqdn(host);
@@ -298,27 +307,52 @@ SSLCertificate *ssl_certificate_find_lookup (gchar *host, gushort port, gboolean
                fqdn_host = g_strdup(host);
 
        buf = g_strdup_printf("%d", port);
-       file = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, 
+       
+       if (fingerprint != NULL) {
+               file = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, 
+                         "certs", G_DIR_SEPARATOR_S,
+                         fqdn_host, ".", buf, ".", fingerprint, ".cert", NULL);
+               fp = g_fopen(file, "rb");
+       }
+       if (fp == NULL) {
+               /* see if we have the old one */
+               g_free(file);
+               file = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, 
                          "certs", G_DIR_SEPARATOR_S,
                          fqdn_host, ".", buf, ".cert", NULL);
+               fp = g_fopen(file, "rb");
 
-       g_free(buf);
-       fp = g_fopen(file, "rb");
+               if (fp)
+                       must_rename = (fingerprint != NULL);
+       }
        if (fp == NULL) {
                g_free(file);
                g_free(fqdn_host);
+               g_free(buf);
                return NULL;
        }
        
-       
        if ((tmp_x509 = d2i_X509_fp(fp, 0)) != NULL) {
                cert = ssl_certificate_new_lookup(tmp_x509, fqdn_host, port, lookup);
                X509_free(tmp_x509);
        }
        fclose(fp);
        g_free(file);
-       g_free(fqdn_host);
        
+       if (must_rename) {
+               gchar *old = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, 
+                         "certs", G_DIR_SEPARATOR_S,
+                         fqdn_host, ".", buf, ".cert", NULL);
+               gchar *new = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, 
+                         "certs", G_DIR_SEPARATOR_S,
+                         fqdn_host, ".", buf, ".", fingerprint, ".cert", NULL);
+               move_file(old, new, TRUE);
+               g_free(old);
+               g_free(new);
+       }
+       g_free(buf);
+       g_free(fqdn_host);
+
        return cert;
 }
 
@@ -370,7 +404,10 @@ gboolean ssl_certificate_check (X509 *x509_cert, gchar *fqdn, gchar *host, gusho
        SSLCertificate *known_cert;
        SSLCertHookData cert_hook_data;
        gchar *fqdn_host = NULL;        
-       
+       gchar *fingerprint;
+       unsigned int n;
+       unsigned char md[EVP_MAX_MD_SIZE];      
+
        if (fqdn)
                fqdn_host = g_strdup(fqdn);
        else if (host)
@@ -388,8 +425,13 @@ gboolean ssl_certificate_check (X509 *x509_cert, gchar *fqdn, gchar *host, gusho
                return FALSE;
        }
 
-       known_cert = ssl_certificate_find_lookup (fqdn_host, port, FALSE);
+       /* fingerprint */
+       X509_digest(x509_cert, EVP_md5(), md, &n);
+       fingerprint = readable_fingerprint(md, (int)n);
 
+       known_cert = ssl_certificate_find_lookup (fqdn_host, port, fingerprint, FALSE);
+
+       g_free(fingerprint);
        g_free(fqdn_host);
 
        if (known_cert == NULL) {
index 82f10d592e20793808fdd29fd301c7a6ac73853e..e29fbfd3d172977f2b6ca91e6bd392544c666d79 100644 (file)
@@ -40,6 +40,7 @@ struct _SSLCertificate
        X509 *x509_cert;
        gchar *host;
        gushort port;
+       gchar *fingerprint;
 };
 
 typedef struct _SSLCertHookData SSLCertHookData;
@@ -52,8 +53,8 @@ struct _SSLCertHookData
        gboolean accept;
 };
 
-SSLCertificate *ssl_certificate_find (gchar *host, gushort port);
-SSLCertificate *ssl_certificate_find_lookup (gchar *host, gushort port, gboolean lookup);
+SSLCertificate *ssl_certificate_find (gchar *host, gushort port, const gchar *fingerprint);
+SSLCertificate *ssl_certificate_find_lookup (gchar *host, gushort port, const gchar *fingerprint, gboolean lookup);
 gboolean ssl_certificate_check (X509 *x509_cert, gchar *fqdn, gchar *host, gushort port);
 char* ssl_certificate_to_string(SSLCertificate *cert);
 void ssl_certificate_destroy(SSLCertificate *cert);
index 19d653442b5eb814cedc442f6eba1caa3ed031b3..af901614fccd365e0e7a5c33e1842aa685793644 100644 (file)
@@ -211,16 +211,24 @@ void ssl_manager_create(void)
 static char *get_server(char *str)
 {
        char *ret = NULL, *tmp = g_strdup(str);
-       char *first_pos = NULL, *last_pos = NULL, *previous_pos = NULL;
+       char *first_pos = NULL, *last_pos = NULL;
+       char *previous_pos = NULL, *pre_previous_pos = NULL;
        int previous_dot_pos;
 
+       if (!strchr(tmp, ':')) {
+               /* no fingerprint */
+               if (strstr(tmp, ".cert"))
+                       *(strstr(tmp, ".cert")+1) = '.';
+       }
+
        first_pos = tmp;
        while (tmp && (tmp = strstr(tmp,".")) != NULL) {
                tmp++;
+               pre_previous_pos = previous_pos;
                previous_pos = last_pos;
                last_pos = tmp;
        }
-       previous_dot_pos = (previous_pos - first_pos);
+       previous_dot_pos = (pre_previous_pos - first_pos);
        if (previous_dot_pos - 1 > 0)
                ret = g_strndup(first_pos, previous_dot_pos - 1);
        else 
@@ -230,10 +238,43 @@ static char *get_server(char *str)
 }
 
 static char *get_port(char *str)
+{
+       char *ret = NULL, *tmp = g_strdup(str);
+       char *last_pos = NULL;
+       char *previous_pos = NULL, *pre_previous_pos = NULL;
+
+       if (!strchr(tmp, ':')) {
+               /* no fingerprint */
+               if (strstr(tmp, ".cert"))
+                       *(strstr(tmp, ".cert")+1) = '.';
+       }
+
+       while (tmp && (tmp = strstr(tmp,".")) != NULL) {
+               tmp++;
+               pre_previous_pos = previous_pos;
+               previous_pos = last_pos;
+               last_pos = tmp;
+       }
+       if (previous_pos && pre_previous_pos && (int)(previous_pos - pre_previous_pos - 1) > 0)
+               ret = g_strndup(pre_previous_pos, (int)(previous_pos - pre_previous_pos - 1));
+       else
+               ret = g_strdup("0");
+       g_free(tmp);
+       return ret;
+       
+}
+
+static char *get_fingerprint(char *str)
 {
        char *ret = NULL, *tmp = g_strdup(str);
        char *previous_pos = NULL, *last_pos = NULL;
 
+       if (!strchr(tmp, ':')) {
+               /* no fingerprint */
+               if (strstr(tmp, ".cert"))
+                       *(strstr(tmp, ".cert")+1) = '.';
+       }
+
        while (tmp && (tmp = strstr(tmp,".")) != NULL) {
                tmp++;
                previous_pos = last_pos;
@@ -242,7 +283,7 @@ static char *get_port(char *str)
        if (last_pos && previous_pos && (int)(last_pos - previous_pos - 1) > 0)
                ret = g_strndup(previous_pos, (int)(last_pos - previous_pos - 1));
        else
-               ret = g_strdup("0");
+               ret = NULL;
        g_free(tmp);
        return ret;
        
@@ -297,7 +338,7 @@ static void ssl_manager_load_certs (void)
        }
        
        while ((d = readdir(dir)) != NULL) {
-               gchar *server, *port;
+               gchar *server, *port, *fp;
                SSLCertificate *cert;
 
                if(!strstr(d->d_name, ".cert")) 
@@ -305,15 +346,16 @@ static void ssl_manager_load_certs (void)
 
                server = get_server(d->d_name);
                port = get_port(d->d_name);
+               fp = get_fingerprint(d->d_name);
                
-               
-               cert = ssl_certificate_find_lookup(server, atoi(port), FALSE);
-               
+               cert = ssl_certificate_find_lookup(server, atoi(port), fp, FALSE);
+
                ssl_manager_list_view_insert_cert(manager.certlist, NULL, 
                                                  server, port, cert);
                
                g_free(server);
                g_free(port);
+               g_free(fp);
                row++;
        }
        closedir(dir);