diff options
author | lloyd <lloyd@randombit.net> | 2012-02-01 17:55:03 +0000 |
---|---|---|
committer | lloyd <lloyd@randombit.net> | 2012-02-01 17:55:03 +0000 |
commit | 863a5420e3ad5efcfc7a175eed0d1a0b641c83c0 (patch) | |
tree | ad82580eca85f784b2965ec61a1d1bb25fac1695 | |
parent | e2e9105071f2d0a1360603f06c2acf68865ff072 (diff) |
Actually check CA signatures in Credentials_Manager. This area needs a
lot more work before this can be deployed.
-rw-r--r-- | src/cert/x509cert/x509cert.cpp | 28 | ||||
-rw-r--r-- | src/cert/x509cert/x509cert.h | 6 | ||||
-rw-r--r-- | src/credentials/credentials_manager.cpp | 28 | ||||
-rw-r--r-- | src/credentials/credentials_manager.h | 5 | ||||
-rw-r--r-- | src/tls/tls_client.cpp | 4 | ||||
-rw-r--r-- | src/tls/tls_server.cpp | 2 |
6 files changed, 55 insertions, 18 deletions
diff --git a/src/cert/x509cert/x509cert.cpp b/src/cert/x509cert/x509cert.cpp index 88aeebd77..7b57f6b1c 100644 --- a/src/cert/x509cert/x509cert.cpp +++ b/src/cert/x509cert/x509cert.cpp @@ -284,6 +284,34 @@ X509_DN X509_Certificate::subject_dn() const return create_dn(subject); } +namespace { + +bool cert_subject_dns_match(const std::string& name, + const std::vector<std::string>& cert_names) + { + for(size_t i = 0; i != cert_names.size(); ++i) + { + // support basic wildcarding? + if(cert_names[i] == name) + return true; + } + + return false; + } + +} + +bool X509_Certificate::matches_dns_name(const std::string& name) const + { + if(cert_subject_dns_match(name, subject_info("DNS"))) + return true; + + if(cert_subject_dns_match(name, subject_info("Name"))) + return true; + + return false; + } + /* * Compare two certificates for equality */ diff --git a/src/cert/x509cert/x509cert.h b/src/cert/x509cert/x509cert.h index cd49aa02f..26c57e524 100644 --- a/src/cert/x509cert/x509cert.h +++ b/src/cert/x509cert/x509cert.h @@ -146,6 +146,12 @@ class BOTAN_DLL X509_Certificate : public X509_Object std::string to_string() const; /** + * Check if a certain DNS name matches up with the information in + * the cert + */ + bool matches_dns_name(const std::string& name) const; + + /** * Check to certificates for equality. * @return true both certificates are (binary) equal */ diff --git a/src/credentials/credentials_manager.cpp b/src/credentials/credentials_manager.cpp index 7ca6ac657..ef5d44819 100644 --- a/src/credentials/credentials_manager.cpp +++ b/src/credentials/credentials_manager.cpp @@ -6,6 +6,7 @@ */ #include <botan/credentials_manager.h> +#include <botan/x509stor.h> namespace Botan { @@ -88,31 +89,32 @@ Credentials_Manager::trusted_certificate_authorities( } void Credentials_Manager::verify_certificate_chain( - const std::vector<X509_Certificate>& cert_chain, - const std::string& purported_hostname) + const std::string& type, + const std::string& purported_hostname, + const std::vector<X509_Certificate>& cert_chain) { if(cert_chain.empty()) throw std::invalid_argument("Certificate chain was empty"); -#if 0 - X509_Store store; + if(!cert_chain[0].matches_dns_name(purported_hostname)) + throw std::runtime_error("Certificate did not match hostname"); + + std::vector<X509_Certificate> CAs = trusted_certificate_authorities(type, purported_hostname); - std::vector<X509_Certificate> CAs = trusted_certificate_authorities(); + X509_Store store; - for(size_t i = 1; i != CAs.size(); ++i) + for(size_t i = 0; i != CAs.size(); ++i) store.add_cert(CAs[i], true); - for(size_t i = 1; i != cert_chain.size(); ++i) + for(size_t i = 0; i != cert_chain.size(); ++i) store.add_cert(cert_chain[i]); - X509_Code result = store.validate_cert(cert_chain[0], TLS_SERVER); + X509_Code result = store.validate_cert(cert_chain[0], X509_Store::TLS_SERVER); + + if(CAs.empty() && result == CERT_ISSUER_NOT_FOUND) + return; if(result != VERIFIED) throw std::runtime_error("Certificate did not validate"); - - if(!cert_chain[0].matches_dns_name(purported_hostname)) - throw std::runtime_error("Certificate did not match hostname"); - -#endif } } diff --git a/src/credentials/credentials_manager.h b/src/credentials/credentials_manager.h index 7dc049722..3994de6c6 100644 --- a/src/credentials/credentials_manager.h +++ b/src/credentials/credentials_manager.h @@ -124,8 +124,9 @@ class BOTAN_DLL Credentials_Manager * certificate chain cannot be verified. */ virtual void verify_certificate_chain( - const std::vector<X509_Certificate>& cert_chain, - const std::string& hostname = ""); + const std::string& type, + const std::string& hostname, + const std::vector<X509_Certificate>& cert_chain); /** * @return private key associated with this certificate if we should diff --git a/src/tls/tls_client.cpp b/src/tls/tls_client.cpp index 2bcdf7457..8b5ea9347 100644 --- a/src/tls/tls_client.cpp +++ b/src/tls/tls_client.cpp @@ -266,8 +266,8 @@ void Client::process_handshake_msg(Handshake_Type type, try { - creds.verify_certificate_chain(peer_certs, - state->client_hello->sni_hostname()); + const std::string hostname = state->client_hello->sni_hostname(); + creds.verify_certificate_chain("tls-client", hostname, peer_certs); } catch(std::exception& e) { diff --git a/src/tls/tls_server.cpp b/src/tls/tls_server.cpp index d186ddac4..a7857edf3 100644 --- a/src/tls/tls_server.cpp +++ b/src/tls/tls_server.cpp @@ -384,7 +384,7 @@ void Server::process_handshake_msg(Handshake_Type type, try { - creds.verify_certificate_chain(client_certs); + creds.verify_certificate_chain("tls-server", "", client_certs); } catch(std::exception& e) { |