diff options
author | Oswald Buddenhagen <ossi@kde.org> | 2013-02-15 12:50:35 -0800 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2013-02-19 21:47:22 -0800 |
commit | b62fb077d5504deadea931fd16075729f39b8f47 (patch) | |
tree | ef911a96c6794d12b52f84be2dfe407102ccd4d5 /imap-send.c | |
parent | 1e1fe52923a8f582c4f50b41f0dd978d5d7c9bd3 (diff) | |
download | git-b62fb077d5504deadea931fd16075729f39b8f47.tar.gz |
imap-send: the subject of SSL certificate must match the host
We did not check a valid certificate's subject at all, and would
have happily talked with a wrong host after connecting to an
incorrect address and getting a valid certificate that does not
belong to the host we intended to talk to.
Signed-off-by: Oswald Buddenhagen <ossi@kde.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'imap-send.c')
-rw-r--r-- | imap-send.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/imap-send.c b/imap-send.c index 94f53c2c1d..0b9c464ad9 100644 --- a/imap-send.c +++ b/imap-send.c @@ -275,6 +275,35 @@ static int ssl_socket_connect(struct imap_socket *sock, int use_tls_only, int ve #else +static int host_matches(const char *host, const char *pattern) +{ + if (pattern[0] == '*' && pattern[1] == '.') { + pattern += 2; + if (!(host = strchr(host, '.'))) + return 0; + host++; + } + + return *host && *pattern && !strcasecmp(host, pattern); +} + +static int verify_hostname(X509 *cert, const char *hostname) +{ + int len; + X509_NAME *subj; + char cname[1000]; + + /* try the common name */ + if (!(subj = X509_get_subject_name(cert))) + return error("cannot get certificate subject"); + if ((len = X509_NAME_get_text_by_NID(subj, NID_commonName, cname, sizeof(cname))) < 0) + return error("cannot get certificate common name"); + if (strlen(cname) == (size_t)len && host_matches(hostname, cname)) + return 0; + return error("certificate owner '%s' does not match hostname '%s'", + cname, hostname); +} + static int ssl_socket_connect(struct imap_socket *sock, int use_tls_only, int verify) { #if (OPENSSL_VERSION_NUMBER >= 0x10000000L) @@ -284,6 +313,7 @@ static int ssl_socket_connect(struct imap_socket *sock, int use_tls_only, int ve #endif SSL_CTX *ctx; int ret; + X509 *cert; SSL_library_init(); SSL_load_error_strings(); @@ -327,6 +357,15 @@ static int ssl_socket_connect(struct imap_socket *sock, int use_tls_only, int ve return -1; } + if (verify) { + /* make sure the hostname matches that of the certificate */ + cert = SSL_get_peer_certificate(sock->ssl); + if (!cert) + return error("unable to get peer certificate."); + if (verify_hostname(cert, server.host) < 0) + return -1; + } + return 0; } #endif |