aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorlloyd <[email protected]>2012-11-13 19:25:35 +0000
committerlloyd <[email protected]>2012-11-13 19:25:35 +0000
commitcf8f87c832273ea2d70ed00be7130e36884e370c (patch)
tree7d8a9f493c74882a83c35b1993e8992ca221412a /src
parent58461a900aea49e5230b7b748fc481114d31904a (diff)
Change Credentials_Manager::trusted_certificate_authorities to return
a list of Certificate_Stores instead of a list of actual certs, allowing for instance the ability to reference a DB cert store without actually pulling all the certs into memory. Add Certificate_Store::all_subjects which returns the DNs of all contained certificates.
Diffstat (limited to 'src')
-rw-r--r--src/cert/x509/certstor.cpp40
-rw-r--r--src/cert/x509/certstor.h24
-rw-r--r--src/credentials/credentials_manager.cpp30
-rw-r--r--src/credentials/credentials_manager.h3
-rw-r--r--src/tls/msg_cert_req.cpp13
-rw-r--r--src/tls/tls_messages.h2
-rw-r--r--src/tls/tls_seq_numbers.h1
-rw-r--r--src/tls/tls_server.cpp12
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(