278 lines
8.0 KiB
C
278 lines
8.0 KiB
C
|
/* 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.
|
||
|
*/
|