OpenVPN 3 Core Library
Loading...
Searching...
No Matches
test_userpass.cpp
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
13#include "test_common.hpp"
14
16
17using namespace openvpn;
18
19const std::string optname = "auth";
20const std::string user_simple(
21 "auth username\n");
22const std::string user_tag(
23 "<auth>\n"
24 "username\n"
25 "</auth>\n");
26const std::string user_file(
27 "auth " UNITTEST_SOURCE_DIR "/userpass/user.txt\n");
28const std::vector<std::string> user_only{
31};
32const std::string userpass_tag(
33 "<auth>\n"
34 "username\n"
35 "password\n"
36 "</auth>\n");
37const std::string userpass_file(
38 "auth " UNITTEST_SOURCE_DIR "/userpass/userpass.txt\n");
39const std::vector<std::string> user_pass{
42};
43const std::vector<std::string> onearg{
48const std::vector<std::string> overflow_files{
49 UNITTEST_SOURCE_DIR "/userpass/useroverflow.txt",
50 UNITTEST_SOURCE_DIR "/userpass/passoverflow.txt",
51};
52
59const std::vector<unsigned int> flag_combos_noargs_okay{
60 0,
62};
96
97TEST(UserPass, missing)
98{
100 {
101 std::string user;
102 std::string pass;
103 std::vector<std::string> userpass;
104 OptionList cfg;
105 cfg.parse_from_config("otheropt", nullptr);
106 cfg.update_map();
107 UserPass::parse(cfg, optname, flags, user, pass);
108 ASSERT_TRUE(user.empty()) << "flags: " << flags;
109 ASSERT_TRUE(pass.empty()) << "flags: " << flags;
110 user = "otheruser";
111 pass = "otherpass";
112 UserPass::parse(cfg, optname, flags, user, pass);
113 ASSERT_TRUE(user.empty()) << "flags: " << flags;
114 ASSERT_TRUE(pass.empty()) << "flags: " << flags;
115 bool ret = UserPass::parse(cfg, optname, flags, &userpass);
116 ASSERT_FALSE(ret) << "flags: " << flags;
117 ASSERT_EQ(userpass.size(), 0) << "flags: " << flags;
118 }
119 for (auto flags : flag_combos_required)
120 {
121 std::string user;
122 std::string pass;
123 std::vector<std::string> userpass;
124 OptionList cfg;
125 cfg.parse_from_config("otheropt", nullptr);
126 cfg.update_map();
127 ASSERT_THROW(
128 UserPass::parse(cfg, optname, flags, user, pass),
129 UserPass::creds_error)
130 << "flags: " << flags;
131 ASSERT_TRUE(user.empty()) << "flags: " << flags;
132 ASSERT_TRUE(pass.empty()) << "flags: " << flags;
133 user = "otheruser";
134 pass = "otherpass";
135 ASSERT_THROW(
136 UserPass::parse(cfg, optname, flags, user, pass),
137 UserPass::creds_error)
138 << "flags: " << flags;
139 ASSERT_TRUE(user.empty()) << "flags: " << flags;
140 ASSERT_TRUE(pass.empty()) << "flags: " << flags;
141 ASSERT_THROW(
142 UserPass::parse(cfg, optname, flags, &userpass),
143 UserPass::creds_error)
144 << "flags: " << flags;
145 ASSERT_EQ(userpass.size(), 0) << "flags: " << flags;
146 }
147}
148
149TEST(UserPass, noargs)
150{
151 for (auto flags : flag_combos_noargs_okay)
152 {
153 std::string user;
154 std::string pass;
155 std::vector<std::string> userpass;
156 OptionList cfg;
157 cfg.parse_from_config(optname, nullptr);
158 cfg.update_map();
159 UserPass::parse(cfg, optname, flags, user, pass);
160 ASSERT_TRUE(user.empty()) << "flags: " << flags;
161 ASSERT_TRUE(pass.empty()) << "flags: " << flags;
162 user = "otheruser";
163 pass = "otherpass";
164 UserPass::parse(cfg, optname, flags, user, pass);
165 ASSERT_TRUE(user.empty()) << "flags: " << flags;
166 ASSERT_TRUE(pass.empty()) << "flags: " << flags;
167 bool ret = UserPass::parse(cfg, optname, flags, &userpass);
168 ASSERT_TRUE(ret) << "flags: " << flags;
169 ASSERT_EQ(userpass.size(), 0) << "flags: " << flags;
170 }
171 for (auto flags : flag_combos_required)
172 {
173 std::string user;
174 std::string pass;
175 std::vector<std::string> userpass;
176 OptionList cfg;
177 cfg.parse_from_config(optname, nullptr);
178 cfg.update_map();
179 ASSERT_THROW(
180 UserPass::parse(cfg, optname, flags, user, pass),
181 UserPass::creds_error)
182 << "flags: " << flags;
183 ASSERT_TRUE(user.empty()) << "flags: " << flags;
184 ASSERT_TRUE(pass.empty()) << "flags: " << flags;
185 user = "otheruser";
186 pass = "otherpass";
187 ASSERT_THROW(
188 UserPass::parse(cfg, optname, flags, user, pass),
189 UserPass::creds_error)
190 << "flags: " << flags;
191 ASSERT_TRUE(user.empty()) << "flags: " << flags;
192 ASSERT_TRUE(pass.empty()) << "flags: " << flags;
193 ASSERT_THROW(
194 UserPass::parse(cfg, optname, flags, &userpass),
195 UserPass::creds_error)
196 << "flags: " << flags;
197 ASSERT_EQ(userpass.size(), 0) << "flags: " << flags;
198 }
199}
200
201TEST(UserPass, user_only)
202{
204 {
205 for (auto &config_text : user_only)
206 {
207 std::string user;
208 std::string pass;
209 std::vector<std::string> userpass;
210 OptionList cfg;
211 cfg.parse_from_config(config_text, nullptr);
212 cfg.update_map();
213 UserPass::parse(cfg, optname, flags, user, pass);
214 ASSERT_EQ(user, "username") << "config: " << config_text << "flags: " << flags;
215 ASSERT_TRUE(pass.empty()) << "config: " << config_text << "flags: " << flags;
216 user = "otheruser";
217 pass = "otherpass";
218 UserPass::parse(cfg, optname, flags, user, pass);
219 ASSERT_EQ(user, "username") << "config: " << config_text << "flags: " << flags;
220 ASSERT_TRUE(pass.empty()) << "config: " << config_text << "flags: " << flags;
221 bool ret = UserPass::parse(cfg, optname, flags, &userpass);
222 ASSERT_TRUE(ret) << "config: " << config_text << "flags: " << flags;
223 ASSERT_EQ(userpass.size(), 1) << "config: " << config_text << "flags: " << flags;
224 ASSERT_EQ(userpass[0], "username") << "config: " << config_text << "flags: " << flags;
225 }
226 /* filename instead of username */
227 {
228 std::string user;
229 std::string pass;
230 std::vector<std::string> userpass;
231 OptionList cfg;
232 cfg.parse_from_config(userpass_file, nullptr);
233 cfg.update_map();
234 UserPass::parse(cfg, optname, flags, user, pass);
235 ASSERT_EQ(user, UNITTEST_SOURCE_DIR "/userpass/userpass.txt") << "flags: " << flags;
236 ASSERT_TRUE(pass.empty()) << "flags: " << flags;
237 user = "otheruser";
238 pass = "otherpass";
239 UserPass::parse(cfg, optname, flags, user, pass);
240 ASSERT_EQ(user, UNITTEST_SOURCE_DIR "/userpass/userpass.txt") << "flags: " << flags;
241 ASSERT_TRUE(pass.empty()) << "flags: " << flags;
242 bool ret = UserPass::parse(cfg, optname, flags, &userpass);
243 ASSERT_TRUE(ret) << "flags: " << flags;
244 ASSERT_EQ(userpass.size(), 1) << "flags: " << flags;
245 ASSERT_EQ(userpass[0], UNITTEST_SOURCE_DIR "/userpass/userpass.txt") << "flags: " << flags;
246 }
247 }
248 for (auto flags : flag_combos_pw_required)
249 {
250 for (auto &config_text : onearg)
251 {
252 std::string user;
253 std::string pass;
254 std::vector<std::string> userpass;
255 OptionList cfg;
256 cfg.parse_from_config(config_text, nullptr);
257 cfg.update_map();
258 ASSERT_THROW(
259 UserPass::parse(cfg, optname, flags, user, pass),
260 UserPass::creds_error)
261 << "config: " << config_text << "flags: " << flags;
262 user = "otheruser";
263 pass = "otherpass";
264 ASSERT_THROW(
265 UserPass::parse(cfg, optname, flags, user, pass),
266 UserPass::creds_error)
267 << "config: " << config_text << "flags: " << flags;
268 bool ret = UserPass::parse(cfg, optname, flags, &userpass);
269 // FIXME?
270 ASSERT_TRUE(ret) << "config: " << config_text << "flags: " << flags;
271 }
272 }
273}
274
275TEST(UserPass, user_pass)
276{
277 for (auto flags : flag_combos_nofile)
278 {
279 for (auto &config_text : user_pass)
280 {
281 std::string user;
282 std::string pass;
283 std::vector<std::string> userpass;
284 auto flags_try_file = flags | UserPass::TRY_FILE;
285 OptionList cfg;
286 cfg.parse_from_config(config_text, nullptr);
287 cfg.update_map();
288 UserPass::parse(cfg, optname, flags_try_file, user, pass);
289 ASSERT_EQ(user, "username") << "config: " << config_text << "flags: " << flags;
290 ASSERT_EQ(pass, "password") << "config: " << config_text << "flags: " << flags;
291 user = "otheruser";
292 pass = "otherpass";
293 UserPass::parse(cfg, optname, flags_try_file, user, pass);
294 ASSERT_EQ(user, "username") << "config: " << config_text << "flags: " << flags;
295 ASSERT_EQ(pass, "password") << "config: " << config_text << "flags: " << flags;
296 bool ret = UserPass::parse(cfg, optname, flags_try_file, &userpass);
297 ASSERT_TRUE(ret) << "config: " << config_text << "flags: " << flags;
298 ASSERT_EQ(userpass.size(), 2) << "config: " << config_text << "flags: " << flags;
299 ASSERT_EQ(userpass[0], "username") << "config: " << config_text << "flags: " << flags;
300 ASSERT_EQ(userpass[1], "password") << "config: " << config_text << "flags: " << flags;
301 }
302 }
303}
304
305TEST(UserPass, parse_file_user_only)
306{
308 {
309 std::string user;
310 std::string pass;
311 UserPass::parse_file(UNITTEST_SOURCE_DIR "/userpass/user.txt", flags, user, pass);
312 ASSERT_EQ(user, "username") << "flags: " << flags;
313 ASSERT_TRUE(pass.empty()) << "flags: " << flags;
314 user = "otheruser";
315 pass = "otherpass";
316 UserPass::parse_file(UNITTEST_SOURCE_DIR "/userpass/user.txt", flags, user, pass);
317 ASSERT_EQ(user, "username") << "flags: " << flags;
318 ASSERT_TRUE(pass.empty()) << "flags: " << flags;
319 }
320 for (auto flags : flag_combos_pw_required)
321 {
322 for (auto &config_text : onearg)
323 {
324 std::string user;
325 std::string pass;
326 ASSERT_THROW(
327 UserPass::parse_file(UNITTEST_SOURCE_DIR "/userpass/user.txt", flags, user, pass),
328 UserPass::creds_error)
329 << "config: " << config_text << "flags: " << flags;
330 user = "otheruser";
331 pass = "otherpass";
332 ASSERT_THROW(
333 UserPass::parse_file(UNITTEST_SOURCE_DIR "/userpass/user.txt", flags, user, pass),
334 UserPass::creds_error)
335 << "config: " << config_text << "flags: " << flags;
336 }
337 }
338}
339
340TEST(UserPass, parse_file_user_pass)
341{
342 for (auto flags : flag_combos_nofile)
343 {
344 std::string user;
345 std::string pass;
346 UserPass::parse_file(UNITTEST_SOURCE_DIR "/userpass/userpass.txt", flags, user, pass);
347 ASSERT_EQ(user, "username") << "flags: " << flags;
348 ASSERT_EQ(pass, "password") << "flags: " << flags;
349 user = "otheruser";
350 pass = "otherpass";
351 UserPass::parse_file(UNITTEST_SOURCE_DIR "/userpass/userpass.txt", flags, user, pass);
352 ASSERT_EQ(user, "username") << "flags: " << flags;
353 ASSERT_EQ(pass, "password") << "flags: " << flags;
354 }
355}
356
357TEST(UserPass, parse_file_overflow)
358{
359 for (auto flags : flag_combos_nofile)
360 {
361 for (auto &filename : overflow_files)
362 {
363 std::string user;
364 std::string pass;
365 ASSERT_ANY_THROW(UserPass::parse_file(filename, flags, user, pass))
366 << "file: " << filename << "flags: " << flags;
367 user = "otheruser";
368 pass = "otherpass";
369 ASSERT_ANY_THROW(UserPass::parse_file(filename, flags, user, pass))
370 << "file: " << filename << "flags: " << flags;
371 auto flags_try_file = flags | UserPass::TRY_FILE;
372 std::string config_text = std::string("auth ") + filename;
373 std::vector<std::string> userpass;
374 OptionList cfg;
375 cfg.parse_from_config(config_text, nullptr);
376 cfg.update_map();
377 ASSERT_ANY_THROW(UserPass::parse(cfg, optname, flags_try_file, &userpass))
378 << "file: " << filename << "flags: " << flags;
379 }
380 }
381}
void parse_from_config(const std::string &str, Limits *lim)
Definition options.hpp:985
@ OPT_REQUIRED
option must be present
Definition userpass.hpp:31
@ PASSWORD_REQUIRED
password must be present
Definition userpass.hpp:34
@ USERNAME_REQUIRED
username must be present
Definition userpass.hpp:33
@ OPT_OPTIONAL
if option is not present, USERNAME_REQUIRED and PASSWORD_REQUIRED are ignored
Definition userpass.hpp:32
@ TRY_FILE
option argument might be a filename, try to load creds from it
Definition userpass.hpp:35
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
void parse_file(const std::string &path, const unsigned int flags, std::string &user, std::string &pass)
read username/password from file
Definition userpass.hpp:186
reroute_gw flags
std::string ret
const std::string user_file("auth " UNITTEST_SOURCE_DIR "/userpass/user.txt\n")
const std::vector< unsigned int > flag_combos_noargs_okay
const std::vector< unsigned int > flag_combos_nofile
const std::vector< unsigned int > flag_combos_pw_not_required
const std::string optname
const std::vector< std::string > user_pass
const std::string userpass_file("auth " UNITTEST_SOURCE_DIR "/userpass/userpass.txt\n")
const std::string userpass_tag("<auth>\n" "username\n" "password\n" "</auth>\n")
const std::vector< unsigned int > flag_combos_missing_okay
const std::vector< std::string > user_only
const std::vector< std::string > overflow_files
const std::vector< std::string > onearg
const std::string user_simple("auth username\n")
const std::vector< unsigned int > flag_combos_pw_required
TEST(UserPass, missing)
const std::vector< unsigned int > flag_combos_required
const std::string user_tag("<auth>\n" "username\n" "</auth>\n")