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);
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;
}
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);
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;
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");
}
/* 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;
}
}