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#if defined(__GNUC__) || defined(__clang__)
76#pragma GCC diagnostic push
77#pragma GCC diagnostic ignored "-Wconversion"
78#endif
79
80#ifdef ENABLE_MANAGEMENT
81/* Get username/password from the management interface */
82static bool
83auth_user_pass_mgmt(struct user_pass *up, const char *prefix, const unsigned int flags,
84 const char *auth_challenge)
85{
86 const char *sc = NULL;
87
89 {
90 management_auth_failure(management, prefix, "previous auth credentials failed");
91 }
92
94 {
95 sc = auth_challenge;
96 }
97 if (!management_query_user_pass(management, up, prefix, flags, sc))
98 {
99 if ((flags & GET_USER_PASS_NOFATAL) != 0)
100 {
101 return false;
102 }
103 else
104 {
105 msg(M_FATAL,
106 "ERROR: could not read %s username/password/ok/string from management interface",
107 prefix);
108 }
109 }
110 return true;
111}
112
126static struct auth_challenge_info *
128{
130
131 struct auth_challenge_info *ac;
132 const int len = strlen(auth_challenge);
133 char *work = (char *)gc_malloc(len + 1, false, gc);
134 char *cp;
135
136 struct buffer b;
138
140
141 /* parse prefix */
142 if (!buf_parse(&b, ':', work, len))
143 {
144 return NULL;
145 }
146 if (strcmp(work, "CRV1"))
147 {
148 return NULL;
149 }
150
151 /* parse flags */
152 if (!buf_parse(&b, ':', work, len))
153 {
154 return NULL;
155 }
156 for (cp = work; *cp != '\0'; ++cp)
157 {
158 const char c = *cp;
159 if (c == 'E')
160 {
161 ac->flags |= CR_ECHO;
162 }
163 else if (c == 'R')
164 {
165 ac->flags |= CR_RESPONSE;
166 }
167 }
168
169 /* parse state ID */
170 if (!buf_parse(&b, ':', work, len))
171 {
172 return NULL;
173 }
174 ac->state_id = string_alloc(work, gc);
175
176 /* parse user name */
177 if (!buf_parse(&b, ':', work, len))
178 {
179 return NULL;
180 }
181 ac->user = (char *)gc_malloc(strlen(work) + 1, true, gc);
182 openvpn_base64_decode(work, (void *)ac->user, -1);
183
184 /* parse challenge text */
185 ac->challenge_text = string_alloc(BSTR(&b), gc);
186
187 return ac;
188}
189
190#endif /* ifdef ENABLE_MANAGEMENT */
191
192#if defined(__GNUC__) || defined(__clang__)
193#pragma GCC diagnostic pop
194#endif
195
196/*
197 * Get and store a username/password
198 */
199
200bool
201get_user_pass_cr(struct user_pass *up, const char *auth_file, const char *prefix,
202 const unsigned int flags, const char *auth_challenge)
203{
204 struct gc_arena gc = gc_new();
205
206 if (!up->defined)
207 {
208 bool from_authfile = (auth_file && !streq(auth_file, "stdin"));
209 bool username_from_stdin = false;
210 bool password_from_stdin = false;
211 bool response_from_stdin = true;
212
215 {
216 msg(M_WARN, "Note: previous '%s' credentials failed", prefix);
217 }
218#ifdef ENABLE_MANAGEMENT
219 /*
220 * Get username/password from management interface?
221 */
222 if (management && (!from_authfile && (flags & GET_USER_PASS_MANAGEMENT))
224 {
225 response_from_stdin = false;
226 if (!auth_user_pass_mgmt(up, prefix, flags, auth_challenge))
227 {
228 return false;
229 }
230 }
231 else
232#endif /* ifdef ENABLE_MANAGEMENT */
233 /*
234 * Get NEED_OK confirmation from the console
235 */
236 if (flags & GET_USER_PASS_NEED_OK)
237 {
238 struct buffer user_prompt = alloc_buf_gc(128, &gc);
239
240 buf_printf(&user_prompt, "NEED-OK|%s|%s:", prefix, up->username);
242 {
243 msg(M_FATAL, "ERROR: could not read %s ok-confirmation from stdin", prefix);
244 }
245
246 if (!strlen(up->password))
247 {
248 strcpy(up->password, "ok");
249 }
250 }
251 else if (flags & GET_USER_PASS_INLINE_CREDS)
252 {
253 struct buffer buf;
254 buf_set_read(&buf, (uint8_t *)auth_file, strlen(auth_file) + 1);
255 if (!(flags & GET_USER_PASS_PASSWORD_ONLY))
256 {
257 buf_parse(&buf, '\n', up->username, USER_PASS_LEN);
258 }
259 buf_parse(&buf, '\n', up->password, USER_PASS_LEN);
260
261 if (strlen(up->password) == 0)
262 {
264 }
265 }
266 /*
267 * Read from auth file unless this is a dynamic challenge request.
268 */
269 else if (from_authfile && !(flags & GET_USER_PASS_DYNAMIC_CHALLENGE))
270 {
271 /*
272 * Try to get username/password from a file.
273 */
274 FILE *fp;
275 char password_buf[USER_PASS_LEN] = { '\0' };
276
277 fp = platform_fopen(auth_file, "r");
278 if (!fp)
279 {
280 msg(M_ERR, "Error opening '%s' auth file: %s", prefix, auth_file);
281 }
282
283 if ((flags & GET_USER_PASS_PASSWORD_ONLY) == 0)
284 {
285 /* Read username first */
286 if (fgets(up->username, USER_PASS_LEN, fp) == NULL)
287 {
288 msg(M_FATAL, "Error reading username from %s authfile: %s", prefix,
289 auth_file);
290 }
291 }
292 chomp(up->username);
293
295 {
297 }
298
299 if (flags & GET_USER_PASS_PASSWORD_ONLY && !password_buf[0])
300 {
301 msg(M_FATAL, "Error reading password from %s authfile: %s", prefix, auth_file);
302 }
303
304 if (password_buf[0])
305 {
307 }
308 /* The auth-file does not have the password: get both username
309 * and password from the management interface if possible.
310 * Otherwise set to read password from console.
311 */
312#if defined(ENABLE_MANAGEMENT)
313 else if (management && (flags & GET_USER_PASS_MANAGEMENT)
315 {
316 msg(D_LOW,
317 "No password found in %s authfile '%s'. Querying the management interface",
318 prefix, auth_file);
319 if (!auth_user_pass_mgmt(up, prefix, flags, auth_challenge))
320 {
321 fclose(fp);
322 return false;
323 }
324 }
325#endif
326 else
327 {
329 }
330
331 fclose(fp);
332
333 if (!(flags & GET_USER_PASS_PASSWORD_ONLY) && strlen(up->username) == 0)
334 {
335 msg(M_FATAL, "ERROR: username from %s authfile '%s' is empty", prefix,
336 auth_file);
337 }
338 }
339 else
340 {
341 username_from_stdin = true;
342 password_from_stdin = true;
343 }
344
345 /*
346 * Get username/password from standard input?
347 */
349 {
350#ifdef ENABLE_MANAGEMENT
352 {
354 if (ac)
355 {
356 char *response = (char *)gc_malloc(USER_PASS_LEN, false, &gc);
358
359 challenge = alloc_buf_gc(14 + strlen(ac->challenge_text), &gc);
360 buf_printf(&challenge, "CHALLENGE: %s", ac->challenge_text);
362
363 if (!query_user_SINGLE(BSTR(&challenge), response,
364 USER_PASS_LEN, BOOL_CAST(ac->flags & CR_ECHO)))
365 {
366 msg(M_FATAL, "ERROR: could not read challenge response from stdin");
367 }
368 strncpynt(up->username, ac->user, USER_PASS_LEN);
369 buf_printf(&packed_resp, "CRV1::%s::%s", ac->state_id, response);
370 }
371 else
372 {
373 msg(M_FATAL, "ERROR: received malformed challenge request from server");
374 }
375 }
376 else
377#endif /* ifdef ENABLE_MANAGEMENT */
378 {
379 struct buffer user_prompt = alloc_buf_gc(128, &gc);
380 struct buffer pass_prompt = alloc_buf_gc(128, &gc);
381
383 buf_printf(&user_prompt, "Enter %s Username:", prefix);
384 buf_printf(&pass_prompt, "Enter %s Password:", prefix);
385
387 {
389 }
390
392 {
394 }
395
396 if (!query_user_exec())
397 {
398 msg(M_FATAL, "ERROR: Failed retrieving username or password");
399 }
400
401 if (!(flags & GET_USER_PASS_PASSWORD_ONLY))
402 {
403 if (strlen(up->username) == 0)
404 {
405 msg(M_FATAL, "ERROR: %s username is empty", prefix);
406 }
407 }
408
409#ifdef ENABLE_MANAGEMENT
412 {
413 char *response = (char *)gc_malloc(USER_PASS_LEN, false, &gc);
415 char *pw64 = NULL, *resp64 = NULL;
416
418 buf_printf(&challenge, "CHALLENGE: %s", auth_challenge);
419
422 {
423 msg(M_FATAL, "ERROR: could not retrieve static challenge response");
424 }
426 {
427 if (openvpn_base64_encode(up->password, (int)strlen(up->password), &pw64) == -1
428 || openvpn_base64_encode(response, (int)strlen(response), &resp64) == -1)
429 {
430 msg(M_FATAL, "ERROR: could not base64-encode password/static_response");
431 }
433 buf_printf(&packed_resp, "SCRV1:%s:%s", pw64, resp64);
435 free(pw64);
437 free(resp64);
438 }
439 else
440 {
441 if (strlen(up->password) + strlen(response) >= USER_PASS_LEN)
442 {
443 msg(M_FATAL,
444 "ERROR: could not concatenate password/static_response: string too long");
445 }
446 strncat(up->password, response, USER_PASS_LEN - strlen(up->password) - 1);
447 }
448 }
449#endif /* ifdef ENABLE_MANAGEMENT */
450 }
451 }
452
453 /* Use tag for blank password if we are not prompting for one */
454 if (flags & GET_USER_PASS_USERNAME_ONLY)
455 {
456 strncpy(up->password, blank_up, sizeof(up->password));
457 }
458
461
462 up->defined = true;
463 }
464
465#if 0
466 msg(M_INFO, "GET_USER_PASS %s u='%s' p='%s'", prefix, up->username, up->password);
467#endif
468
469 gc_free(&gc);
470
471 return true;
472}
473
474void
475purge_user_pass(struct user_pass *up, const bool force)
476{
477 const bool nocache = up->nocache;
478 static bool warn_shown = false;
479 if (nocache || force)
480 {
481 secure_memzero(up, sizeof(*up));
482 up->nocache = nocache;
483 }
484 else
485 {
487 /*
488 * don't show warning if the pass has been replaced by a token: this is an
489 * artificial "auth-nocache"
490 */
491 if (!warn_shown)
492 {
493 msg(M_WARN,
494 "WARNING: this configuration may cache passwords in memory -- use the auth-nocache option to prevent this");
495 warn_shown = true;
496 }
497 }
498}
499
500void
501set_auth_token(struct user_pass *tk, const char *token)
502{
503 if (strlen(token))
504 {
506 strncpynt(tk->password, token, USER_PASS_LEN);
507 tk->token_defined = true;
508
509 /*
510 * If username already set, tk is fully defined.
511 */
512 if (strlen(tk->username))
513 {
514 tk->defined = true;
515 }
517 }
518}
519
520void
521set_auth_token_user(struct user_pass *tk, const char *username)
522{
523 if (strlen(username))
524 {
526 /* Clear the username before decoding to ensure no old material is left
527 * and also allow decoding to not use all space to ensure the last byte is
528 * always 0 */
529 CLEAR(tk->username);
530 int len = openvpn_base64_decode(username, tk->username, USER_PASS_LEN - 1);
531 tk->defined = len > 0;
532 if (!tk->defined)
533 {
534 msg(D_PUSH, "Error decoding auth-token-username");
535 }
537 }
538}
539
540
541/*
542 * Process string received by untrusted peer before
543 * printing to console or log file.
544 *
545 * Assumes that string has been null terminated.
546 */
547const char *
548safe_print(const char *str, struct gc_arena *gc)
549{
550 return string_mod_const(str, CC_PRINT, CC_CRLF, '.', gc);
551}
552
553const char **
554make_arg_array(const char *first, const char *parms, struct gc_arena *gc)
555{
556 char **ret = NULL;
557 int base = 0;
558 const int max_parms = MAX_PARMS + 2;
559 int n = 0;
560
561 /* alloc return array */
562 ALLOC_ARRAY_CLEAR_GC(ret, char *, max_parms, gc);
563
564 /* process first parameter, if provided */
565 if (first)
566 {
567 ret[base++] = string_alloc(first, gc);
568 }
569
570 if (parms)
571 {
572 n = parse_line(parms, &ret[base], max_parms - base - 1, "make_arg_array", 0, M_WARN, gc);
573 ASSERT(n >= 0 && n + base + 1 <= max_parms);
574 }
575 ret[base + n] = NULL;
576
577 return (const char **)ret;
578}
579
580static const char **
581make_inline_array(const char *str, struct gc_arena *gc)
582{
584 struct buffer buf;
585 int len = 0;
586 char **ret = NULL;
587 int i = 0;
588
589 buf_set_read(&buf, (const uint8_t *)str, strlen(str));
590 while (buf_parse(&buf, '\n', line, sizeof(line)))
591 {
592 ++len;
593 }
594
595 /* alloc return array */
596 ALLOC_ARRAY_CLEAR_GC(ret, char *, len + 1, gc);
597
598 buf_set_read(&buf, (const uint8_t *)str, strlen(str));
599 while (buf_parse(&buf, '\n', line, sizeof(line)))
600 {
601 chomp(line);
602 ASSERT(i < len);
604 ++i;
605 }
606 ASSERT(i <= len);
607 ret[i] = NULL;
608 return (const char **)ret;
609}
610
611static const char **
612make_arg_copy(char **p, struct gc_arena *gc)
613{
614 char **ret = NULL;
615 const int len = string_array_len((const char **)p);
616 const int max_parms = len + 1;
617 int i;
618
619 /* alloc return array */
620 ALLOC_ARRAY_CLEAR_GC(ret, char *, max_parms, gc);
621
622 for (i = 0; i < len; ++i)
623 {
624 ret[i] = p[i];
625 }
626
627 return (const char **)ret;
628}
629
630const char **
632{
633 const int argc = string_array_len((const char **)p);
634 if (is_inline)
635 {
636 return make_inline_array(p[0], gc);
637 }
638 else if (argc == 0)
639 {
640 return make_arg_array(NULL, NULL, gc);
641 }
642 else if (argc == 1)
643 {
644 return make_arg_array(p[0], NULL, gc);
645 }
646 else if (argc == 2)
647 {
648 return make_arg_array(p[0], p[1], gc);
649 }
650 else
651 {
652 return make_arg_copy(p, gc);
653 }
654}
655
656/*
657 * Remove security-sensitive strings from control message
658 * so that they will not be output to log file.
659 */
660const char *
662{
663 char *ret = gc_malloc(strlen(src) + 1, false, gc);
664 char *dest = ret;
665 bool redact = false;
666 int skip = 0;
667
668 for (;;)
669 {
670 const char c = *src;
671 if (c == '\0')
672 {
673 break;
674 }
675 if (c == 'S' && !strncmp(src, "SESS_ID_", 8))
676 {
677 skip = 7;
678 redact = true;
679 }
680 else if (c == 'e' && !strncmp(src, "echo ", 5))
681 {
682 skip = 4;
683 redact = true;
684 }
685 else if (!check_debug_level(D_SHOW_KEYS) && (c == 'a' && !strncmp(src, "auth-token ", 11)))
686 {
687 /* Unless --verb is 7 or higher (D_SHOW_KEYS), hide
688 * the auth-token value coming in the src string
689 */
690 skip = 10;
691 redact = true;
692 }
693
694 if (c == ',') /* end of redacted item? */
695 {
696 skip = 0;
697 redact = false;
698 }
699
700 if (redact)
701 {
702 if (skip > 0)
703 {
704 --skip;
705 *dest++ = c;
706 }
707 }
708 else
709 {
710 *dest++ = c;
711 }
712
713 ++src;
714 }
715 *dest = '\0';
716 return ret;
717}
718
719/* helper to parse peer_info received from multi client, validate
720 * (this is untrusted data) and put into environment
721 */
722bool
724{
725 uint8_t c;
726 int state = 0;
727 while (*line)
728 {
729 c = *line;
730 switch (state)
731 {
732 case 0:
733 case 1:
734 if (c == '=' && state == 1)
735 {
736 state = 2;
737 }
738 else if (isalnum(c) || c == '_')
739 {
740 state = 1;
741 }
742 else
743 {
744 return false;
745 }
746 /* Intentional [[fallthrough]]; */
747 case 2:
748 /* after the '=', replace non-printable or shell meta with '_' */
749 if (!isprint(c) || isspace(c) || c == '$' || c == '(' || c == '`')
750 {
751 *line = '_';
752 }
753 }
754 line++;
755 }
756 return (state == 2);
757}
758
759void
760output_peer_info_env(struct env_set *es, const char *peer_info)
761{
762 char line[256];
763 struct buffer buf;
764 buf_set_read(&buf, (const uint8_t *)peer_info, strlen(peer_info));
765 while (buf_parse(&buf, '\n', line, sizeof(line)))
766 {
767 chomp(line);
769 && (strncmp(line, "IV_", 3) == 0 || strncmp(line, "UV_", 3) == 0))
770 {
771 msg(M_INFO, "peer info: %s", line);
773 }
774 else
775 {
776 msg(M_WARN, "validation failed on peer_info line received from client");
777 }
778 }
779}
780
781struct buffer
782prepend_dir(const char *dir, const char *path, struct gc_arena *gc)
783{
784 size_t len = strlen(dir) + strlen(PATH_SEPARATOR_STR) + strlen(path) + 1;
787 ASSERT(combined_path.len > 0);
788
789 return combined_path;
790}
791
792void
794{
795 if (up->protected)
796 {
797 return;
798 }
799#ifdef _WIN32
800 if (protect_buffer_win32(up->username, sizeof(up->username))
801 && protect_buffer_win32(up->password, sizeof(up->password)))
802 {
803 up->protected = true;
804 }
805 else
806 {
807 purge_user_pass(up, true);
808 }
809#endif
810}
811
812void
814{
815 if (!up->protected)
816 {
817 return;
818 }
819#ifdef _WIN32
820 if (unprotect_buffer_win32(up->username, sizeof(up->username))
821 && unprotect_buffer_win32(up->password, sizeof(up->password)))
822 {
823 up->protected = false;
824 }
825 else
826 {
827 purge_user_pass(up, true);
828 }
829#endif
830}
const char * skip_leading_whitespace(const char *str)
Definition buffer.c:578
bool buf_printf(struct buffer *buf, const char *format,...)
Definition buffer.c:241
void string_clear(char *str)
Definition buffer.c:690
void chomp(char *str)
Definition buffer.c:613
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
Definition buffer.c:336
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Definition buffer.c:89
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:1054
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:1104
int string_array_len(const char **array)
Definition buffer.c:702
bool buf_parse(struct buffer *buf, const int delim, char *line, const int size)
Definition buffer.c:824
char * string_alloc(const char *str, struct gc_arena *gc)
Definition buffer.c:648
#define BSTR(buf)
Definition buffer.h:129
#define ALLOC_ARRAY_CLEAR_GC(dptr, type, n, gc)
Definition buffer.h:1110
#define CC_CRLF
carriage return or newline
Definition buffer.h:915
static void buf_set_write(struct buffer *buf, uint8_t *data, int size)
Definition buffer.h:332
static void buf_set_read(struct buffer *buf, const uint8_t *data, size_t size)
Definition buffer.h:349
static void secure_memzero(void *data, size_t len)
Securely zeroise memory.
Definition buffer.h:415
#define ALLOC_OBJ_CLEAR_GC(dptr, type, gc)
Definition buffer.h:1125
static void strncpynt(char *dest, const char *src, size_t maxlen)
Definition buffer.h:362
static void gc_free(struct gc_arena *a)
Definition buffer.h:1049
#define CC_PRINT
printable (>= 32, != 127)
Definition buffer.h:886
static struct gc_arena gc_new(void)
Definition buffer.h:1041
#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:193
#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
void management_auth_failure(struct management *man, const char *type, const char *reason)
Definition manage.c:3130
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:3528
static bool management_query_user_pass_enabled(const struct management *man)
Definition manage.h:420
static const char ** make_inline_array(const char *str, struct gc_arena *gc)
Definition misc.c:581
void unprotect_user_pass(struct user_pass *up)
Decrypt username and password buffers in user_pass.
Definition misc.c:813
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:201
const char ** make_arg_array(const char *first, const char *parms, struct gc_arena *gc)
Definition misc.c:554
void purge_user_pass(struct user_pass *up, const bool force)
Definition misc.c:475
bool validate_peer_info_line(char *line)
Definition misc.c:723
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:521
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:760
struct buffer prepend_dir(const char *dir, const char *path, struct gc_arena *gc)
Prepend a directory to a path.
Definition misc.c:782
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:127
void protect_user_pass(struct user_pass *up)
Encrypt username and password buffers in user_pass.
Definition misc.c:793
const char ** make_extended_arg_array(char **p, bool is_inline, struct gc_arena *gc)
Definition misc.c:631
static const char ** make_arg_copy(char **p, struct gc_arena *gc)
Definition misc.c:612
const char * safe_print(const char *str, struct gc_arena *gc)
Definition misc.c:548
const char * sanitize_control_message(const char *src, struct gc_arena *gc)
Definition misc.c:661
static bool auth_user_pass_mgmt(struct user_pass *up, const char *prefix, const unsigned int flags, const char *auth_challenge)
Definition misc.c:83
void set_auth_token(struct user_pass *tk, const char *token)
Sets the auth-token to token.
Definition misc.c:501
#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:251
#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:219
#define M_WARN
Definition error.h:92
#define streq(x, y)
Definition options.h:721
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:283
Wrapper structure for dynamically allocated memory.
Definition buffer.h:60
int len
Length in bytes of the actual content within the allocated memory.
Definition buffer.h:65
Garbage collection arena used to keep track of dynamically allocated memory.
Definition buffer.h:116
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 env_set * es
struct gc_arena gc
Definition test_ssl.c:131
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:1601
bool unprotect_buffer_win32(char *buf, DWORD len)
Decrypt a previously encrypted region of memory using CryptUnProtectMemory() with access restricted t...
Definition win32.c:1619