Exemplo n.º 1
0
static void
plugin_common_open (struct plugin_common *pc,
		    const struct plugin_option_list *list,
		    struct plugin_return *pr,
		    const struct env_set *es,
		    const int init_point)
{
  struct gc_arena gc = gc_new ();
  int i;
  const char **envp;

  envp = make_env_array (es, false, &gc);

  if (pr)
    plugin_return_init (pr);

  for (i = 0; i < pc->n; ++i)
    {
      plugin_open_item (&pc->plugins[i],
			&list->plugins[i],
			pr ? &pr->list[i] : NULL,
			envp,
			init_point);
    }

  if (pr)
    pr->n = i;

  gc_free (&gc);
}
Exemplo n.º 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;
}
Exemplo n.º 3
0
int
plugin_call_ssl (const struct plugin_list *pl,
	     const int type,
	     const struct argv *av,
	     struct plugin_return *pr,
	     struct env_set *es
#ifdef USE_SSL
             , int certdepth,
	     x509_cert_t *current_cert
#endif
	    )
{
  if (pr)
    plugin_return_init (pr);

  if (plugin_defined (pl, type))
    {
      struct gc_arena gc = gc_new ();
      int i;
      const char **envp;
      const int n = plugin_n (pl);
      bool success = false;
      bool error = false;
      bool deferred = false;
      
      setenv_del (es, "script_type");
      envp = make_env_array (es, false, &gc);

      for (i = 0; i < n; ++i)
	{
	  const int status = plugin_call_item (&pl->common->plugins[i],
					       pl->per_client.per_client_context[i],
					       type,
					       av,
					       pr ? &pr->list[i] : NULL,
					       envp
#ifdef USE_SSL
					       ,certdepth,
					       current_cert
#endif
					      );
	  switch (status)
	    {
	    case OPENVPN_PLUGIN_FUNC_SUCCESS:
	      success = true;
	      break;
	    case OPENVPN_PLUGIN_FUNC_DEFERRED:
	      deferred = true;
	      break;
	    default:
	      error = true;
	      break;
	    }
	}

      if (pr)
	pr->n = i;

      gc_free (&gc);

      if (type == OPENVPN_PLUGIN_ENABLE_PF && success)
	return OPENVPN_PLUGIN_FUNC_SUCCESS;
      else if (error)
	return OPENVPN_PLUGIN_FUNC_ERROR;
      else if (deferred)
	return OPENVPN_PLUGIN_FUNC_DEFERRED;
    }

  return OPENVPN_PLUGIN_FUNC_SUCCESS;
}
Exemplo n.º 4
0
/*
 * Run execve() inside a fork(), duping stdout.  Designed to replicate the semantics of popen() 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_popen (const struct argv *a,  const struct env_set *es)
{
  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 (script_security >= SSEC_BUILT_IN)
	{
	      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;
	      int pipe_stdout[2];

              if (pipe (pipe_stdout) == 0) {
		      pid = fork ();
		      if (pid == (pid_t)0) /* child side */
			{
			  close (pipe_stdout[0]);  /* Close read end */
			  dup2 (pipe_stdout[1],1);
			  execve (cmd, argv, envp);
			  exit (127);
			}
		      else if (pid > (pid_t)0) /* parent side */
			{
                          int status = 0;

                          close (pipe_stdout[1]); /* Close write end */
                          waitpid(pid, &status, 0);
                          ret = pipe_stdout[0];
			}
		      else /* fork failed */
			{
                          close (pipe_stdout[0]);
                          close (pipe_stdout[1]);
			  msg (M_ERR, "openvpn_popen: unable to fork %s", cmd);
			}
	      }
	      else {
                msg (M_WARN, "openvpn_popen: unable to create stdout pipe for %s", cmd);
                ret = -1;
	      }
	}
      else if (!warn_shown && (script_security < SSEC_SCRIPTS))
	{
	  msg (M_WARN, SCRIPT_SECURITY_WARNING);
          warn_shown = true;
	}
#else
      msg (M_WARN, "openvpn_popen: execve function not available");
#endif
    }
  else
    {
      msg (M_FATAL, "openvpn_popen: called with empty argv");
    }

  gc_free (&gc);
  return ret;
}