/* pam_wheel module */ /* * Written by Cristian Gafton 1996/09/10 * See the end of the file for Copyright Information * * * 1.2 - added 'deny' and 'group=' options * 1.1 - added 'trust' option * 1.0 - the code is working for at least another person, so... :-) * 0.1 - use vsyslog instead of vfprintf/syslog in _pam_log * - return PAM_IGNORE on success (take care of sloppy sysadmins..) * - use pam_get_user instead of pam_get_item(...,PAM_USER,...) * - a new arg use_uid to auth the current uid instead of the * initial (logged in) one. * 0.0 - first release * * TODO: * - try to use make_remark from pam_unix/support.c * - consider returning on failure PAM_FAIL_NOW if the user is not * a wheel member. */ #define _BSD_SOURCE #include #include #include #include #include #include #include #include /* * here, we make a definition for the externally accessible function * in this file (this definition is required for static a module * but strongly encouraged generally) it is used to instruct the * modules include file to define the function prototypes. */ #define PAM_SM_AUTH #include /* variables */ static char use_group[BUFSIZ]; /* some syslogging */ static void _pam_log(int err, const char *format, ...) { va_list args; va_start(args, format); openlog("PAM-Wheel", LOG_CONS|LOG_PID, LOG_AUTH); vsyslog(err, format, args); va_end(args); closelog(); } /* checks if a user is on a list of members of the GID 0 group */ static int is_on_list(char * const *list, const char *member) { while (*list) { if (strcmp(*list, member) == 0) return 1; list++; } return 0; } /* argument parsing */ #define PAM_DEBUG_ARG 0x0001 #define PAM_USE_UID_ARG 0x0002 #define PAM_TRUST_ARG 0x0004 #define PAM_DENY_ARG 0x0010 static int _pam_parse(int argc, const char **argv) { int ctrl=0; /* step through arguments */ for (ctrl=0; argc-- > 0; ++argv) { /* generic options */ if (!strcmp(*argv,"debug")) ctrl |= PAM_DEBUG_ARG; else if (!strcmp(*argv,"use_uid")) ctrl |= PAM_USE_UID_ARG; else if (!strcmp(*argv,"trust")) ctrl |= PAM_TRUST_ARG; else if (!strcmp(*argv,"deny")) ctrl |= PAM_DENY_ARG; else if (!strncmp(*argv,"group=",6)) strcpy(use_group,*argv+6); else { _pam_log(LOG_ERR,"pam_parse: unknown option; %s",*argv); } } return ctrl; } /* --- authentication management functions (only) --- */ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc ,const char **argv) { int ctrl; const char *username; char *fromsu; struct passwd *pwd, *tpwd; struct group *grp; int retval = PAM_AUTH_ERR; /* Init the optional group */ bzero(use_group,sizeof(use_group)); ctrl = _pam_parse(argc, argv); retval = pam_get_user(pamh,&username,NULL); if ((retval != PAM_SUCCESS) || (!username)) { if (ctrl & PAM_DEBUG_ARG) _pam_log(LOG_DEBUG,"can not get the username"); return PAM_SERVICE_ERR; } /* su to a uid 0 account ? */ pwd = getpwnam(username); if (!pwd) { if (ctrl & PAM_DEBUG_ARG) _pam_log(LOG_NOTICE,"unknown user %s",username); return PAM_USER_UNKNOWN; } /* Now we know that the username exists, pass on to other modules... * the call to pam_get_user made this obsolete, so is commented out * * pam_set_item(pamh,PAM_USER,(const void *)username); */ /* is this user an UID 0 account ? */ if(pwd->pw_uid) { /* no need to check for wheel */ return PAM_IGNORE; } if (ctrl & PAM_USE_UID_ARG) { tpwd = getpwuid(getuid()); if (!tpwd) { if (ctrl & PAM_DEBUG_ARG) _pam_log(LOG_NOTICE,"who is running me ?!"); return PAM_SERVICE_ERR; } fromsu = tpwd->pw_name; } else { fromsu = getlogin(); if (!fromsu) { if (ctrl & PAM_DEBUG_ARG) _pam_log(LOG_NOTICE,"who is running me ?!"); return PAM_SERVICE_ERR; } } if (!use_group[0]) { if ((grp = getgrnam("wheel")) == NULL) { grp = getgrgid(0); } } else grp = getgrnam(use_group); if (!grp || !grp->gr_mem) { if (ctrl & PAM_DEBUG_ARG) { if (!use_group[0]) _pam_log(LOG_NOTICE,"no members in a GID 0 group"); else _pam_log(LOG_NOTICE,"no members in '%s' group",use_group); } if (ctrl & PAM_DENY_ARG) /* if this was meant to deny access to the members * of this group and the group does not exist, allow * access */ return PAM_IGNORE; else return PAM_AUTH_ERR; } if (is_on_list(grp->gr_mem, fromsu)) { if (ctrl & PAM_DEBUG_ARG) _pam_log(LOG_NOTICE,"Access %s to '%s' for '%s'", (ctrl & PAM_DENY_ARG)?"denied":"granted", fromsu,username); if (ctrl & PAM_DENY_ARG) return PAM_PERM_DENIED; else if (ctrl & PAM_TRUST_ARG) return PAM_SUCCESS; else return PAM_IGNORE; } if (ctrl & PAM_DEBUG_ARG) _pam_log(LOG_NOTICE,"Access %s for '%s' to '%s'", (ctrl & PAM_DENY_ARG)?"granted":"denied",fromsu,username); if (ctrl & PAM_DENY_ARG) return PAM_SUCCESS; else return PAM_PERM_DENIED; } PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh,int flags,int argc ,const char **argv) { return PAM_SUCCESS; } #ifdef PAM_STATIC /* static module data */ struct pam_module _pam_wheel_modstruct = { "pam_wheel", pam_sm_authenticate, pam_sm_setcred, NULL, NULL, NULL, NULL, }; #endif /* * Copyright (c) Cristian Gafton , 1996, 1997 * All rights reserved * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, and the entire permission notice in its entirety, * including the disclaimer of warranties. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * ALTERNATIVELY, this product may be distributed under the terms of * the GNU Public License, in which case the provisions of the GPL are * required INSTEAD OF the above restrictions. (This clause is * necessary due to a potential bad interaction between the GPL and * the restrictions contained in a BSD-style copyright.) * * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */