Beispiel #1
0
/*
 * 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;
}
Beispiel #2
0
/*
 * 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;
}
Beispiel #3
0
/*
 * 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;
}