diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cert/x509/certstor.cpp | 40 | ||||
-rw-r--r-- | src/cert/x509/certstor.h | 24 | ||||
-rw-r--r-- | src/credentials/credentials_manager.cpp | 30 | ||||
-rw-r--r-- | src/credentials/credentials_manager.h | 3 | ||||
-rw-r--r-- | src/tls/msg_cert_req.cpp | 13 | ||||
-rw-r--r-- | src/tls/tls_messages.h | 2 | ||||
-rw-r--r-- | src/tls/tls_seq_numbers.h | 1 | ||||
-rw-r--r-- | src/tls/tls_server.cpp | 12 |
8 files changed, 78 insertions, 47 deletions
diff --git a/src/cert/x509/certstor.cpp b/src/cert/x509/certstor.cpp index f68177230..afb0ddd0c 100644 --- a/src/cert/x509/certstor.cpp +++ b/src/cert/x509/certstor.cpp @@ -20,13 +20,21 @@ bool Certificate_Store::certificate_known(const X509_Certificate& cert) const void Certificate_Store_In_Memory::add_certificate(const X509_Certificate& cert) { - for(size_t i = 0; i != certs.size(); ++i) + for(size_t i = 0; i != m_certs.size(); ++i) { - if(certs[i] == cert) + if(m_certs[i] == cert) return; } - certs.push_back(cert); + m_certs.push_back(cert); + } + +std::vector<X509_DN> Certificate_Store_In_Memory::all_subjects() const + { + std::vector<X509_DN> subjects; + for(size_t i = 0; i != m_certs.size(); ++i) + subjects.push_back(m_certs[i].subject_dn()); + return subjects; } std::vector<X509_Certificate> @@ -36,19 +44,19 @@ Certificate_Store_In_Memory::find_cert_by_subject_and_key_id( { std::vector<X509_Certificate> result; - for(size_t i = 0; i != certs.size(); ++i) + for(size_t i = 0; i != m_certs.size(); ++i) { // Only compare key ids if set in both call and in the cert if(key_id.size()) { - std::vector<byte> skid = certs[i].subject_key_id(); + std::vector<byte> skid = m_certs[i].subject_key_id(); if(skid.size() && skid != key_id) // no match continue; } - if(certs[i].subject_dn() == subject_dn) - result.push_back(certs[i]); + if(m_certs[i].subject_dn() == subject_dn) + result.push_back(m_certs[i]); } return result; @@ -58,19 +66,19 @@ void Certificate_Store_In_Memory::add_crl(const X509_CRL& crl) { X509_DN crl_issuer = crl.issuer_dn(); - for(size_t i = 0; i != crls.size(); ++i) + for(size_t i = 0; i != m_crls.size(); ++i) { // Found an update of a previously existing one; replace it - if(crls[i].issuer_dn() == crl_issuer) + if(m_crls[i].issuer_dn() == crl_issuer) { - if(crls[i].this_update() <= crl.this_update()) - crls[i] = crl; + if(m_crls[i].this_update() <= crl.this_update()) + m_crls[i] = crl; return; } } // Totally new CRL, add to the list - crls.push_back(crl); + m_crls.push_back(crl); } std::vector<X509_CRL> @@ -80,19 +88,19 @@ Certificate_Store_In_Memory::find_crl_by_issuer_and_key_id( { std::vector<X509_CRL> result; - for(size_t i = 0; i != crls.size(); ++i) + for(size_t i = 0; i != m_crls.size(); ++i) { // Only compare key ids if set in both call and in the CRL if(key_id.size()) { - std::vector<byte> akid = crls[i].authority_key_id(); + std::vector<byte> akid = m_crls[i].authority_key_id(); if(akid.size() && akid != key_id) // no match continue; } - if(crls[i].issuer_dn() == issuer_dn) - result.push_back(crls[i]); + if(m_crls[i].issuer_dn() == issuer_dn) + result.push_back(m_crls[i]); } return result; diff --git a/src/cert/x509/certstor.h b/src/cert/x509/certstor.h index 584259f8c..6faa0bfae 100644 --- a/src/cert/x509/certstor.h +++ b/src/cert/x509/certstor.h @@ -33,6 +33,8 @@ class BOTAN_DLL Certificate_Store bool certificate_known(const X509_Certificate& cert) const; + virtual std::vector<X509_DN> all_subjects() const = 0; + /** * Subject DN and (optionally) key identifier */ @@ -56,26 +58,30 @@ class BOTAN_DLL Certificate_Store class BOTAN_DLL Certificate_Store_In_Memory : public Certificate_Store { public: - void add_certificate(const X509_Certificate& cert); + Certificate_Store_In_Memory() {} + + void add_certificate(const X509_Certificate& cert) override; - void add_crl(const X509_CRL& crl); + void add_crl(const X509_CRL& crl) override; + + std::vector<X509_DN> all_subjects() const override; std::vector<X509_Certificate> find_cert_by_subject_and_key_id( const X509_DN& subject_dn, - const std::vector<byte>& key_id) const; + const std::vector<byte>& key_id) const override; std::vector<X509_CRL> find_crl_by_issuer_and_key_id( const X509_DN& issuer_dn, - const std::vector<byte>& key_id) const; - - Certificate_Store_In_Memory() {} + const std::vector<byte>& key_id) const override; private: // TODO: Add indexing on the DN and key id to avoid linear search - std::vector<X509_Certificate> certs; - std::vector<X509_CRL> crls; + std::vector<X509_Certificate> m_certs; + std::vector<X509_CRL> m_crls; }; -// TODO: file-backed store +// TODO: file backed store +// TODO: directory backed store (eg /usr/share/ca-certificates) +// TODO: sqlite3 backed store } diff --git a/src/credentials/credentials_manager.cpp b/src/credentials/credentials_manager.cpp index 95a54d1ae..1077edf61 100644 --- a/src/credentials/credentials_manager.cpp +++ b/src/credentials/credentials_manager.cpp @@ -85,14 +85,27 @@ Private_Key* Credentials_Manager::private_key_for(const X509_Certificate&, return nullptr; } -std::vector<X509_Certificate> +std::vector<Certificate_Store*> Credentials_Manager::trusted_certificate_authorities( const std::string&, const std::string&) { - return std::vector<X509_Certificate>(); + return std::vector<Certificate_Store*>(); + } + +namespace { + +bool cert_in_some_store(const std::vector<Certificate_Store*>& trusted_CAs, + const X509_Certificate& trust_root) + { + for(auto CAs : trusted_CAs) + if(CAs->certificate_known(trust_root)) + return true; + return false; } +} + void Credentials_Manager::verify_certificate_chain( const std::string& type, const std::string& purported_hostname, @@ -103,19 +116,16 @@ void Credentials_Manager::verify_certificate_chain( auto trusted_CAs = trusted_certificate_authorities(type, purported_hostname); - Certificate_Store_In_Memory CAs; - for(auto cert : trusted_CAs) - CAs.add_certificate(cert); + Path_Validation_Restrictions restrictions; - Path_Validation_Result result = - x509_path_validate(cert_chain, - Path_Validation_Restrictions(), - CAs); + auto result = x509_path_validate(cert_chain, + restrictions, + trusted_CAs); if(!result.successful_validation()) throw std::runtime_error("Certificate validation failure: " + result.result_string()); - if(!CAs.certificate_known(result.trust_root())) + if(!cert_in_some_store(trusted_CAs, result.trust_root())) throw std::runtime_error("Certificate chain roots in unknown/untrusted CA"); if(purported_hostname != "" && !cert_chain[0].matches_dns_name(purported_hostname)) diff --git a/src/credentials/credentials_manager.h b/src/credentials/credentials_manager.h index 8493ccd92..85db078e3 100644 --- a/src/credentials/credentials_manager.h +++ b/src/credentials/credentials_manager.h @@ -9,6 +9,7 @@ #define BOTAN_CREDENTIALS_MANAGER_H__ #include <botan/x509cert.h> +#include <botan/certstor.h> #include <botan/symkey.h> #include <string> @@ -38,7 +39,7 @@ class BOTAN_DLL Credentials_Manager * @param context specifies a context relative to type. For instance * for type "tls-client", context specifies the servers name. */ - virtual std::vector<X509_Certificate> trusted_certificate_authorities( + virtual std::vector<Certificate_Store*> trusted_certificate_authorities( const std::string& type, const std::string& context); diff --git a/src/tls/msg_cert_req.cpp b/src/tls/msg_cert_req.cpp index 4104025cf..23d59c6d4 100644 --- a/src/tls/msg_cert_req.cpp +++ b/src/tls/msg_cert_req.cpp @@ -54,16 +54,11 @@ byte cert_type_name_to_code(const std::string& name) Certificate_Req::Certificate_Req(Handshake_IO& io, Handshake_Hash& hash, const Policy& policy, - const std::vector<X509_Certificate>& ca_certs, - Protocol_Version version) + const std::vector<X509_DN>& ca_certs, + Protocol_Version version) : + m_names(ca_certs), + m_cert_key_types({ "RSA", "DSA", "ECDSA" }) { - for(size_t i = 0; i != ca_certs.size(); ++i) - m_names.push_back(ca_certs[i].subject_dn()); - - m_cert_key_types.push_back("RSA"); - m_cert_key_types.push_back("DSA"); - m_cert_key_types.push_back("ECDSA"); - if(version.supports_negotiable_signature_algorithms()) { std::vector<std::string> hashes = policy.allowed_signature_hashes(); diff --git a/src/tls/tls_messages.h b/src/tls/tls_messages.h index 52ff52c12..557677c4a 100644 --- a/src/tls/tls_messages.h +++ b/src/tls/tls_messages.h @@ -356,7 +356,7 @@ class Certificate_Req : public Handshake_Message Certificate_Req(Handshake_IO& io, Handshake_Hash& hash, const Policy& policy, - const std::vector<X509_Certificate>& allowed_cas, + const std::vector<X509_DN>& allowed_cas, Protocol_Version version); Certificate_Req(const std::vector<byte>& buf, diff --git a/src/tls/tls_seq_numbers.h b/src/tls/tls_seq_numbers.h index 4a8a0fab8..87edf3130 100644 --- a/src/tls/tls_seq_numbers.h +++ b/src/tls/tls_seq_numbers.h @@ -8,6 +8,7 @@ #ifndef BOTAN_TLS_SEQ_NUMBERS_H__ #define BOTAN_TLS_SEQ_NUMBERS_H__ +#include <botan/types.h> #include <stdexcept> namespace Botan { diff --git a/src/tls/tls_server.cpp b/src/tls/tls_server.cpp index b91dfc9aa..380d3d5b1 100644 --- a/src/tls/tls_server.cpp +++ b/src/tls/tls_server.cpp @@ -534,9 +534,19 @@ void Server::process_handshake_msg(const Handshake_State* active_state, ); } - std::vector<X509_Certificate> client_auth_CAs = + auto trusted_CAs = m_creds.trusted_certificate_authorities("tls-server", sni_hostname); + std::vector<X509_DN> client_auth_CAs; + + for(auto store : trusted_CAs) + { + auto subjects = store->all_subjects(); + client_auth_CAs.insert(client_auth_CAs.end(), + subjects.begin(), + subjects.end()); + } + if(!client_auth_CAs.empty() && state.ciphersuite().sig_algo() != "") { state.cert_req( |