591
static int ssl_check_certificate (sslsockdata * data)
604
/* port to mutt from msmtp's tls.c */
605
static int hostname_match (const char *hostname, const char *certname)
607
const char *cmp1, *cmp2;
609
if (strncmp(certname, "*.", 2) == 0)
612
cmp2 = strchr(hostname, '.');
628
if (*cmp1 == '\0' || *cmp2 == '\0')
633
if (strcasecmp(cmp1, cmp2) != 0)
641
/* port to mutt from msmtp's tls.c */
642
static int check_host (X509 *x509cert, const char *hostname, char *err, size_t errlen)
645
/* hostname in ASCII format: */
646
char *hostname_ascii = NULL;
647
/* needed to get the common name: */
648
X509_NAME *x509_subject;
651
/* needed to get the DNS subjectAltNames: */
652
STACK *subj_alt_names;
653
int subj_alt_names_count;
654
GENERAL_NAME *subj_alt_name;
655
/* did we find a name matching hostname? */
658
/* Check if 'hostname' matches the one of the subjectAltName extensions of
659
* type DNS or the Common Name (CN). */
662
if (idna_to_ascii_lz(hostname, &hostname_ascii, 0) != IDNA_SUCCESS)
664
hostname_ascii = safe_strdup(hostname);
667
hostname_ascii = safe_strdup(hostname);
670
/* Try the DNS subjectAltNames. */
672
if ((subj_alt_names = X509_get_ext_d2i(x509cert, NID_subject_alt_name,
675
subj_alt_names_count = sk_GENERAL_NAME_num(subj_alt_names);
676
for (i = 0; i < subj_alt_names_count; i++)
678
subj_alt_name = sk_GENERAL_NAME_value(subj_alt_names, i);
679
if (subj_alt_name->type == GEN_DNS)
681
if ((match_found = hostname_match(hostname_ascii,
682
(char *)(subj_alt_name->d.ia5->data))))
692
/* Try the common name */
693
if (!(x509_subject = X509_get_subject_name(x509cert)))
696
strfcpy (err, _("cannot get certificate subject"), errlen);
700
bufsize = X509_NAME_get_text_by_NID(x509_subject, NID_commonName,
703
buf = safe_malloc((size_t)bufsize);
704
if (X509_NAME_get_text_by_NID(x509_subject, NID_commonName,
708
strfcpy (err, _("cannot get certificate common name"), errlen);
711
match_found = hostname_match(hostname_ascii, buf);
717
snprintf (err, errlen, _("certificate owner does not match hostname %s"),
726
FREE(&hostname_ascii);
731
static int ssl_cache_trusted_cert (X509 *c)
733
dprint (1, (debugfile, "trusted: %s\n", c->name));
734
if (!SslSessionCerts)
735
SslSessionCerts = sk_new_null();
736
return (sk_X509_push (SslSessionCerts, X509_dup(c)));
739
/* check whether cert is preauthorized */
740
static int ssl_check_preauth (X509 *cert, CONNECTION *conn)
742
char buf[SHORT_STRING];
744
/* check session cache first */
745
if (check_certificate_cache (cert))
747
dprint (2, (debugfile, "ssl_check_preauth: using cached certificate\n"));
752
if (!check_host (cert, conn->account.host, buf, sizeof (buf)))
754
mutt_error (_("Certificate host check failed: %s"), buf);
758
dprint (2, (debugfile, "ssl_check_preauth: hostname check passed\n"));
760
if (check_certificate_by_signer (cert))
762
dprint (2, (debugfile, "ssl_check_preauth: signer check passed\n"));
766
/* automatic check from user's database */
767
if (SslCertFile && check_certificate_by_digest (cert))
769
dprint (2, (debugfile, "ssl_check_preauth: digest check passed\n"));
776
static int ssl_check_certificate (CONNECTION *conn, sslsockdata *data)
778
int i, preauthrc, chain_len;
779
STACK_OF(X509) *chain;
782
if ((preauthrc = ssl_check_preauth (data->cert, conn)) > 0)
785
chain = SSL_get_peer_cert_chain (data->ssl);
786
chain_len = sk_X509_num (chain);
787
if (!chain || (chain_len < 1))
788
return interactive_check_cert (data->cert, 0, 0);
790
/* check the chain from root to peer */
791
for (i = chain_len-1; i >= 0; i--)
793
cert = sk_X509_value (chain, i);
794
if (check_certificate_cache (cert))
795
dprint (2, (debugfile, "ssl chain: already cached: %s\n", cert->name));
796
else if (i /* 0 is the peer */ || !preauthrc)
798
if (check_certificate_by_signer (cert))
800
dprint (2, (debugfile, "ssl chain: checked by signer: %s\n", cert->name));
801
ssl_cache_trusted_cert (cert);
804
else if (SslCertFile && check_certificate_by_digest (cert))
806
dprint (2, (debugfile, "ssl chain: trusted with file: %s\n", cert->name));
807
ssl_cache_trusted_cert (cert);
810
else /* allow users to shoot their foot */
812
dprint (2, (debugfile, "ssl chain: check failed: %s\n", cert->name));
813
if (interactive_check_cert (cert, i, chain_len))
817
else /* highly suspicious because (i==0 && preauthrc < 0) */
818
if (interactive_check_cert (cert, i, chain_len))
825
static int interactive_check_cert (X509 *cert, int idx, int len)
594
{"/CN=", "/Email=", "/O=", "/OU=", "/L=", "/ST=", "/C="};
828
{"/CN=", "/Email=", "/O=", "/OU=", "/L=", "/ST=", "/C="};
595
829
char helpstr[LONG_STRING];
596
char buf[SHORT_STRING];
832
MUTTMENU *menu = mutt_new_menu (-1);
598
833
int done, row, i;
600
835
char *name = NULL, *c;
602
/* check session cache first */
603
if (check_certificate_cache (data->cert))
605
dprint (1, (debugfile, "ssl_check_certificate: using cached certificate\n"));
609
if (check_certificate_by_signer (data->cert))
611
dprint (1, (debugfile, "ssl_check_certificate: signer check passed\n"));
615
/* automatic check from user's database */
616
if (SslCertFile && check_certificate_by_digest (data->cert))
618
dprint (1, (debugfile, "ssl_check_certificate: digest check passed\n"));
622
/* interactive check from user */
623
menu = mutt_new_menu ();
837
dprint (2, (debugfile, "interactive_check_cert: %s\n", cert->name));
625
840
menu->dialog = (char **) safe_calloc (1, menu->max * sizeof (char *));
626
841
for (i = 0; i < menu->max; i++)
652
869
snprintf (menu->dialog[row++], SHORT_STRING, _("This certificate is valid"));
653
870
snprintf (menu->dialog[row++], SHORT_STRING, _(" from %s"),
654
asn1time_to_string (X509_get_notBefore (data->cert)));
871
asn1time_to_string (X509_get_notBefore (cert)));
655
872
snprintf (menu->dialog[row++], SHORT_STRING, _(" to %s"),
656
asn1time_to_string (X509_get_notAfter (data->cert)));
873
asn1time_to_string (X509_get_notAfter (cert)));
660
x509_fingerprint (buf, sizeof (buf), data->cert);
877
x509_fingerprint (buf, sizeof (buf), cert);
661
878
snprintf (menu->dialog[row++], SHORT_STRING, _("Fingerprint: %s"), buf);
663
menu->title = _("SSL Certificate check");
664
if (SslCertFile && X509_cmp_current_time (X509_get_notAfter (data->cert)) >= 0
665
&& X509_cmp_current_time (X509_get_notBefore (data->cert)) < 0)
880
snprintf (title, sizeof (title),
881
_("SSL Certificate check (certificate %d of %d in chain)"),
884
if (SslCertFile && X509_cmp_current_time (X509_get_notAfter (cert)) >= 0
885
&& X509_cmp_current_time (X509_get_notBefore (cert)) < 0)
667
887
menu->prompt = _("(r)eject, accept (o)nce, (a)ccept always");
668
888
menu->keys = _("roa");