/* * Attempt to simulate fork/execve on Windows */ int openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned int flags) { int ret = -1; static bool exec_warn = false; if (a && a->argv[0]) { if (openvpn_execve_allowed (flags)) { struct gc_arena gc = gc_new (); STARTUPINFOW start_info; PROCESS_INFORMATION proc_info; char *env = env_block (es); WCHAR *cl = wide_cmd_line (a, &gc); WCHAR *cmd = wide_string (a->argv[0], &gc); /* this allows console programs to run, and is ignored otherwise */ DWORD proc_flags = CREATE_NO_WINDOW; CLEAR (start_info); CLEAR (proc_info); /* fill in STARTUPINFO struct */ GetStartupInfoW(&start_info); start_info.cb = sizeof(start_info); start_info.dwFlags = STARTF_USESHOWWINDOW; start_info.wShowWindow = SW_HIDE; if (CreateProcessW (cmd, cl, NULL, NULL, FALSE, proc_flags, env, NULL, &start_info, &proc_info)) { DWORD exit_status = 0; CloseHandle (proc_info.hThread); WaitForSingleObject (proc_info.hProcess, INFINITE); if (GetExitCodeProcess (proc_info.hProcess, &exit_status)) ret = (int)exit_status; else msg (M_WARN|M_ERRNO, "openvpn_execve: GetExitCodeProcess %S failed", cmd); CloseHandle (proc_info.hProcess); } else { msg (M_WARN|M_ERRNO, "openvpn_execve: CreateProcess %S failed", cmd); } free (env); gc_free (&gc); } else if (!exec_warn && (script_security < SSEC_SCRIPTS)) { msg (M_WARN, SCRIPT_SECURITY_WARNING); exec_warn = true; } } else { msg (M_WARN, "openvpn_execve: called with empty argv"); } return ret; }
/* * Run execve() inside a fork(). Designed to replicate the semantics of system() but * in a safer way that doesn't require the invocation of a shell or the risks * assocated with formatting and parsing a command line. */ int openvpn_execve(const struct argv *a, const struct env_set *es, const unsigned int flags) { struct gc_arena gc = gc_new(); int ret = -1; static bool warn_shown = false; if (a && a->argv[0]) { #if defined(ENABLE_FEATURE_EXECVE) if (openvpn_execve_allowed(flags)) { const char *cmd = a->argv[0]; char *const *argv = a->argv; char *const *envp = (char *const *)make_env_array(es, true, &gc); pid_t pid; pid = fork(); if (pid == (pid_t)0) /* child side */ { execve(cmd, argv, envp); exit(127); } else if (pid < (pid_t)0) /* fork failed */ { msg(M_ERR, "openvpn_execve: unable to fork"); } else /* parent side */ { if (waitpid(pid, &ret, 0) != pid) { ret = -1; } } } else if (!warn_shown && (script_security() < SSEC_SCRIPTS)) { msg(M_WARN, SCRIPT_SECURITY_WARNING); warn_shown = true; } #else /* if defined(ENABLE_FEATURE_EXECVE) */ msg(M_WARN, "openvpn_execve: execve function not available"); #endif /* if defined(ENABLE_FEATURE_EXECVE) */ } else { msg(M_FATAL, "openvpn_execve: called with empty argv"); } gc_free(&gc); return ret; }
/* * Attempt to simulate fork/execve on Windows */ int openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned int flags) { int ret = -1; if (a && a->argv[0]) { if (openvpn_execve_allowed (flags)) { if (script_method == SM_EXECVE) { STARTUPINFO start_info; PROCESS_INFORMATION proc_info; char *env = env_block (es); char *cl = cmd_line (a); char *cmd = a->argv[0]; CLEAR (start_info); CLEAR (proc_info); /* fill in STARTUPINFO struct */ GetStartupInfo(&start_info); start_info.cb = sizeof(start_info); start_info.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW; start_info.wShowWindow = SW_HIDE; start_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE); start_info.hStdOutput = start_info.hStdError = GetStdHandle(STD_OUTPUT_HANDLE); if (CreateProcess (cmd, cl, NULL, NULL, FALSE, 0, env, NULL, &start_info, &proc_info)) { DWORD exit_status = 0; CloseHandle (proc_info.hThread); WaitForSingleObject (proc_info.hProcess, INFINITE); if (GetExitCodeProcess (proc_info.hProcess, &exit_status)) ret = (int)exit_status; else msg (M_WARN|M_ERRNO, "openvpn_execve: GetExitCodeProcess %s failed", cmd); CloseHandle (proc_info.hProcess); } else { msg (M_WARN|M_ERRNO, "openvpn_execve: CreateProcess %s failed", cmd); } free (cl); free (env); } else if (script_method == SM_SYSTEM) { configure_win_path (); ret = openvpn_system (argv_system_str (a), es, flags); } else { ASSERT (0); } } else { msg (M_WARN, SCRIPT_SECURITY_WARNING); } } else { msg (M_WARN, "openvpn_execve: called with empty argv"); } return ret; }