I've implemented a PAM module that when used in a stack allows for individual authentication, but then assigns the user to a local "role" account. First, is there any interest by the pam-linux community for this module. Second, if so how do I go about submitting the module for formal review. Third, regardless of interest in the pam-linux community is there someone willing to review my code? <patch against Linux-PAM "CVS from today" attached> -- James R. Leu jleu at inoc.com INOC -> http://inoc.com/ DELIVERING UPTIME
diff -uNr Linux-PAM/configure.in Linux-PAM.jleu/configure.in --- Linux-PAM/configure.in 2007-05-24 15:55:58.000000000 -0500 +++ Linux-PAM.jleu/configure.in 2007-05-24 16:24:25.000000000 -0500 @@ -501,7 +501,7 @@ modules/pam_mkhomedir/Makefile modules/pam_motd/Makefile \ modules/pam_namespace/Makefile \ modules/pam_nologin/Makefile modules/pam_permit/Makefile \ - modules/pam_rhosts/Makefile \ + modules/pam_rhosts/Makefile modules/pam_roles/Makefile \ modules/pam_rootok/Makefile modules/pam_exec/Makefile \ modules/pam_securetty/Makefile modules/pam_selinux/Makefile \ modules/pam_shells/Makefile modules/pam_stress/Makefile \ diff -uNr Linux-PAM/modules/Makefile.am Linux-PAM.jleu/modules/Makefile.am --- Linux-PAM/modules/Makefile.am 2007-05-24 15:56:08.000000000 -0500 +++ Linux-PAM.jleu/modules/Makefile.am 2007-05-24 16:17:15.000000000 -0500 @@ -9,7 +9,7 @@ pam_securetty pam_selinux pam_shells pam_stress pam_succeed_if \ pam_tally pam_time pam_umask pam_unix pam_userdb pam_warn \ pam_wheel pam_xauth pam_exec pam_namespace pam_loginuid \ - pam_faildelay + pam_faildelay pam_roles CLEANFILES = *~ diff -uNr Linux-PAM/modules/pam_roles/Makefile.am Linux-PAM.jleu/modules/pam_roles/Makefile.am --- Linux-PAM/modules/pam_roles/Makefile.am 1969-12-31 18:00:00.000000000 -0600 +++ Linux-PAM.jleu/modules/pam_roles/Makefile.am 2007-05-24 16:28:21.000000000 -0500 @@ -0,0 +1,24 @@ +# +# Copyright (c) 2007 James R. Leu <jleu@xxxxxxxx> +# + +CLEANFILES = *~ + +EXTRA_DIST = README roles.conf tst-pam_roles + +securelibdir = $(SECUREDIR) +secureconfdir = $(SCONFIGDIR) + +AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \ + -DPAM_ROLES_CONF=\"$(SCONFIGDIR)/roles.conf\" +AM_LDFLAGS = -no-undefined -avoid-version -module \ + -L$(top_builddir)/libpam -lpam +if HAVE_VERSIONING + AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map +endif + +securelib_LTLIBRARIES = pam_roles.la + +secureconf_DATA = roles.conf + +TESTS = tst-pam_roles diff -uNr Linux-PAM/modules/pam_roles/pam_roles.c Linux-PAM.jleu/modules/pam_roles/pam_roles.c --- Linux-PAM/modules/pam_roles/pam_roles.c 1969-12-31 18:00:00.000000000 -0600 +++ Linux-PAM.jleu/modules/pam_roles/pam_roles.c 2007-05-24 16:32:52.000000000 -0500 @@ -0,0 +1,261 @@ +/* + * Written by James R. Leu <jleu@xxxxxxxx> 2007/5/24 + */ + +#define _BSD_SOURCE + +#include <sys/types.h> +#include <pwd.h> +#include <unistd.h> +#include <stdio.h> +#include <strings.h> +#include <grp.h> +#include <libintl.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <stdarg.h> + +#define PAM_SM_AUTH +#define PAM_SM_ACCOUNT +#define PAM_SM_SESSION +#define _PAM_EXTERN_FUNCTIONS + +#include <security/pam_appl.h> +#include <security/pam_modules.h> +#include <security/_pam_macros.h> + +#define LIST_SIZE 1024 +#ifndef PAM_ROLE_CONF +#define PAM_ROLES_CONF "/etc/security/roles.conf" +#endif + +static void +_log_err(const char *format, ... ) +{ + va_list args; + + va_start(args, format); + openlog("pam_roles", LOG_CONS|LOG_PID, LOG_AUTH); + vsyslog(LOG_CRIT, format, args); + va_end(args); + closelog(); +} + +static int +check_roles(char *list, char *result, int size) +{ + char *line = malloc(LIST_SIZE); + char *toks[LIST_SIZE]; + char *tok; + int num = 0; + FILE *filep; + int i; + int retval = 0; + + filep = fopen(PAM_ROLES_CONF, "r"); + + if (!line || !filep) + goto done; + + while((tok = strtok(list, ":"))) { + toks[num++] = tok; + list = NULL; + } + + while(fgets(line, LIST_SIZE, filep)) { + char *role; + char *name; + + if (line[0] == '#') + continue; + + line[strlen(line) - 1] = '\0'; + + role = strtok(line, ":"); + name = strtok(NULL, ":"); + + if (!role || !name) + continue; + + for (i = 0; i < num; i++) { + if (!strcmp(name, toks[i])) { + strncpy(result, role, size); + retval = 1; + goto done; + } + } + } + +done: + if (filep) + fclose(filep); + if (line) + free(line); + + return retval; +} + +static int +pam_roles(const char *mode, pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + struct passwd *pw_entry; + struct group *grp; + const void *username; + gid_t *grps; + int no_grps; + int retval = PAM_IGNORE; + + int debug = 0; + int i; + + char *list = malloc(LIST_SIZE); + char *role = malloc(LIST_SIZE); + + (void) pam_get_item(pamh, PAM_USER, &username); + + for (i = 0; i < argc; i++) { + if (strcmp(argv[i], "debug") == 0) { + debug = 1; + } else { + _log_err("pam_roles(%s): illegal module option %s\n", + mode, argv[i]); + } + } + + if (debug) { + const void *service; + + (void) pam_get_item(pamh, PAM_SERVICE, &service); + _log_err("pam_roles(%s): service = %s, user = %s\n", mode, + (service) ? service : "not set", + (username) ? username : "not set"); + } + + if (username == NULL) { + retval = PAM_USER_UNKNOWN; + goto done; + } + + /* stop masquerades by mapping username to uid to username */ + + if (!(pw_entry = getpwnam(username))) { + retval = PAM_USER_UNKNOWN; + goto done; + } + + if (!(pw_entry = getpwuid(pw_entry->pw_uid))) { + retval = PAM_USER_UNKNOWN; + goto done; + } + + if (strcmp(username, pw_entry->pw_name) != 0) { + _log_err("pam_roles(%s): username %s " + "maps to userid %d which is username %s\n", mode, + username, pw_entry->pw_uid, pw_entry->pw_name); + } + + if (pw_entry->pw_uid == 0) { + /* + * Root entry cannot have roles, ignore. + */ + retval = PAM_SUCCESS; + goto done; + } + + if (initgroups(pw_entry->pw_name, pw_entry->pw_gid)) { + retval = PAM_USER_UNKNOWN; + goto done; + } + + no_grps = getgroups(0, NULL); /* find the current number of groups */ + if (no_grps > 0) { + grps = calloc(no_grps, sizeof(gid_t)); + (void) getgroups(no_grps, grps); + } else { + no_grps = 0; + grps = NULL; + } + + list[0] = '\0'; + strcat(list, pw_entry->pw_name); + if ((grp = getgrgid(pw_entry->pw_gid))) { + strcat(list, ":"); + strcat(list, grp->gr_name); + } + + for (i = 0; i < no_grps; i++) { + if ((grp = getgrgid(grps[i]))) { + strcat(list, ":"); + strcat(list, grp->gr_name); + } + } + + if (check_roles(list, role, LIST_SIZE)) { + int err = pam_set_item(pamh, PAM_USER, (const void *)role); + if (err != PAM_SUCCESS) { + _log_err("pam_roles(%s): failed to set user to %s\n", + mode, role); + } + if (debug) { + const void *service; + + (void) pam_get_item(pamh, PAM_SERVICE, &service); + _log_err("pam_roles(%s): service = %s, role = %s\n", + mode, (service) ? service : "not set", + (role) ? role : "not set"); + } + retval = PAM_SUCCESS; + } + +done: + if (list) + free(list); + if (role) + free(role); + + return retval; +} + +PAM_EXTERN +int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + return pam_roles("auth", pamh,flags,argc,argv); +} + +PAM_EXTERN +int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + return pam_roles("acct", pamh,flags,argc,argv); +} + +PAM_EXTERN +int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + return PAM_SUCCESS; +} + +PAM_EXTERN +int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + return pam_roles("open session", pamh,flags,argc,argv); +} + +PAM_EXTERN +int pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + return pam_roles("close session", pamh,flags,argc,argv); +} + +/* static module data */ +#ifdef PAM_STATIC +struct pam_module _pam_roles_modstruct = { + "pam_roles_acct", + pam_sm_authenticate, + pam_sm_setcred, + pam_sm_acct_mgmt, + pam_sm_open_session, + pam_sm_close_session, + NULL, +}; +#endif diff -uNr Linux-PAM/modules/pam_roles/README Linux-PAM.jleu/modules/pam_roles/README --- Linux-PAM/modules/pam_roles/README 1969-12-31 18:00:00.000000000 -0600 +++ Linux-PAM.jleu/modules/pam_roles/README 2007-05-24 15:56:22.000000000 -0500 @@ -0,0 +1,42 @@ +pam_roles PAM module for role account access + +DESCRIPTION + +The pam_roles PAM module does not authenticate the user, but instead it +reassigns users to a local role account. + +By default rules for role assignments are taken from config file /etc/security +/roles.conf. + +The pam_roles module can be used to allow individual credientials for +autherntication (most likely non-local users) but then assigns +the user to a local "role" account. Criteria for assignment to a role +accountis are limited to user and group name. The processing of the file +is linear (ie the first match is used). If no match is found the +modules does nothing, but will still return PAM_SUCCESS. + +This module implements "auth" (just authenticate, no creds), "session", +and "account". + +EXAMPLES + +These are some example lines which might be specified in /etc/security/ +roles.conf. + +Users fred and bob login with there individual credientials, but +are assigned to the "operator" role account. User bill, is assigned to +the "luser" role account. + +operator:bob +operator:fred +luser:bill + +Users in the group "admin" login with there individual credientials, but +are assigned to the "root" role account. + +root:admin + +MODULE OPTIONS + +The only option supported by this module is "debug" which will send messages +to syslog to aid in tracking what the module is doing. diff -uNr Linux-PAM/modules/pam_roles/roles.conf Linux-PAM.jleu/modules/pam_roles/roles.conf --- Linux-PAM/modules/pam_roles/roles.conf 1969-12-31 18:00:00.000000000 -0600 +++ Linux-PAM.jleu/modules/pam_roles/roles.conf 2007-05-24 15:56:22.000000000 -0500 @@ -0,0 +1,30 @@ +# +# This is the configuration file for the pam_roles module. +# + +# +# The syntax of the lines is as follows: +# +# <role>:<group|user> +# +# white space is and lines begining with '#' are ignored. +# +# role +# is a local user name +# +# group +# is a group name available via the system call getgroups() +# if using the nscd system they can be from LDAP, RADIUS etc. +# +# user +# is the user name presented by the PAM system (aka PAM_USER) +# + +#operator:fred +#operator:bob +#luser:bill +#root:admin + +# +# End of group.conf file +# diff -uNr Linux-PAM/modules/pam_roles/tst-pam_roles Linux-PAM.jleu/modules/pam_roles/tst-pam_roles --- Linux-PAM/modules/pam_roles/tst-pam_roles 1969-12-31 18:00:00.000000000 -0600 +++ Linux-PAM.jleu/modules/pam_roles/tst-pam_roles 2007-05-24 16:10:07.000000000 -0500 @@ -0,0 +1,2 @@ +#!/bin/sh +../../tests/tst-dlopen .libs/pam_roles.so
Attachment:
pgpAJcD131v7L.pgp
Description: PGP signature
_______________________________________________ Pam-list mailing list Pam-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/pam-list