aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
authorlloyd <[email protected]>2015-01-23 22:29:13 +0000
committerlloyd <[email protected]>2015-01-23 22:29:13 +0000
commit72883a57553a1e6845eec71d1b53254ee041c6ec (patch)
treef66ea82daa6b15d6fb05194dcd622fdbcdb6f1ab /src/lib
parentb8814d2833741156a5ddc2c758da4e907581c823 (diff)
Add support for configuring a TLS::Policy by text file
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/tls/tls_policy.cpp48
-rw-r--r--src/lib/tls/tls_policy.h121
-rw-r--r--src/lib/utils/info.txt2
-rw-r--r--src/lib/utils/parsing.h11
-rw-r--r--src/lib/utils/read_cfg.cpp129
5 files changed, 202 insertions, 109 deletions
diff --git a/src/lib/tls/tls_policy.cpp b/src/lib/tls/tls_policy.cpp
index fc8f54e8e..e9f5bb209 100644
--- a/src/lib/tls/tls_policy.cpp
+++ b/src/lib/tls/tls_policy.cpp
@@ -119,9 +119,9 @@ std::string Policy::choose_curve(const std::vector<std::string>& curve_names) co
return ""; // no shared curve
}
-DL_Group Policy::dh_group() const
+std::string Policy::dh_group() const
{
- return DL_Group("modp/ietf/2048");
+ return "modp/ietf/2048";
}
size_t Policy::minimum_dh_group_size() const
@@ -311,6 +311,50 @@ std::vector<u16bit> Policy::ciphersuite_list(Protocol_Version version,
return ciphersuite_codes;
}
+namespace {
+
+void print_vec(std::ostream& o,
+ const char* key,
+ const std::vector<std::string>& v)
+ {
+ o << key << " = ";
+ for(size_t i = 0; i != v.size(); ++i)
+ {
+ o << v[i];
+ if(i != v.size() - 1)
+ o << ' ';
+ }
+ o << '\n';
+ }
+
+void print_bool(std::ostream& o,
+ const char* key, bool b)
+ {
+ o << key << " = " << (b ? "true" : "false") << '\n';
+ }
+
+}
+
+void Policy::print(std::ostream& o) const
+ {
+ print_vec(o, "ciphers", allowed_ciphers());
+ print_vec(o, "macs", allowed_macs());
+ print_vec(o, "signature_hashes", allowed_signature_hashes());
+ print_vec(o, "signature_methods", allowed_signature_methods());
+ print_vec(o, "key_exchange_methods", allowed_key_exchange_methods());
+ print_vec(o, "ecc_curves", allowed_ecc_curves());
+
+ print_bool(o, "negotiate_heartbeat_support", negotiate_heartbeat_support());
+ print_bool(o, "allow_insecure_renegotiation", allow_insecure_renegotiation());
+ print_bool(o, "include_time_in_hello_random", include_time_in_hello_random());
+ print_bool(o, "allow_server_initiated_renegotiation", allow_server_initiated_renegotiation());
+ print_bool(o, "hide_unknown_users", hide_unknown_users());
+ print_bool(o, "server_uses_own_ciphersuite_preferences", server_uses_own_ciphersuite_preferences());
+ o << "session_ticket_lifetime = " << session_ticket_lifetime() << '\n';
+ o << "dh_group = " << dh_group() << '\n';
+ o << "minimum_dh_group_size = " << minimum_dh_group_size() << '\n';
+ }
+
}
}
diff --git a/src/lib/tls/tls_policy.h b/src/lib/tls/tls_policy.h
index 089494f24..fdfbb6478 100644
--- a/src/lib/tls/tls_policy.h
+++ b/src/lib/tls/tls_policy.h
@@ -102,10 +102,7 @@ class BOTAN_DLL Policy
*/
virtual bool allow_server_initiated_renegotiation() const;
- /**
- * Return the group to use for ephemeral Diffie-Hellman key agreement
- */
- virtual DL_Group dh_group() const;
+ virtual std::string dh_group() const;
/**
* Return the minimum DH group size we're willing to use
@@ -176,6 +173,8 @@ class BOTAN_DLL Policy
virtual std::vector<u16bit> ciphersuite_list(Protocol_Version version,
bool have_srp) const;
+ virtual void print(std::ostream& o) const;
+
virtual ~Policy() {}
};
@@ -220,6 +219,120 @@ class BOTAN_DLL Datagram_Policy : public Policy
{ return version == Protocol_Version::DTLS_V12; }
};
+class BOTAN_DLL Text_Policy : public Policy
+ {
+ public:
+
+ std::vector<std::string> allowed_ciphers() const override
+ { return get_list("ciphers", Policy::allowed_ciphers()); }
+
+ std::vector<std::string> allowed_signature_hashes() const override
+ { return get_list("signature_hashes", Policy::allowed_signature_hashes()); }
+
+ std::vector<std::string> allowed_macs() const override
+ { return get_list("macs", Policy::allowed_macs()); }
+
+ std::vector<std::string> allowed_key_exchange_methods() const override
+ { return get_list("key_exchange_methods", Policy::allowed_key_exchange_methods()); }
+
+ std::vector<std::string> allowed_signature_methods() const override
+ { return get_list("signature_methods", Policy::allowed_signature_methods()); }
+
+ std::vector<std::string> allowed_ecc_curves() const override
+ { return get_list("ecc_curves", Policy::allowed_ecc_curves()); }
+
+ bool negotiate_heartbeat_support() const override
+ { return get_bool("negotiate_heartbeat_support", Policy::negotiate_heartbeat_support()); }
+
+ bool allow_insecure_renegotiation() const override
+ { return get_bool("allow_insecure_renegotiation", Policy::allow_insecure_renegotiation()); }
+
+ bool include_time_in_hello_random() const override
+ { return get_bool("include_time_in_hello_random", Policy::include_time_in_hello_random()); }
+
+ bool allow_server_initiated_renegotiation() const override
+ { return get_bool("allow_server_initiated_renegotiation", Policy::allow_server_initiated_renegotiation()); }
+
+ bool server_uses_own_ciphersuite_preferences() const override
+ { return get_bool("server_uses_own_ciphersuite_preferences", Policy::server_uses_own_ciphersuite_preferences()); }
+
+ std::string dh_group() const override
+ { return get_str("dh_group", Policy::dh_group()); }
+
+ size_t minimum_dh_group_size() const override
+ { return get_len("minimum_dh_group_size", Policy::minimum_dh_group_size()); }
+
+ bool hide_unknown_users() const override
+ { return get_bool("hide_unknown_users", Policy::hide_unknown_users()); }
+
+ u32bit session_ticket_lifetime() const override
+ { return get_len("session_ticket_lifetime", Policy::session_ticket_lifetime()); }
+
+ std::vector<u16bit> srtp_profiles() const override
+ {
+ std::vector<u16bit> r;
+ for(auto&& p : get_list("srtp_profiles", std::vector<std::string>()))
+ {
+ r.push_back(to_u32bit(p));
+ }
+ return r;
+ }
+
+ Text_Policy(std::istream& in)
+ {
+ m_kv = read_cfg(in);
+ }
+
+ private:
+
+ std::vector<std::string> get_list(const std::string& key,
+ const std::vector<std::string>& def) const
+ {
+ const std::string v = get_str(key);
+
+ if(v == "")
+ return def;
+
+ return split_on(v, ' ');
+ }
+
+ size_t get_len(const std::string& key, size_t def) const
+ {
+ const std::string v = get_str(key);
+
+ if(v == "")
+ return def;
+
+ return to_u32bit(v);
+ }
+
+ bool get_bool(const std::string& key, bool def) const
+ {
+ const std::string v = get_str(key);
+
+ if(v == "")
+ return def;
+
+ if(v == "true" || v == "True")
+ return true;
+ else if(v == "false" || v == "False")
+ return false;
+ else
+ throw std::runtime_error("Invalid boolean '" + v + "'");
+ }
+
+ std::string get_str(const std::string& key, const std::string& def = "") const
+ {
+ auto i = m_kv.find(key);
+ if(i == m_kv.end())
+ return def;
+
+ return i->second;
+ }
+
+ std::map<std::string, std::string> m_kv;
+ };
+
}
}
diff --git a/src/lib/utils/info.txt b/src/lib/utils/info.txt
index 84e1c8740..fafb73c72 100644
--- a/src/lib/utils/info.txt
+++ b/src/lib/utils/info.txt
@@ -1,4 +1,4 @@
-define UTIL_FUNCTIONS 20131128
+define UTIL_FUNCTIONS 20140123
load_on always
diff --git a/src/lib/utils/parsing.h b/src/lib/utils/parsing.h
index 8e7a3a22a..24d0576fd 100644
--- a/src/lib/utils/parsing.h
+++ b/src/lib/utils/parsing.h
@@ -124,16 +124,7 @@ BOTAN_DLL u32bit string_to_ipv4(const std::string& ip_str);
*/
BOTAN_DLL std::string ipv4_to_string(u32bit ip_addr);
-void BOTAN_DLL lex_cfg(std::istream& is,
- std::function<void (std::string)> cb);
-
-void BOTAN_DLL lex_cfg_w_headers(std::istream& is,
- std::function<void (std::string)> cb,
- std::function<void (std::string)> header_cb);
-
-std::map<std::string, std::map<std::string, std::string>>
-BOTAN_DLL
-parse_cfg(std::istream& is);
+std::map<std::string, std::string> BOTAN_DLL read_cfg(std::istream& is);
}
diff --git a/src/lib/utils/read_cfg.cpp b/src/lib/utils/read_cfg.cpp
index 8f186cefd..02708c3d6 100644
--- a/src/lib/utils/read_cfg.cpp
+++ b/src/lib/utils/read_cfg.cpp
@@ -1,121 +1,66 @@
/*
* Simple config/test file reader
-* (C) 2013,2014 Jack Lloyd
+* (C) 2013,2014,2015 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
#include <botan/parsing.h>
-#include <ctype.h>
namespace Botan {
-void lex_cfg(std::istream& is,
- std::function<void (std::string)> cb)
+namespace {
+
+std::string clean_ws(const std::string& s)
{
+ const char* ws = " \t\n";
+ auto start = s.find_first_not_of(ws);
+ auto end = s.find_last_not_of(ws);
+
+ if(start == std::string::npos)
+ return "";
+
+ if(end == std::string::npos)
+ return s.substr(start, end);
+ else
+ return s.substr(start, start + end + 1);
+ }
+
+}
+
+std::map<std::string, std::string> read_cfg(std::istream& is)
+ {
+ std::map<std::string, std::string> kv;
+ size_t line = 0;
+
while(is.good())
{
std::string s;
std::getline(is, s);
- while(is.good() && s.back() == '\\')
- {
- while(s.size() && (s.back() == '\\' || s.back() == '\n'))
- s.resize(s.size()-1);
-
- std::string x;
- std::getline(is, x);
-
- size_t i = 0;
+ ++line;
- while(i < x.size() && (::isspace(x[i])))
- ++i;
-
- s += x.substr(i);
- }
+ if(s == "" || s[0] == '#')
+ continue;
- auto comment = s.find('#');
- if(comment)
- s = s.substr(0, comment);
+ s = clean_ws(s.substr(0, s.find('#')));
- if(s.empty())
+ if(s == "")
continue;
- auto parts = split_on_pred(s, [](char c) { return ::isspace(c); });
-
- for(auto& p : parts)
- {
- if(p.empty())
- continue;
-
- auto eq = p.find("=");
-
- if(eq == std::string::npos || p.size() < 2)
- {
- cb(p);
- }
- else if(eq == 0)
- {
- cb("=");
- cb(p.substr(1, std::string::npos));
- }
- else if(eq == p.size() - 1)
- {
- cb(p.substr(0, p.size() - 1));
- cb("=");
- }
- else if(eq != std::string::npos)
- {
- cb(p.substr(0, eq));
- cb("=");
- cb(p.substr(eq + 1, std::string::npos));
- }
- }
- }
- }
+ auto eq = s.find("=");
-void lex_cfg_w_headers(std::istream& is,
- std::function<void (std::string)> cb,
- std::function<void (std::string)> hdr_cb)
- {
- auto intercept = [cb,hdr_cb](const std::string& s)
- {
- if(s[0] == '[' && s[s.length()-1] == ']')
- hdr_cb(s.substr(1, s.length()-2));
- else
- cb(s);
- };
+ if(eq == std::string::npos || eq == 0 || eq == s.size() - 1)
+ throw std::runtime_error("Bad read_cfg input '" + s + "' on line " + std::to_string(line));
- lex_cfg(is, intercept);
- }
+ const std::string key = clean_ws(s.substr(0, eq));
+ const std::string val = clean_ws(s.substr(eq + 1, std::string::npos));
-std::map<std::string, std::map<std::string, std::string>>
- parse_cfg(std::istream& is)
- {
- std::string header = "default";
- std::map<std::string, std::map<std::string, std::string>> vals;
- std::string key;
+ kv[key] = val;
+ }
- auto header_cb = [&header](const std::string i) { header = i; };
- auto cb = [&header,&key,&vals](const std::string s)
- {
- if(s == "=")
- {
- BOTAN_ASSERT(!key.empty(), "Valid assignment in config");
- }
- else if(key.empty())
- key = s;
- else
- {
- vals[header][key] = s;
- key = "";
- }
- };
-
- lex_cfg_w_headers(is, cb, header_cb);
-
- return vals;
+ return kv;
}
}