⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 auth-pam.c

📁 the open vpn source code in linux
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  OpenVPN -- An application to securely tunnel IP networks *             over a single TCP/UDP port, with support for SSL/TLS-based *             session authentication and key exchange, *             packet encryption, packet authentication, and *             packet compression. * *  Copyright (C) 2002-2005 OpenVPN Solutions LLC <info@openvpn.net> * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License version 2 *  as published by the Free Software Foundation. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program (see the file COPYING included with this *  distribution); if not, write to the Free Software Foundation, Inc., *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA *//* * OpenVPN plugin module to do PAM authentication using a split * privilege model. */#if DLOPEN_PAM#include <dlfcn.h>#include "pamdl.h"#else#include <security/pam_appl.h>#endif#include <stdio.h>#include <string.h>#include <ctype.h>#include <unistd.h>#include <stdlib.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/wait.h>#include <fcntl.h>#include <signal.h>#include <syslog.h>#include "openvpn-plugin.h"#define DEBUG(verb) ((verb) >= 7)/* Command codes for foreground -> background communication */#define COMMAND_VERIFY 0#define COMMAND_EXIT   1/* Response codes for background -> foreground communication */#define RESPONSE_INIT_SUCCEEDED   10#define RESPONSE_INIT_FAILED      11#define RESPONSE_VERIFY_SUCCEEDED 12#define RESPONSE_VERIFY_FAILED    13/* * Plugin state, used by foreground */struct auth_pam_context{  /* Foreground's socket to background process */  int foreground_fd;  /* Process ID of background process */  pid_t background_pid;  /* Verbosity level of OpenVPN */  int verb;};/* * Name/Value pairs for conversation function. * Special Values: * *  "USERNAME" -- substitute client-supplied username *  "PASSWORD" -- substitute client-specified password */#define N_NAME_VALUE 16struct name_value {  const char *name;  const char *value;};struct name_value_list {  int len;  struct name_value data[N_NAME_VALUE];};/* * Used to pass the username/password * to the PAM conversation function. */struct user_pass {  int verb;  char username[128];  char password[128];  const struct name_value_list *name_value_list;};/* Background process function */static void pam_server (int fd, const char *service, int verb, const struct name_value_list *name_value_list);/* * Given an environmental variable name, search * the envp array for its value, returning it * if found or NULL otherwise. */static const char *get_env (const char *name, const char *envp[]){  if (envp)    {      int i;      const int namelen = strlen (name);      for (i = 0; envp[i]; ++i)	{	  if (!strncmp (envp[i], name, namelen))	    {	      const char *cp = envp[i] + namelen;	      if (*cp == '=')		return cp + 1;	    }	}    }  return NULL;}/* * Return the length of a string array */static intstring_array_len (const char *array[]){  int i = 0;  if (array)    {      while (array[i])	++i;    }  return i;}/* * Socket read/write functions. */static intrecv_control (int fd){  unsigned char c;  const ssize_t size = read (fd, &c, sizeof (c));  if (size == sizeof (c))    return c;  else    {      /*fprintf (stderr, "AUTH-PAM: DEBUG recv_control.read=%d\n", (int)size);*/      return -1;    }}static intsend_control (int fd, int code){  unsigned char c = (unsigned char) code;  const ssize_t size = write (fd, &c, sizeof (c));  if (size == sizeof (c))    return (int) size;  else    return -1;}static intrecv_string (int fd, char *buffer, int len){  if (len > 0)    {      ssize_t size;      memset (buffer, 0, len);      size = read (fd, buffer, len);      buffer[len-1] = 0;      if (size >= 1)	return (int)size;    }  return -1;}static intsend_string (int fd, const char *string){  const int len = strlen (string) + 1;  const ssize_t size = write (fd, string, len);  if (size == len)    return (int) size;  else    return -1;}/* * Daemonize if "daemon" env var is true. * Preserve stderr across daemonization if * "daemon_log_redirect" env var is true. */static voiddaemonize (const char *envp[]){  const char *daemon_string = get_env ("daemon", envp);  if (daemon_string && daemon_string[0] == '1')    {      const char *log_redirect = get_env ("daemon_log_redirect", envp);      int fd = -1;      if (log_redirect && log_redirect[0] == '1')	fd = dup (2);      if (daemon (0, 0) < 0)	{	  fprintf (stderr, "AUTH-PAM: daemonization failed\n");	}      else if (fd >= 3)	{	  dup2 (fd, 2);	  close (fd);	}    }}/* * Close most of parent's fds. * Keep stdin/stdout/stderr, plus one * other fd which is presumed to be * our pipe back to parent. * Admittedly, a bit of a kludge, * but posix doesn't give us a kind * of FD_CLOEXEC which will stop * fds from crossing a fork(). */static voidclose_fds_except (int keep){  int i;  closelog ();  for (i = 3; i <= 100; ++i)    {      if (i != keep)	close (i);    }}/* * Usually we ignore signals, because our parent will * deal with them. */static voidset_signals (void){  signal (SIGTERM, SIG_DFL);  signal (SIGINT, SIG_IGN);  signal (SIGHUP, SIG_IGN);  signal (SIGUSR1, SIG_IGN);  signal (SIGUSR2, SIG_IGN);  signal (SIGPIPE, SIG_IGN);}/* * Return 1 if query matches match. */static intname_value_match (const char *query, const char *match){  while (!isalnum (*query))    {      if (*query == '\0')	return 0;      ++query;    }  return strncasecmp (match, query, strlen (match)) == 0;}OPENVPN_EXPORT openvpn_plugin_handle_topenvpn_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));  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       */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -