home *** CD-ROM | disk | FTP | other *** search
/ pc.louisiana.edu/pub/unix/ / Louisiana_UNIX.tar / Louisiana_UNIX / pam_groupok.zoo / pam_groupok.c < prev    next >
C/C++ Source or Header  |  1998-06-15  |  10KB  |  343 lines

  1. /* pam_groupok module */
  2.  
  3. /*
  4.  * Written by Cristian Gafton <gafton@sorosis.ro> 1996/09/10
  5.  * See the end of the file for Copyright Information
  6.  *
  7.  *
  8.  * 1.4 - add file=<path> option ... jpd@usl.edu
  9.  * 1.3 - mods by jpd@usl.edu to test group of user being authenticated
  10.  *       [adapted from pam_wheel].  Add feedback flag to print refusal msg to stdout.
  11.  * 1.2 - added 'deny' and 'group=' options
  12.  * 1.1 - added 'trust' option
  13.  * 1.0 - the code is working for at least another person, so... :-)
  14.  * 0.1 - use vsyslog instead of vfprintf/syslog in _pam_log
  15.  *     - return PAM_IGNORE on success (take care of sloppy sysadmins..)
  16.  *     - use pam_get_user instead of pam_get_item(...,PAM_USER,...)
  17.  *     - a new arg use_uid to auth the current uid instead of the
  18.  *       initial (logged in) one.
  19.  * 0.0 - first release
  20.  *
  21.  * TODO:
  22.  *  - try to use make_remark from pam_unix/support.c
  23.  *  - consider returning on failure PAM_FAIL_NOW if the user is not
  24.  *    a wheel member.
  25.  */
  26.  
  27. #include <stdio.h>
  28. #ifdef linux
  29. #define __USE_BSD
  30. #endif
  31. #include <unistd.h>
  32. #include <string.h>
  33. #include <syslog.h>
  34. #include <stdarg.h>
  35. #include <sys/types.h>
  36. #ifdef linux
  37. #include <pwdb/pwdb_map.h>
  38. #else
  39. #include <pwd.h>
  40. #include <grp.h>
  41. #endif
  42.  
  43. /*
  44.  * here, we make a definition for the externally accessible function
  45.  * in this file (this definition is required for static a module
  46.  * but strongly encouraged generally) it is used to instruct the
  47.  * modules include file to define the function prototypes.
  48.  */
  49.  
  50. #ifdef linux
  51. #define PAM_SM_AUTH
  52. #else
  53. #include <security/pam_appl.h>
  54. #define PAM_EXTERN extern
  55. #endif
  56.  
  57. #include <security/pam_modules.h>
  58.  
  59. /* variables */
  60. static char use_group[BUFSIZ];
  61. static char use_file[BUFSIZ];
  62.  
  63. /* some syslogging */
  64.  
  65. static void _pam_log(int err, const char *format, ...)
  66. {
  67.     va_list args;
  68.  
  69.     va_start(args, format);
  70.     openlog("pam_groupok", LOG_CONS|LOG_PID, LOG_AUTH);
  71.     vsyslog(err, format, args);
  72.     va_end(args);
  73.     closelog();
  74. }
  75.  
  76. /* checks if a user is on a list of members of the group being examined */
  77.  
  78. static int is_on_list(char * const *list, const char *member)
  79. {
  80.     while (*list) {
  81.         if (strcmp(*list, member) == 0)
  82.             return 1;
  83.         list++;
  84.     }
  85.     return 0;
  86. }
  87.  
  88. /* argument parsing */
  89.  
  90. #define PAM_DEBUG_ARG       0x0001
  91. /*#define PAM_USE_UID_ARG     0x0002*/
  92. #define PAM_TRUST_ARG       0x0004
  93. #define PAM_FEEDBACK        0x0008
  94. #define PAM_DENY_ARG        0x0010  
  95.  
  96. static int _pam_parse(int argc, const char **argv)
  97. {
  98.      int ctrl=0;
  99.  
  100.      /* step through arguments */
  101.      for (ctrl=0; argc-- > 0; ++argv) {
  102.  
  103.           /* generic options */
  104.  
  105.           if (!strcmp(*argv,"debug"))
  106.                ctrl |= PAM_DEBUG_ARG;
  107.           else if (!strcmp(*argv,"trust"))
  108.                ctrl |= PAM_TRUST_ARG;
  109.           else if (!strcmp(*argv,"deny"))
  110.                ctrl |= PAM_DENY_ARG;
  111.           else if (!strcmp(*argv,"feedback"))
  112.                ctrl |= PAM_FEEDBACK;
  113.           else if (!strncmp(*argv,"group=",6))
  114.                 strcpy(use_group,*argv+6);
  115.           else if (!strncmp(*argv,"file=",5))
  116.                 strcpy(use_file,*argv+5);
  117.           else {
  118.                _pam_log(LOG_ERR,"pam_parse: unknown option; %s",*argv);
  119.           }
  120.      }
  121.  
  122.      return ctrl;
  123. }
  124.  
  125.  
  126. struct group *fudge_grnam ( char *file, int ctrl)
  127. {
  128.      static struct group g;
  129.      char line[BUFSIZ];
  130.      int i;
  131.      FILE *fp;
  132.      char **ids, **idp;
  133.      extern int errno;
  134.  
  135.      if ((fp = fopen(file, "r")) == NULL) {
  136.           if (ctrl & PAM_DEBUG_ARG)
  137.                _pam_log(LOG_DEBUG,"can not open file %s [code=%d]", file, errno);
  138.           return NULL;
  139.      }
  140.      else {
  141.           i=0;
  142.       while (fgets(line, sizeof(line), fp) != NULL) i++;
  143.           rewind(fp);
  144.           ids = idp = (char **)malloc((i+1) * sizeof(char *));
  145.           while (i) {
  146.                strcpy(line,"\n");  /* just in case fgets fails */
  147.                fgets(line, sizeof(line), fp);
  148.                if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = '\0';
  149.                *idp++ = strdup(line);
  150.            i--;
  151.           }
  152.           *idp = NULL;
  153.           fclose(fp);
  154.           g.gr_name = strdup("nogroup");
  155.           g.gr_passwd = strdup("");
  156.           g.gr_gid = 65534;
  157.           g.gr_mem = ids;
  158.           return (&g);
  159.      }
  160. }
  161.  
  162. void free_grp(struct group *g)
  163. {
  164.      if (g) {
  165.           free (g->gr_name);
  166.           free (g->gr_passwd);
  167.           while (*(g->gr_mem)) {
  168.                free (*(g->gr_mem));
  169.                g->gr_mem++;
  170.           }
  171.      }
  172. }
  173.  
  174. /* --- authentication management functions (only) --- */
  175.  
  176. PAM_EXTERN
  177. int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc
  178.             ,const char **argv)
  179. {
  180.      int ctrl;
  181.      char *username;
  182.      struct passwd *pwd;
  183.      struct group *grp;
  184.      int retval = PAM_AUTH_ERR;
  185.     
  186.      /* Init the optional group */
  187.      bzero(use_group,sizeof(use_group));
  188.      bzero(use_file,sizeof(use_file));
  189.      
  190.      ctrl = _pam_parse(argc, argv);
  191.      retval = pam_get_user(pamh,&username,NULL);
  192.      if ((retval != PAM_SUCCESS) || (!username)) {
  193.         if (ctrl & PAM_DEBUG_ARG)
  194.             _pam_log(LOG_DEBUG,"can not get the username");
  195.         return PAM_SERVICE_ERR;
  196.      }
  197. #ifdef PDEBUG
  198.     _pam_log(LOG_DEBUG, "pam_get_user returned %s", username);
  199. #endif
  200.  
  201.      /* Get passwd info for provided username account */
  202.      pwd = getpwnam(username);
  203.      if (!pwd) {
  204.         if (ctrl & PAM_DEBUG_ARG)
  205.             _pam_log(LOG_NOTICE,"unknown user %s",username);
  206.         return PAM_USER_UNKNOWN;
  207.      }
  208. #ifdef PDEBUG
  209.     _pam_log(LOG_DEBUG, "getpwnam returned uid=%d", pwd->pw_uid);
  210. #endif
  211.      
  212.      /* Now we know that the username exists, pass on to other modules...
  213.       * the call to pam_get_user made this obsolete, so is commented out
  214.       *
  215.       * pam_set_item(pamh,PAM_USER,(const void *)username);
  216.       */
  217.  
  218.      /* is this user a UID 0 account ? */
  219.      if(!pwd->pw_uid) {
  220.         /* no need to check group */
  221.         return PAM_IGNORE;
  222.      }
  223.      
  224.      if (use_file[0])
  225.          grp = fudge_grnam(use_file, ctrl);
  226.      else if (!use_group[0])
  227.          grp = getgrgid(0);
  228.      else
  229.         grp = getgrnam(use_group);
  230.         
  231.      if (!grp || !grp->gr_mem || !*(grp->gr_mem)) {
  232.         if (ctrl & PAM_DEBUG_ARG) {
  233.             if (use_file[0])
  234.                 _pam_log(LOG_NOTICE,"no members in '%s' file",use_file);
  235.             else if (!use_group[0])
  236.                 _pam_log(LOG_NOTICE,"no members in a GID 0 group");
  237.             else
  238.                 _pam_log(LOG_NOTICE,"no members in '%s' group",use_group);
  239.         }
  240.         if (use_file[0]) free_grp(grp);
  241.         if (ctrl & PAM_DENY_ARG)
  242.             /* if this was meant to deny access to the members
  243.              * of this group and the group does not exist, allow
  244.              * access
  245.              */
  246.             return PAM_IGNORE;
  247.         else {
  248.         if (ctrl & PAM_FEEDBACK)
  249.         printf("pam_groupok: Id %s disallowed on this system.\n", username);
  250.             return PAM_AUTH_ERR;
  251.         }
  252.      }
  253.         
  254.      if (is_on_list(grp->gr_mem, username) || (use_group[0] && grp->gr_gid==pwd->pw_gid)) {
  255.         if (ctrl & PAM_DEBUG_ARG)
  256.             _pam_log(LOG_NOTICE,"Access %s to '%s'",
  257.                      (ctrl & PAM_DENY_ARG)?"denied":"granted", username);
  258.         if (use_file[0]) free_grp(grp);
  259.         if (ctrl & PAM_DENY_ARG) {
  260.         if (ctrl & PAM_FEEDBACK)
  261.         printf("pam_groupok: Id %s disallowed on this system.\n", username);
  262.             return PAM_PERM_DENIED;
  263.     }
  264.         else
  265.             if (ctrl & PAM_TRUST_ARG)
  266.                 return PAM_SUCCESS;
  267.             else
  268.                 return PAM_IGNORE;
  269.      }
  270.  
  271.      if (ctrl & PAM_DEBUG_ARG)
  272.         _pam_log(LOG_NOTICE,"Access %s to '%s'",
  273.         (ctrl & PAM_DENY_ARG)?"granted":"denied",username);
  274.      if (use_file[0]) free_grp(grp);
  275.      if (ctrl & PAM_DENY_ARG)
  276.         return PAM_SUCCESS;
  277.      else {
  278.     if (ctrl & PAM_FEEDBACK)
  279.         printf("pam_groupok: Id %s disallowed on this system.\n", username);
  280.         return PAM_PERM_DENIED;
  281.     }
  282. }
  283.  
  284. PAM_EXTERN
  285. int pam_sm_setcred(pam_handle_t *pamh,int flags,int argc
  286.            ,const char **argv)
  287. {
  288.      return PAM_SUCCESS;
  289. }
  290.  
  291.  
  292. #ifdef PAM_STATIC
  293.  
  294. /* static module data */
  295.  
  296. struct pam_module _pam_groupok_modstruct = {
  297.      "pam_groupok",
  298.      pam_sm_authenticate,
  299.      pam_sm_setcred,
  300.      NULL,
  301.      NULL,
  302.      NULL,
  303.      NULL,
  304. };
  305.  
  306. #endif
  307.  
  308. /*
  309.  * Copyright (c) Cristian Gafton <gafton@sorosis.ro>, 1996.
  310.  *                                              All rights reserved
  311.  *
  312.  * Redistribution and use in source and binary forms, with or without
  313.  * modification, are permitted provided that the following conditions
  314.  * are met:
  315.  * 1. Redistributions of source code must retain the above copyright
  316.  *    notice, and the entire permission notice in its entirety,
  317.  *    including the disclaimer of warranties.
  318.  * 2. Redistributions in binary form must reproduce the above copyright
  319.  *    notice, this list of conditions and the following disclaimer in the
  320.  *    documentation and/or other materials provided with the distribution.
  321.  * 3. The name of the author may not be used to endorse or promote
  322.  *    products derived from this software without specific prior
  323.  *    written permission.
  324.  *
  325.  * ALTERNATIVELY, this product may be distributed under the terms of
  326.  * the GNU Public License, in which case the provisions of the GPL are
  327.  * required INSTEAD OF the above restrictions.  (This clause is
  328.  * necessary due to a potential bad interaction between the GPL and
  329.  * the restrictions contained in a BSD-style copyright.)
  330.  *
  331.  * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED
  332.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  333.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  334.  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
  335.  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  336.  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  337.  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  338.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  339.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  340.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  341.  * OF THE POSSIBILITY OF SUCH DAMAGE.
  342.  */
  343.