cosmetics
[tomato.git] / release / src / router / openvpn / misc.c
blob33e676213d14d6af04ede5b0a9acc3a1905df779
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.
8 * Copyright (C) 2002-2009 OpenVPN Technologies, Inc. <sales@openvpn.net>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program (see the file COPYING included with this
21 * distribution); if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "syshead.h"
27 #include "buffer.h"
28 #include "misc.h"
29 #include "tun.h"
30 #include "error.h"
31 #include "thread.h"
32 #include "otime.h"
33 #include "plugin.h"
34 #include "options.h"
35 #include "manage.h"
36 #include "crypto.h"
37 #include "route.h"
38 #include "win32.h"
40 #include "memdbg.h"
42 #ifdef CONFIG_FEATURE_IPROUTE
43 const char *iproute_path = IPROUTE_PATH; /* GLOBAL */
44 #endif
46 /* contains an SSEC_x value defined in misc.h */
47 int script_security = SSEC_BUILT_IN; /* GLOBAL */
49 /* contains SM_x value defined in misc.h */
50 int script_method = SM_EXECVE; /* GLOBAL */
52 /* Redefine the top level directory of the filesystem
53 to restrict access to files for security */
54 void
55 do_chroot (const char *path)
57 if (path)
59 #ifdef HAVE_CHROOT
60 const char *top = "/";
61 if (chroot (path))
62 msg (M_ERR, "chroot to '%s' failed", path);
63 if (openvpn_chdir (top))
64 msg (M_ERR, "cd to '%s' failed", top);
65 msg (M_INFO, "chroot to '%s' and cd to '%s' succeeded", path, top);
66 #else
67 msg (M_FATAL, "Sorry but I can't chroot to '%s' because this operating system doesn't appear to support the chroot() system call", path);
68 #endif
72 /* Get/Set UID of process */
74 bool
75 get_user (const char *username, struct user_state *state)
77 bool ret = false;
78 CLEAR (*state);
79 if (username)
81 #if defined(HAVE_GETPWNAM) && defined(HAVE_SETUID)
82 state->pw = getpwnam (username);
83 if (!state->pw)
84 msg (M_ERR, "failed to find UID for user %s", username);
85 state->username = username;
86 ret = true;
87 #else
88 msg (M_FATAL, "cannot get UID for user %s -- platform lacks getpwname() or setuid() system calls", username);
89 #endif
91 return ret;
94 void
95 set_user (const struct user_state *state)
97 #if defined(HAVE_GETPWNAM) && defined(HAVE_SETUID)
98 if (state->username && state->pw)
100 if (setuid (state->pw->pw_uid))
101 msg (M_ERR, "setuid('%s') failed", state->username);
102 msg (M_INFO, "UID set to %s", state->username);
104 #endif
107 /* Get/Set GID of process */
109 bool
110 get_group (const char *groupname, struct group_state *state)
112 bool ret = false;
113 CLEAR (*state);
114 if (groupname)
116 #if defined(HAVE_GETGRNAM) && defined(HAVE_SETGID)
117 state->gr = getgrnam (groupname);
118 if (!state->gr)
119 msg (M_ERR, "failed to find GID for group %s", groupname);
120 state->groupname = groupname;
121 ret = true;
122 #else
123 msg (M_FATAL, "cannot get GID for group %s -- platform lacks getgrnam() or setgid() system calls", groupname);
124 #endif
126 return ret;
129 void
130 set_group (const struct group_state *state)
132 #if defined(HAVE_GETGRNAM) && defined(HAVE_SETGID)
133 if (state->groupname && state->gr)
135 if (setgid (state->gr->gr_gid))
136 msg (M_ERR, "setgid('%s') failed", state->groupname);
137 msg (M_INFO, "GID set to %s", state->groupname);
138 #ifdef HAVE_SETGROUPS
140 gid_t gr_list[1];
141 gr_list[0] = state->gr->gr_gid;
142 if (setgroups (1, gr_list))
143 msg (M_ERR, "setgroups('%s') failed", state->groupname);
145 #endif
147 #endif
150 /* Change process priority */
151 void
152 set_nice (int niceval)
154 if (niceval)
156 #ifdef HAVE_NICE
157 errno = 0;
158 nice (niceval);
159 if (errno != 0)
160 msg (M_WARN | M_ERRNO, "WARNING: nice %d failed", niceval);
161 else
162 msg (M_INFO, "nice %d succeeded", niceval);
163 #else
164 msg (M_WARN, "WARNING: nice %d failed (function not implemented)", niceval);
165 #endif
170 * Pass tunnel endpoint and MTU parms to a user-supplied script.
171 * Used to execute the up/down script/plugins.
173 void
174 run_up_down (const char *command,
175 const struct plugin_list *plugins,
176 int plugin_type,
177 const char *arg,
178 int tun_mtu,
179 int link_mtu,
180 const char *ifconfig_local,
181 const char* ifconfig_remote,
182 const char *context,
183 const char *signal_text,
184 const char *script_type,
185 struct env_set *es)
187 struct gc_arena gc = gc_new ();
189 if (signal_text)
190 setenv_str (es, "signal", signal_text);
191 setenv_str (es, "script_context", context);
192 setenv_int (es, "tun_mtu", tun_mtu);
193 setenv_int (es, "link_mtu", link_mtu);
194 setenv_str (es, "dev", arg);
196 if (!ifconfig_local)
197 ifconfig_local = "";
198 if (!ifconfig_remote)
199 ifconfig_remote = "";
200 if (!context)
201 context = "";
203 if (plugin_defined (plugins, plugin_type))
205 struct argv argv = argv_new ();
206 ASSERT (arg);
207 argv_printf (&argv,
208 "%s %d %d %s %s %s",
209 arg,
210 tun_mtu, link_mtu,
211 ifconfig_local, ifconfig_remote,
212 context);
214 if (plugin_call (plugins, plugin_type, &argv, NULL, es) != OPENVPN_PLUGIN_FUNC_SUCCESS)
215 msg (M_FATAL, "ERROR: up/down plugin call failed");
217 argv_reset (&argv);
220 if (command)
222 struct argv argv = argv_new ();
223 ASSERT (arg);
224 setenv_str (es, "script_type", script_type);
225 argv_printf (&argv,
226 "%sc %s %d %d %s %s %s",
227 command,
228 arg,
229 tun_mtu, link_mtu,
230 ifconfig_local, ifconfig_remote,
231 context);
232 argv_msg (M_INFO, &argv);
233 openvpn_execve_check (&argv, es, S_SCRIPT|S_FATAL, "script failed");
234 argv_reset (&argv);
237 gc_free (&gc);
240 /* Get the file we will later write our process ID to */
241 void
242 get_pid_file (const char* filename, struct pid_state *state)
244 CLEAR (*state);
245 if (filename)
247 state->fp = fopen (filename, "w");
248 if (!state->fp)
249 msg (M_ERR, "Open error on pid file %s", filename);
250 state->filename = filename;
254 /* Write our PID to a file */
255 void
256 write_pid (const struct pid_state *state)
258 if (state->filename && state->fp)
260 unsigned int pid = openvpn_getpid ();
261 fprintf(state->fp, "%u\n", pid);
262 if (fclose (state->fp))
263 msg (M_ERR, "Close error on pid file %s", state->filename);
267 /* Get current PID */
268 unsigned int
269 openvpn_getpid ()
271 #ifdef WIN32
272 return (unsigned int) GetCurrentProcessId ();
273 #else
274 #ifdef HAVE_GETPID
275 return (unsigned int) getpid ();
276 #else
277 return 0;
278 #endif
279 #endif
282 /* Disable paging */
283 void
284 do_mlockall(bool print_msg)
286 #ifdef HAVE_MLOCKALL
287 if (mlockall (MCL_CURRENT | MCL_FUTURE))
288 msg (M_WARN | M_ERRNO, "WARNING: mlockall call failed");
289 else if (print_msg)
290 msg (M_INFO, "mlockall call succeeded");
291 #else
292 msg (M_WARN, "WARNING: mlockall call failed (function not implemented)");
293 #endif
296 #ifndef HAVE_DAEMON
299 daemon(int nochdir, int noclose)
301 #if defined(HAVE_FORK) && defined(HAVE_SETSID)
302 switch (fork())
304 case -1:
305 return (-1);
306 case 0:
307 break;
308 default:
309 openvpn_exit (OPENVPN_EXIT_STATUS_GOOD); /* exit point */
312 if (setsid() == -1)
313 return (-1);
315 if (!nochdir)
316 openvpn_chdir ("/");
318 if (!noclose)
319 set_std_files_to_null (false);
320 #else
321 msg (M_FATAL, "Sorry but I can't become a daemon because this operating system doesn't appear to support either the daemon() or fork() system calls");
322 #endif
323 return (0);
326 #endif
329 * Set standard file descriptors to /dev/null
331 void
332 set_std_files_to_null (bool stdin_only)
334 #if defined(HAVE_DUP) && defined(HAVE_DUP2)
335 int fd;
336 if ((fd = open ("/dev/null", O_RDWR, 0)) != -1)
338 dup2 (fd, 0);
339 if (!stdin_only)
341 dup2 (fd, 1);
342 dup2 (fd, 2);
344 if (fd > 2)
345 close (fd);
347 #endif
351 * Wrapper for chdir library function
354 openvpn_chdir (const char* dir)
356 #ifdef HAVE_CHDIR
357 return chdir (dir);
358 #else
359 return -1;
360 #endif
364 * dup inetd/xinetd socket descriptor and save
367 int inetd_socket_descriptor = SOCKET_UNDEFINED; /* GLOBAL */
369 void
370 save_inetd_socket_descriptor (void)
372 inetd_socket_descriptor = INETD_SOCKET_DESCRIPTOR;
373 #if defined(HAVE_DUP) && defined(HAVE_DUP2)
374 /* use handle passed by inetd/xinetd */
375 if ((inetd_socket_descriptor = dup (INETD_SOCKET_DESCRIPTOR)) < 0)
376 msg (M_ERR, "INETD_SOCKET_DESCRIPTOR dup(%d) failed", INETD_SOCKET_DESCRIPTOR);
377 set_std_files_to_null (true);
378 #endif
382 * Warn if a given file is group/others accessible.
384 void
385 warn_if_group_others_accessible (const char* filename)
387 #ifndef WIN32
388 #ifdef HAVE_STAT
389 #if ENABLE_INLINE_FILES
390 if (strcmp (filename, INLINE_FILE_TAG))
391 #endif
393 struct stat st;
394 if (stat (filename, &st))
396 msg (M_WARN | M_ERRNO, "WARNING: cannot stat file '%s'", filename);
398 else
400 if (st.st_mode & (S_IRWXG|S_IRWXO))
401 msg (M_WARN, "WARNING: file '%s' is group or others accessible", filename);
404 #endif
405 #endif
409 * convert system() return into a success/failure value
411 bool
412 system_ok (int stat)
414 #ifdef WIN32
415 return stat == 0;
416 #else
417 return stat != -1 && WIFEXITED (stat) && WEXITSTATUS (stat) == 0;
418 #endif
422 * did system() call execute the given command?
424 bool
425 system_executed (int stat)
427 #ifdef WIN32
428 return stat != -1;
429 #else
430 return stat != -1 && WEXITSTATUS (stat) != 127;
431 #endif
435 * Print an error message based on the status code returned by system().
437 const char *
438 system_error_message (int stat, struct gc_arena *gc)
440 struct buffer out = alloc_buf_gc (256, gc);
441 #ifdef WIN32
442 if (stat == -1)
443 buf_printf (&out, "external program did not execute -- ");
444 buf_printf (&out, "returned error code %d", stat);
445 #else
446 if (stat == -1)
447 buf_printf (&out, "external program fork failed");
448 else if (!WIFEXITED (stat))
449 buf_printf (&out, "external program did not exit normally");
450 else
452 const int cmd_ret = WEXITSTATUS (stat);
453 if (!cmd_ret)
454 buf_printf (&out, "external program exited normally");
455 else if (cmd_ret == 127)
456 buf_printf (&out, "could not execute external program");
457 else
458 buf_printf (&out, "external program exited with error status: %d", cmd_ret);
460 #endif
461 return (const char *)out.data;
465 * Wrapper around openvpn_execve
467 bool
468 openvpn_execve_check (const struct argv *a, const struct env_set *es, const unsigned int flags, const char *error_message)
470 struct gc_arena gc = gc_new ();
471 const int stat = openvpn_execve (a, es, flags);
472 int ret = false;
474 if (system_ok (stat))
475 ret = true;
476 else
478 if (error_message)
479 msg (((flags & S_FATAL) ? M_FATAL : M_WARN), "%s: %s",
480 error_message,
481 system_error_message (stat, &gc));
483 gc_free (&gc);
484 return ret;
487 bool
488 openvpn_execve_allowed (const unsigned int flags)
490 if (flags & S_SCRIPT)
491 return script_security >= SSEC_SCRIPTS;
492 else
493 return script_security >= SSEC_BUILT_IN;
496 #ifndef WIN32
498 * Run execve() inside a fork(). Designed to replicate the semantics of system() but
499 * in a safer way that doesn't require the invocation of a shell or the risks
500 * assocated with formatting and parsing a command line.
503 openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned int flags)
505 struct gc_arena gc = gc_new ();
506 int ret = -1;
508 if (a && a->argv[0])
510 #if defined(ENABLE_EXECVE)
511 if (openvpn_execve_allowed (flags))
513 if (script_method == SM_EXECVE)
515 const char *cmd = a->argv[0];
516 char *const *argv = a->argv;
517 char *const *envp = (char *const *)make_env_array (es, true, &gc);
518 pid_t pid;
520 pid = fork ();
521 if (pid == (pid_t)0) /* child side */
523 execve (cmd, argv, envp);
524 exit (127);
526 else if (pid < (pid_t)0) /* fork failed */
528 else /* parent side */
530 if (waitpid (pid, &ret, 0) != pid)
531 ret = -1;
534 else if (script_method == SM_SYSTEM)
536 ret = openvpn_system (argv_system_str (a), es, flags);
538 else
540 ASSERT (0);
543 else
545 msg (M_WARN, SCRIPT_SECURITY_WARNING);
547 #else
548 msg (M_WARN, "openvpn_execve: execve function not available");
549 #endif
551 else
553 msg (M_WARN, "openvpn_execve: called with empty argv");
556 gc_free (&gc);
557 return ret;
559 #endif
562 * Wrapper around the system() call.
565 openvpn_system (const char *command, const struct env_set *es, unsigned int flags)
567 #ifdef HAVE_SYSTEM
568 int ret;
570 perf_push (PERF_SCRIPT);
573 * add env_set to environment.
575 if (flags & S_SCRIPT)
576 env_set_add_to_environment (es);
579 /* debugging */
580 dmsg (D_SCRIPT, "SYSTEM[%u] '%s'", flags, command);
581 if (flags & S_SCRIPT)
582 env_set_print (D_SCRIPT, es);
585 * execute the command
587 ret = system (command);
589 /* debugging */
590 dmsg (D_SCRIPT, "SYSTEM return=%u", ret);
593 * remove env_set from environment
595 if (flags & S_SCRIPT)
596 env_set_remove_from_environment (es);
598 perf_pop ();
599 return ret;
601 #else
602 msg (M_FATAL, "Sorry but I can't execute the shell command '%s' because this operating system doesn't appear to support the system() call", command);
603 return -1; /* NOTREACHED */
604 #endif
608 * Initialize random number seed. random() is only used
609 * when "weak" random numbers are acceptable.
610 * OpenSSL routines are always used when cryptographically
611 * strong random numbers are required.
614 void
615 init_random_seed(void)
617 #ifdef HAVE_GETTIMEOFDAY
618 struct timeval tv;
620 if (!gettimeofday (&tv, NULL))
622 const unsigned int seed = (unsigned int) tv.tv_sec ^ tv.tv_usec;
623 srandom (seed);
625 #else /* HAVE_GETTIMEOFDAY */
626 const time_t current = time (NULL);
627 srandom ((unsigned int)current);
628 #endif /* HAVE_GETTIMEOFDAY */
631 /* thread-safe strerror */
633 const char *
634 strerror_ts (int errnum, struct gc_arena *gc)
636 #ifdef HAVE_STRERROR
637 struct buffer out = alloc_buf_gc (256, gc);
639 mutex_lock_static (L_STRERR);
640 buf_printf (&out, "%s", openvpn_strerror (errnum, gc));
641 mutex_unlock_static (L_STRERR);
642 return BSTR (&out);
643 #else
644 return "[error string unavailable]";
645 #endif
649 * Set environmental variable (int or string).
651 * On Posix, we use putenv for portability,
652 * and put up with its painful semantics
653 * that require all the support code below.
656 /* General-purpose environmental variable set functions */
658 static char *
659 construct_name_value (const char *name, const char *value, struct gc_arena *gc)
661 struct buffer out;
663 ASSERT (name);
664 if (!value)
665 value = "";
666 out = alloc_buf_gc (strlen (name) + strlen (value) + 2, gc);
667 buf_printf (&out, "%s=%s", name, value);
668 return BSTR (&out);
671 bool
672 deconstruct_name_value (const char *str, const char **name, const char **value, struct gc_arena *gc)
674 char *cp;
676 ASSERT (str);
677 ASSERT (name && value);
679 *name = cp = string_alloc (str, gc);
680 *value = NULL;
682 while ((*cp))
684 if (*cp == '=' && !*value)
686 *cp = 0;
687 *value = cp + 1;
689 ++cp;
691 return *name && *value;
694 static bool
695 env_string_equal (const char *s1, const char *s2)
697 int c1, c2;
698 ASSERT (s1);
699 ASSERT (s2);
701 while (true)
703 c1 = *s1++;
704 c2 = *s2++;
705 if (c1 == '=')
706 c1 = 0;
707 if (c2 == '=')
708 c2 = 0;
709 if (!c1 && !c2)
710 return true;
711 if (c1 != c2)
712 break;
714 return false;
717 static bool
718 remove_env_item (const char *str, const bool do_free, struct env_item **list)
720 struct env_item *current, *prev;
722 ASSERT (str);
723 ASSERT (list);
725 for (current = *list, prev = NULL; current != NULL; current = current->next)
727 if (env_string_equal (current->string, str))
729 if (prev)
730 prev->next = current->next;
731 else
732 *list = current->next;
733 if (do_free)
735 memset (current->string, 0, strlen (current->string));
736 free (current->string);
737 free (current);
739 return true;
741 prev = current;
743 return false;
746 static void
747 add_env_item (char *str, const bool do_alloc, struct env_item **list, struct gc_arena *gc)
749 struct env_item *item;
751 ASSERT (str);
752 ASSERT (list);
754 ALLOC_OBJ_GC (item, struct env_item, gc);
755 item->string = do_alloc ? string_alloc (str, gc): str;
756 item->next = *list;
757 *list = item;
760 /* struct env_set functions */
762 static bool
763 env_set_del_nolock (struct env_set *es, const char *str)
765 return remove_env_item (str, es->gc == NULL, &es->list);
768 static void
769 env_set_add_nolock (struct env_set *es, const char *str)
771 remove_env_item (str, es->gc == NULL, &es->list);
772 add_env_item ((char *)str, true, &es->list, es->gc);
775 struct env_set *
776 env_set_create (struct gc_arena *gc)
778 struct env_set *es;
779 mutex_lock_static (L_ENV_SET);
780 ALLOC_OBJ_CLEAR_GC (es, struct env_set, gc);
781 es->list = NULL;
782 es->gc = gc;
783 mutex_unlock_static (L_ENV_SET);
784 return es;
787 void
788 env_set_destroy (struct env_set *es)
790 mutex_lock_static (L_ENV_SET);
791 if (es && es->gc == NULL)
793 struct env_item *e = es->list;
794 while (e)
796 struct env_item *next = e->next;
797 free (e->string);
798 free (e);
799 e = next;
801 free (es);
803 mutex_unlock_static (L_ENV_SET);
806 bool
807 env_set_del (struct env_set *es, const char *str)
809 bool ret;
810 ASSERT (es);
811 ASSERT (str);
812 mutex_lock_static (L_ENV_SET);
813 ret = env_set_del_nolock (es, str);
814 mutex_unlock_static (L_ENV_SET);
815 return ret;
818 void
819 env_set_add (struct env_set *es, const char *str)
821 ASSERT (es);
822 ASSERT (str);
823 mutex_lock_static (L_ENV_SET);
824 env_set_add_nolock (es, str);
825 mutex_unlock_static (L_ENV_SET);
828 void
829 env_set_print (int msglevel, const struct env_set *es)
831 if (check_debug_level (msglevel))
833 const struct env_item *e;
834 int i;
836 if (es)
838 mutex_lock_static (L_ENV_SET);
839 e = es->list;
840 i = 0;
842 while (e)
844 if (env_safe_to_print (e->string))
845 msg (msglevel, "ENV [%d] '%s'", i, e->string);
846 ++i;
847 e = e->next;
849 mutex_unlock_static (L_ENV_SET);
854 void
855 env_set_inherit (struct env_set *es, const struct env_set *src)
857 const struct env_item *e;
859 ASSERT (es);
861 if (src)
863 mutex_lock_static (L_ENV_SET);
864 e = src->list;
865 while (e)
867 env_set_add_nolock (es, e->string);
868 e = e->next;
870 mutex_unlock_static (L_ENV_SET);
874 void
875 env_set_add_to_environment (const struct env_set *es)
877 if (es)
879 struct gc_arena gc = gc_new ();
880 const struct env_item *e;
882 mutex_lock_static (L_ENV_SET);
883 e = es->list;
885 while (e)
887 const char *name;
888 const char *value;
890 if (deconstruct_name_value (e->string, &name, &value, &gc))
891 setenv_str (NULL, name, value);
893 e = e->next;
895 mutex_unlock_static (L_ENV_SET);
896 gc_free (&gc);
900 void
901 env_set_remove_from_environment (const struct env_set *es)
903 if (es)
905 struct gc_arena gc = gc_new ();
906 const struct env_item *e;
908 mutex_lock_static (L_ENV_SET);
909 e = es->list;
911 while (e)
913 const char *name;
914 const char *value;
916 if (deconstruct_name_value (e->string, &name, &value, &gc))
917 setenv_del (NULL, name);
919 e = e->next;
921 mutex_unlock_static (L_ENV_SET);
922 gc_free (&gc);
926 #ifdef HAVE_PUTENV
928 /* companion functions to putenv */
930 static struct env_item *global_env = NULL; /* GLOBAL */
932 static void
933 manage_env (char *str)
935 remove_env_item (str, true, &global_env);
936 add_env_item (str, false, &global_env, NULL);
939 #endif
941 /* add/modify/delete environmental strings */
943 void
944 setenv_counter (struct env_set *es, const char *name, counter_type value)
946 char buf[64];
947 openvpn_snprintf (buf, sizeof(buf), counter_format, value);
948 setenv_str (es, name, buf);
951 void
952 setenv_int (struct env_set *es, const char *name, int value)
954 char buf[64];
955 openvpn_snprintf (buf, sizeof(buf), "%d", value);
956 setenv_str (es, name, buf);
959 void
960 setenv_unsigned (struct env_set *es, const char *name, unsigned int value)
962 char buf[64];
963 openvpn_snprintf (buf, sizeof(buf), "%u", value);
964 setenv_str (es, name, buf);
967 void
968 setenv_str (struct env_set *es, const char *name, const char *value)
970 setenv_str_ex (es, name, value, CC_NAME, 0, 0, CC_PRINT, 0, 0);
973 void
974 setenv_str_safe (struct env_set *es, const char *name, const char *value)
976 uint8_t b[64];
977 struct buffer buf;
978 buf_set_write (&buf, b, sizeof (b));
979 if (buf_printf (&buf, "OPENVPN_%s", name))
980 setenv_str (es, BSTR(&buf), value);
981 else
982 msg (M_WARN, "setenv_str_safe: name overflow");
985 void
986 setenv_del (struct env_set *es, const char *name)
988 ASSERT (name);
989 setenv_str (es, name, NULL);
992 void
993 setenv_str_ex (struct env_set *es,
994 const char *name,
995 const char *value,
996 const unsigned int name_include,
997 const unsigned int name_exclude,
998 const char name_replace,
999 const unsigned int value_include,
1000 const unsigned int value_exclude,
1001 const char value_replace)
1003 struct gc_arena gc = gc_new ();
1004 const char *name_tmp;
1005 const char *val_tmp = NULL;
1007 ASSERT (name && strlen (name) > 1);
1009 name_tmp = string_mod_const (name, name_include, name_exclude, name_replace, &gc);
1011 if (value)
1012 val_tmp = string_mod_const (value, value_include, value_exclude, value_replace, &gc);
1014 if (es)
1016 if (val_tmp)
1018 const char *str = construct_name_value (name_tmp, val_tmp, &gc);
1019 env_set_add (es, str);
1020 /*msg (M_INFO, "SETENV_ES '%s'", str);*/
1022 else
1023 env_set_del (es, name_tmp);
1025 else
1027 #if defined(WIN32)
1029 /*msg (M_INFO, "SetEnvironmentVariable '%s' '%s'", name_tmp, val_tmp ? val_tmp : "NULL");*/
1030 if (!SetEnvironmentVariable (name_tmp, val_tmp))
1031 msg (M_WARN | M_ERRNO, "SetEnvironmentVariable failed, name='%s', value='%s'",
1032 name_tmp,
1033 val_tmp ? val_tmp : "NULL");
1035 #elif defined(HAVE_PUTENV)
1037 char *str = construct_name_value (name_tmp, val_tmp, NULL);
1038 int status;
1040 mutex_lock_static (L_PUTENV);
1041 status = putenv (str);
1042 /*msg (M_INFO, "PUTENV '%s'", str);*/
1043 if (!status)
1044 manage_env (str);
1045 mutex_unlock_static (L_PUTENV);
1046 if (status)
1047 msg (M_WARN | M_ERRNO, "putenv('%s') failed", str);
1049 #endif
1052 gc_free (&gc);
1056 * Setenv functions that append an integer index to the name
1058 static const char *
1059 setenv_format_indexed_name (const char *name, const int i, struct gc_arena *gc)
1061 struct buffer out = alloc_buf_gc (strlen (name) + 16, gc);
1062 if (i >= 0)
1063 buf_printf (&out, "%s_%d", name, i);
1064 else
1065 buf_printf (&out, "%s", name);
1066 return BSTR (&out);
1069 void
1070 setenv_int_i (struct env_set *es, const char *name, const int value, const int i)
1072 struct gc_arena gc = gc_new ();
1073 const char *name_str = setenv_format_indexed_name (name, i, &gc);
1074 setenv_int (es, name_str, value);
1075 gc_free (&gc);
1078 void
1079 setenv_str_i (struct env_set *es, const char *name, const char *value, const int i)
1081 struct gc_arena gc = gc_new ();
1082 const char *name_str = setenv_format_indexed_name (name, i, &gc);
1083 setenv_str (es, name_str, value);
1084 gc_free (&gc);
1088 * taken from busybox networking/ifupdown.c
1090 unsigned int
1091 count_bits(unsigned int a)
1093 unsigned int result;
1094 result = (a & 0x55) + ((a >> 1) & 0x55);
1095 result = (result & 0x33) + ((result >> 2) & 0x33);
1096 return((result & 0x0F) + ((result >> 4) & 0x0F));
1100 count_netmask_bits(const char *dotted_quad)
1102 unsigned int result, a, b, c, d;
1103 /* Found a netmask... Check if it is dotted quad */
1104 if (sscanf(dotted_quad, "%u.%u.%u.%u", &a, &b, &c, &d) != 4)
1105 return -1;
1106 result = count_bits(a);
1107 result += count_bits(b);
1108 result += count_bits(c);
1109 result += count_bits(d);
1110 return ((int)result);
1114 * Go to sleep for n milliseconds.
1116 void
1117 sleep_milliseconds (unsigned int n)
1119 #ifdef WIN32
1120 Sleep (n);
1121 #else
1122 struct timeval tv;
1123 tv.tv_sec = n / 1000;
1124 tv.tv_usec = (n % 1000) * 1000;
1125 select (0, NULL, NULL, NULL, &tv);
1126 #endif
1130 * Go to sleep indefinitely.
1132 void
1133 sleep_until_signal (void)
1135 #ifdef WIN32
1136 ASSERT (0);
1137 #else
1138 select (0, NULL, NULL, NULL, NULL);
1139 #endif
1142 /* return true if filename can be opened for read */
1143 bool
1144 test_file (const char *filename)
1146 bool ret = false;
1147 if (filename)
1149 FILE *fp = fopen (filename, "r");
1150 if (fp)
1152 fclose (fp);
1153 ret = true;
1157 dmsg (D_TEST_FILE, "TEST FILE '%s' [%d]",
1158 filename ? filename : "UNDEF",
1159 ret);
1161 return ret;
1164 #ifdef USE_CRYPTO
1166 /* create a temporary filename in directory */
1167 const char *
1168 create_temp_filename (const char *directory, const char *prefix, struct gc_arena *gc)
1170 static unsigned int counter;
1171 struct buffer fname = alloc_buf_gc (256, gc);
1173 mutex_lock_static (L_CREATE_TEMP);
1174 ++counter;
1175 mutex_unlock_static (L_CREATE_TEMP);
1178 uint8_t rndbytes[16];
1179 const char *rndstr;
1181 prng_bytes (rndbytes, sizeof (rndbytes));
1182 rndstr = format_hex_ex (rndbytes, sizeof (rndbytes), 40, 0, NULL, gc);
1183 buf_printf (&fname, PACKAGE "_%s_%s.tmp", prefix, rndstr);
1186 return gen_path (directory, BSTR (&fname), gc);
1190 * Add a random string to first DNS label of hostname to prevent DNS caching.
1191 * For example, foo.bar.gov would be modified to <random-chars>.foo.bar.gov.
1192 * Of course, this requires explicit support in the DNS server.
1194 const char *
1195 hostname_randomize(const char *hostname, struct gc_arena *gc)
1197 const int n_rnd_bytes = 6;
1199 char *hst = string_alloc(hostname, gc);
1200 char *dot = strchr(hst, '.');
1202 if (dot)
1204 uint8_t rnd_bytes[n_rnd_bytes];
1205 const char *rnd_str;
1206 struct buffer hname = alloc_buf_gc (strlen(hostname)+sizeof(rnd_bytes)*2+4, gc);
1208 *dot++ = '\0';
1209 prng_bytes (rnd_bytes, sizeof (rnd_bytes));
1210 rnd_str = format_hex_ex (rnd_bytes, sizeof (rnd_bytes), 40, 0, NULL, gc);
1211 buf_printf(&hname, "%s-0x%s.%s", hst, rnd_str, dot);
1212 return BSTR(&hname);
1214 else
1215 return hostname;
1218 #else
1220 const char *
1221 hostname_randomize(const char *hostname, struct gc_arena *gc)
1223 msg (M_WARN, "WARNING: hostname randomization disabled when crypto support is not compiled");
1224 return hostname;
1227 #endif
1230 * Put a directory and filename together.
1232 const char *
1233 gen_path (const char *directory, const char *filename, struct gc_arena *gc)
1235 const char *safe_filename = string_mod_const (filename, CC_ALNUM|CC_UNDERBAR|CC_DASH|CC_DOT|CC_AT, 0, '_', gc);
1237 if (safe_filename
1238 && strcmp (safe_filename, ".")
1239 && strcmp (safe_filename, "..")
1240 #ifdef WIN32
1241 && win_safe_filename (safe_filename)
1242 #endif
1245 const size_t outsize = strlen(safe_filename) + (directory ? strlen (directory) : 0) + 16;
1246 struct buffer out = alloc_buf_gc (outsize, gc);
1247 char dirsep[2];
1249 dirsep[0] = OS_SPECIFIC_DIRSEP;
1250 dirsep[1] = '\0';
1252 if (directory)
1253 buf_printf (&out, "%s%s", directory, dirsep);
1254 buf_printf (&out, "%s", safe_filename);
1256 return BSTR (&out);
1258 else
1259 return NULL;
1262 /* delete a file, return true if succeeded */
1263 bool
1264 delete_file (const char *filename)
1266 #if defined(WIN32)
1267 return (DeleteFile (filename) != 0);
1268 #elif defined(HAVE_UNLINK)
1269 return (unlink (filename) == 0);
1270 #else
1271 return false;
1272 #endif
1275 bool
1276 absolute_pathname (const char *pathname)
1278 if (pathname)
1280 const int c = pathname[0];
1281 #ifdef WIN32
1282 return c == '\\' || (isalpha(c) && pathname[1] == ':' && pathname[2] == '\\');
1283 #else
1284 return c == '/';
1285 #endif
1287 else
1288 return false;
1291 #ifdef HAVE_GETPASS
1293 static FILE *
1294 open_tty (const bool write)
1296 FILE *ret;
1297 ret = fopen ("/dev/tty", write ? "w" : "r");
1298 if (!ret)
1299 ret = write ? stderr : stdin;
1300 return ret;
1303 static void
1304 close_tty (FILE *fp)
1306 if (fp != stderr && fp != stdin)
1307 fclose (fp);
1310 #endif
1313 * Get input from console
1315 bool
1316 get_console_input (const char *prompt, const bool echo, char *input, const int capacity)
1318 bool ret = false;
1319 ASSERT (prompt);
1320 ASSERT (input);
1321 ASSERT (capacity > 0);
1322 input[0] = '\0';
1324 #if defined(WIN32)
1325 return get_console_input_win32 (prompt, echo, input, capacity);
1326 #elif defined(HAVE_GETPASS)
1327 if (echo)
1329 FILE *fp;
1331 fp = open_tty (true);
1332 fprintf (fp, "%s", prompt);
1333 fflush (fp);
1334 close_tty (fp);
1336 fp = open_tty (false);
1337 if (fgets (input, capacity, fp) != NULL)
1339 chomp (input);
1340 ret = true;
1342 close_tty (fp);
1344 else
1346 char *gp = getpass (prompt);
1347 if (gp)
1349 strncpynt (input, gp, capacity);
1350 memset (gp, 0, strlen (gp));
1351 ret = true;
1354 #else
1355 msg (M_FATAL, "Sorry, but I can't get console input on this OS");
1356 #endif
1357 return ret;
1361 * Get and store a username/password
1364 bool
1365 get_user_pass (struct user_pass *up,
1366 const char *auth_file,
1367 const char *prefix,
1368 const unsigned int flags)
1370 struct gc_arena gc = gc_new ();
1372 if (!up->defined)
1374 const bool from_stdin = (!auth_file || !strcmp (auth_file, "stdin"));
1376 #ifdef ENABLE_MANAGEMENT
1378 * Get username/password from standard input?
1380 if (management
1381 && ((auth_file && streq (auth_file, "management")) || (from_stdin && (flags & GET_USER_PASS_MANAGEMENT)))
1382 && management_query_user_pass_enabled (management))
1384 if (!management_query_user_pass (management, up, prefix, flags))
1386 if ((flags & GET_USER_PASS_NOFATAL) != 0)
1387 return false;
1388 else
1389 msg (M_FATAL, "ERROR: could not read %s username/password/ok/string from management interface", prefix);
1392 else
1393 #endif
1395 * Get NEED_OK confirmation from the console
1397 if (flags & GET_USER_PASS_NEED_OK)
1399 struct buffer user_prompt = alloc_buf_gc (128, &gc);
1401 buf_printf (&user_prompt, "NEED-OK|%s|%s:", prefix, up->username);
1403 if (!get_console_input (BSTR (&user_prompt), true, up->password, USER_PASS_LEN))
1404 msg (M_FATAL, "ERROR: could not read %s ok-confirmation from stdin", prefix);
1406 if (!strlen (up->password))
1407 strcpy (up->password, "ok");
1411 * Get username/password from standard input?
1413 else if (from_stdin)
1415 struct buffer user_prompt = alloc_buf_gc (128, &gc);
1416 struct buffer pass_prompt = alloc_buf_gc (128, &gc);
1418 buf_printf (&user_prompt, "Enter %s Username:", prefix);
1419 buf_printf (&pass_prompt, "Enter %s Password:", prefix);
1421 if (!(flags & GET_USER_PASS_PASSWORD_ONLY))
1423 if (!get_console_input (BSTR (&user_prompt), true, up->username, USER_PASS_LEN))
1424 msg (M_FATAL, "ERROR: could not read %s username from stdin", prefix);
1425 if (strlen (up->username) == 0)
1426 msg (M_FATAL, "ERROR: %s username is empty", prefix);
1429 if (!get_console_input (BSTR (&pass_prompt), false, up->password, USER_PASS_LEN))
1430 msg (M_FATAL, "ERROR: could not not read %s password from stdin", prefix);
1432 else
1435 * Get username/password from a file.
1437 FILE *fp;
1439 #ifndef ENABLE_PASSWORD_SAVE
1441 * Unless ENABLE_PASSWORD_SAVE is defined, don't allow sensitive passwords
1442 * to be read from a file.
1444 if (flags & GET_USER_PASS_SENSITIVE)
1445 msg (M_FATAL, "Sorry, '%s' password cannot be read from a file", prefix);
1446 #endif
1448 warn_if_group_others_accessible (auth_file);
1450 fp = fopen (auth_file, "r");
1451 if (!fp)
1452 msg (M_ERR, "Error opening '%s' auth file: %s", prefix, auth_file);
1454 if (flags & GET_USER_PASS_PASSWORD_ONLY)
1456 if (fgets (up->password, USER_PASS_LEN, fp) == NULL)
1457 msg (M_FATAL, "Error reading password from %s authfile: %s",
1458 prefix,
1459 auth_file);
1461 else
1463 if (fgets (up->username, USER_PASS_LEN, fp) == NULL
1464 || fgets (up->password, USER_PASS_LEN, fp) == NULL)
1465 msg (M_FATAL, "Error reading username and password (must be on two consecutive lines) from %s authfile: %s",
1466 prefix,
1467 auth_file);
1470 fclose (fp);
1472 chomp (up->username);
1473 chomp (up->password);
1475 if (!(flags & GET_USER_PASS_PASSWORD_ONLY) && strlen (up->username) == 0)
1476 msg (M_FATAL, "ERROR: username from %s authfile '%s' is empty", prefix, auth_file);
1479 string_mod (up->username, CC_PRINT, CC_CRLF, 0);
1480 string_mod (up->password, CC_PRINT, CC_CRLF, 0);
1482 up->defined = true;
1485 #if 0
1486 msg (M_INFO, "GET_USER_PASS %s u='%s' p='%s'", prefix, up->username, up->password);
1487 #endif
1489 gc_free (&gc);
1491 return true;
1494 #if AUTO_USERID
1496 static const char *
1497 get_platform_prefix (void)
1499 #if defined(TARGET_LINUX)
1500 return "L";
1501 #elif defined(TARGET_SOLARIS)
1502 return "S";
1503 #elif defined(TARGET_OPENBSD)
1504 return "O";
1505 #elif defined(TARGET_DARWIN)
1506 return "M";
1507 #elif defined(TARGET_NETBSD)
1508 return "N";
1509 #elif defined(TARGET_FREEBSD)
1510 return "F";
1511 #elif defined(WIN32)
1512 return "W";
1513 #else
1514 return "X";
1515 #endif
1518 void
1519 get_user_pass_auto_userid (struct user_pass *up, const char *tag)
1521 struct gc_arena gc = gc_new ();
1522 MD5_CTX ctx;
1523 struct buffer buf;
1524 uint8_t macaddr[6];
1525 static uint8_t digest [MD5_DIGEST_LENGTH];
1526 static const uint8_t hashprefix[] = "AUTO_USERID_DIGEST";
1528 CLEAR (*up);
1529 buf_set_write (&buf, (uint8_t*)up->username, USER_PASS_LEN);
1530 buf_printf (&buf, "%s", get_platform_prefix ());
1531 if (get_default_gateway_mac_addr (macaddr))
1533 dmsg (D_AUTO_USERID, "GUPAU: macaddr=%s", format_hex_ex (macaddr, sizeof (macaddr), 0, 1, ":", &gc));
1534 MD5_Init (&ctx);
1535 MD5_Update (&ctx, hashprefix, sizeof (hashprefix) - 1);
1536 MD5_Update (&ctx, macaddr, sizeof (macaddr));
1537 MD5_Final (digest, &ctx);
1538 buf_printf (&buf, "%s", format_hex_ex (digest, sizeof (digest), 0, 256, " ", &gc));
1540 else
1542 buf_printf (&buf, "UNKNOWN");
1544 if (tag && strcmp (tag, "stdin"))
1545 buf_printf (&buf, "-%s", tag);
1546 up->defined = true;
1547 gc_free (&gc);
1549 dmsg (D_AUTO_USERID, "GUPAU: AUTO_USERID: '%s'", up->username);
1552 #endif
1554 void
1555 purge_user_pass (struct user_pass *up, const bool force)
1557 const bool nocache = up->nocache;
1558 if (nocache || force)
1560 CLEAR (*up);
1561 up->nocache = nocache;
1563 else
1565 msg (M_WARN, "WARNING: this configuration may cache passwords in memory -- use the auth-nocache option to prevent this");
1570 * Process string received by untrusted peer before
1571 * printing to console or log file.
1573 * Assumes that string has been null terminated.
1575 const char *
1576 safe_print (const char *str, struct gc_arena *gc)
1578 return string_mod_const (str, CC_PRINT, CC_CRLF, '.', gc);
1581 static bool
1582 is_password_env_var (const char *str)
1584 return (strncmp (str, "password", 8) == 0);
1587 bool
1588 env_allowed (const char *str)
1590 return (script_security >= SSEC_PW_ENV || !is_password_env_var (str));
1593 bool
1594 env_safe_to_print (const char *str)
1596 #ifndef UNSAFE_DEBUG
1597 if (is_password_env_var (str))
1598 return false;
1599 #endif
1600 return true;
1603 /* Make arrays of strings */
1605 const char **
1606 make_env_array (const struct env_set *es,
1607 const bool check_allowed,
1608 struct gc_arena *gc)
1610 char **ret = NULL;
1611 struct env_item *e = NULL;
1612 int i = 0, n = 0;
1614 /* figure length of es */
1615 if (es)
1617 for (e = es->list; e != NULL; e = e->next)
1618 ++n;
1621 /* alloc return array */
1622 ALLOC_ARRAY_CLEAR_GC (ret, char *, n+1, gc);
1624 /* fill return array */
1625 if (es)
1627 i = 0;
1628 for (e = es->list; e != NULL; e = e->next)
1630 if (!check_allowed || env_allowed (e->string))
1632 ASSERT (i < n);
1633 ret[i++] = e->string;
1638 ret[i] = NULL;
1639 return (const char **)ret;
1642 const char **
1643 make_arg_array (const char *first, const char *parms, struct gc_arena *gc)
1645 char **ret = NULL;
1646 int base = 0;
1647 const int max_parms = MAX_PARMS + 2;
1648 int n = 0;
1650 /* alloc return array */
1651 ALLOC_ARRAY_CLEAR_GC (ret, char *, max_parms, gc);
1653 /* process first parameter, if provided */
1654 if (first)
1656 ret[base++] = string_alloc (first, gc);
1659 if (parms)
1661 n = parse_line (parms, &ret[base], max_parms - base - 1, "make_arg_array", 0, M_WARN, gc);
1662 ASSERT (n >= 0 && n + base + 1 <= max_parms);
1664 ret[base + n] = NULL;
1666 return (const char **)ret;
1669 #if ENABLE_INLINE_FILES
1670 static const char **
1671 make_inline_array (const char *str, struct gc_arena *gc)
1673 char line[OPTION_LINE_SIZE];
1674 struct buffer buf;
1675 int len = 0;
1676 char **ret = NULL;
1677 int i = 0;
1679 buf_set_read (&buf, (const uint8_t *) str, strlen (str));
1680 while (buf_parse (&buf, '\n', line, sizeof (line)))
1681 ++len;
1683 /* alloc return array */
1684 ALLOC_ARRAY_CLEAR_GC (ret, char *, len + 1, gc);
1686 buf_set_read (&buf, (const uint8_t *) str, strlen(str));
1687 while (buf_parse (&buf, '\n', line, sizeof (line)))
1689 chomp (line);
1690 ASSERT (i < len);
1691 ret[i] = string_alloc (skip_leading_whitespace (line), gc);
1692 ++i;
1694 ASSERT (i <= len);
1695 ret[i] = NULL;
1696 return (const char **)ret;
1698 #endif
1700 static const char **
1701 make_arg_copy (char **p, struct gc_arena *gc)
1703 char **ret = NULL;
1704 const int len = string_array_len ((const char **)p);
1705 const int max_parms = len + 1;
1706 int i;
1708 /* alloc return array */
1709 ALLOC_ARRAY_CLEAR_GC (ret, char *, max_parms, gc);
1711 for (i = 0; i < len; ++i)
1712 ret[i] = p[i];
1714 return (const char **)ret;
1717 const char **
1718 make_extended_arg_array (char **p, struct gc_arena *gc)
1720 const int argc = string_array_len ((const char **)p);
1721 #if ENABLE_INLINE_FILES
1722 if (!strcmp (p[0], INLINE_FILE_TAG) && argc == 2)
1723 return make_inline_array (p[1], gc);
1724 else
1725 #endif
1726 if (argc == 0)
1727 return make_arg_array (NULL, NULL, gc);
1728 else if (argc == 1)
1729 return make_arg_array (p[0], NULL, gc);
1730 else if (argc == 2)
1731 return make_arg_array (p[0], p[1], gc);
1732 else
1733 return make_arg_copy (p, gc);
1736 void
1737 openvpn_sleep (const int n)
1739 #ifdef ENABLE_MANAGEMENT
1740 if (management)
1742 management_event_loop_n_seconds (management, n);
1743 return;
1745 #endif
1746 sleep (n);
1750 * Return the next largest power of 2
1751 * or u if u is a power of 2.
1753 size_t
1754 adjust_power_of_2 (size_t u)
1756 size_t ret = 1;
1758 while (ret < u)
1760 ret <<= 1;
1761 ASSERT (ret > 0);
1764 return ret;
1768 * A printf-like function (that only recognizes a subset of standard printf
1769 * format operators) that prints arguments to an argv list instead
1770 * of a standard string. This is used to build up argv arrays for passing
1771 * to execve.
1774 void
1775 argv_init (struct argv *a)
1777 a->capacity = 0;
1778 a->argc = 0;
1779 a->argv = NULL;
1780 a->system_str = NULL;
1783 struct argv
1784 argv_new (void)
1786 struct argv ret;
1787 argv_init (&ret);
1788 return ret;
1791 void
1792 argv_reset (struct argv *a)
1794 size_t i;
1795 for (i = 0; i < a->argc; ++i)
1796 free (a->argv[i]);
1797 free (a->argv);
1798 free (a->system_str);
1799 argv_init (a);
1802 static void
1803 argv_extend (struct argv *a, const size_t newcap)
1805 if (newcap > a->capacity)
1807 char **newargv;
1808 size_t i;
1809 ALLOC_ARRAY_CLEAR (newargv, char *, newcap);
1810 for (i = 0; i < a->argc; ++i)
1811 newargv[i] = a->argv[i];
1812 free (a->argv);
1813 a->argv = newargv;
1814 a->capacity = newcap;
1818 static void
1819 argv_grow (struct argv *a, const size_t add)
1821 const size_t newargc = a->argc + add + 1;
1822 ASSERT (newargc > a->argc);
1823 argv_extend (a, adjust_power_of_2 (newargc));
1826 static void
1827 argv_append (struct argv *a, char *str) /* str must have been malloced or be NULL */
1829 argv_grow (a, 1);
1830 a->argv[a->argc++] = str;
1833 static void
1834 argv_system_str_append (struct argv *a, const char *str, const bool enquote)
1836 if (str)
1838 char *newstr;
1840 /* compute length of new system_str */
1841 size_t l = strlen (str) + 1; /* space for new string plus trailing '\0' */
1842 if (a->system_str)
1843 l += strlen (a->system_str) + 1; /* space for existing string + space (" ") separator */
1844 if (enquote)
1845 l += 2; /* space for two quotes */
1847 /* build new system_str */
1848 newstr = (char *) malloc (l);
1849 newstr[0] = '\0';
1850 check_malloc_return (newstr);
1851 if (a->system_str)
1853 strcpy (newstr, a->system_str);
1854 strcat (newstr, " ");
1856 if (enquote)
1857 strcat (newstr, "\"");
1858 strcat (newstr, str);
1859 if (enquote)
1860 strcat (newstr, "\"");
1861 free (a->system_str);
1862 a->system_str = newstr;
1866 static char *
1867 argv_extract_cmd_name (const char *path)
1869 if (path)
1871 const char *bn = openvpn_basename (path);
1872 if (bn)
1874 char *ret = string_alloc (bn, NULL);
1875 char *dot = strrchr (ret, '.');
1876 if (dot)
1877 *dot = '\0';
1878 if (ret[0] != '\0')
1879 return ret;
1882 return NULL;
1885 const char *
1886 argv_system_str (const struct argv *a)
1888 return a->system_str;
1891 struct argv
1892 argv_clone (const struct argv *a, const size_t headroom)
1894 struct argv r;
1895 size_t i;
1897 argv_init (&r);
1898 for (i = 0; i < headroom; ++i)
1899 argv_append (&r, NULL);
1900 if (a)
1902 for (i = 0; i < a->argc; ++i)
1903 argv_append (&r, string_alloc (a->argv[i], NULL));
1904 r.system_str = string_alloc (a->system_str, NULL);
1906 return r;
1909 struct argv
1910 argv_insert_head (const struct argv *a, const char *head)
1912 struct argv r;
1913 char *s;
1915 r = argv_clone (a, 1);
1916 r.argv[0] = string_alloc (head, NULL);
1917 s = r.system_str;
1918 r.system_str = string_alloc (head, NULL);
1919 if (s)
1921 argv_system_str_append (&r, s, false);
1922 free (s);
1924 return r;
1927 char *
1928 argv_term (const char **f)
1930 const char *p = *f;
1931 const char *term = NULL;
1932 size_t termlen = 0;
1934 if (*p == '\0')
1935 return NULL;
1937 while (true)
1939 const int c = *p;
1940 if (c == '\0')
1941 break;
1942 if (term)
1944 if (!isspace (c))
1945 ++termlen;
1946 else
1947 break;
1949 else
1951 if (!isspace (c))
1953 term = p;
1954 termlen = 1;
1957 ++p;
1959 *f = p;
1961 if (term)
1963 char *ret;
1964 ASSERT (termlen > 0);
1965 ret = malloc (termlen + 1);
1966 check_malloc_return (ret);
1967 memcpy (ret, term, termlen);
1968 ret[termlen] = '\0';
1969 return ret;
1971 else
1972 return NULL;
1975 const char *
1976 argv_str (const struct argv *a, struct gc_arena *gc, const unsigned int flags)
1978 if (a->argv)
1979 return print_argv ((const char **)a->argv, gc, flags);
1980 else
1981 return "";
1984 void
1985 argv_msg (const int msglev, const struct argv *a)
1987 struct gc_arena gc = gc_new ();
1988 msg (msglev, "%s", argv_str (a, &gc, 0));
1989 gc_free (&gc);
1992 void
1993 argv_msg_prefix (const int msglev, const struct argv *a, const char *prefix)
1995 struct gc_arena gc = gc_new ();
1996 msg (msglev, "%s: %s", prefix, argv_str (a, &gc, 0));
1997 gc_free (&gc);
2000 void
2001 argv_printf (struct argv *a, const char *format, ...)
2003 va_list arglist;
2004 va_start (arglist, format);
2005 argv_printf_arglist (a, format, 0, arglist);
2006 va_end (arglist);
2009 void
2010 argv_printf_cat (struct argv *a, const char *format, ...)
2012 va_list arglist;
2013 va_start (arglist, format);
2014 argv_printf_arglist (a, format, APA_CAT, arglist);
2015 va_end (arglist);
2018 void
2019 argv_printf_arglist (struct argv *a, const char *format, const unsigned int flags, va_list arglist)
2021 struct gc_arena gc = gc_new ();
2022 char *term;
2023 const char *f = format;
2025 if (!(flags & APA_CAT))
2026 argv_reset (a);
2027 argv_extend (a, 1); /* ensure trailing NULL */
2029 while ((term = argv_term (&f)) != NULL)
2031 if (term[0] == '%')
2033 if (!strcmp (term, "%s"))
2035 char *s = va_arg (arglist, char *);
2036 if (!s)
2037 s = "";
2038 argv_append (a, string_alloc (s, NULL));
2039 argv_system_str_append (a, s, true);
2041 else if (!strcmp (term, "%sc"))
2043 char *s = va_arg (arglist, char *);
2044 if (s)
2046 int nparms;
2047 char *parms[MAX_PARMS+1];
2048 int i;
2050 nparms = parse_line (s, parms, MAX_PARMS, "SCRIPT-ARGV", 0, D_ARGV_PARSE_CMD, &gc);
2051 if (nparms)
2053 for (i = 0; i < nparms; ++i)
2054 argv_append (a, string_alloc (parms[i], NULL));
2056 else
2057 argv_append (a, string_alloc (s, NULL));
2059 argv_system_str_append (a, s, false);
2061 else
2063 argv_append (a, string_alloc ("", NULL));
2064 argv_system_str_append (a, "echo", false);
2067 else if (!strcmp (term, "%d"))
2069 char numstr[64];
2070 openvpn_snprintf (numstr, sizeof (numstr), "%d", va_arg (arglist, int));
2071 argv_append (a, string_alloc (numstr, NULL));
2072 argv_system_str_append (a, numstr, false);
2074 else if (!strcmp (term, "%u"))
2076 char numstr[64];
2077 openvpn_snprintf (numstr, sizeof (numstr), "%u", va_arg (arglist, unsigned int));
2078 argv_append (a, string_alloc (numstr, NULL));
2079 argv_system_str_append (a, numstr, false);
2081 else if (!strcmp (term, "%s/%d"))
2083 char numstr[64];
2084 char *s = va_arg (arglist, char *);
2086 if (!s)
2087 s = "";
2089 openvpn_snprintf (numstr, sizeof (numstr), "%d", va_arg (arglist, int));
2092 const size_t len = strlen(s) + strlen(numstr) + 2;
2093 char *combined = (char *) malloc (len);
2094 check_malloc_return (combined);
2096 strcpy (combined, s);
2097 strcat (combined, "/");
2098 strcat (combined, numstr);
2099 argv_append (a, combined);
2100 argv_system_str_append (a, combined, false);
2103 else if (!strcmp (term, "%s%sc"))
2105 char *s1 = va_arg (arglist, char *);
2106 char *s2 = va_arg (arglist, char *);
2107 char *combined;
2108 char *cmd_name;
2110 if (!s1) s1 = "";
2111 if (!s2) s2 = "";
2112 combined = (char *) malloc (strlen(s1) + strlen(s2) + 1);
2113 check_malloc_return (combined);
2114 strcpy (combined, s1);
2115 strcat (combined, s2);
2116 argv_append (a, combined);
2118 cmd_name = argv_extract_cmd_name (combined);
2119 if (cmd_name)
2121 argv_system_str_append (a, cmd_name, false);
2122 free (cmd_name);
2125 else
2126 ASSERT (0);
2127 free (term);
2129 else
2131 argv_append (a, term);
2132 argv_system_str_append (a, term, false);
2135 gc_free (&gc);
2138 #ifdef ARGV_TEST
2139 void
2140 argv_test (void)
2142 struct gc_arena gc = gc_new ();
2143 const char *s;
2145 struct argv a;
2147 argv_init (&a);
2148 argv_printf (&a, "%sc foo bar %s", "c:\\\\src\\\\test\\\\jyargs.exe", "foo bar");
2149 argv_msg_prefix (M_INFO, &a, "ARGV");
2150 msg (M_INFO, "ARGV-S: %s", argv_system_str(&a));
2151 //openvpn_execve_check (&a, NULL, 0, "command failed");
2153 argv_printf (&a, "%sc %s %s", "c:\\\\src\\\\test files\\\\batargs.bat", "foo", "bar");
2154 argv_msg_prefix (M_INFO, &a, "ARGV");
2155 msg (M_INFO, "ARGV-S: %s", argv_system_str(&a));
2156 //openvpn_execve_check (&a, NULL, 0, "command failed");
2158 argv_printf (&a, "%s%sc foo bar %s %s/%d %d %u", "/foo", "/bar.exe", "one two", "1.2.3.4", 24, -69, 96);
2159 argv_msg_prefix (M_INFO, &a, "ARGV");
2160 msg (M_INFO, "ARGV-S: %s", argv_system_str(&a));
2161 //openvpn_execve_check (&a, NULL, 0, "command failed");
2163 argv_printf (&a, "this is a %s test of int %d unsigned %u", "FOO", -69, 42);
2164 s = argv_str (&a, &gc, PA_BRACKET);
2165 printf ("PF: %s\n", s);
2166 printf ("PF-S: %s\n", argv_system_str(&a));
2169 struct argv b = argv_insert_head (&a, "MARK");
2170 s = argv_str (&b, &gc, PA_BRACKET);
2171 printf ("PF: %s\n", s);
2172 printf ("PF-S: %s\n", argv_system_str(&b));
2173 argv_reset (&b);
2176 argv_printf (&a, "%sc foo bar %d", "\"multi term\" command following \\\"spaces", 99);
2177 s = argv_str (&a, &gc, PA_BRACKET);
2178 printf ("PF: %s\n", s);
2179 printf ("PF-S: %s\n", argv_system_str(&a));
2180 argv_reset (&a);
2182 s = argv_str (&a, &gc, PA_BRACKET);
2183 printf ("PF: %s\n", s);
2184 printf ("PF-S: %s\n", argv_system_str(&a));
2185 argv_reset (&a);
2187 argv_printf (&a, "foo bar %d", 99);
2188 argv_printf_cat (&a, "bar %d foo %sc", 42, "nonesuch");
2189 argv_printf_cat (&a, "cool %s %d u %s/%d end", "frood", 4, "hello", 7);
2190 s = argv_str (&a, &gc, PA_BRACKET);
2191 printf ("PF: %s\n", s);
2192 printf ("PF-S: %s\n", argv_system_str(&a));
2193 argv_reset (&a);
2195 #if 0
2197 char line[512];
2198 while (fgets (line, sizeof(line), stdin) != NULL)
2200 char *term;
2201 const char *f = line;
2202 int i = 0;
2204 while ((term = argv_term (&f)) != NULL)
2206 printf ("[%d] '%s'\n", i, term);
2207 ++i;
2208 free (term);
2212 #endif
2214 argv_reset (&a);
2215 gc_free (&gc);
2217 #endif
2219 const char *
2220 openvpn_basename (const char *path)
2222 const char *ret;
2223 const int dirsep = OS_SPECIFIC_DIRSEP;
2225 if (path)
2227 ret = strrchr (path, dirsep);
2228 if (ret && *ret)
2229 ++ret;
2230 else
2231 ret = path;
2232 if (*ret)
2233 return ret;
2235 return NULL;