From 691c2e4dc528a8bde510fa29a9dda7c9702a1a9e Mon Sep 17 00:00:00 2001 From: tmraz Date: Jul 14 2005 13:13:44 +0000 Subject: * pam_console: support perms.d directory with permissions files * pam_loginuid: test for non existing loginuid file (module shouldn't fail) --- diff --git a/CHANGELOG b/CHANGELOG index e9a9edb..45d8195 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -4,6 +4,11 @@ Changelog of pam-redhat modules This changelog describes only changes after branching of pam-redhat modules without autoconf support. +0.80-1: Thu Jul 14 2005 + +* pam_console: support perms.d directory with permissions files +* pam_loginuid: test for non existing loginuid file (module shouldn't fail) + 0.79-1: Thu Mar 31 2005 * pam_console: Modify dri permissions for open source dri drivers diff --git a/pam_console/50-default.perms b/pam_console/50-default.perms new file mode 100644 index 0000000..4f6344c --- /dev/null +++ b/pam_console/50-default.perms @@ -0,0 +1,59 @@ +# device classes -- these are shell-style globs +=/dev/fd[0-1]* \ + /dev/floppy* /mnt/floppy* +=/dev/dsp* /dev/audio* /dev/midi* \ + /dev/mixer* /dev/sequencer \ + /dev/sound/* /dev/beep \ + /dev/snd/* +=/dev/cdrom* /dev/cdroms/* /dev/cdwriter* /mnt/cdrom* +=/dev/pilot +=/mnt/jaz* +=/mnt/pocketzip* /mnt/zip* /dev/zip* +=/dev/ls120 /mnt/ls120* +=/dev/scanner* /dev/usb/scanner* +=/dev/usb/rio500 +=/mnt/camera* /dev/usb/dc2xx* /dev/usb/mdc800* +=/mnt/memstick* +=/mnt/flash* /dev/flash* +=/mnt/diskonkey* +=/mnt/microdrive* +=/dev/fb /dev/fb[0-9]* \ + /dev/fb/* +=/dev/kbd +=/dev/js[0-9]* +=/dev/video* /dev/radio* /dev/winradio* /dev/vtx* /dev/vbi* \ + /dev/video/* +=/dev/gpmctl +=/dev/nvidia* /dev/3dfx* /dev/dri/card* +=/dev/apm_bios +=/dev/pmu +=/dev/rfcomm* +=/dev/raw1394 + +# permission definitions + 0660 0660 root.floppy + 0600 0600 root + 0600 0660 root.disk + 0600 0660 root.uucp + 0600 0660 root.disk + 0600 0660 root.disk + 0600 0660 root.disk + 0600 0600 root + 0600 0600 root.disk + 0600 0600 root.disk + 0600 0600 root.disk + 0600 0660 root.disk + 0600 0660 root.disk + 0600 0600 root + 0600 0600 root + 0600 0600 root + 0600 0600 root + 0700 0700 root + 0600 0600 root + 0600 0600 root + 0600 0600 root + 0600 0600 root + 0600 0600 root + + 0600 /dev/console 0600 root.root + 0600 0600 root diff --git a/pam_console/Makefile b/pam_console/Makefile index 7fbdcfa..39bfd3e 100644 --- a/pam_console/Makefile +++ b/pam_console/Makefile @@ -25,6 +25,8 @@ LOCAL_CONF1 = console.perms INSTALLED_CONF1 = $(SCONFIGD)/console.perms LOCAL_CONF2 = console.handlers INSTALLED_CONF2 = $(SCONFIGD)/console.handlers +LOCAL_CONF3 = 50-default.perms +INSTALLED_CONF3 = $(SCONFIGD)/console.perms.d/50-default.perms MAN5 = console.apps.5 console.perms.5 console.handlers.5 MAN8 = pam_console.8 pam_console_apply.8 @@ -114,9 +116,11 @@ ifdef MAN8 test -d $(FAKEROOT)$(MANDIR)/man8 || $(MKDIR) $(FAKEROOT)$(MANDIR)/man8 $(INSTALL) -m $(MANMODE) $(MAN8) $(FAKEROOT)$(MANDIR)/man8/ endif - if $(MKDIR) -m $(LOCKMODE) $(FAKEROOT)$(LOCKDIR) $(FAKEROOT)/$(SCONFIGD)/console.apps ; then \ + if $(MKDIR) -m $(LOCKMODE) $(FAKEROOT)$(LOCKDIR) \ + $(FAKEROOT)/$(SCONFIGD)/console.apps $(FAKEROOT)/$(SCONFIGD)/console.perms.d; then \ bash -f ../install_conf "$(FAKEROOT)" "$(SCONFIGD)" "$(INSTALLED_CONF1)" "$(TITLE)" "$(LOCAL_CONF1)" ;\ bash -f ../install_conf "$(FAKEROOT)" "$(SCONFIGD)" "$(INSTALLED_CONF2)" "$(TITLE)" "$(LOCAL_CONF2)" ;\ + bash -f ../install_conf "$(FAKEROOT)" "$(SCONFIGD)/console.perms.d" "$(INSTALLED_CONF3)" "$(TITLE)" "$(LOCAL_CONF3)" ;\ fi test -d $(FAKEROOT)$(SUPLEMENTED) || install -m 755 -d $(FAKEROOT)$(SUPLEMENTED) install -m 555 $(BINARY) $(FAKEROOT)$(SUPLEMENTED) diff --git a/pam_console/README b/pam_console/README index d58c02d..4e528f6 100644 --- a/pam_console/README +++ b/pam_console/README @@ -21,7 +21,8 @@ the console. It also cooperates with the pam_listfile module to make it possible to allow users who are at the console to run various programs that would otherwise be restricted to root only. -The pam_console.8 man page explains this software in more detail. +The pam_console.8 and pam_console_apply.8 man pages explain this +software in more detail. Please note: the current version depends on too many external tools and libraries, making it big and hard to evaluate for security. diff --git a/pam_console/config.h b/pam_console/config.h index 957513d..2fecad2 100644 --- a/pam_console/config.h +++ b/pam_console/config.h @@ -23,7 +23,7 @@ struct config_s { }; STATIC void -parse_file(char *name); +parse_file(const char *name); STATIC int check_console_name (const char *consolename); diff --git a/pam_console/config.l b/pam_console/config.l index 3130c42..2b8b34d 100644 --- a/pam_console/config.l +++ b/pam_console/config.l @@ -12,7 +12,7 @@ #include static int lineno; -static char *filename; +static const char *filename; STATIC char * strip_slash(const char *); @@ -37,7 +37,7 @@ lex_file (FILE *in) { } static void -lex_set_filename(char *name) { +lex_set_filename(const char *name) { filename = name; } diff --git a/pam_console/config.y b/pam_console/config.y index 286711a..81e5f0a 100644 --- a/pam_console/config.y +++ b/pam_console/config.y @@ -28,7 +28,7 @@ static void do_yyerror(const char *format, ...); static void -free_class(class *c); +empty_class(class *c); %} @@ -51,16 +51,17 @@ line: config classdef: OBRACKET string CBEQUALS stringlist EOL { - void *old; class *c; - old = g_hash_table_lookup(namespace, $2); - if (old) free_class(old); - - c = g_malloc(sizeof(class)); + c = g_hash_table_lookup(namespace, $2); + if (c) { + empty_class(c); + } else { + c = g_malloc(sizeof(class)); + g_hash_table_insert(namespace, g_strdup($2), c); + } c->name = $2; c->list = $4; - g_hash_table_insert(namespace, $2, c); } ; @@ -98,7 +99,7 @@ config: classlist STRING classlist optstring optstring EOL { classlist: OBRACKET string CBRACKET { class *c = g_hash_table_lookup(namespace, $2); if(!c) { - g_log(G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + _pam_log(LOG_ERR, FALSE, "unknown class \"%s\" at line %d in %s\n", (const char *)$2, lineno, filename); _exit(1); @@ -130,7 +131,7 @@ string: STRING {$$=$1;} ; /* parse a file given by a name */ STATIC void -parse_file(char *name) { +parse_file(const char *name) { FILE *infile; _pam_log(LOG_DEBUG, TRUE, "parsing config file %s", name); @@ -289,7 +290,9 @@ do_yyerror(const char *format, ...) { } static void -free_class(class *c) { - if (c->name) free (c->name); - if (c) free (c); +empty_class(class *c) { + g_free(c->name); + c->name = NULL; + g_slist_free(c->list); + c->list = NULL; } diff --git a/pam_console/console.perms b/pam_console/console.perms index ef2035e..968b727 100644 --- a/pam_console/console.perms +++ b/pam_console/console.perms @@ -13,67 +13,13 @@ # # For more information: # man 5 console.perms +# +# This file should not be modified. +# Rather a new file in the console.perms.d directory should be created. # file classes -- these are regular expressions =tty[0-9][0-9]* vc/[0-9][0-9]* :[0-9]\.[0-9] :[0-9] =:[0-9]\.[0-9] :[0-9] -# device classes -- these are shell-style globs -=/dev/fd[0-1]* \ - /dev/floppy/* /mnt/floppy* -=/dev/dsp* /dev/audio* /dev/midi* \ - /dev/mixer* /dev/sequencer \ - /dev/sound/* /dev/beep \ - /dev/snd/* -=/dev/cdrom* /dev/cdroms/* /dev/cdwriter* /mnt/cdrom* -=/dev/pilot -=/mnt/jaz* -=/mnt/pocketzip* /mnt/zip* /dev/zip* -=/dev/ls120 /mnt/ls120* -=/dev/scanner* /dev/usb/scanner* -=/dev/usb/rio500 -=/mnt/camera* /dev/usb/dc2xx* /dev/usb/mdc800* -=/mnt/memstick* -=/mnt/flash* /dev/flash* -=/mnt/diskonkey* -=/mnt/microdrive* -=/dev/fb /dev/fb[0-9]* \ - /dev/fb/* -=/dev/kbd -=/dev/js[0-9]* -=/dev/video* /dev/radio* /dev/winradio* /dev/vtx* /dev/vbi* \ - /dev/video/* -=/dev/gpmctl -=/dev/nvidia* /dev/3dfx* /dev/dri/card* -=/dev/apm_bios -=/dev/pmu -=/dev/rfcomm* -=/dev/raw1394 - -# permission definitions - 0660 0660 root.floppy - 0600 0600 root - 0600 0660 root.disk - 0600 0660 root.uucp - 0600 0660 root.disk - 0600 0660 root.disk - 0600 0660 root.disk - 0600 0600 root - 0600 0600 root.disk - 0600 0600 root.disk - 0600 0600 root.disk - 0600 0660 root.disk - 0600 0660 root.disk - 0600 0600 root - 0600 0600 root - 0600 0600 root - 0600 0600 root - 0700 0700 root - 0600 0600 root - 0600 0600 root - 0600 0600 root - 0600 0600 root - 0600 0600 root - - 0600 /dev/console 0600 root.root - 0600 0600 root +# device classes -- see console.perms.d/50-default.perms +# permission definitions -- see console.perms.d/50-default.perms diff --git a/pam_console/console.perms.5 b/pam_console/console.perms.5 index eab2a35..84e5819 100644 --- a/pam_console/console.perms.5 +++ b/pam_console/console.perms.5 @@ -1,13 +1,14 @@ -.\" Copyright 1999 Red Hat Software, Inc. +.\" Copyright 1999,2005 Red Hat Software, Inc. .\" Written by Michael K. Johnson -.TH console.perms 5 1999/2/3 "Red Hat Software" "System Administrator's Manual" +.TH console.perms 5 2005/5/2 "Red Hat Software" "System Administrator's Manual" .SH NAME console.perms \- permissions control file for users at the system console .SH DESCRIPTION -/etc/security/console.perms determines the permissions that will be +/etc/security/console.perms and .perms files in the +/etc/security/console.perms.d directory determine the permissions that will be given to priviledged users of the console at login time, and the -permissions to which to revert when the users log out. It is -read by the pam_console module. +permissions to which to revert when the users log out. They are +read by the pam_console_apply helper executable. The format is: diff --git a/pam_console/pam_console.8 b/pam_console/pam_console.8 index 15401d2..fe4da66 100644 --- a/pam_console/pam_console.8 +++ b/pam_console/pam_console.8 @@ -1,6 +1,6 @@ .\" Copyright 1999 Red Hat Software, Inc. .\" Written by Michael K. Johnson -.TH pam_console 8 2005/3/18 "Red Hat" "System Administrator's Manual" +.TH pam_console 8 2005/5/2 "Red Hat" "System Administrator's Manual" .SH NAME pam_console \- determine user owning the system console .SH SYNOPSIS @@ -79,8 +79,6 @@ session optional pam_console.so .br \fI/etc/security/console.apps\fP .br -\fI/etc/security/console.perms\fP -.br \fI/etc/security/console.handlers\fP .SH SECURITY NOTES When pam_console "auth" is used for login services which provide @@ -100,5 +98,8 @@ Currently, /bin/login (invoked from telnetd) and gdm is OK, others may be not. .SH BUGS Let's hope not, but if you find any, please report them via the "Bug Track" link at http://bugzilla.redhat.com/bugzilla/ -.SH AUTHOR +.SH AUTHORS Michael K. Johnson +.br +Support of console.handlers and other improvements by +Tomas Mraz diff --git a/pam_console/pam_console.c b/pam_console/pam_console.c index 8dd34e1..d05e8af 100644 --- a/pam_console/pam_console.c +++ b/pam_console/pam_console.c @@ -53,9 +53,9 @@ */ #define CAST_ME_HARDER (const void**) -static char consolelock[PATH_MAX] = LOCKDIR "/console.lock"; -static char consolerefs[PATH_MAX] = LOCKDIR "/"; -static char consoleapps[PATH_MAX] = "/etc/security/console.apps/"; +static char consolelock[] = LOCKDIR "/" LOCKFILE; +static char consolerefs[] = LOCKDIR "/"; +static char consoleapps[] = "/etc/security/console.apps/"; static char consolehandlers[PATH_MAX] = "/etc/security/console.handlers"; static int configfileparsed = 0; static int debug = 0; @@ -98,7 +98,11 @@ _args_parse(int argc, const char **argv) else if (!strcmp(*argv,"allow_nonroot_tty")) allow_nonroot_tty = 1; else if (!strncmp(*argv,"handlersfile=",13)) - strcpy(consolehandlers,*argv+13); + if (strlen(*argv+13) < PATH_MAX) + strcpy(consolehandlers,*argv+13); + else + _pam_log(LOG_ERR, FALSE, + "_args_parse: handlersfile filename too long"); else { _pam_log(LOG_ERR, FALSE, "_args_parse: unknown option; %s",*argv); @@ -606,6 +610,7 @@ pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv) if (fstat (fd, &st)) { _pam_log(LOG_ERR, FALSE, "\"impossible\" fstat error on %s", consolelock); + close(fd); err = PAM_SESSION_ERR; goto return_error; } consoleuser = _do_malloc(st.st_size+1); diff --git a/pam_console/pam_console.h b/pam_console/pam_console.h index 373b43e..84c4c4b 100644 --- a/pam_console/pam_console.h +++ b/pam_console/pam_console.h @@ -6,7 +6,7 @@ #define _PAM_CONSOLE_H #include -/* pam_console.c */ +#define LOCKFILE "console.lock" static void _pam_log(int err, int debug_p, const char *format, ...); diff --git a/pam_console/pam_console_apply.8 b/pam_console/pam_console_apply.8 index 3464bc7..46827a6 100644 --- a/pam_console/pam_console_apply.8 +++ b/pam_console/pam_console_apply.8 @@ -1,19 +1,26 @@ .\" Copyright 2001 Red Hat, Inc. -.TH pam_console_apply 8 2005/3/18 "Red Hat" "System Administrator's Manual" +.TH pam_console_apply 8 2005/5/2 "Red Hat" "System Administrator's Manual" .SH NAME pam_console_apply \- set or revoke permissions for users at the system console .SH SYNOPSIS .B pam_console_apply [-f ] [-c ] [-r] [-t ] [-s] [-d] [ ...] .SH DESCRIPTION -\fBpam_console_apply\fP sets or resets permissions on devices in the same -manner as pam_console. +\fBpam_console_apply\fP is a helper executable which sets or resets permissions +on device nodes. .br If \fI/var/run/console.lock\fP exists, \fBpam_console_apply\fP will grant permissions to the user listed therein. If the lock file does not exist, -permissions are reset to those listed in \fI/etc/security/console.perms\fP, -which should be configured to set permissions on devices so that \fBroot\fP +permissions are reset according to defaults set in \fIconsole.perms\fP files, +normally configured to set permissions on devices so that \fBroot\fP owns them. + +When initializing its configuration it first parses +the \fI/etc/security/console.perms\fP file and then it searches for files +ending with the \fI.perms\fP suffix in the \fI/etc/security/console.perms.d\fP +directory. These files are parsed in the lexical order in "C" locale. +Permission rules are appended to a global list, console and device class +definitions override previous definitions of the same class. .SH ARGUMENTS .IP -c Load other console.perms file than the default one. @@ -37,6 +44,8 @@ changed on all files specified in the \fIconsole.perms\fP file. \fI/var/run/console.lock\fP .br \fI/etc/security/console.perms\fP +.br +\fI/etc/security/console.perms.d/50-default.perms\fP .SH "SEE ALSO" .BR pam_console(8) .br @@ -45,6 +54,9 @@ changed on all files specified in the \fIconsole.perms\fP file. .SH BUGS Let's hope not, but if you find any, please report them via the "Bug Track" link at http://bugzilla.redhat.com/bugzilla/ -.SH AUTHOR +.SH AUTHORS Nalin Dahyabhai , using code shamelessly stolen from parts of pam_console. +.br +Support of console.perms.d and other improvements by +Tomas Mraz . diff --git a/pam_console/pam_console_apply.c b/pam_console/pam_console_apply.c index e7eb968..1cca7aa 100644 --- a/pam_console/pam_console_apply.c +++ b/pam_console/pam_console_apply.c @@ -16,6 +16,8 @@ #include #include #include +#include +#include #define STATIC static #include "chmod.h" #include "pam_console.h" @@ -24,9 +26,11 @@ #include #define CAST_ME_HARDER (const void**) +#define DEFAULT_PERMSFILE "/etc/security/console.perms" +#define PERMS_GLOB "/etc/security/console.perms.d/*.perms" -static char consolelock[PATH_MAX] = LOCKDIR "/console.lock"; -static char consoleperms[PATH_MAX] = "/etc/security/console.perms"; +static const char consolelock[] = LOCKDIR "/" LOCKFILE; +static char consoleperms[PATH_MAX]; static char tty[PATH_MAX] = "tty0"; static int debug = 0; static int syslogging = 0; @@ -53,10 +57,44 @@ _pam_log(int err, int debug_p, const char *format, ...) } else { vfprintf(stderr, format, args); + fprintf(stderr, "\n"); } va_end(args); } +static int +pf_glob_errorfn(const char *epath, int eerrno) +{ + return 0; +} + +static void +parse_files(void) +{ + int rc; + glob_t globbuf; + int i; + const char *oldlocale; + + /* first we parse the console.perms file */ + parse_file(DEFAULT_PERMSFILE); + + /* set the LC_COLLATE so the sorting order doesn't depend + on system locale */ + oldlocale = setlocale(LC_COLLATE, "C"); + + rc = glob(PERMS_GLOB, GLOB_NOCHECK, pf_glob_errorfn, &globbuf); + setlocale(LC_COLLATE, oldlocale); + if (rc == GLOB_NOSPACE) { + return; + } + + for (i = 0; globbuf.gl_pathv[i] != NULL; i++) { + parse_file(globbuf.gl_pathv[i]); + } + globfree(&globbuf); +} + int main(int argc, char **argv) { @@ -69,12 +107,20 @@ main(int argc, char **argv) while((c = getopt(argc, argv, "c:f:t:rsd")) != -1) { switch(c) { - case 'c': strncpy(consoleperms, optarg, sizeof(consoleperms) - 1); + case 'c': if (strlen(optarg) >= sizeof(consoleperms)) { + fprintf(stderr, "Console.perms filename too long\n"); + exit(1); + } + strncpy(consoleperms, optarg, sizeof(consoleperms) - 1); consoleperms[sizeof(consoleperms) - 1] = '\0'; break; case 'f': chmod_set_fstab(optarg); break; - case 't': strncpy(tty, optarg, sizeof(tty) - 1); + case 't': if (strlen(optarg) >= sizeof(tty)) { + fprintf(stderr, "TTY name too long\n"); + exit(1); + } + strncpy(tty, optarg, sizeof(tty) - 1); tty[sizeof(tty) - 1] = '\0'; break; case 'r': @@ -98,7 +144,11 @@ main(int argc, char **argv) files = g_slist_prepend(files, argv[i]); } - parse_file(consoleperms); + if (*consoleperms == '\0') + parse_files(); + else + parse_file(consoleperms); + fd = open(consolelock, O_RDONLY); if (fd != -1) { if (fstat (fd, &st)) { diff --git a/pam_loginuid/pam_loginuid.c b/pam_loginuid/pam_loginuid.c index e7a5c26..748b7a1 100644 --- a/pam_loginuid/pam_loginuid.c +++ b/pam_loginuid/pam_loginuid.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -56,16 +57,18 @@ static void _pam_log(int err, const char *format, ...) static int set_loginuid(uid_t uid) { int fd, count, rc = 0; - char fn[PATH_MAX]; char loginuid[16]; - memset(loginuid, 0, sizeof(loginuid)); count = snprintf(loginuid, sizeof(loginuid), "%d", uid); - snprintf(fn, sizeof(fn), "/proc/%d/loginuid", getpid()); - fd = open(fn, O_NOFOLLOW|O_WRONLY|O_TRUNC); + fd = open("/proc/self/loginuid", O_NOFOLLOW|O_WRONLY|O_TRUNC); if (fd < 0) { - _pam_log(LOG_ERR, "set_loginuid failed opening loginuid\n"); - return 1; + int loglevel = LOG_DEBUG; + if (errno != ENOENT) { + rc = 1; + loglevel = LOG_ERR; + } + _pam_log(loglevel, "set_loginuid failed opening loginuid\n"); + return rc; } if (_pammodutil_write(fd, loginuid, count) != count) rc = 1; diff --git a/pam_timestamp/pam_timestamp.c b/pam_timestamp/pam_timestamp.c index 7ee5411..356bea8 100644 --- a/pam_timestamp/pam_timestamp.c +++ b/pam_timestamp/pam_timestamp.c @@ -499,6 +499,7 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) /* Check oldest login against timestamp */ if (get_ruser(pamh, ruser, sizeof(ruser))) { + close(fd); return PAM_AUTH_ERR; } if (check_login_time(ruser, then) != PAM_SUCCESS) @@ -507,6 +508,7 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) "older than oldest login, disallowing " "access to %s for user %s", path, service, ruser); + close(fd); return PAM_AUTH_ERR; }