libfilezilla
basic_tls_params.hpp
1 #ifndef LIBFILEZILLA_BASIC_TLS_PARAMS_HEADER
2 #define LIBFILEZILLA_BASIC_TLS_PARAMS_HEADER
3 
9 #include "format.hpp"
10 #include "hash.hpp"
11 #include "string.hpp"
12 #include "forward_like.hpp"
13 
14 #include <variant>
15 
16 namespace fz {
17 
18 template <typename T, typename Tag, typename Policy>
19 struct basic_tls_param;
20 
21 template <typename T, typename Tag>
22 struct is_same_kind_of_basic_tls_param : std::false_type{};
23 
24 template <typename T, typename Tag, typename Policy>
25 struct is_same_kind_of_basic_tls_param<basic_tls_param<T, Tag, Policy>, Tag> : std::true_type{};
26 
27 template <typename T, typename Tag, typename Policy>
28 struct basic_tls_param final
29 {
30  basic_tls_param(basic_tls_param const &) = default;
31  basic_tls_param& operator=(basic_tls_param &&) = default;
32  basic_tls_param& operator=(basic_tls_param const &) = default;
33 
34  template <typename U = T, std::enable_if_t<std::is_default_constructible_v<U>>* = nullptr>
35  basic_tls_param()
36  : value{}
37  {}
38 
39  template <typename U, std::enable_if_t<std::is_constructible_v<T, U>>* = nullptr>
40  explicit basic_tls_param(U && v)
41  : value(std::forward<U>(v))
42  {}
43 
44  template <typename U, typename V = std::remove_cv_t<std::remove_reference_t<U>>, std::enable_if_t<
45  !std::is_same_v<V, basic_tls_param> &&
46  is_same_kind_of_basic_tls_param<V, Tag>::value>* = nullptr>
47  basic_tls_param(U && other)
48  : value(forward_like<U>(other.value))
49  {}
50 
51  explicit operator bool() const
52  {
53  return Policy::is_valid(value);
54  }
55 
56  bool is_valid() const
57  {
58  return Policy::is_valid(value);
59  }
60 
61  template <typename U, typename P>
62  bool operator ==(basic_tls_param<U, Tag, P> const & rhs) const
63  {
64  return value == rhs.value;
65  }
66 
67  template <typename U, typename P>
68  bool operator !=(basic_tls_param<U, Tag, P> const & rhs) const
69  {
70  return value != rhs.value;
71  }
72 
73  template <typename U, typename P>
74  bool operator <(basic_tls_param<U, Tag, P> const & rhs) const
75  {
76  return value < rhs.value;
77  }
78 
79  template <typename U, typename P>
80  bool operator <=(basic_tls_param<U, Tag, P> const & rhs) const
81  {
82  return value <= rhs.value;
83  }
84 
85  template <typename U, typename P>
86  bool operator >(basic_tls_param<U, Tag, P> const & rhs) const
87  {
88  return value > rhs.value;
89  }
90 
91  template <typename U, typename P>
92  bool operator >=(basic_tls_param<U, Tag, P> const & rhs) const
93  {
94  return value >= rhs.value;
95  }
96 
97  T value;
98 };
99 
100 struct basic_tls_param_policy
101 {
102  template <typename T>
103  static bool is_valid(T const & v)
104  {
105  return !v.empty();
106  }
107 };
108 
109 struct tls_pkcs11url_policy
110 {
111  static bool is_valid(std::string_view v)
112  {
113  static constexpr std::string_view pkcs11_scheme = "pkcs11:";
114 
115  return fz::starts_with(v, pkcs11_scheme);
116  }
117 };
118 
119 template <typename T>
120 using basic_tls_blob = basic_tls_param<T, struct tls_blob_tag, basic_tls_param_policy>;
121 
122 template <typename T>
123 using basic_tls_filepath = basic_tls_param<T, struct tls_filepath_tag, basic_tls_param_policy>;
124 
125 template <typename T>
126 using basic_tls_pkcs11url = basic_tls_param<T, struct tls_pkcs11url_tag, tls_pkcs11url_policy>;
127 
128 template <typename B, typename F, typename P>
129 struct basic_tls_param_variant;
130 
131 template <typename T>
132 struct is_basic_tls_param_variant : std::false_type{};
133 
134 template <typename B, typename F, typename P>
135 struct is_basic_tls_param_variant<basic_tls_param_variant<B, F, P>> : std::true_type{};
136 
137 template <typename B, typename F, typename P>
138 struct basic_tls_param_variant final
139 {
140  using blob_type = basic_tls_blob<B>;
141  using filepath_type = basic_tls_filepath<F>;
142  using pkcs11url_type = basic_tls_pkcs11url<P>;
143 
144  using variant_type = std::variant<
145  blob_type,
146  filepath_type,
147  pkcs11url_type
148  >;
149 
150  blob_type const *blob() const
151  {
152  return std::get_if<blob_type>(&value);
153  }
154 
155  filepath_type const *filepath() const
156  {
157  return std::get_if<filepath_type>(&value);
158  }
159 
160  pkcs11url_type const *pkcs11url() const
161  {
162  return std::get_if<pkcs11url_type>(&value);
163  }
164 
165  blob_type *blob()
166  {
167  return std::get_if<blob_type>(&value);
168  }
169 
170  filepath_type *filepath()
171  {
172  return std::get_if<filepath_type>(&value);
173  }
174 
175  pkcs11url_type *pkcs11url()
176  {
177  return std::get_if<pkcs11url_type>(&value);
178  }
179 
180  native_string url() const
181  {
182  struct visitor
183  {
184  native_string operator()(filepath_type const &v)
185  {
186  return fz::sprintf(fzT("file:%s"), v ? v.value : fzT("<invalid>"));
187  }
188 
189  native_string operator()(pkcs11url_type const &v)
190  {
191  if (v) {
192  return to_native(v.value);
193  }
194 
195  return fzT("pkcs11:<invalid>");
196  }
197 
198  native_string operator()(blob_type const &v)
199  {
200  if (v) {
201  return fz::sprintf(fzT("blob:md5:%s"), hex_encode<native_string>(md5(v.value)));
202  }
203 
204  return fzT("blob:<invalid>");
205  }
206  };
207 
208  return std::visit(visitor(), value);
209  }
210 
211  basic_tls_param_variant() = default;
212  basic_tls_param_variant(basic_tls_param_variant &&) = default;
213  basic_tls_param_variant(basic_tls_param_variant const &) = default;
214  basic_tls_param_variant& operator=(basic_tls_param_variant &&) = default;
215  basic_tls_param_variant& operator=(basic_tls_param_variant const &) = default;
216 
217  template <typename T, std::enable_if_t<std::is_constructible_v<variant_type, T>>* = nullptr>
218  basic_tls_param_variant(T && v)
219  : value(std::forward<T>(v))
220  {}
221 
222  template <typename T, typename U = std::remove_cv_t<std::remove_reference_t<T>>, std::enable_if_t<
223  !std::is_same_v<U, basic_tls_param_variant>
224  && is_basic_tls_param_variant<U>::value>* = nullptr>
225  basic_tls_param_variant(T && other)
226  : value(std::visit([](auto && v) {
227  return variant_type(std::forward<decltype(v)>(v));
228  }, forward_like<T>(other.value)))
229  {
230  }
231 
232  template <typename T, std::enable_if_t<!std::is_same_v<T, basic_tls_param_variant> && is_basic_tls_param_variant<T>::value>* = nullptr>
233  basic_tls_param_variant& operator=(T && other)
234  {
235  *this = basic_tls_param_variant(std::forward<T>(other));
236  return *this;
237  }
238 
239  explicit operator bool() const
240  {
241  return std::visit([](auto && v) {
242  return bool(v);
243  }, value);
244  }
245 
246  bool is_valid() const
247  {
248  return bool(*this);
249  }
250 
251  template <typename F2, typename P2, typename B2>
252  bool operator ==(basic_tls_param_variant<F2, P2, B2> const & rhs) const
253  {
254  return value == rhs.value;
255  }
256 
257  template <typename F2, typename P2, typename B2>
258  bool operator !=(basic_tls_param_variant<F2, P2, B2> const & rhs) const
259  {
260  return value != rhs.value;
261  }
262 
263  template <typename F2, typename P2, typename B2>
264  bool operator <(basic_tls_param_variant<F2, P2, B2> const & rhs) const
265  {
266  return value < rhs.value;
267  }
268 
269  template <typename F2, typename P2, typename B2>
270  bool operator <=(basic_tls_param_variant<F2, P2, B2> const & rhs) const
271  {
272  return value <= rhs.value;
273  }
274 
275  template <typename F2, typename P2, typename B2>
276  bool operator >(basic_tls_param_variant<F2, P2, B2> const & rhs) const
277  {
278  return value > rhs.value;
279  }
280 
281  template <typename F2, typename P2, typename B2>
282  bool operator >=(basic_tls_param_variant<F2, P2, B2> const & rhs) const
283  {
284  return value >= rhs.value;
285  }
286 
287  variant_type value;
288 };
289 
290 }
291 
292 #endif
293 
std::vector< uint8_t > md5(std::string_view const &data)
Standard MD5.
bool starts_with(String const &s, String const &beginning)
Tests whether the first string starts with the second string.
Definition: string.hpp:663
A function that acts like std::forward, but applies the value category of its first template paramete...
bool operator==(symmetric_key const &lhs, symmetric_key const &rhs)
Side-channel safe comparison.
native_string to_native(std::string_view const &in)
Converts std::string to native_string.
Header for the sprintf string formatting function.
Definition: impersonation.hpp:85
std::string sprintf(std::string_view const &fmt, Args &&...args)
A simple type-safe sprintf replacement.
Definition: format.hpp:456
constexpr detail::apply_value_category_t< T, U > forward_like(U &&u) noexcept
applies the value category of T to u, so that u can be perfectly forwarded as-if it were of type T...
Definition: forward_like.hpp:31
std::wstring native_string
A string in the system's native character type and encoding. Note: This typedef changes depending on...
Definition: string.hpp:34
String types and assorted functions.
The namespace used by libfilezilla.
Definition: apply.hpp:17
Collection of cryptographic hash and MAC functions.
#define fzT(x)
Macro for a string literal in system-native character type. Note: Macro definition changes depending...
Definition: string.hpp:257