X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=mutt_ssl.c;h=870ab8936d0f22b6b4b2f1861f79b6021141637c;hp=0cf05f7c4765c2bdc28ffc9ed94cf7d34f4b589d;hb=a8477ebaa09990b3688164cbe5cf661c4189541d;hpb=814a01519c9605d479201b99eb16c97b0ad8635d diff --git a/mutt_ssl.c b/mutt_ssl.c index 0cf05f7..870ab89 100644 --- a/mutt_ssl.c +++ b/mutt_ssl.c @@ -343,8 +343,9 @@ static int ssl_socket_close (CONNECTION * conn) if (data) { SSL_shutdown (data->ssl); - +#if 0 X509_free (data->cert); +#endif SSL_free (data->ssl); SSL_CTX_free (data->ctx); FREE (&conn->sockdata); @@ -353,6 +354,46 @@ static int ssl_socket_close (CONNECTION * conn) return raw_socket_close (conn); } +static int compare_certificates (X509 *cert, X509 *peercert, + unsigned char *peermd, + unsigned int peermdlen) { + unsigned char md[EVP_MAX_MD_SIZE]; + unsigned int mdlen; + + /* Avoid CPU-intensive digest calculation if the certificates are + * not even remotely equal. + */ + if (X509_subject_name_cmp (cert, peercert) != 0 || + X509_issuer_name_cmp (cert, peercert) != 0) + return -1; + + if (!X509_digest (cert, EVP_sha1(), md, &mdlen) || peermdlen != mdlen) + return -1; + + if (memcmp(peermd, md, mdlen) != 0) + return -1; + + return 0; +} + +static int check_certificate_cache (X509 *peercert) { + unsigned char peermd[EVP_MAX_MD_SIZE]; + unsigned int peermdlen; + X509 *cert; + LIST *scert; + + if (!X509_digest (peercert, EVP_sha1(), peermd, &peermdlen)) + return 0; + + for (scert = SslSessionCerts; scert; scert = scert->next) { + cert = *(X509**)scert->data; + if (!compare_certificates (cert, peercert, peermd, peermdlen)) { + return 1; + } + } + return 0; +} + static int tls_close (CONNECTION * conn) { int rc; @@ -374,7 +415,7 @@ static char *x509_get_part (char *line, const char *ndx) c = strstr (line, ndx); if (c) { - c += safe_strlen (ndx); + c += str_len (ndx); c2 = strchr (c, '/'); if (c2) *c2 = '\0'; @@ -400,7 +441,7 @@ static void x509_fingerprint (char *s, int l, X509 * cert) char ch[8]; snprintf (ch, 8, "%02X%s", md[j], (j % 2 ? " " : "")); - safe_strcat (s, l, ch); + str_cat (s, l, ch); } } } @@ -501,24 +542,9 @@ static int check_certificate_by_digest (X509 * peercert) } while ((cert = READ_X509_KEY (fp, &cert)) != NULL) { - unsigned char md[EVP_MAX_MD_SIZE]; - unsigned int mdlen; - - /* Avoid CPU-intensive digest calculation if the certificates are - * not even remotely equal. - */ - if (X509_subject_name_cmp (cert, peercert) != 0 || - X509_issuer_name_cmp (cert, peercert) != 0) - continue; - - if (!X509_digest (cert, EVP_sha1 (), md, &mdlen) || peermdlen != mdlen) - continue; - - if (memcmp (peermd, md, mdlen) != 0) - continue; - - pass = 1; - break; + pass = compare_certificates (cert, peercert, peermd, peermdlen) ? 0 : 1; + if (pass) + break; } X509_free (cert); fclose (fp); @@ -536,6 +562,12 @@ static int ssl_check_certificate (sslsockdata * data) FILE *fp; char *name = NULL, *c; + /* check session cache first */ + if (check_certificate_cache (data->cert)) { + debug_print (1, ("ssl_check_certificate: using cached certificate\n")); + return 1; + } + if (check_certificate_by_signer (data->cert)) { debug_print (1, ("signer check passed\n")); return 1; @@ -590,7 +622,9 @@ static int ssl_check_certificate (sslsockdata * data) snprintf (menu->dialog[row++], SHORT_STRING, _("Fingerprint: %s"), buf); menu->title = _("SSL Certificate check"); - if (SslCertFile) { + + if (SslCertFile && X509_cmp_current_time (X509_get_notAfter (data->cert)) >= 0 + && X509_cmp_current_time (X509_get_notBefore (data->cert)) < 0) { menu->prompt = _("(r)eject, accept (o)nce, (a)ccept always"); menu->keys = _("roa"); } @@ -601,9 +635,9 @@ static int ssl_check_certificate (sslsockdata * data) helpstr[0] = '\0'; mutt_make_help (buf, sizeof (buf), _("Exit "), MENU_GENERIC, OP_EXIT); - safe_strcat (helpstr, sizeof (helpstr), buf); + str_cat (helpstr, sizeof (helpstr), buf); mutt_make_help (buf, sizeof (buf), _("Help"), MENU_GENERIC, OP_HELP); - safe_strcat (helpstr, sizeof (helpstr), buf); + str_cat (helpstr, sizeof (helpstr), buf); menu->help = helpstr; done = 0; @@ -633,6 +667,10 @@ static int ssl_check_certificate (sslsockdata * data) /* fall through */ case OP_MAX + 2: /* accept once */ done = 2; + /* keep a handle on accepted certificates in case we want to + * open up another connection to the same server in this session */ + SslSessionCerts = mutt_add_list_n (SslSessionCerts, &data->cert, + sizeof (X509 **)); break; } }