diff options
author | lloyd <[email protected]> | 2015-01-11 02:30:20 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2015-01-11 02:30:20 +0000 |
commit | e330e8d66faa0faa0c427acbb7ce42eefe06bd08 (patch) | |
tree | db0027da3cfc3c82e7655ab3ae649de9218102a8 /src/cmd/credentials.h | |
parent | 74522169a907715d4d41b3680f20b6f866733de7 (diff) |
Have TLS server take certificate and key from command line
Diffstat (limited to 'src/cmd/credentials.h')
-rw-r--r-- | src/cmd/credentials.h | 303 |
1 files changed, 80 insertions, 223 deletions
diff --git a/src/cmd/credentials.h b/src/cmd/credentials.h index c67fe22e3..b5ee701f3 100644 --- a/src/cmd/credentials.h +++ b/src/cmd/credentials.h @@ -27,277 +27,134 @@ inline bool value_exists(const std::vector<std::string>& vec, return false; } -class Credentials_Manager_Simple : public Botan::Credentials_Manager +class Basic_Credentials_Manager : public Credentials_Manager { public: - Credentials_Manager_Simple(Botan::RandomNumberGenerator& rng) : - rng(rng) + Basic_Credentials_Manager() { - try - { - m_certstores.push_back(new Botan::Certificate_Store_In_Memory("/usr/share/ca-certificates")); - } - catch(...) {} + } - std::string srp_identifier(const std::string& type, - const std::string& hostname) + Basic_Credentials_Manager(RandomNumberGenerator& rng, + const std::string& server_crt, + const std::string& server_key) { - if(type == "tls-client" && hostname == "srp-host") - return "user"; - return ""; + Certificate_Info cert; + + cert.key.reset(PKCS8::load_key(server_key, rng)); + + DataSource_Stream in(server_crt); + while(!in.end_of_data()) + { + try + { + cert.certs.push_back(X509_Certificate(in)); + } + catch(std::exception& e) + { + + } + } + + // TODO: attempt to validate chain ourselves + + m_creds.push_back(cert); } - bool attempt_srp(const std::string& type, - const std::string& hostname) + void load_certstores() { - if(hostname == "srp-host" && (type == "tls-client" || type == "tls-server")) - return true; - return false; + try + { + // TODO: make path configurable + const std::vector<std::string> paths = { "/usr/share/ca-certificates" }; + + for(auto&& path : paths) + { + std::shared_ptr<Certificate_Store> cs(new Certificate_Store_In_Memory(path)); + m_certstores.push_back(cs); + } + } + catch(std::exception& e) + { + //std::cout << e.what() << "\n"; + } } std::vector<Botan::Certificate_Store*> trusted_certificate_authorities(const std::string& type, const std::string& /*hostname*/) { - // don't ask for client cert + std::vector<Botan::Certificate_Store*> v; + + // don't ask for client certs if(type == "tls-server") - return std::vector<Botan::Certificate_Store*>(); + return v; - return m_certstores; + for(auto&& cs : m_certstores) + v.push_back(cs.get()); + + return v; } void verify_certificate_chain( const std::string& type, const std::string& purported_hostname, - const std::vector<Botan::X509_Certificate>& cert_chain) + const std::vector<X509_Certificate>& cert_chain) { try { - Botan::Credentials_Manager::verify_certificate_chain(type, - purported_hostname, - cert_chain); + Credentials_Manager::verify_certificate_chain(type, + purported_hostname, + cert_chain); } catch(std::exception& e) { - std::cout << "Certificate verification failed - " << e.what() << " - but will ignore\n"; + std::cout << e.what() << "\n"; + //throw; } } - std::string srp_password(const std::string& type, - const std::string& hostname, - const std::string& identifier) - { - if(type == "tls-client" && hostname == "srp-host" && identifier == "user") - return "password"; - - return ""; - } - - bool srp_verifier(const std::string& /*type*/, - const std::string& context, - const std::string& identifier, - std::string& group_id, - Botan::BigInt& verifier, - std::vector<Botan::byte>& salt, - bool generate_fake_on_unknown) + std::vector<X509_Certificate> cert_chain( + const std::vector<std::string>& algos, + const std::string& type, + const std::string& hostname) { - - std::string pass = srp_password("tls-client", context, identifier); - if(pass == "") + for(auto&& i : m_creds) { - if(!generate_fake_on_unknown) - return false; - - pass.resize(16); - rng.randomize(reinterpret_cast<byte*>(&pass[0]), pass.size()); - } - - group_id = "modp/srp/2048"; - - salt.resize(16); - rng.randomize(&salt[0], salt.size()); + if(std::find(algos.begin(), algos.end(), i.key->algo_name()) == algos.end()) + continue; - verifier = Botan::generate_srp6_verifier(identifier, - pass, - salt, - group_id, - "SHA-1"); + if(hostname != "" && !i.certs[0].matches_dns_name(hostname)) + continue; - return true; - } - - std::string psk_identity_hint(const std::string&, - const std::string&) - { - return ""; - } - - std::string psk_identity(const std::string&, const std::string&, - const std::string& identity_hint) - { - std::cout << "Server sent PSK identity_hint " << identity_hint << "\n"; - return "Client_identity"; - } - - Botan::SymmetricKey psk(const std::string& type, const std::string& context, - const std::string& identity) - { - if(type == "tls-server" && context == "session-ticket") - { - if(session_ticket_key.length() == 0) - session_ticket_key = Botan::SymmetricKey(rng, 32); - return session_ticket_key; + return i.certs; } - if(identity == "Client_identity") - return Botan::SymmetricKey("b5a72e1387552e6dc10766dc0eda12961f5b21e17f98ef4c41e6572e53bd7527"); - if(identity == "lloyd") - return Botan::SymmetricKey("85b3c1b7dc62b507636ac767999c9630"); - - throw Botan::Internal_Error("No PSK set for " + identity); + return std::vector<X509_Certificate>(); } - std::pair<Botan::X509_Certificate,Botan::Private_Key*> - load_or_make_cert(const std::string& hostname, - const std::string& key_type, - Botan::RandomNumberGenerator& rng) + Private_Key* private_key_for(const X509_Certificate& cert, + const std::string& /*type*/, + const std::string& /*context*/) { - using namespace Botan; - - const std::string key_fsname_prefix = hostname + "." + key_type + "."; - const std::string key_file_name = key_fsname_prefix + "key"; - const std::string cert_file_name = key_fsname_prefix + "crt"; - - try + for(auto&& i : m_creds) { - X509_Certificate cert(cert_file_name); - Private_Key* key = PKCS8::load_key(key_file_name, rng); - - //std::cout << "Loaded existing key/cert from " << cert_file_name << " and " << key_file_name << "\n"; - - return std::make_pair(cert, key); + if(cert == i.certs[0]) + return i.key.get(); } - catch(...) {} - - // Failed. Instead, make a new one - - std::cout << "Creating new certificate for identifier '" << hostname << "'\n"; - - X509_Cert_Options opts; - - opts.common_name = hostname; - opts.country = "US"; - opts.email = "root@" + hostname; - opts.dns = hostname; - - std::unique_ptr<Private_Key> key; - if(key_type == "rsa") - key.reset(new RSA_PrivateKey(rng, 1024)); - else if(key_type == "dsa") - key.reset(new DSA_PrivateKey(rng, DL_Group("dsa/jce/1024"))); - else if(key_type == "ecdsa") - key.reset(new ECDSA_PrivateKey(rng, EC_Group("secp256r1"))); - else - throw std::runtime_error("Don't know what to do about key type '" + key_type + "'"); - - X509_Certificate cert = - X509::create_self_signed_cert(opts, *key, "SHA-1", rng); - - // Now save both - std::cout << "Saving new " << key_type << " key to " << key_file_name << "\n"; - std::ofstream key_file(key_file_name.c_str()); - key_file << PKCS8::PEM_encode(*key, rng, ""); - key_file.close(); - - std::cout << "Saving new " << key_type << " cert to " << key_file_name << "\n"; - std::ofstream cert_file(cert_file_name.c_str()); - cert_file << cert.PEM_encode() << "\n"; - cert_file.close(); - - return std::make_pair(cert, key.release()); + return nullptr; } - std::vector<Botan::X509_Certificate> cert_chain( - const std::vector<std::string>& cert_key_types, - const std::string& type, - const std::string& context) + private: + struct Certificate_Info { - using namespace Botan; - std::vector<X509_Certificate> certs; + std::shared_ptr<Private_Key> key; + }; - try - { - if(type == "tls-server") - { - const std::string hostname = (context == "" ? "localhost" : context); - - if(hostname == "nosuchname") - return std::vector<Botan::X509_Certificate>(); - - for(auto i : certs_and_keys) - { - if(hostname != "" && !i.first.matches_dns_name(hostname)) - continue; - - if(!value_exists(cert_key_types, i.second->algo_name())) - continue; - - certs.push_back(i.first); - } - - if(!certs.empty()) - return certs; - - std::string key_name = ""; - - if(value_exists(cert_key_types, "RSA")) - key_name = "rsa"; - else if(value_exists(cert_key_types, "DSA")) - key_name = "dsa"; - else if(value_exists(cert_key_types, "ECDSA")) - key_name = "ecdsa"; - - std::pair<X509_Certificate, Private_Key*> cert_and_key = - load_or_make_cert(hostname, key_name, rng); - - certs_and_keys[cert_and_key.first] = cert_and_key.second; - certs.push_back(cert_and_key.first); - } - else if(type == "tls-client") - { - X509_Certificate cert("user-rsa.crt"); - Private_Key* key = PKCS8::load_key("user-rsa.key", rng); - - certs_and_keys[cert] = key; - certs.push_back(cert); - } - } - catch(std::exception& e) - { - std::cout << e.what() << "\n"; - } - - 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; - - Botan::SymmetricKey session_ticket_key; - - std::map<Botan::X509_Certificate, Botan::Private_Key*> certs_and_keys; - - std::vector<Botan::Certificate_Store*> m_certstores; + std::vector<Certificate_Info> m_creds; + std::vector<std::shared_ptr<Certificate_Store>> m_certstores; }; #endif |