aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/examples/asio_tls_server.cpp56
-rw-r--r--doc/examples/credentials.h53
-rw-r--r--doc/examples/tls_client.cpp54
-rw-r--r--doc/examples/tls_server.cpp55
-rw-r--r--src/credentials/credentials_manager.cpp30
-rw-r--r--src/credentials/credentials_manager.h27
-rw-r--r--src/tls/tls_client.cpp12
-rw-r--r--src/tls/tls_policy.h11
-rw-r--r--src/tls/tls_server.cpp12
9 files changed, 137 insertions, 173 deletions
diff --git a/doc/examples/asio_tls_server.cpp b/doc/examples/asio_tls_server.cpp
index 90f4fc20a..1a46bc8e8 100644
--- a/doc/examples/asio_tls_server.cpp
+++ b/doc/examples/asio_tls_server.cpp
@@ -14,6 +14,8 @@
#include <botan/auto_rng.h>
#include <botan/init.h>
+#include "credentials.h"
+
using Botan::byte;
using asio::ip::tcp;
@@ -181,58 +183,6 @@ class tls_server_session : public boost::enable_shared_from_this<tls_server_sess
std::vector<byte> m_outbox;
};
-class Credentials_Manager_Simple : public Botan::Credentials_Manager
- {
- public:
- Credentials_Manager_Simple(Botan::RandomNumberGenerator& rng) : rng(rng) {}
-
- std::vector<Botan::X509_Certificate> cert_chain(
- const std::string& cert_key_type,
- const std::string& type,
- const std::string& context)
- {
- const std::string hostname = (context == "" ? "localhost" : context);
-
- Botan::X509_Certificate cert(hostname + ".crt");
- Botan::Private_Key* key = Botan::PKCS8::load_key(hostname + ".key", rng);
-
- certs_and_keys[cert] = key;
-
- std::vector<Botan::X509_Certificate> certs;
- certs.push_back(cert);
- return certs;
- }
-
- Botan::Private_Key* private_key_for(const Botan::X509_Certificate& cert,
- const std::string& type,
- const std::string& context)
- {
- return certs_and_keys[cert];
- }
-
- private:
- Botan::RandomNumberGenerator& rng;
- std::map<Botan::X509_Certificate, Botan::Private_Key*> certs_and_keys;
- };
-
-class Server_TLS_Policy : public Botan::TLS::Policy
- {
- public:
- //bool require_client_auth() const { return true; }
-
- bool check_cert(const std::vector<Botan::X509_Certificate>& certs) const
- {
- for(size_t i = 0; i != certs.size(); ++i)
- {
- std::cout << certs[i].to_string();
- }
-
- std::cout << "Warning: not checking cert signatures\n";
-
- return true;
- }
- };
-
class tls_server
{
public:
@@ -290,7 +240,7 @@ class tls_server
Botan::AutoSeeded_RNG m_rng;
Botan::TLS::Session_Manager_In_Memory m_session_manager;
- Server_TLS_Policy m_policy;
+ Botan::TLS::Policy m_policy;
Credentials_Manager_Simple m_creds;
};
diff --git a/doc/examples/credentials.h b/doc/examples/credentials.h
new file mode 100644
index 000000000..802e3233c
--- /dev/null
+++ b/doc/examples/credentials.h
@@ -0,0 +1,53 @@
+
+#ifndef EXAMPLE_CREDENTIALS_MANAGER_H__
+#define EXAMPLE_CREDENTIALS_MANAGER_H__
+
+#include <botan/credentials_manager.h>
+
+class Credentials_Manager_Simple : public Botan::Credentials_Manager
+ {
+ public:
+ Credentials_Manager_Simple(Botan::RandomNumberGenerator& rng) : rng(rng) {}
+
+ std::vector<Botan::X509_Certificate> cert_chain(
+ const std::string& cert_key_type,
+ const std::string& type,
+ const std::string& context)
+ {
+ std::vector<Botan::X509_Certificate> certs;
+
+ if(type == "tls-server")
+ {
+ const std::string hostname = (context == "" ? "localhost" : context);
+
+ Botan::X509_Certificate cert(hostname + ".crt");
+ Botan::Private_Key* key = Botan::PKCS8::load_key(hostname + ".key", rng);
+
+ certs_and_keys[cert] = key;
+ certs.push_back(cert);
+ }
+ else if(type == "tls-client")
+ {
+ Botan::X509_Certificate cert("user-rsa.crt");
+ Botan::Private_Key* key = Botan::PKCS8::load_key("user-rsa.key", rng);
+
+ certs_and_keys[cert] = key;
+ certs.push_back(cert);
+ }
+
+ return certs;
+ }
+
+ Botan::Private_Key* private_key_for(const Botan::X509_Certificate& cert,
+ const std::string& type,
+ const std::string& context)
+ {
+ return certs_and_keys[cert];
+ }
+
+ private:
+ Botan::RandomNumberGenerator& rng;
+ std::map<Botan::X509_Certificate, Botan::Private_Key*> certs_and_keys;
+ };
+
+#endif
diff --git a/doc/examples/tls_client.cpp b/doc/examples/tls_client.cpp
index 000f63ed4..80947af62 100644
--- a/doc/examples/tls_client.cpp
+++ b/doc/examples/tls_client.cpp
@@ -16,28 +16,12 @@
#include <errno.h>
#include <fcntl.h>
+#include "credentials.h"
+
using namespace Botan;
using namespace std::tr1::placeholders;
-class Client_TLS_Policy : public TLS::Policy
- {
- public:
- //Version_Code pref_version() const { return TLS_V12; }
-
- bool check_cert(const std::vector<X509_Certificate>& certs) const
- {
- for(size_t i = 0; i != certs.size(); ++i)
- {
- std::cout << certs[i].to_string();
- }
-
- std::cout << "Warning: not checking cert signatures\n";
-
- return true;
- }
- };
-
int connect_to_host(const std::string& host, u16bit port)
{
hostent* host_addr = ::gethostbyname(host.c_str());
@@ -206,38 +190,6 @@ void doit(RandomNumberGenerator& rng,
::close(sockfd);
}
-class Credentials_Manager_Simple : public Credentials_Manager
- {
- public:
- Credentials_Manager_Simple(RandomNumberGenerator& rng) : rng(rng) {}
-
- std::vector<X509_Certificate> cert_chain(
- const std::string& cert_key_type,
- const std::string& type,
- const std::string& context)
- {
- X509_Certificate cert("user-rsa.crt");
- Private_Key* key = PKCS8::load_key("user-rsa.key", rng);
-
- certs_and_keys[cert] = key;
-
- std::vector<X509_Certificate> certs;
- certs.push_back(cert);
- return certs;
- }
-
- Private_Key* private_key_for(const X509_Certificate& cert,
- const std::string& type,
- const std::string& context)
- {
- return certs_and_keys[cert];
- }
-
- private:
- RandomNumberGenerator& rng;
- std::map<X509_Certificate, Private_Key*> certs_and_keys;
- };
-
int main(int argc, char* argv[])
{
if(argc != 2 && argc != 3)
@@ -250,7 +202,7 @@ int main(int argc, char* argv[])
{
LibraryInitializer botan_init;
AutoSeeded_RNG rng;
- Client_TLS_Policy policy;
+ TLS::Policy policy;
TLS::Session_Manager_In_Memory session_manager;
Credentials_Manager_Simple creds(rng);
diff --git a/doc/examples/tls_server.cpp b/doc/examples/tls_server.cpp
index 0f6287599..e896b5bcc 100644
--- a/doc/examples/tls_server.cpp
+++ b/doc/examples/tls_server.cpp
@@ -8,6 +8,7 @@
#include <botan/secqueue.h>
#include "socket.h"
+#include "credentials.h"
using namespace Botan;
@@ -18,40 +19,6 @@ using namespace std::tr1::placeholders;
#include <iostream>
#include <memory>
-class Credentials_Manager_Simple : public Credentials_Manager
- {
- public:
- Credentials_Manager_Simple(RandomNumberGenerator& rng) : rng(rng) {}
-
- std::vector<X509_Certificate> cert_chain(
- const std::string& cert_key_type,
- const std::string& type,
- const std::string& context)
- {
- const std::string hostname = (context == "" ? "localhost" : context);
-
- X509_Certificate cert(hostname + ".crt");
- Private_Key* key = PKCS8::load_key(hostname + ".key", rng);
-
- certs_and_keys[cert] = key;
-
- std::vector<X509_Certificate> certs;
- certs.push_back(cert);
- return certs;
- }
-
- Private_Key* private_key_for(const X509_Certificate& cert,
- const std::string& type,
- const std::string& context)
- {
- return certs_and_keys[cert];
- }
-
- private:
- RandomNumberGenerator& rng;
- std::map<X509_Certificate, Private_Key*> certs_and_keys;
- };
-
bool handshake_complete(const TLS::Session& session)
{
printf("Handshake complete, protocol=%04X ciphersuite=%s compression=%d\n",
@@ -158,24 +125,6 @@ class Blocking_TLS_Server
bool exit;
};
-class Server_TLS_Policy : public TLS::Policy
- {
- public:
- //bool require_client_auth() const { return true; }
-
- bool check_cert(const std::vector<X509_Certificate>& certs) const
- {
- for(size_t i = 0; i != certs.size(); ++i)
- {
- std::cout << certs[i].to_string();
- }
-
- std::cout << "Warning: not checking cert signatures\n";
-
- return true;
- }
- };
-
int main(int argc, char* argv[])
{
int port = 4433;
@@ -192,7 +141,7 @@ int main(int argc, char* argv[])
Server_Socket listener(port);
- Server_TLS_Policy policy;
+ TLS::Policy policy;
TLS::Session_Manager_In_Memory sessions;
diff --git a/src/credentials/credentials_manager.cpp b/src/credentials/credentials_manager.cpp
index e7886d307..82da8a75d 100644
--- a/src/credentials/credentials_manager.cpp
+++ b/src/credentials/credentials_manager.cpp
@@ -49,4 +49,34 @@ Private_Key* Credentials_Manager::private_key_for(const X509_Certificate&,
return 0;
}
+std::vector<X509_Certificate>
+Credentials_Manager::trusted_certificate_authorities(
+ const std::string&,
+ const std::string&)
+ {
+ return std::vector<X509_Certificate>();
+ }
+
+void Credentials_Manager::verify_certificate_chain(
+ const std::vector<X509_Certificate>& cert_chain,
+ const std::string& purported_hostname)
+ {
+ if(cert_chain.empty())
+ throw std::invalid_argument("Certificate chain was empty");
+
+#if 0
+ if(!cert_chain[0].matches_dns_name(purported_hostname))
+ return false;
+
+ X509_Store store;
+
+ std::vector<X509_Certificate> CAs = trusted_certificate_authorities();
+
+ for(size_t i = 1; i != CAs.size(); ++i)
+ store.add_cert(CAs[i], true);
+ for(size_t i = 1; i != cert_chain.size(); ++i)
+ store.add_cert(cert_chain[i]);
+#endif
+ }
+
}
diff --git a/src/credentials/credentials_manager.h b/src/credentials/credentials_manager.h
index 43bccec69..fdcfa74da 100644
--- a/src/credentials/credentials_manager.h
+++ b/src/credentials/credentials_manager.h
@@ -62,6 +62,10 @@ class BOTAN_DLL Credentials_Manager
bool generate_fake_on_unknown);
/**
+ * Return a cert chain we can use, ordered from leaf to root.
+ * Assumed that we can get the private key of the leaf with
+ * private_key_for
+ *
* @param cert_key_type is a string representing the key type
* ("rsa", "dsa", "ecdsa", etc) or empty if no preference.
*/
@@ -71,8 +75,29 @@ class BOTAN_DLL Credentials_Manager
const std::string& context);
/**
+ * Return a list of the certificates of CAs that we trust in this
+ * type/context.
+ */
+ virtual std::vector<X509_Certificate> trusted_certificate_authorities(
+ const std::string& type,
+ const std::string& context);
+
+ /**
+ * Check the certificate chain is valid up to a trusted root, and
+ * optionally (if hostname != "") that the hostname given is
+ * consistent with the leaf certificate.
+ *
+ * This function should throw an exception derived from
+ * std::exception with an informative what() result if the
+ * certificate chain cannot be verified.
+ */
+ virtual void verify_certificate_chain(
+ const std::vector<X509_Certificate>& cert_chain,
+ const std::string& hostname = "");
+
+ /**
* @return private key associated with this certificate if we should
- * use it with this context
+ * use it with this context. cert was returned by cert_chain
*/
virtual Private_Key* private_key_for(const X509_Certificate& cert,
const std::string& type,
diff --git a/src/tls/tls_client.cpp b/src/tls/tls_client.cpp
index 835e8d4bd..215ff6972 100644
--- a/src/tls/tls_client.cpp
+++ b/src/tls/tls_client.cpp
@@ -251,9 +251,15 @@ void Client::process_handshake_msg(Handshake_Type type,
throw TLS_Exception(HANDSHAKE_FAILURE,
"Client: No certificates sent by server");
- if(!policy.check_cert(peer_certs))
- throw TLS_Exception(BAD_CERTIFICATE,
- "Client: Server certificate is not valid");
+ try
+ {
+ creds.verify_certificate_chain(peer_certs,
+ state->client_hello->sni_hostname());
+ }
+ catch(std::exception& e)
+ {
+ throw TLS_Exception(BAD_CERTIFICATE, e.what());
+ }
std::auto_ptr<Public_Key> peer_key(peer_certs[0].subject_public_key());
diff --git a/src/tls/tls_policy.h b/src/tls/tls_policy.h
index 61de53dcd..68de2c4df 100644
--- a/src/tls/tls_policy.h
+++ b/src/tls/tls_policy.h
@@ -46,15 +46,6 @@ class BOTAN_DLL Policy
virtual std::vector<byte> compression() const;
- virtual bool check_cert(const std::vector<X509_Certificate>& cert_chain) const = 0;
-
- /**
- * If client authentication is desired, returns a list of allowable
- * CAs for same. If not desired, returns empty list.
- */
- virtual std::vector<X509_Certificate> client_auth_CAs() const
- { return std::vector<X509_Certificate>(); }
-
/**
* Require support for RFC 5746 extensions to enable
* renegotiation.
@@ -70,7 +61,7 @@ class BOTAN_DLL Policy
virtual DL_Group dh_group() const { return DL_Group("modp/ietf/1536"); }
/*
- * @return the minimum version that we will negotiate
+ * @return the minimum version that we are willing to negotiate
*/
virtual Protocol_Version min_version() const
{ return Protocol_Version::SSL_V3; }
diff --git a/src/tls/tls_server.cpp b/src/tls/tls_server.cpp
index cd7888c8b..b38a010dd 100644
--- a/src/tls/tls_server.cpp
+++ b/src/tls/tls_server.cpp
@@ -270,7 +270,8 @@ void Server::process_handshake_msg(Handshake_Type type,
else
state->kex_priv = PKCS8::copy_key(*private_key, rng);
- std::vector<X509_Certificate> client_auth_CAs = policy.client_auth_CAs();
+ std::vector<X509_Certificate> client_auth_CAs =
+ creds.trusted_certificate_authorities("tls-server", m_hostname);
if(!client_auth_CAs.empty() && state->suite.sig_algo() != "")
{
@@ -342,7 +343,14 @@ void Server::process_handshake_msg(Handshake_Type type,
if(!sig_valid)
throw TLS_Exception(DECRYPT_ERROR, "Client cert verify failed");
- // FIXME: check cert was issued by a CA we requested, signatures, etc.
+ try
+ {
+ creds.verify_certificate_chain(client_certs);
+ }
+ catch(std::exception& e)
+ {
+ throw TLS_Exception(BAD_CERTIFICATE, e.what());
+ }
state->set_expected_next(HANDSHAKE_CCS);
}