• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 13262741994

11 Feb 2025 12:19PM UTC coverage: 91.656% (-0.003%) from 91.659%
13262741994

Pull #4647

github

web-flow
Merge 0b8e56724 into f372b5a9e
Pull Request #4647: Avoid using mem_ops.h or assert.h in public headers

94864 of 103500 relevant lines covered (91.66%)

11330304.66 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.71
/src/lib/tls/tls_text_policy.cpp
1
/*
2
* Text-Based TLS Policy
3
* (C) 2016,2017 Jack Lloyd
4
*     2017 Harry Reimann, Rohde & Schwarz Cybersecurity
5
*
6
* Botan is released under the Simplified BSD License (see license.txt)
7
*/
8

9
#include <botan/tls_policy.h>
10

11
#include <botan/assert.h>
12
#include <botan/exceptn.h>
13
#include <botan/internal/parsing.h>
14
#include <optional>
15
#include <sstream>
16

17
namespace Botan::TLS {
18

19
bool Text_Policy::allow_ssl_key_log_file() const {
530✔
20
   return get_bool("allow_ssl_key_log_file", Policy::allow_ssl_key_log_file());
530✔
21
}
22

23
std::vector<std::string> Text_Policy::allowed_ciphers() const {
28,001✔
24
   return get_list("ciphers", Policy::allowed_ciphers());
56,002✔
25
}
26

27
std::vector<std::string> Text_Policy::allowed_signature_hashes() const {
4,909✔
28
   return get_list("signature_hashes", Policy::allowed_signature_hashes());
9,818✔
29
}
30

31
std::vector<std::string> Text_Policy::allowed_macs() const {
3,619✔
32
   return get_list("macs", Policy::allowed_macs());
7,238✔
33
}
34

35
std::vector<std::string> Text_Policy::allowed_key_exchange_methods() const {
384✔
36
   return get_list("key_exchange_methods", Policy::allowed_key_exchange_methods());
768✔
37
}
38

39
std::vector<std::string> Text_Policy::allowed_signature_methods() const {
4,880✔
40
   return get_list("signature_methods", Policy::allowed_signature_methods());
9,760✔
41
}
42

43
bool Text_Policy::use_ecc_point_compression() const {
260✔
44
   return get_bool("use_ecc_point_compression", Policy::use_ecc_point_compression());
260✔
45
}
46

47
bool Text_Policy::allow_tls12() const {
1,019✔
48
   return get_bool("allow_tls12", Policy::allow_tls12());
1,019✔
49
}
50

51
bool Text_Policy::allow_tls13() const {
357✔
52
   return get_bool("allow_tls13", Policy::allow_tls13());
357✔
53
}
54

55
bool Text_Policy::allow_dtls12() const {
235✔
56
   return get_bool("allow_dtls12", Policy::allow_dtls12());
235✔
57
}
58

59
bool Text_Policy::allow_insecure_renegotiation() const {
226✔
60
   return get_bool("allow_insecure_renegotiation", Policy::allow_insecure_renegotiation());
226✔
61
}
62

63
bool Text_Policy::include_time_in_hello_random() const {
549✔
64
   return get_bool("include_time_in_hello_random", Policy::include_time_in_hello_random());
549✔
65
}
66

67
bool Text_Policy::require_client_certificate_authentication() const {
125✔
68
   return get_bool("require_client_certificate_authentication", Policy::require_client_certificate_authentication());
125✔
69
}
70

71
bool Text_Policy::allow_client_initiated_renegotiation() const {
×
72
   return get_bool("allow_client_initiated_renegotiation", Policy::allow_client_initiated_renegotiation());
×
73
}
74

75
std::vector<Certificate_Type> Text_Policy::accepted_client_certificate_types() const {
43✔
76
   const auto cert_types = get_str("accepted_client_certificate_types");
86✔
77
   return (cert_types.empty()) ? Policy::accepted_client_certificate_types() : read_cert_type_list(cert_types);
43✔
78
}
43✔
79

80
std::vector<Certificate_Type> Text_Policy::accepted_server_certificate_types() const {
43✔
81
   const auto cert_types = get_str("accepted_server_certificate_types");
86✔
82
   return (cert_types.empty()) ? Policy::accepted_server_certificate_types() : read_cert_type_list(cert_types);
43✔
83
}
43✔
84

85
bool Text_Policy::allow_server_initiated_renegotiation() const {
6✔
86
   return get_bool("allow_server_initiated_renegotiation", Policy::allow_server_initiated_renegotiation());
6✔
87
}
88

89
bool Text_Policy::server_uses_own_ciphersuite_preferences() const {
188✔
90
   return get_bool("server_uses_own_ciphersuite_preferences", Policy::server_uses_own_ciphersuite_preferences());
188✔
91
}
92

93
bool Text_Policy::negotiate_encrypt_then_mac() const {
168✔
94
   return get_bool("negotiate_encrypt_then_mac", Policy::negotiate_encrypt_then_mac());
168✔
95
}
96

97
std::optional<uint16_t> Text_Policy::record_size_limit() const {
73✔
98
   const auto limit = get_len("record_size_limit", 0);
73✔
99
   // RFC 8449 4.
100
   //    TLS 1.3 uses a limit of 2^14+1 octets.
101
   BOTAN_ARG_CHECK(limit <= 16385, "record size limit too large");
73✔
102
   return (limit > 0) ? std::make_optional(static_cast<uint16_t>(limit)) : std::nullopt;
73✔
103
}
104

105
bool Text_Policy::support_cert_status_message() const {
328✔
106
   return get_bool("support_cert_status_message", Policy::support_cert_status_message());
328✔
107
}
108

109
std::vector<Group_Params> Text_Policy::key_exchange_groups() const {
859✔
110
   std::string group_str = get_str("key_exchange_groups");
1,718✔
111

112
   if(group_str.empty()) {
859✔
113
      // fall back to previously used name
114
      group_str = get_str("groups");
757✔
115
   }
116

117
   if(group_str.empty()) {
859✔
118
      return Policy::key_exchange_groups();
695✔
119
   }
120

121
   return read_group_list(group_str);
164✔
122
}
859✔
123

124
std::vector<Group_Params> Text_Policy::key_exchange_groups_to_offer() const {
59✔
125
   std::string group_str = get_str("key_exchange_groups_to_offer", "notset");
118✔
126

127
   if(group_str.empty() || group_str == "notset") {
59✔
128
      // policy was not set, fall back to default behaviour
129
      return Policy::key_exchange_groups_to_offer();
39✔
130
   }
131

132
   if(group_str == "none") {
20✔
133
      return {};
2✔
134
   }
135

136
   return read_group_list(group_str);
18✔
137
}
59✔
138

139
size_t Text_Policy::minimum_ecdh_group_size() const {
231✔
140
   return get_len("minimum_ecdh_group_size", Policy::minimum_ecdh_group_size());
231✔
141
}
142

143
size_t Text_Policy::minimum_ecdsa_group_size() const {
77✔
144
   return get_len("minimum_ecdsa_group_size", Policy::minimum_ecdsa_group_size());
77✔
145
}
146

147
size_t Text_Policy::minimum_dh_group_size() const {
18✔
148
   return get_len("minimum_dh_group_size", Policy::minimum_dh_group_size());
18✔
149
}
150

151
size_t Text_Policy::minimum_rsa_bits() const {
47✔
152
   return get_len("minimum_rsa_bits", Policy::minimum_rsa_bits());
47✔
153
}
154

155
size_t Text_Policy::minimum_signature_strength() const {
13✔
156
   return get_len("minimum_signature_strength", Policy::minimum_signature_strength());
13✔
157
}
158

159
size_t Text_Policy::dtls_default_mtu() const {
124✔
160
   return get_len("dtls_default_mtu", Policy::dtls_default_mtu());
124✔
161
}
162

163
size_t Text_Policy::dtls_initial_timeout() const {
×
164
   return get_len("dtls_initial_timeout", Policy::dtls_initial_timeout());
×
165
}
166

167
size_t Text_Policy::dtls_maximum_timeout() const {
×
168
   return get_len("dtls_maximum_timeout", Policy::dtls_maximum_timeout());
×
169
}
170

171
bool Text_Policy::require_cert_revocation_info() const {
106✔
172
   return get_bool("require_cert_revocation_info", Policy::require_cert_revocation_info());
106✔
173
}
174

175
bool Text_Policy::hide_unknown_users() const {
6✔
176
   return get_bool("hide_unknown_users", Policy::hide_unknown_users());
6✔
177
}
178

179
size_t Text_Policy::maximum_session_tickets_per_client_hello() const {
332✔
180
   return get_len("maximum_session_tickets_per_client_hello", Policy::maximum_session_tickets_per_client_hello());
332✔
181
}
182

183
std::chrono::seconds Text_Policy::session_ticket_lifetime() const {
368✔
184
   return get_duration("session_ticket_lifetime", Policy::session_ticket_lifetime());
368✔
185
}
186

187
bool Text_Policy::reuse_session_tickets() const {
169✔
188
   return get_bool("reuse_session_tickets", Policy::reuse_session_tickets());
169✔
189
}
190

191
size_t Text_Policy::new_session_tickets_upon_handshake_success() const {
27✔
192
   return get_len("new_session_tickets_upon_handshake_success", Policy::new_session_tickets_upon_handshake_success());
27✔
193
}
194

195
std::vector<uint16_t> Text_Policy::srtp_profiles() const {
118✔
196
   std::vector<uint16_t> r;
118✔
197
   for(const auto& p : get_list("srtp_profiles", std::vector<std::string>())) {
118✔
198
      r.push_back(to_uint16(p));
×
199
   }
118✔
200
   return r;
118✔
201
}
×
202

203
bool Text_Policy::tls_13_middlebox_compatibility_mode() const {
110✔
204
   return get_bool("tls_13_middlebox_compatibility_mode", Policy::tls_13_middlebox_compatibility_mode());
110✔
205
}
206

207
bool Text_Policy::hash_hello_random() const {
549✔
208
   return get_bool("hash_hello_random", Policy::hash_hello_random());
549✔
209
}
210

211
void Text_Policy::set(const std::string& key, const std::string& value) {
162✔
212
   m_kv[key] = value;
162✔
213
}
162✔
214

215
Text_Policy::Text_Policy(std::string_view s) {
57✔
216
   std::istringstream iss{std::string(s)};  // FIXME C++23 avoid copy
114✔
217
   m_kv = read_cfg(iss);
57✔
218
}
57✔
219

220
Text_Policy::Text_Policy(std::istream& in) : m_kv(read_cfg(in)) {}
31✔
221

222
std::vector<std::string> Text_Policy::get_list(const std::string& key, const std::vector<std::string>& def) const {
41,911✔
223
   const std::string v = get_str(key);
41,911✔
224

225
   if(v.empty()) {
41,911✔
226
      return def;
19,913✔
227
   }
228

229
   return split_on(v, ' ');
21,998✔
230
}
41,911✔
231

232
std::vector<Group_Params> Text_Policy::read_group_list(std::string_view group_str) const {
182✔
233
   std::vector<Group_Params> groups;
182✔
234
   for(const auto& group_name : split_on(group_str, ' ')) {
785✔
235
      Group_Params group_id = Group_Params::from_string(group_name).value_or(Group_Params::NONE);
603✔
236

237
      if(!group_id.is_available()) {
603✔
238
         continue;
×
239
      }
240

241
      if(group_id == Group_Params::NONE) {
603✔
242
         try {
4✔
243
            size_t consumed = 0;
4✔
244
            unsigned long ll_id = std::stoul(group_name, &consumed, 0);
4✔
245
            if(consumed != group_name.size()) {
4✔
246
               continue;  // some other cruft
×
247
            }
248

249
            const uint16_t id = static_cast<uint16_t>(ll_id);
4✔
250

251
            if(id != ll_id) {
4✔
252
               continue;  // integer too large
×
253
            }
254

255
            group_id = static_cast<Group_Params>(id);
4✔
256
         } catch(...) {
×
257
            continue;
×
258
         }
×
259
      }
260

261
      if(group_id != Group_Params::NONE) {
603✔
262
         groups.push_back(group_id);
603✔
263
      }
264
   }
182✔
265

266
   return groups;
182✔
267
}
×
268

269
std::vector<Certificate_Type> Text_Policy::read_cert_type_list(const std::string& cert_type_names) const {
10✔
270
   std::vector<Certificate_Type> cert_types;
10✔
271
   for(const std::string& cert_type_name : split_on(cert_type_names, ' ')) {
20✔
272
      cert_types.push_back(certificate_type_from_string(cert_type_name));
10✔
273
   }
10✔
274

275
   return cert_types;
10✔
276
}
×
277

278
size_t Text_Policy::get_len(const std::string& key, size_t def) const {
1,310✔
279
   const std::string v = get_str(key);
1,310✔
280

281
   if(v.empty()) {
1,310✔
282
      return def;
283
   }
284

285
   return to_u32bit(v);
99✔
286
}
1,310✔
287

288
std::chrono::seconds Text_Policy::get_duration(const std::string& key, std::chrono::seconds def) const {
368✔
289
   using rep_t = std::chrono::seconds::rep;
368✔
290
   constexpr rep_t max_seconds = std::chrono::seconds::max().count();
368✔
291
   constexpr auto max_sizet = std::numeric_limits<size_t>::max();
368✔
292
   using ull = unsigned long long;
368✔
293

294
   // The concrete type of `rep` is not specified exactly. Let's play it extra safe...
295
   // e.g. on 32-bit platforms size_t is 32 bits but rep_t is "at least 35 bits"
296

297
   // at least zero and certainly fitting into rep_t
298
   const rep_t positive_default = std::max(def.count(), rep_t(0));
368✔
299
   // at least zero but capped to whatever size_t can handle
300
   const size_t positive_capped_default = static_cast<size_t>(std::min<ull>(positive_default, max_sizet));
368✔
301
   // at least zero but capped to whatever rep_t can handle
302
   const rep_t result = static_cast<rep_t>(std::min<ull>(get_len(key, positive_capped_default), max_seconds));
368✔
303

304
   return std::chrono::seconds(result);
368✔
305
}
306

307
bool Text_Policy::get_bool(const std::string& key, bool def) const {
4,931✔
308
   const std::string v = get_str(key);
4,931✔
309

310
   if(v.empty()) {
4,931✔
311
      return def;
312
   }
313

314
   if(v == "true" || v == "True") {
1,510✔
315
      return true;
316
   } else if(v == "false" || v == "False") {
338✔
317
      return false;
318
   } else {
319
      throw Decoding_Error("Invalid boolean '" + v + "'");
×
320
   }
321
}
4,931✔
322

323
std::string Text_Policy::get_str(const std::string& key, const std::string& def) const {
49,913✔
324
   auto i = m_kv.find(key);
49,913✔
325
   if(i == m_kv.end()) {
49,913✔
326
      return def;
26,112✔
327
   }
328

329
   return i->second;
23,801✔
330
}
331

332
bool Text_Policy::set_value(const std::string& key, std::string_view val, bool overwrite) {
×
333
   auto i = m_kv.find(key);
×
334

335
   if(overwrite == false && i != m_kv.end()) {
×
336
      return false;
337
   }
338

339
   m_kv.insert(i, std::make_pair(key, val));
×
340
   return true;
×
341
}
342

343
}  // namespace Botan::TLS
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc