diff options
-rw-r--r-- | doc/examples/asio_tls_server.cpp | 56 | ||||
-rw-r--r-- | doc/examples/credentials.h | 53 | ||||
-rw-r--r-- | doc/examples/tls_client.cpp | 54 | ||||
-rw-r--r-- | doc/examples/tls_server.cpp | 55 | ||||
-rw-r--r-- | src/credentials/credentials_manager.cpp | 30 | ||||
-rw-r--r-- | src/credentials/credentials_manager.h | 27 | ||||
-rw-r--r-- | src/tls/tls_client.cpp | 12 | ||||
-rw-r--r-- | src/tls/tls_policy.h | 11 | ||||
-rw-r--r-- | src/tls/tls_server.cpp | 12 |
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); } |