diff options
Diffstat (limited to 'contrib/libpam/modules/pam_wheel/pam_wheel.c')
-rw-r--r-- | contrib/libpam/modules/pam_wheel/pam_wheel.c | 277 |
1 files changed, 277 insertions, 0 deletions
diff --git a/contrib/libpam/modules/pam_wheel/pam_wheel.c b/contrib/libpam/modules/pam_wheel/pam_wheel.c new file mode 100644 index 0000000..db262d8 --- /dev/null +++ b/contrib/libpam/modules/pam_wheel/pam_wheel.c @@ -0,0 +1,277 @@ +/* pam_wheel module */ + +/* + * Written by Cristian Gafton <gafton@redhat.com> 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. + */ + +#include <stdio.h> +#define __USE_BSD +#include <unistd.h> +#include <string.h> +#include <syslog.h> +#include <stdarg.h> +#include <sys/types.h> +#ifdef HAVE_PWDBLIB +# include <pwdb/pwdb_public.h> +#else +# include <pwd.h> +# include <grp.h> +#endif + + +/* + * 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 <security/pam_modules.h> + +/* 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]) + 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 <gafton@redhat.com>, 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. + */ |