Ejemplo n.º 1
0
OPENVPN_EXPORT openvpn_plugin_handle_t
openvpn_plugin_open_v1 (unsigned int *type_mask, const char *argv[], const char *envp[])
{
  struct down_root_context *context;

  /*
   * Allocate our context
   */
  context = (struct down_root_context *) calloc (1, sizeof (struct down_root_context));
  if (!context)
    goto error;
  context->foreground_fd = -1;

  /*
   * Intercept the --up and --down callbacks
   */
  *type_mask = OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_UP) | OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_DOWN);

  /*
   * Make sure we have two string arguments: the first is the .so name,
   * the second is the script command.
   */
  if (string_array_len (argv) < 2)
    {
      fprintf (stderr, "DOWN-ROOT: need down script command\n");
      goto error;
    }

  /*
   * Save our argument in context
   */
  context->command = build_command_line (&argv[1]);

  /*
   * Get verbosity level from environment
   */
  {
    const char *verb_string = get_env ("verb", envp);
    if (verb_string)
      context->verb = atoi (verb_string);
  }

  return (openvpn_plugin_handle_t) context;

 error:
  free_context (context);
  return NULL;
}
Ejemplo n.º 2
0
OPENVPN_PLUGIN_DEF openvpn_plugin_handle_t OPENVPN_PLUGIN_FUNC(openvpn_plugin_open_v2)(
    unsigned int *type_mask, 
    const char *argv[],
    const char *envp[],
    struct openvpn_plugin_string_list **return_list)
{
    const char *verb_str = NULL;
    auth_http_plugin_context_t *context = NULL;

    if (curl_global_init(CURL_GLOBAL_ALL)) {
        PLUGIN_ERROR("Can not init curl.");
        return NULL;
    }

    /* Init logginig */
    verb_str = get_openvpn_env("verb", envp);
    if (verb_str)
        init_plugin_logging(atoi(verb_str));
    else
        init_plugin_logging(3);

    if (string_array_len(argv) < 2) {
        PLUGIN_ERROR("Missed path to file with settings.");
        goto error;
    }

     context = create_auth_http_plugin_context(argv[1]);
     if (!context)
        goto error;

    /* Intercept the --auth-user-pass-verify, --client-connect and --client-disconnect callback. */
    *type_mask = OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY)
               | OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_CLIENT_CONNECT)
               | OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_CLIENT_DISCONNECT);

    return (openvpn_plugin_handle_t)context;

error:
    if (context)
        free(context);
    clear_plugin_logging();
    curl_global_cleanup();
    return NULL;
}
Ejemplo n.º 3
0
OPENVPN_EXPORT openvpn_plugin_handle_t
openvpn_plugin_open_v1 (unsigned int *type_mask, const char *argv[], const char *envp[])
{
  pid_t pid;
  int fd[2];

  struct auth_pam_context *context;
  struct name_value_list name_value_list;

  const int base_parms = 2;

  /*
   * Allocate our context
   */
  context = (struct auth_pam_context *) calloc (1, sizeof (struct auth_pam_context));
  if (!context)
    goto error;
  context->foreground_fd = -1;

  /*
   * Intercept the --auth-user-pass-verify callback.
   */
  *type_mask = OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY);

  /*
   * Make sure we have two string arguments: the first is the .so name,
   * the second is the PAM service type.
   */
  if (string_array_len (argv) < base_parms)
    {
      fprintf (stderr, "AUTH-PAM: need PAM service parameter\n");
      goto error;
    }

  /*
   * See if we have optional name/value pairs to match against
   * PAM module queried fields in the conversation function.
   */
  name_value_list.len = 0;
  if (string_array_len (argv) > base_parms)
    {
      const int nv_len = string_array_len (argv) - base_parms;
      int i;

      if ((nv_len & 1) == 1 || (nv_len / 2) > N_NAME_VALUE)
	{
	  fprintf (stderr, "AUTH-PAM: bad name/value list length\n");
	  goto error;
	}

      name_value_list.len = nv_len / 2;
      for (i = 0; i < name_value_list.len; ++i)
	{
	  const int base = base_parms + i * 2;
	  name_value_list.data[i].name = argv[base];
	  name_value_list.data[i].value = argv[base+1];
	}
    }

  /*
   * Get verbosity level from environment
   */
  {
    const char *verb_string = get_env ("verb", envp);
    if (verb_string)
      context->verb = atoi (verb_string);
  }

  /*
   * Make a socket for foreground and background processes
   * to communicate.
   */
  if (socketpair (PF_UNIX, SOCK_DGRAM, 0, fd) == -1)
    {
      fprintf (stderr, "AUTH-PAM: socketpair call failed\n");
      goto error;
    }

  /*
   * Fork off the privileged process.  It will remain privileged
   * even after the foreground process drops its privileges.
   */
  pid = fork ();

  if (pid)
    {
      int status;

      /*
       * Foreground Process
       */

      context->background_pid = pid;

      /* close our copy of child's socket */
      close (fd[1]);

      /* don't let future subprocesses inherit child socket */
      if (fcntl (fd[0], F_SETFD, FD_CLOEXEC) < 0)
	fprintf (stderr, "AUTH-PAM: Set FD_CLOEXEC flag on socket file descriptor failed\n");

      /* wait for background child process to initialize */
      status = recv_control (fd[0]);
      if (status == RESPONSE_INIT_SUCCEEDED)
	{
	  context->foreground_fd = fd[0];
	  return (openvpn_plugin_handle_t) context;
	}
    }
  else
    {
      /*
       * Background Process
       */

      /* close all parent fds except our socket back to parent */
      close_fds_except (fd[1]);

      /* Ignore most signals (the parent will receive them) */
      set_signals ();

#ifdef DO_DAEMONIZE
      /* Daemonize if --daemon option is set. */
      daemonize (envp);
#endif

      /* execute the event loop */
      pam_server (fd[1], argv[1], context->verb, &name_value_list);

      close (fd[1]);

      exit (0);
      return 0; /* NOTREACHED */
    }

 error:
  if (context)
    free (context);
  return NULL;
}
Ejemplo n.º 4
0
/*
 * Background process -- runs with privilege.
 */
static void
down_root_server (const int fd, char *command, const char *argv[], const char *envp[], const int verb)
{
  const char *p[3];
  char *command_line = NULL;
  char *argv_cat = NULL;
  int i;

  /*
   * Do initialization
   */
  if (DEBUG (verb))
    fprintf (stderr, "DOWN-ROOT: BACKGROUND: INIT command='%s'\n", command);

  /*
   * Tell foreground that we initialized successfully
   */
  if (send_control (fd, RESPONSE_INIT_SUCCEEDED) == -1)
    {
      fprintf (stderr, "DOWN-ROOT: BACKGROUND: write error on response socket [1]\n");
      goto done;
    }

  /*
   * Build command line
   */
  if (string_array_len (argv) >= 2)
    argv_cat = build_command_line (&argv[1]);
  else
    argv_cat = build_command_line (NULL);
  p[0] = command;
  p[1] = argv_cat;
  p[2] = NULL;
  command_line = build_command_line (p);

  /*
   * Save envp in environment
   */
  for (i = 0; envp[i]; ++i)
    {
      putenv ((char *)envp[i]);
    }

  /*
   * Event loop
   */
  while (1)
    {
      int command_code;
      int status;

      /* get a command from foreground process */
      command_code = recv_control (fd);

      if (DEBUG (verb))
	fprintf (stderr, "DOWN-ROOT: BACKGROUND: received command code: %d\n", command_code);

      switch (command_code)
	{
	case COMMAND_RUN_SCRIPT:
	  status = system (command_line);
	  if (system_ok (status)) /* Succeeded */
	    {
	      if (send_control (fd, RESPONSE_SCRIPT_SUCCEEDED) == -1)
		{
		  fprintf (stderr, "DOWN-ROOT: BACKGROUND: write error on response socket [2]\n");
		  goto done;
		}
	    }
	  else /* Failed */
	    {
	      if (send_control (fd, RESPONSE_SCRIPT_FAILED) == -1)
		{
		  fprintf (stderr, "DOWN-ROOT: BACKGROUND: write error on response socket [3]\n");
		  goto done;
		}
	    }
	  break;

	case COMMAND_EXIT:
	  goto done;

	case -1:
	  fprintf (stderr, "DOWN-ROOT: BACKGROUND: read error on command channel\n");
	  goto done;

	default:
	  fprintf (stderr, "DOWN-ROOT: BACKGROUND: unknown command code: code=%d, exiting\n",
		   command_code);
	  goto done;
	}
    }

 done:
  if (argv_cat)
    free (argv_cat);
  if (command_line)
    free (command_line);
  if (DEBUG (verb))
    fprintf (stderr, "DOWN-ROOT: BACKGROUND: EXIT\n");

  return;
}
Ejemplo n.º 5
0
OPENVPN_EXPORT openvpn_plugin_handle_t
openvpn_plugin_open_v1(unsigned int *type_mask, const char *argv[], const char *envp[])
{
    struct down_root_context *context;
    int i = 0;

    /*
     * Allocate our context
     */
    context = (struct down_root_context *) calloc(1, sizeof(struct down_root_context));
    if (!context)
    {
        warn("DOWN-ROOT: Could not allocate memory for plug-in context");
        goto error;
    }
    context->foreground_fd = -1;

    /*
     * Intercept the --up and --down callbacks
     */
    *type_mask = OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_UP) | OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_DOWN);

    /*
     * Make sure we have two string arguments: the first is the .so name,
     * the second is the script command.
     */
    if (string_array_len(argv) < 2)
    {
        fprintf(stderr, "DOWN-ROOT: need down script command\n");
        goto error;
    }

    /*
     * Save the arguments in our context
     */
    context->command = calloc(string_array_len(argv), sizeof(char *));
    if (!context->command)
    {
        warn("DOWN-ROOT: Could not allocate memory for command array");
        goto error;
    }

    /* Ignore argv[0], as it contains just the plug-in file name */
    for (i = 1; i < string_array_len(argv); i++)
    {
        context->command[i-1] = (char *) argv[i];
    }

    /*
     * Get verbosity level from environment
     */
    {
        const char *verb_string = get_env("verb", envp);
        if (verb_string)
        {
            context->verb = atoi(verb_string);
        }
    }

    return (openvpn_plugin_handle_t) context;

error:
    free_context(context);
    return NULL;
}
Ejemplo n.º 6
0
OPENVPN_EXPORT openvpn_plugin_handle_t
openvpn_plugin_open_v2 (unsigned int *type_mask, const char *argv[], const char *envp[], struct openvpn_plugin_string_list **return_list)
{

  ldap_context_t *context;
  const char *daemon_string = NULL;
  const char *log_redirect = NULL;

  const char *configfile = NULL;
  int rc = 0;
  uint8_t     allow_core_files = 0;

  /* Are we in daemonized mode? If so, are we redirecting the logs? */
  daemon_string = get_env ("daemon", envp);
  use_syslog = 0;
  if( daemon_string && daemon_string[0] == '1'){
    log_redirect = get_env ("daemon_log_redirect", envp);
    if( !(log_redirect && log_redirect[0] == '1'))
      use_syslog = 1;
  }
  /*
   * Allocate our context
   */
  context = ldap_context_new( );
  if( !context ){
    LOGERROR( "Failed to initialize ldap_context, no memory available?" );
    goto error;
  }
  /*
   * Intercept the --auth-user-pass-verify callback.
   */
  *type_mask = OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY);

   while ( ( rc = getopt ( string_array_len (argv), (char **)argv, ":H:D:c:t:WZC" ) ) != - 1 ){
    switch( rc ) {
      case 'H':
        context->config->ldap->uri = strdup(optarg);
        break;
      case 'Z':
        context->config->ldap->ssl = strdup("start_tls");
        break;
      case 'D':
        context->config->ldap->binddn = strdup(optarg);
        break;
      case 'W':
        context->config->ldap->bindpw = get_passwd("BindPW Password: "******"Password is %s: length: %d\n", config->bindpw, strlen(config->bindpw) );
        break;
      case 'c':
        configfile = optarg;
        break;
      case 't':
        context->config->ldap->timeout = atoi( optarg );
        break;
      case 'C':
        LOGDEBUG("Core file generation requested");
        allow_core_files = 1;
        break;
      case '?':
        LOGERROR("Unknown Option -%c !!", optopt );
        break;
      case ':':
        LOGERROR ("Missing argument for option -%c !!", optopt );
        break;
      default:
        LOGERROR ("?? getopt returned character code 0%o ??", rc);
        abort();
    }
  }

#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
  if (allow_core_files){
    LOGDEBUG ("Setting core file");
    unlimit_core_size();
  }
#endif

  /**
   * Parse configuration file is -c filename is provided
   * If not provided, use a default config file OCONFIG
   * This file must exists even though it might be empty
   */
  if( configfile == NULL) {
    configfile = OCONFIG;
  }

  if( config_parse_file( configfile, context->config ) ){
    goto error;
  }
  /**
   * Set default config values
   */
  config_set_default( context->config );


  /* when ldap userconf is define, we need to hook onto those callbacks */
  if( config_is_pf_enabled( context->config )){
    *type_mask |= OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_ENABLE_PF);
  }
#ifdef ENABLE_LDAPUSERCONF
  *type_mask |= OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_CLIENT_CONNECT_V2)
                | OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_CLIENT_DISCONNECT);
#else
  if( config_is_redirect_gw_enabled( context->config ) ){
    *type_mask |= OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_CLIENT_CONNECT_V2);
  }
#endif

  /*
   * Get verbosity level from environment
   */
  const char *verb_string = get_env ("verb", envp);
  if (verb_string)
    context->verb = atoi (verb_string);

  if( DODEBUG( context->verb ) )
      config_dump( context->config );


  /* set up mutex/cond */
  pthread_mutex_init (&action_mutex, NULL);
  pthread_cond_init (&action_cond, NULL);

  /* start our authentication thread */
  pthread_attr_setdetachstate(&action_thread_attr, PTHREAD_CREATE_JOINABLE);
  rc = pthread_create(&action_thread, &action_thread_attr, action_thread_main_loop, context);

  switch( rc ){
    case EAGAIN:
      LOGERROR( "pthread_create returned EAGAIN: lacking resources" );
      break;
    case EINVAL:
      LOGERROR( "pthread_create returned EINVAL: invalid attributes" );
      break;
    case EPERM:
      LOGERROR( "pthread_create returned EPERM: no permission to create thread" );
      break;
    case 0:
      break;
    default:
      LOGERROR( "pthread_create returned an unhandled value: %d", rc );
  }
  if( rc == 0)
    return (openvpn_plugin_handle_t) context;

  /* Failed to initialize, free resources */
  pthread_attr_destroy( &action_thread_attr );
  pthread_mutex_destroy( &action_mutex );
  pthread_cond_destroy( &action_cond );

error:
  if ( context ){
    ldap_context_free (context);
  }
  return NULL;
}