OpenVPN
misc.c
Go to the documentation of this file.
1/*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single TCP/UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
6 * packet compression.
7 *
8 * Copyright (C) 2002-2026 OpenVPN Inc <sales@openvpn.net>
9 * Copyright (C) 2014-2015 David Sommerseth <davids@redhat.com>
10 * Copyright (C) 2016-2026 David Sommerseth <davids@openvpn.net>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2
14 * as published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, see <https://www.gnu.org/licenses/>.
23 */
24
25#ifdef HAVE_CONFIG_H
26#include "config.h"
27#endif
28
29#include "syshead.h"
30
31#include "buffer.h"
32#include "misc.h"
33#include "base64.h"
34#include "tun.h"
35#include "error.h"
36#include "otime.h"
37#include "plugin.h"
38#include "options.h"
39#include "manage.h"
40#include "crypto.h"
41#include "route.h"
42#include "console.h"
43#include "win32.h"
44
45#include "memdbg.h"
46
47#ifdef ENABLE_IPROUTE
48const char *iproute_path = IPROUTE_PATH; /* GLOBAL */
49#endif
50
51/*
52 * Set standard file descriptors to /dev/null
53 */
54void
55set_std_files_to_null(bool stdin_only)
56{
57#if defined(HAVE_DUP) && defined(HAVE_DUP2)
58 int fd;
59 if ((fd = open("/dev/null", O_RDWR, 0)) != -1)
60 {
61 dup2(fd, 0);
62 if (!stdin_only)
63 {
64 dup2(fd, 1);
65 dup2(fd, 2);
66 }
67 if (fd > 2)
68 {
69 close(fd);
70 }
71 }
72#endif
73}
74
75#ifdef ENABLE_MANAGEMENT
76/* Get username/password from the management interface */
77static bool
78auth_user_pass_mgmt(struct user_pass *up, const char *prefix, const unsigned int flags,
79 const char *auth_challenge)
80{
81 const char *sc = NULL;
82
84 {
85 management_auth_failure(management, prefix, "previous auth credentials failed");
86 }
87
89 {
90 sc = auth_challenge;
91 }
92 if (!management_query_user_pass(management, up, prefix, flags, sc))
93 {
94 if ((flags & GET_USER_PASS_NOFATAL) != 0)
95 {
96 return false;
97 }
98 else
99 {
100 msg(M_FATAL,
101 "ERROR: could not read %s username/password/ok/string from management interface",
102 prefix);
103 }
104 }
105 return true;
106}
107
121static struct auth_challenge_info *
123{
125 const size_t len = strlen(auth_challenge);
126 if (!buf_size_valid(len))
127 {
128 return NULL;
129 }
130
131 const int work_len = (int)len + 1;
132 char *work = (char *)gc_malloc(work_len, false, gc);
133
134 struct buffer b;
136
137 struct auth_challenge_info *ac;
139
140 /* parse prefix */
141 if (!buf_parse(&b, ':', work, work_len))
142 {
143 return NULL;
144 }
145 if (strcmp(work, "CRV1"))
146 {
147 return NULL;
148 }
149
150 /* parse flags */
151 if (!buf_parse(&b, ':', work, work_len))
152 {
153 return NULL;
154 }
155 for (const char *cp = work; *cp != '\0'; ++cp)
156 {
157 const char c = *cp;
158 if (c == 'E')
159 {
160 ac->flags |= CR_ECHO;
161 }
162 else if (c == 'R')
163 {
164 ac->flags |= CR_RESPONSE;
165 }
166 }
167
168 /* parse state ID */
169 if (!buf_parse(&b, ':', work, work_len))
170 {
171 return NULL;
172 }
173 ac->state_id = string_alloc(work, gc);
174
175 /* parse user name */
176 if (!buf_parse(&b, ':', work, work_len))
177 {
178 return NULL;
179 }
180 ac->user = (char *)gc_malloc(strlen(work) + 1, true, gc);
181 openvpn_base64_decode(work, (void *)ac->user, -1);
182
183 /* parse challenge text */
185
186 return ac;
187}
188
189#endif /* ifdef ENABLE_MANAGEMENT */
190
191/*
192 * Get and store a username/password
193 */
194
195bool
196get_user_pass_cr(struct user_pass *up, const char *auth_file, const char *prefix,
197 const unsigned int flags, const char *auth_challenge)
198{
199 struct gc_arena gc = gc_new();
200
201 if (!up->defined)
202 {
203 bool from_authfile = (auth_file && !streq(auth_file, "stdin"));
204 bool username_from_stdin = false;
205 bool password_from_stdin = false;
206 bool response_from_stdin = true;
207
210 {
211 msg(M_WARN, "Note: previous '%s' credentials failed", prefix);
212 }
213#ifdef ENABLE_MANAGEMENT
214 /*
215 * Get username/password from management interface?
216 */
217 if (management && (!from_authfile && (flags & GET_USER_PASS_MANAGEMENT))
219 {
220 response_from_stdin = false;
221 if (!auth_user_pass_mgmt(up, prefix, flags, auth_challenge))
222 {
223 return false;
224 }
225 }
226 else
227#endif /* ifdef ENABLE_MANAGEMENT */
228 /*
229 * Get NEED_OK confirmation from the console
230 */
231 if (flags & GET_USER_PASS_NEED_OK)
232 {
233 struct buffer user_prompt = alloc_buf_gc(128, &gc);
234
235 buf_printf(&user_prompt, "NEED-OK|%s|%s:", prefix, up->username);
237 {
238 msg(M_FATAL, "ERROR: could not read %s ok-confirmation from stdin", prefix);
239 }
240
241 if (!strlen(up->password))
242 {
243 strcpy(up->password, "ok");
244 }
245 }
246 else if (flags & GET_USER_PASS_INLINE_CREDS)
247 {
248 struct buffer buf;
249 buf_set_read(&buf, (uint8_t *)auth_file, strlen(auth_file) + 1);
250 if (!(flags & GET_USER_PASS_PASSWORD_ONLY))
251 {
252 buf_parse(&buf, '\n', up->username, USER_PASS_LEN);
253 /* The password starts on the next line, even if the username was truncated. */
254 const char *password = strchr(auth_file, '\n');
255 password = password ? password + 1 : "";
256 buf_set_read(&buf, (uint8_t *)password, strlen(password) + 1);
257 }
258 buf_parse(&buf, '\n', up->password, USER_PASS_LEN);
259
260 if (strlen(up->password) == 0)
261 {
263 }
264 }
265 /*
266 * Read from auth file unless this is a dynamic challenge request.
267 */
268 else if (from_authfile && !(flags & GET_USER_PASS_DYNAMIC_CHALLENGE))
269 {
270 /*
271 * Try to get username/password from a file.
272 */
273 FILE *fp;
274 char password_buf[USER_PASS_LEN] = { '\0' };
275
276 fp = platform_fopen(auth_file, "r");
277 if (!fp)
278 {
279 msg(M_ERR, "Error opening '%s' auth file: %s", prefix, auth_file);
280 }
281
282 if ((flags & GET_USER_PASS_PASSWORD_ONLY) == 0)
283 {
284 /* Read username first */
285 if (fgets(up->username, USER_PASS_LEN, fp) == NULL)
286 {
287 msg(M_FATAL, "Error reading username from %s authfile: %s", prefix,
288 auth_file);
289 }
290 if (!strchr(up->username, '\n'))
291 {
292 /* Consume the rest of the username line before reading the password. */
293 int c;
294 while ((c = fgetc(fp)) != '\n' && c != EOF)
295 {
296 }
297 }
298 }
299 chomp(up->username);
300
302 {
304 }
305
306 if (flags & GET_USER_PASS_PASSWORD_ONLY && !password_buf[0])
307 {
308 msg(M_FATAL, "Error reading password from %s authfile: %s", prefix, auth_file);
309 }
310
311 if (password_buf[0])
312 {
314 }
315 else
316 {
318 }
319
320 fclose(fp);
321
322 if (!(flags & GET_USER_PASS_PASSWORD_ONLY) && strlen(up->username) == 0)
323 {
324 msg(M_FATAL, "ERROR: username from %s authfile '%s' is empty", prefix,
325 auth_file);
326 }
327 }
328 else
329 {
330 username_from_stdin = true;
331 password_from_stdin = true;
332 }
333
334 /*
335 * Get username/password from standard input?
336 */
338 {
339#ifdef ENABLE_MANAGEMENT
340 /* If management-query-passwords is true, we could be here because
341 * of no password present in auth-file or inline. In that case
342 * query via the management interface instead of stdin/console.
343 */
344 if (management && (flags & GET_USER_PASS_MANAGEMENT)
347 && !(flags & GET_USER_PASS_USERNAME_ONLY))
348 {
349 msg(D_LOW,
350 "No '%s' password found in authfile or inline. Querying the management interface",
351 prefix);
352 if (!auth_user_pass_mgmt(up, prefix, flags, auth_challenge))
353 {
354 return false;
355 }
356 }
358 {
360 if (ac)
361 {
362 char *response = (char *)gc_malloc(USER_PASS_LEN, false, &gc);
364
365 challenge = alloc_buf_gc(14 + strlen(ac->challenge_text), &gc);
366 buf_printf(&challenge, "CHALLENGE: %s", ac->challenge_text);
368
369 if (!query_user_SINGLE(BSTR(&challenge), response,
370 USER_PASS_LEN, BOOL_CAST(ac->flags & CR_ECHO)))
371 {
372 msg(M_FATAL, "ERROR: could not read challenge response from stdin");
373 }
374 strlcpy(up->username, ac->user, USER_PASS_LEN);
375 buf_printf(&packed_resp, "CRV1::%s::%s", ac->state_id, response);
376 }
377 else
378 {
379 msg(M_FATAL, "ERROR: received malformed challenge request from server");
380 }
381 }
382 else
383#endif /* ifdef ENABLE_MANAGEMENT */
384 {
385 struct buffer user_prompt = alloc_buf_gc(128, &gc);
386 struct buffer pass_prompt = alloc_buf_gc(128, &gc);
387
389 buf_printf(&user_prompt, "Enter %s Username:", prefix);
390 buf_printf(&pass_prompt, "Enter %s Password:", prefix);
391
393 {
395 }
396
398 {
400 }
401
402 if (!query_user_exec())
403 {
404 msg(M_FATAL, "ERROR: Failed retrieving username or password");
405 }
406
407 if (!(flags & GET_USER_PASS_PASSWORD_ONLY))
408 {
409 if (strlen(up->username) == 0)
410 {
411 msg(M_FATAL, "ERROR: %s username is empty", prefix);
412 }
413 }
414
415#ifdef ENABLE_MANAGEMENT
418 {
419 char *response = (char *)gc_malloc(USER_PASS_LEN, false, &gc);
421 char *pw64 = NULL, *resp64 = NULL;
422
424 buf_printf(&challenge, "CHALLENGE: %s", auth_challenge);
425
428 {
429 msg(M_FATAL, "ERROR: could not retrieve static challenge response");
430 }
432 {
433 if (openvpn_base64_encode(up->password, (int)strlen(up->password), &pw64) == -1
434 || openvpn_base64_encode(response, (int)strlen(response), &resp64) == -1)
435 {
436 msg(M_FATAL, "ERROR: could not base64-encode password/static_response");
437 }
439 buf_printf(&packed_resp, "SCRV1:%s:%s", pw64, resp64);
441 free(pw64);
443 free(resp64);
444 }
445 else
446 {
447 if (strlcat(up->password, response, USER_PASS_LEN) >= USER_PASS_LEN)
448 {
449 msg(M_FATAL,
450 "ERROR: could not concatenate password/static_response: string too long");
451 }
452 }
453 }
454#endif /* ifdef ENABLE_MANAGEMENT */
455 }
456 }
457
458 /* Use tag for blank password if we are not prompting for one */
459 if (flags & GET_USER_PASS_USERNAME_ONLY)
460 {
461 strlcpy(up->password, blank_up, sizeof(up->password));
462 }
463
466
467 up->defined = true;
468 }
469
470#if 0
471 msg(M_INFO, "GET_USER_PASS %s u='%s' p='%s'", prefix, up->username, up->password);
472#endif
473
474 gc_free(&gc);
475
476 return true;
477}
478
479void
480purge_user_pass(struct user_pass *up, const bool force)
481{
482 const bool nocache = up->nocache;
483
484 if (nocache || force)
485 {
486 secure_memzero(up, sizeof(*up));
487 up->nocache = nocache;
488 }
489 else
490 {
491 static bool warn_shown = false;
492
494 /*
495 * don't show warning if the pass has been replaced by a token: this is an
496 * artificial "auth-nocache"
497 */
498 if (!warn_shown)
499 {
500 msg(M_WARN,
501 "WARNING: this configuration may cache passwords in memory -- use the auth-nocache option to prevent this");
502 warn_shown = true;
503 }
504 }
505}
506
507void
508set_auth_token(struct user_pass *tk, const char *token)
509{
510 if (strlen(token))
511 {
513 strlcpy(tk->password, token, USER_PASS_LEN);
514 tk->token_defined = true;
515
516 /*
517 * If username already set, tk is fully defined.
518 */
519 if (strlen(tk->username))
520 {
521 tk->defined = true;
522 }
524 }
525}
526
527void
528set_auth_token_user(struct user_pass *tk, const char *username)
529{
530 if (strlen(username))
531 {
533 /* Clear the username before decoding to ensure no old material is left
534 * and also allow decoding to not use all space to ensure the last byte is
535 * always 0 */
536 CLEAR(tk->username);
537 int len = openvpn_base64_decode(username, tk->username, USER_PASS_LEN - 1);
538 tk->defined = len > 0;
539 if (!tk->defined)
540 {
541 msg(D_PUSH, "Error decoding auth-token-username");
542 }
544 }
545}
546
547
548/*
549 * Process string received by untrusted peer before
550 * printing to console or log file.
551 *
552 * Assumes that string has been null terminated.
553 */
554const char *
555safe_print(const char *str, struct gc_arena *gc)
556{
557 return string_mod_const(str, CC_PRINT, CC_CRLF, '.', gc);
558}
559
560const char **
561make_arg_array(const char *first, const char *parms, struct gc_arena *gc)
562{
563 char **ret = NULL;
564 int base = 0;
565 const int max_parms = MAX_PARMS + 2;
566 int n = 0;
567
568 /* alloc return array */
570
571 /* process first parameter, if provided */
572 if (first)
573 {
574 ret[base++] = string_alloc(first, gc);
575 }
576
577 if (parms)
578 {
579 n = parse_line(parms, &ret[base], max_parms - base - 1, "make_arg_array", 0, M_WARN, gc);
580 ASSERT(n >= 0 && n + base + 1 <= max_parms);
581 }
582 ret[base + n] = NULL;
583
584 return (const char **)ret;
585}
586
587static const char **
588make_inline_array(const char *str, struct gc_arena *gc)
589{
591 struct buffer buf;
592 int len = 0;
593 char **ret = NULL;
594 int i = 0;
595
596 buf_set_read(&buf, (const uint8_t *)str, strlen(str));
597 while (buf_parse(&buf, '\n', line, sizeof(line)))
598 {
599 ++len;
600 }
601
602 /* alloc return array */
603 ALLOC_ARRAY_CLEAR_GC(ret, char *, len + 1, gc);
604
605 buf_set_read(&buf, (const uint8_t *)str, strlen(str));
606 while (buf_parse(&buf, '\n', line, sizeof(line)))
607 {
608 chomp(line);
609 ASSERT(i < len);
611 ++i;
612 }
613 ASSERT(i <= len);
614 ret[i] = NULL;
615 return (const char **)ret;
616}
617
618static const char **
619make_arg_copy(char **p, struct gc_arena *gc)
620{
621 char **ret = NULL;
622 const int len = string_array_len((const char **)p);
623 const int max_parms = len + 1;
624 int i;
625
626 /* alloc return array */
628
629 for (i = 0; i < len; ++i)
630 {
631 ret[i] = p[i];
632 }
633
634 return (const char **)ret;
635}
636
637const char **
639{
640 const int argc = string_array_len((const char **)p);
641 if (is_inline)
642 {
643 return make_inline_array(p[0], gc);
644 }
645 else if (argc == 0)
646 {
647 return make_arg_array(NULL, NULL, gc);
648 }
649 else if (argc == 1)
650 {
651 return make_arg_array(p[0], NULL, gc);
652 }
653 else if (argc == 2)
654 {
655 return make_arg_array(p[0], p[1], gc);
656 }
657 else
658 {
659 return make_arg_copy(p, gc);
660 }
661}
662
663/*
664 * Remove security-sensitive strings from control message
665 * so that they will not be output to log file.
666 */
667const char *
669{
670 char *ret = gc_malloc(strlen(src) + 1, false, gc);
671 char *dest = ret;
672 bool redact = false;
673 int skip = 0;
674
675 for (;;)
676 {
677 const char c = *src;
678 if (c == '\0')
679 {
680 break;
681 }
682 if (c == 'S' && !strncmp(src, "SESS_ID_", 8))
683 {
684 skip = 7;
685 redact = true;
686 }
687 else if (c == 'e' && !strncmp(src, "echo ", 5))
688 {
689 skip = 4;
690 redact = true;
691 }
692 else if (!check_debug_level(D_SHOW_KEYS) && (c == 'a' && !strncmp(src, "auth-token ", 11)))
693 {
694 /* Unless --verb is 7 or higher (D_SHOW_KEYS), hide
695 * the auth-token value coming in the src string
696 */
697 skip = 10;
698 redact = true;
699 }
700
701 if (c == ',') /* end of redacted item? */
702 {
703 skip = 0;
704 redact = false;
705 }
706
707 if (redact)
708 {
709 if (skip > 0)
710 {
711 --skip;
712 *dest++ = c;
713 }
714 }
715 else
716 {
717 *dest++ = c;
718 }
719
720 ++src;
721 }
722 *dest = '\0';
723 return ret;
724}
725
726/* helper to parse peer_info received from multi client, validate
727 * (this is untrusted data) and put into environment
728 */
729bool
731{
732 int state = 0;
733 while (*line)
734 {
735 const uint8_t c = *line;
736 switch (state)
737 {
738 case 0:
739 case 1:
740 if (c == '=' && state == 1)
741 {
742 state = 2;
743 }
744 else if (isalnum(c) || c == '_')
745 {
746 state = 1;
747 }
748 else
749 {
750 return false;
751 }
752 /* Intentional [[fallthrough]]; */
753 case 2:
754 /* after the '=', replace non-printable or shell meta with '_' */
755 if (!isprint(c) || isspace(c) || c == '$' || c == '(' || c == '`')
756 {
757 *line = '_';
758 }
759 }
760 line++;
761 }
762 return (state == 2);
763}
764
765void
766output_peer_info_env(struct env_set *es, const char *peer_info)
767{
768 char line[256];
769 struct buffer buf;
770 buf_set_read(&buf, (const uint8_t *)peer_info, strlen(peer_info));
771 while (buf_parse(&buf, '\n', line, sizeof(line)))
772 {
773 chomp(line);
775 && (strncmp(line, "IV_", 3) == 0 || strncmp(line, "UV_", 3) == 0
776 || strncmp(line, "ID", 2) == 0))
777 {
778 msg(M_INFO, "peer info: %s", line);
779 env_set_add(es, line);
780 }
781 else
782 {
783 msg(M_WARN, "validation failed on peer_info line received");
784 }
785 }
786}
787
788struct buffer
789prepend_dir(const char *dir, const char *path, struct gc_arena *gc)
790{
791 size_t len = strlen(dir) + strlen(PATH_SEPARATOR_STR) + strlen(path) + 1;
794 ASSERT(combined_path.len > 0);
795
796 return combined_path;
797}
798
799void
801{
802 if (up->protected)
803 {
804 return;
805 }
806#ifdef _WIN32
807 if (protect_buffer_win32(up->username, sizeof(up->username))
808 && protect_buffer_win32(up->password, sizeof(up->password)))
809 {
810 up->protected = true;
811 }
812 else
813 {
814 purge_user_pass(up, true);
815 }
816#endif
817}
818
819void
821{
822 if (!up->protected)
823 {
824 return;
825 }
826#ifdef _WIN32
827 if (unprotect_buffer_win32(up->username, sizeof(up->username))
828 && unprotect_buffer_win32(up->password, sizeof(up->password)))
829 {
830 up->protected = false;
831 }
832 else
833 {
834 purge_user_pass(up, true);
835 }
836#endif
837}
const char * skip_leading_whitespace(const char *str)
Return a pointer past any leading whitespace in a string.
Definition buffer.c:542
bool buf_printf(struct buffer *buf, const char *format,...)
printf-style append to a buffer with overflow check.
Definition buffer.c:226
void string_clear(char *str)
Securely clear a null-terminated string.
Definition buffer.c:634
void chomp(char *str)
Remove trailing newline and carriage-return characters from a string.
Definition buffer.c:579
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
Allocate memory and, optionally, zero it.
Definition buffer.c:313
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Allocate a buffer of the given size under garbage collection.
Definition buffer.c:77
bool string_mod(char *str, const unsigned int inclusive, const unsigned int exclusive, const char replace)
Modifies a string in place by replacing certain classes of characters of it with a specified characte...
Definition buffer.c:986
const char * string_mod_const(const char *str, const unsigned int inclusive, const unsigned int exclusive, const char replace, struct gc_arena *gc)
Returns a copy of a string with certain classes of characters of it replaced with a specified charact...
Definition buffer.c:1037
int string_array_len(const char **array)
Return the number of elements in a NULL-terminated array of strings.
Definition buffer.c:646
bool buf_parse(struct buffer *buf, const int delim, char *line, const int size)
Extract the next token from a buffer, delimited by a given character.
Definition buffer.c:757
char * string_alloc(const char *str, struct gc_arena *gc)
Duplicate a string, allocating memory under garbage collection.
Definition buffer.c:601
Buffer management functions and garbage collection.
static bool buf_size_valid(const size_t size)
Return true iff size is within the allowed buffer size range.
Definition buffer.h:543
#define BSTR(buf)
Return the buffer content pointer cast to char *.
Definition buffer.h:157
#define streq(x, y)
helper to work around the semantics of the strcmp() return value
Definition buffer.h:1813
#define ALLOC_ARRAY_CLEAR_GC(dptr, type, n, gc)
Allocate and zero-initialise a garbage-collected array of n elements.
Definition buffer.h:2082
#define CC_CRLF
carriage return or newline
Definition buffer.h:1714
static void buf_set_write(struct buffer *buf, uint8_t *data, int size)
Initialise a buffer with an externally provided writable memory region.
Definition buffer.h:658
static void buf_set_read(struct buffer *buf, const uint8_t *data, size_t size)
Initialise a buffer with an externally provided read-only memory region.
Definition buffer.h:687
static void secure_memzero(void *data, size_t len)
Securely zeroise memory.
Definition buffer.h:748
#define ALLOC_OBJ_CLEAR_GC(dptr, type, gc)
Allocate and zero-initialise a garbage-collected object of the given type.
Definition buffer.h:2123
static void gc_free(struct gc_arena *a)
Free all allocations in a garbage collection arena.
Definition buffer.h:1965
#define CC_PRINT
printable (>= 32, != 127)
Definition buffer.h:1685
static struct gc_arena gc_new(void)
Allocate and return a new, empty garbage collection arena.
Definition buffer.h:1949
size_t strlcpy(char *dest, const char *src, size_t maxlen)
size_t strlcat(char *dest, const char *src, size_t maxlen)
#define IPROUTE_PATH
Definition config.h:468
void query_user_clear(void)
Wipes all data put into all of the query_user structs.
Definition console.c:44
void query_user_add(char *prompt, char *resp, int resp_len, bool echo)
Adds an item to ask the user for.
Definition console.c:56
static bool query_user_SINGLE(char *prompt, char *resp, int resp_len, bool echo)
A plain "make Gert happy" wrapper.
Definition console.h:118
static bool query_user_exec(void)
Wrapper function enabling query_user_exec() if no alternative methods have been enabled.
Definition console.h:103
Data Channel Cryptography Module.
void env_set_add(struct env_set *es, const char *str)
Definition env_set.c:192
#define D_PUSH
Definition errlevel.h:82
#define D_SHOW_KEYS
Definition errlevel.h:120
#define D_LOW
Definition errlevel.h:96
#define M_INFO
Definition errlevel.h:54
bool management_query_user_pass(struct management *man, struct user_pass *up, const char *type, const unsigned int flags, const char *static_challenge)
Definition manage.c:3672
void management_auth_failure(const struct management *man, const char *type, const char *reason)
Definition manage.c:3274
static bool management_query_user_pass_enabled(const struct management *man)
Definition manage.h:430
static const char ** make_inline_array(const char *str, struct gc_arena *gc)
Definition misc.c:588
void unprotect_user_pass(struct user_pass *up)
Decrypt username and password buffers in user_pass.
Definition misc.c:820
bool get_user_pass_cr(struct user_pass *up, const char *auth_file, const char *prefix, const unsigned int flags, const char *auth_challenge)
Retrieves the user credentials from various sources depending on the flags.
Definition misc.c:196
const char ** make_arg_array(const char *first, const char *parms, struct gc_arena *gc)
Definition misc.c:561
void purge_user_pass(struct user_pass *up, const bool force)
Definition misc.c:480
bool validate_peer_info_line(char *line)
Definition misc.c:730
void set_auth_token_user(struct user_pass *tk, const char *username)
Sets the auth-token username by base64 decoding the passed username.
Definition misc.c:528
void set_std_files_to_null(bool stdin_only)
Definition misc.c:55
void output_peer_info_env(struct env_set *es, const char *peer_info)
Definition misc.c:766
struct buffer prepend_dir(const char *dir, const char *path, struct gc_arena *gc)
Prepend a directory to a path.
Definition misc.c:789
static struct auth_challenge_info * parse_auth_challenge(const char *auth_challenge, struct gc_arena *gc)
Parses an authentication challenge string and returns an auth_challenge_info structure.
Definition misc.c:122
void protect_user_pass(struct user_pass *up)
Encrypt username and password buffers in user_pass.
Definition misc.c:800
const char ** make_extended_arg_array(char **p, bool is_inline, struct gc_arena *gc)
Definition misc.c:638
static const char ** make_arg_copy(char **p, struct gc_arena *gc)
Definition misc.c:619
const char * safe_print(const char *str, struct gc_arena *gc)
Definition misc.c:555
const char * sanitize_control_message(const char *src, struct gc_arena *gc)
Definition misc.c:668
static bool auth_user_pass_mgmt(struct user_pass *up, const char *prefix, const unsigned int flags, const char *auth_challenge)
Definition misc.c:78
void set_auth_token(struct user_pass *tk, const char *token)
Sets the auth-token to token.
Definition misc.c:508
#define USER_PASS_LEN
Definition misc.h:67
#define GET_USER_PASS_STATIC_CHALLENGE_CONCAT
indicates password and response should be concatenated
Definition misc.h:128
#define GET_USER_PASS_MANAGEMENT
Definition misc.h:113
#define GET_USER_PASS_PASSWORD_ONLY
Definition misc.h:115
#define GET_USER_PASS_USERNAME_ONLY
indicate that only username should be prompted for auth-user-pass
Definition misc.h:130
#define GET_USER_PASS_STATIC_CHALLENGE_ECHO
SCRV1 protocol – echo response.
Definition misc.h:123
#define CR_ECHO
Definition misc.h:80
#define CR_RESPONSE
Definition misc.h:81
#define GET_USER_PASS_INLINE_CREDS
indicates that auth_file is actually inline creds
Definition misc.h:126
#define GET_USER_PASS_STATIC_CHALLENGE
SCRV1 protocol – static challenge.
Definition misc.h:122
#define GET_USER_PASS_NEED_OK
Definition misc.h:116
#define GET_USER_PASS_NOFATAL
Definition misc.h:117
static const char blank_up[]
Definition misc.h:52
#define GET_USER_PASS_PREVIOUS_CREDS_FAILED
Definition misc.h:119
#define GET_USER_PASS_DYNAMIC_CHALLENGE
CRV1 protocol – dynamic challenge.
Definition misc.h:121
#define BOOL_CAST(x)
Definition basic.h:26
#define CLEAR(x)
Definition basic.h:32
static bool check_debug_level(msglvl_t level)
Definition error.h:253
#define M_FATAL
Definition error.h:90
#define M_ERR
Definition error.h:106
#define msg(flags,...)
Definition error.h:152
#define ASSERT(x)
Definition error.h:221
#define M_WARN
Definition error.h:92
int parse_line(const char *line, char *p[], const int n, const char *file, const int line_num, msglvl_t msglevel, struct gc_arena *gc)
#define MAX_PARMS
Definition options.h:51
#define OPTION_LINE_SIZE
Definition options.h:57
FILE * platform_fopen(const char *path, const char *mode)
Definition platform.c:500
int openvpn_base64_decode(const char *str, void *data, int size)
Definition base64.c:160
int openvpn_base64_encode(const void *data, int size, char **str)
Definition base64.c:51
static char * auth_challenge
Definition ssl.c:298
const char * user
Definition misc.h:84
const char * state_id
Definition misc.h:85
const char * challenge_text
Definition misc.h:86
unsigned int flags
Definition misc.h:82
Wrapper structure for dynamically allocated memory.
Definition buffer.h:71
int len
Length in bytes of the actual content within the allocated memory.
Definition buffer.h:76
Garbage collection arena used to keep track of dynamically allocated memory.
Definition buffer.h:127
bool protected
Definition misc.h:61
bool defined
Definition misc.h:56
char password[USER_PASS_LEN]
Definition misc.h:71
bool nocache
Definition misc.h:60
char username[USER_PASS_LEN]
Definition misc.h:70
#define PATH_SEPARATOR_STR
Definition syshead.h:433
struct gc_arena gc
Definition test_ssl.c:138
bool protect_buffer_win32(char *buf, DWORD len)
Encrypt a region of memory using CryptProtectMemory() with access restricted to the current process.
Definition win32.c:1629
bool unprotect_buffer_win32(char *buf, DWORD len)
Decrypt a previously encrypted region of memory using CryptUnProtectMemory() with access restricted t...
Definition win32.c:1647