Changeset 5452:934a802dff7f
- Timestamp:
- 2008-07-10 23:47:01 (3 months ago)
- Author:
- Rocco Rutte <pdmef@…>
- Branch:
- HEAD
- Message:
-
Verify hostname in (Open)SSL certificate validation
This is based on the patch by gkloepfer attached to #3087 but passes the
proper connection as argument (avoiding adding hostname to struct
sslsockdata) and validates the hostname even in case OpenSSL cannot find
the local issuer certificate. GnuTLS already supports hostname
checking. Closes #3087.
- Files:
-
Legend:
- Unmodified
- Added
- Removed
-
|
r5010
|
r5452
|
|
| 75 | 75 | static int ssl_socket_close (CONNECTION * conn); |
| 76 | 76 | static int tls_close (CONNECTION* conn); |
| 77 | | static int ssl_check_certificate (sslsockdata * data); |
| | 77 | static int ssl_check_certificate (CONNECTION *conn, sslsockdata * data); |
| 78 | 78 | static void ssl_get_client_cert(sslsockdata *ssldata, CONNECTION *conn); |
| 79 | 79 | static int ssl_passwd_cb(char *buf, int size, int rwflag, void *userdata); |
| 80 | | static int ssl_negotiate (sslsockdata*); |
| | 80 | static int ssl_negotiate (CONNECTION *conn, sslsockdata*); |
| 81 | 81 | |
| 82 | 82 | /* mutt_ssl_starttls: Negotiate TLS over an already opened connection. |
| … |
… |
|
| 112 | 112 | } |
| 113 | 113 | |
| 114 | | if (ssl_negotiate (ssldata)) |
| | 114 | if (ssl_negotiate (conn, ssldata)) |
| 115 | 115 | goto bail_ssl; |
| 116 | 116 | |
| … |
… |
|
| 291 | 291 | SSL_set_fd (data->ssl, conn->fd); |
| 292 | 292 | |
| 293 | | if (ssl_negotiate(data)) |
| | 293 | if (ssl_negotiate(conn, data)) |
| 294 | 294 | { |
| 295 | 295 | mutt_socket_close (conn); |
| … |
… |
|
| 305 | 305 | /* ssl_negotiate: After SSL state has been initialised, attempt to negotiate |
| 306 | 306 | * SSL over the wire, including certificate checks. */ |
| 307 | | static int ssl_negotiate (sslsockdata* ssldata) |
| | 307 | static int ssl_negotiate (CONNECTION *conn, sslsockdata* ssldata) |
| 308 | 308 | { |
| 309 | 309 | int err; |
| … |
… |
|
| 344 | 344 | } |
| 345 | 345 | |
| 346 | | if (!ssl_check_certificate (ssldata)) |
| | 346 | if (!ssl_check_certificate (conn, ssldata)) |
| 347 | 347 | return -1; |
| 348 | 348 | |
| … |
… |
|
| 589 | 589 | } |
| 590 | 590 | |
| 591 | | static int ssl_check_certificate (sslsockdata * data) |
| | 591 | static int check_certificate_hostname(X509 *peercert, const char *host) |
| | 592 | { |
| | 593 | char cert_CN[STRING]; |
| | 594 | |
| | 595 | if (!host || !*host) |
| | 596 | return 0; |
| | 597 | |
| | 598 | X509_NAME_get_text_by_NID (X509_get_subject_name (peercert), |
| | 599 | NID_commonName, cert_CN, sizeof (cert_CN)); |
| | 600 | |
| | 601 | dprint (2, (debugfile, "check_certificate_hostname: cert=[%s] host=[%s]\n", |
| | 602 | cert_CN, host)); |
| | 603 | |
| | 604 | return strcmp (cert_CN, host) == 0; |
| | 605 | } |
| | 606 | |
| | 607 | static int ssl_check_certificate (CONNECTION *conn, sslsockdata * data) |
| 592 | 608 | { |
| 593 | 609 | char *part[] = |
| … |
… |
|
| 596 | 612 | char buf[SHORT_STRING]; |
| 597 | 613 | MUTTMENU *menu; |
| 598 | | int done, row, i; |
| | 614 | int done, row, i, certerr_hostname = 0; |
| 599 | 615 | FILE *fp; |
| 600 | 616 | char *name = NULL, *c; |
| … |
… |
|
| 607 | 623 | } |
| 608 | 624 | |
| 609 | | if (check_certificate_by_signer (data->cert)) |
| | 625 | if (check_certificate_hostname (data->cert, conn->account.host)) |
| | 626 | { |
| | 627 | dprint (1, (debugfile, "ssl_check_certificate: hostname check passed\n")); |
| | 628 | } |
| | 629 | else |
| | 630 | certerr_hostname = 1; |
| | 631 | |
| | 632 | if (!certerr_hostname && check_certificate_by_signer (data->cert)) |
| 610 | 633 | { |
| 611 | 634 | dprint (1, (debugfile, "ssl_check_certificate: signer check passed\n")); |
| … |
… |
|
| 614 | 637 | |
| 615 | 638 | /* automatic check from user's database */ |
| 616 | | if (SslCertFile && check_certificate_by_digest (data->cert)) |
| | 639 | if (!certerr_hostname && SslCertFile && check_certificate_by_digest (data->cert)) |
| 617 | 640 | { |
| 618 | 641 | dprint (1, (debugfile, "ssl_check_certificate: digest check passed\n")); |