OpenVPN 3 Core Library
Loading...
Searching...
No Matches
httpcreds.hpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12#pragma once
13
14#include <string>
15#include <vector>
16#include <atomic>
17
29
30namespace openvpn::WS {
31struct Creds
32{
33 OPENVPN_EXCEPTION(web_creds_error);
34
35 static Creds load_from_header(const HTTP::HeaderList &headlist,
36 const bool password_required,
37 const bool throw_on_error)
38 {
39 Creds ret;
40 try
41 {
42 // Authorization: Basic Zm9vOmJhcg==
43 for (auto &h : headlist)
44 {
45 if (string::strcasecmp(h.name, "authorization") == 0
46 && h.value.length() >= 7
47 && string::strcasecmp(h.value.substr(0, 6), "basic ") == 0)
48 {
49 const std::string creds = base64->decode(h.value.substr(6));
50 const auto cv = string::split(creds, ':', 1);
51 if (cv.size() != 2)
52 throw Exception("error splitting credentials");
53 if (!Unicode::is_valid_utf8(cv[0]))
54 throw Exception("username not UTF-8");
55 if (!Unicode::is_valid_utf8(cv[1]))
56 throw Exception("password not UTF-8");
57 if (cv[0].empty())
58 throw Exception("username empty");
59 if (password_required && cv[1].empty())
60 throw Exception("password empty");
61 ret.username = cv[0];
62 ret.password = cv[1];
63 break;
64 }
65 }
66 }
67 catch (const std::exception &e)
68 {
69 if (throw_on_error)
70 throw web_creds_error(e.what());
71 }
72 return ret;
73 }
74
75 static Creds load_from_file(const std::string &fn,
76 const bool password_required,
77 const bool throw_on_error)
78 {
79 Creds ret;
80 try
81 {
82 const std::string content = read_text_utf8(fn);
83 SplitLines sl(content, 1024);
84 std::string u, p;
85 if (sl.next(u) != SplitLines::S_OKAY)
86 throw Exception(fn + " : username missing");
87 if (sl.next(p) != SplitLines::S_OKAY)
88 throw Exception(fn + " : password missing");
89 if (u.empty())
90 throw Exception(fn + " : username empty");
91 if (password_required && p.empty())
92 throw Exception(fn + " : password empty");
93 ret.username = std::move(u);
94 ret.password = std::move(p);
95 }
96 catch (const std::exception &e)
97 {
98 if (throw_on_error)
99 throw web_creds_error(e.what());
100 }
101 return ret;
102 }
103
105 const std::string &opt_name,
106 const unsigned int flags)
107 {
108 Creds ret;
109 UserPass::parse(opt, opt_name, flags, ret.username, ret.password);
110 return ret;
111 }
112
113 bool defined() const
114 {
115 return !username.empty();
116 }
117
118 bool defined_full() const
119 {
120 return !username.empty() && !password.empty();
121 }
122
123 void save_to_file(const std::string &fn) const
124 {
125 write_private(fn, username + '\n' + password + '\n');
126 }
127
128 bool operator==(const Creds &rhs) const
129 {
130 return !operator!=(rhs);
131 }
132
133 bool operator!=(const Creds &rhs) const
134 {
135 bool neq = crypto::str_neq(username, rhs.username);
136 atomic_thread_fence(std::memory_order_acq_rel);
137 neq |= crypto::str_neq(password, rhs.password);
138 atomic_thread_fence(std::memory_order_acq_rel);
139 return neq;
140 }
141
142 bool password_eq(const Creds &rhs) const
143 {
144 bool neq = crypto::str_neq(password, rhs.password);
145 atomic_thread_fence(std::memory_order_acq_rel);
146 return !neq;
147 }
148
149 std::string to_string() const
150 {
151 return username + '/' + password;
152 }
153
154 std::string username;
155 std::string password;
156};
157} // namespace openvpn::WS
size_t decode(void *data, size_t len, const std::string &str) const
Definition base64.hpp:186
Status next(std::string &ln, const bool trim=true)
@ S_OKAY
next line was successfully read
bool is_valid_utf8(const STRING &str, const size_t max_len_flags=0)
Definition unicode.hpp:75
bool parse(const OptionList &options, const std::string &opt_name, const unsigned int flags, std::vector< std::string > *user_pass)
interpret user-pass option
Definition userpass.hpp:74
bool str_neq(const char *s1, const char *s2)
Definition strneq.hpp:25
int strcasecmp(const char *s1, const char *s2)
Definition string.hpp:29
std::vector< T > split(const T &str, const typename T::value_type sep, const int maxsplit=-1)
Definition string.hpp:492
std::string read_text_utf8(const std::string &filename, const std::uint64_t max_size=0)
Definition file.hpp:136
void write_private(const std::string &path, const void *buf, ssize_t count)
const Base64 * base64
Definition base64.hpp:299
static Creds load_from_options(const OptionList &opt, const std::string &opt_name, const unsigned int flags)
static Creds load_from_header(const HTTP::HeaderList &headlist, const bool password_required, const bool throw_on_error)
Definition httpcreds.hpp:35
bool defined_full() const
bool operator!=(const Creds &rhs) const
std::string password
static Creds load_from_file(const std::string &fn, const bool password_required, const bool throw_on_error)
Definition httpcreds.hpp:75
std::string to_string() const
void save_to_file(const std::string &fn) const
bool defined() const
std::string username
OPENVPN_EXCEPTION(web_creds_error)
bool password_eq(const Creds &rhs) const
bool operator==(const Creds &rhs) const
reroute_gw flags
std::string ret