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 >
Wrap
C/C++ Source or Header
|
1998-06-15
|
10KB
|
343 lines
/* pam_groupok module */
/*
* Written by Cristian Gafton <gafton@sorosis.ro> 1996/09/10
* See the end of the file for Copyright Information
*
*
* 1.4 - add file=<path> option ... jpd@usl.edu
* 1.3 - mods by jpd@usl.edu to test group of user being authenticated
* [adapted from pam_wheel]. Add feedback flag to print refusal msg to stdout.
* 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>
#ifdef linux
#define __USE_BSD
#endif
#include <unistd.h>
#include <string.h>
#include <syslog.h>
#include <stdarg.h>
#include <sys/types.h>
#ifdef linux
#include <pwdb/pwdb_map.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.
*/
#ifdef linux
#define PAM_SM_AUTH
#else
#include <security/pam_appl.h>
#define PAM_EXTERN extern
#endif
#include <security/pam_modules.h>
/* variables */
static char use_group[BUFSIZ];
static char use_file[BUFSIZ];
/* some syslogging */
static void _pam_log(int err, const char *format, ...)
{
va_list args;
va_start(args, format);
openlog("pam_groupok", 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 group being examined */
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_FEEDBACK 0x0008
#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,"trust"))
ctrl |= PAM_TRUST_ARG;
else if (!strcmp(*argv,"deny"))
ctrl |= PAM_DENY_ARG;
else if (!strcmp(*argv,"feedback"))
ctrl |= PAM_FEEDBACK;
else if (!strncmp(*argv,"group=",6))
strcpy(use_group,*argv+6);
else if (!strncmp(*argv,"file=",5))
strcpy(use_file,*argv+5);
else {
_pam_log(LOG_ERR,"pam_parse: unknown option; %s",*argv);
}
}
return ctrl;
}
struct group *fudge_grnam ( char *file, int ctrl)
{
static struct group g;
char line[BUFSIZ];
int i;
FILE *fp;
char **ids, **idp;
extern int errno;
if ((fp = fopen(file, "r")) == NULL) {
if (ctrl & PAM_DEBUG_ARG)
_pam_log(LOG_DEBUG,"can not open file %s [code=%d]", file, errno);
return NULL;
}
else {
i=0;
while (fgets(line, sizeof(line), fp) != NULL) i++;
rewind(fp);
ids = idp = (char **)malloc((i+1) * sizeof(char *));
while (i) {
strcpy(line,"\n"); /* just in case fgets fails */
fgets(line, sizeof(line), fp);
if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = '\0';
*idp++ = strdup(line);
i--;
}
*idp = NULL;
fclose(fp);
g.gr_name = strdup("nogroup");
g.gr_passwd = strdup("");
g.gr_gid = 65534;
g.gr_mem = ids;
return (&g);
}
}
void free_grp(struct group *g)
{
if (g) {
free (g->gr_name);
free (g->gr_passwd);
while (*(g->gr_mem)) {
free (*(g->gr_mem));
g->gr_mem++;
}
}
}
/* --- authentication management functions (only) --- */
PAM_EXTERN
int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc
,const char **argv)
{
int ctrl;
char *username;
struct passwd *pwd;
struct group *grp;
int retval = PAM_AUTH_ERR;
/* Init the optional group */
bzero(use_group,sizeof(use_group));
bzero(use_file,sizeof(use_file));
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;
}
#ifdef PDEBUG
_pam_log(LOG_DEBUG, "pam_get_user returned %s", username);
#endif
/* Get passwd info for provided username account */
pwd = getpwnam(username);
if (!pwd) {
if (ctrl & PAM_DEBUG_ARG)
_pam_log(LOG_NOTICE,"unknown user %s",username);
return PAM_USER_UNKNOWN;
}
#ifdef PDEBUG
_pam_log(LOG_DEBUG, "getpwnam returned uid=%d", pwd->pw_uid);
#endif
/* 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 a UID 0 account ? */
if(!pwd->pw_uid) {
/* no need to check group */
return PAM_IGNORE;
}
if (use_file[0])
grp = fudge_grnam(use_file, ctrl);
else if (!use_group[0])
grp = getgrgid(0);
else
grp = getgrnam(use_group);
if (!grp || !grp->gr_mem || !*(grp->gr_mem)) {
if (ctrl & PAM_DEBUG_ARG) {
if (use_file[0])
_pam_log(LOG_NOTICE,"no members in '%s' file",use_file);
else 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 (use_file[0]) free_grp(grp);
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 {
if (ctrl & PAM_FEEDBACK)
printf("pam_groupok: Id %s disallowed on this system.\n", username);
return PAM_AUTH_ERR;
}
}
if (is_on_list(grp->gr_mem, username) || (use_group[0] && grp->gr_gid==pwd->pw_gid)) {
if (ctrl & PAM_DEBUG_ARG)
_pam_log(LOG_NOTICE,"Access %s to '%s'",
(ctrl & PAM_DENY_ARG)?"denied":"granted", username);
if (use_file[0]) free_grp(grp);
if (ctrl & PAM_DENY_ARG) {
if (ctrl & PAM_FEEDBACK)
printf("pam_groupok: Id %s disallowed on this system.\n", username);
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 to '%s'",
(ctrl & PAM_DENY_ARG)?"granted":"denied",username);
if (use_file[0]) free_grp(grp);
if (ctrl & PAM_DENY_ARG)
return PAM_SUCCESS;
else {
if (ctrl & PAM_FEEDBACK)
printf("pam_groupok: Id %s disallowed on this system.\n", username);
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_groupok_modstruct = {
"pam_groupok",
pam_sm_authenticate,
pam_sm_setcred,
NULL,
NULL,
NULL,
NULL,
};
#endif
/*
* Copyright (c) Cristian Gafton <gafton@sorosis.ro>, 1996.
* 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.
*/