Submitted By: Jim Gifford (jim at linuxfromscratch dot org) Date: 2007-01-21 Initial Package Version: 0.99.7.0 Origin: http://redhat.download.fedoraproject.org/pub/fedora/linux/core/updates/6/SRPMS/pam-0.99.6.2-3.9.fc6.src.rpm Upstream Status: From Fedora/Redhat Description: Adds pam_console module Rediffed against 1.1.0 by Joe Ciccone on 2009-07-09 Rediffed against 1.1.3 by Joe Ciccone on 2011-01-26 diff -Naur Linux-PAM-1.1.3.orig/configure.in Linux-PAM-1.1.3/configure.in --- Linux-PAM-1.1.3.orig/configure.in 2010-10-27 09:19:13.000000000 -0400 +++ Linux-PAM-1.1.3/configure.in 2011-01-26 22:14:52.059406906 -0500 @@ -568,7 +568,7 @@ AC_CONFIG_FILES([Makefile libpam/Makefile libpamc/Makefile libpamc/test/Makefile \ libpam_misc/Makefile conf/Makefile conf/pam_conv1/Makefile \ po/Makefile.in \ - modules/Makefile \ + modules/Makefile modules/pam_console/Makefile \ modules/pam_access/Makefile modules/pam_cracklib/Makefile \ modules/pam_debug/Makefile modules/pam_deny/Makefile \ modules/pam_echo/Makefile modules/pam_env/Makefile \ diff -Naur Linux-PAM-1.1.3.orig/modules/Makefile.am Linux-PAM-1.1.3/modules/Makefile.am --- Linux-PAM-1.1.3.orig/modules/Makefile.am 2008-11-28 09:29:12.000000000 -0500 +++ Linux-PAM-1.1.3/modules/Makefile.am 2011-01-26 22:14:52.059406906 -0500 @@ -2,7 +2,7 @@ # Copyright (c) 2005, 2006, 2008 Thorsten Kukuk # -SUBDIRS = pam_access pam_cracklib pam_debug pam_deny pam_echo \ +SUBDIRS = pam_access pam_cracklib pam_console pam_debug pam_deny pam_echo \ pam_env pam_exec pam_faildelay pam_filter pam_ftp \ pam_group pam_issue pam_keyinit pam_lastlog pam_limits \ pam_listfile pam_localuser pam_loginuid pam_mail \ diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/.cvsignore Linux-PAM-1.1.3/modules/pam_console/.cvsignore --- Linux-PAM-1.1.3.orig/modules/pam_console/.cvsignore 1969-12-31 19:00:00.000000000 -0500 +++ Linux-PAM-1.1.3/modules/pam_console/.cvsignore 2011-01-26 22:14:52.062657563 -0500 @@ -0,0 +1,3 @@ +configfile.tab.c +configfile.tab.h +configfile.lex.c diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/50-default.perms Linux-PAM-1.1.3/modules/pam_console/50-default.perms --- Linux-PAM-1.1.3.orig/modules/pam_console/50-default.perms 1969-12-31 19:00:00.000000000 -0500 +++ Linux-PAM-1.1.3/modules/pam_console/50-default.perms 2011-01-26 22:14:52.059406906 -0500 @@ -0,0 +1,61 @@ +# 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 +=/dev/ircomm* + +# 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 0600 root + + 0600 /dev/console 0600 root.root + 0600 0600 root diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/COPYING Linux-PAM-1.1.3/modules/pam_console/COPYING --- Linux-PAM-1.1.3.orig/modules/pam_console/COPYING 1969-12-31 19:00:00.000000000 -0500 +++ Linux-PAM-1.1.3/modules/pam_console/COPYING 2011-01-26 22:14:52.062657563 -0500 @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/Makefile.am Linux-PAM-1.1.3/modules/pam_console/Makefile.am --- Linux-PAM-1.1.3.orig/modules/pam_console/Makefile.am 1969-12-31 19:00:00.000000000 -0500 +++ Linux-PAM-1.1.3/modules/pam_console/Makefile.am 2011-01-26 22:14:52.062657563 -0500 @@ -0,0 +1,64 @@ +# +# Copyright (c) 2005 Thorsten Kukuk +# Copyright (c) 2005 Red Hat, Inc. +# + +CLEANFILES = *~ + +CONFFILES = console.perms console.handlers 50-default.perms +MAN5 = console.apps.5 console.perms.5 console.handlers.5 +MAN8 = pam_console.8 pam_console_apply.8 + +man_MANS = $(MAN5) $(MAN8) + +EXTRA_DIST = README $(man_MANS) $(CONFFILES) sed-static configfile.y configfile.l + +LOCKDIR = /var/run/console +LOCKMODE = 755 + +securelibdir = $(SECUREDIR) +secureconfdir = $(SCONFIGDIR) +permsddir = $(SCONFIGDIR)/console.perms.d + +noinst_HEADERS = chmod.h configfile.h configfile.tab.h handlers.h modechange.h pam_console.h + +AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \ + $(GLIB_CFLAGS) -DLOCKDIR=\"$(LOCKDIR)\" + +pam_console_la_LDFLAGS = -no-undefined -avoid-version -module +if HAVE_VERSIONING + pam_console_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map +endif +pam_console_la_LIBADD = -L$(top_builddir)/libpam -lpam + +pam_console_apply_LDADD = -L$(top_builddir)/libpam -lpam + +securelib_LTLIBRARIES = pam_console.la +sbin_PROGRAMS = pam_console_apply + + +secureconf_DATA = console.perms console.handlers + +FLEX_OPTS = -Cr +BISON_OPTS = -d + +pam_console_la_SOURCES = pam_console.c pam_console.h regerr.c handlers.c handlers.h +pam_console_apply_SOURCES = pam_console_apply.c pam_console.h chmod.c modechange.c regerr.c \ + configfile.c configfile.h hashtable.c hashtable.h hashtable_private.h + +pam_console_la_CFLAGS = $(AM_CFLAGS) +pam_console_apply_CFLAGS = $(AM_CFLAGS) + +configfile.tab.c: configfile.y + $(YACC) $(BISON_OPTS) -o $@ -p _pc_yy $< + sh $(srcdir)/sed-static $@ + +configfile.lex.c: configfile.l configfile.tab.c + $(LEX) $(FLEX_OPTS) -o$@ -P_pc_yy $< + sh $(srcdir)/sed-static $@ + +configfile.c: configfile.tab.c configfile.lex.c + +install-data-local: + mkdir -p $(DESTDIR)$(secureconfdir)/console.apps + mkdir -m $(LOCKMODE) -p -p $(DESTDIR)$(LOCKDIR) diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/README Linux-PAM-1.1.3/modules/pam_console/README --- Linux-PAM-1.1.3.orig/modules/pam_console/README 1969-12-31 19:00:00.000000000 -0500 +++ Linux-PAM-1.1.3/modules/pam_console/README 2011-01-26 22:14:52.062657563 -0500 @@ -0,0 +1,45 @@ +README for pam_console +====================== + +NOTE: This software is very powerful. Incautious use could leave your +system open to attack, or difficult to use. + +pam_console is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +Because pam_console integrates GPL-licensed code, all of pam_console +is licensed only under the GPL, unlike most PAM modules. See the +file COPYING for the license terms under which this software is +licensed. + +(If this software breaks your system, you get to keep all the pieces.) + +The pam_console module exists to change file permissions when users +log on at the console, and to change them back when they log out of +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 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. +This is only a bootstrap stage; I'll be fixing it later. I'm using +lex/yacc right now so that it is trivial to change the grammar, and +I'm using glib because I didn't want to write my own hashtables +while I was busy thinking about file locking. Don't report those +as bugs, I'll fix them later once I've ironed out the important +details... + +Michael K. Johnson +Red Hat Software, Inc. + +Additional note: the current version is improved so that the functionality +of changing the ownership and permissions of the devices is split out +of the pam_console.so module to the pam_console_apply executable, +which is called from the pam_console module when the lock is obtained. +Thus the module doesn't depend on the glib. + +Copyright 1999, 2005 Red Hat, Inc. diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/chmod.c Linux-PAM-1.1.3/modules/pam_console/chmod.c --- Linux-PAM-1.1.3.orig/modules/pam_console/chmod.c 1969-12-31 19:00:00.000000000 -0500 +++ Linux-PAM-1.1.3/modules/pam_console/chmod.c 2011-01-26 22:14:52.059406906 -0500 @@ -0,0 +1,240 @@ +/* This file is derived from chmod.c and stpcpy.c, included + in the GNU fileutils distribution. It has been changed to be a + library specifically for use within the Red Hat pam_console module. + Changes Copyright 1999,2001 Red Hat, Inc. + */ + +/* chmod -- change permission modes of files + Copyright (C) 89, 90, 91, 95, 1996 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define NAMLEN(dirent) strlen((dirent)->d_name) + +#include "configfile.h" +#include "chmod.h" +#include "modechange.h" + +#define CLOSEDIR(d) closedir (d) + +#ifdef _D_NEED_STPCPY +/* stpcpy.c -- copy a string and return pointer to end of new string + Copyright (C) 1989, 1990 Free Software Foundation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Copy SRC to DEST, returning the address of the terminating '\0' in DEST. */ + +static char * +stpcpy (char *dest, const char *src) +{ + while ((*dest++ = *src++) != '\0') + /* Do nothing. */ ; + return dest - 1; +} +#endif /* _D_NEED_STPCPY */ + +/* end included files */ + +static const char *fstab_filename = "/etc/fstab"; + +static int change_via_fstab __P ((const char *dir, + const struct mode_change *changes, + uid_t user, gid_t group)); + +/* Change the mode of FILE according to the list of operations CHANGES. + If DEREF_SYMLINK is nonzero and FILE is a symbolic link, change the + mode of the referenced file. If DEREF_SYMLINK is zero, ignore symbolic + links. Return 0 if successful, 1 if errors occurred. */ + +static int +change_file (const char *file, const struct mode_change *changes, + const int deref_symlink, uid_t user, gid_t group) +{ + struct stat file_stats; + unsigned short newmode; + int errors = 0; + + if (lstat (file, &file_stats) == -1) + { + if (errno == ENOENT) + { + /* doesn't exist, check fstab */ + errors |= change_via_fstab (file, changes, user, group); + return errors; + } + else + { + return 1; + } + } + + if (S_ISLNK (file_stats.st_mode)) + { + /* don't bother with dangling symlinks */ + if (stat (file, &file_stats)) + { + return 1; + } + } + + newmode = mode_adjust (file_stats.st_mode, changes); + + if (S_ISDIR (file_stats.st_mode)) + errors |= change_via_fstab (file, changes, user, group); + else + { + if (newmode != (file_stats.st_mode & 07777)) + { + if (chmod (file, (int) newmode) == -1) + { + errors = 1; + } + } + errors |= chown (file, user, group); + } + + return errors; +} + +void +chmod_set_fstab(const char *fstab) +{ + fstab_filename = strdup(fstab); +} + + +/* If the directory spec given matches a filesystem listed in /etc/fstab, + * modify the device special associated with that filesystem. */ +static int +change_via_fstab (const char *dir, const struct mode_change *changes, + uid_t user, gid_t group) +{ + int errors = 0; + FILE *fstab; + struct mntent *mntent; + + fstab = setmntent(fstab_filename, "r"); + + if (fstab == NULL) + { + return 1; + } + + for(mntent = getmntent(fstab); mntent != NULL; mntent = getmntent(fstab)) + { + if(mntent->mnt_dir && + mntent->mnt_fsname && + (fnmatch(dir, mntent->mnt_dir, 0) == 0)) + { + errors |= change_file(mntent->mnt_fsname, changes, TRUE, user, group); + } + } + + endmntent(fstab); + + return errors; +} + +/* Parse the ASCII mode into a linked list + of `struct mode_change' and apply that to each file argument. */ + + +static int +glob_errfn(const char *pathname, int theerr) { + /* silently ignore inaccessible files */ + return 0; +} + +#define DIE(n) {fprintf(stderr, "chmod failure\n"); return (n);} + +static int +match_files(GSList *files, const char *filename) { + + if (!files) + return 0; /* empty list matches */ + for (; files; files = files->next) { + if (!fnmatch(files->data, filename, FNM_PATHNAME)) + return 0; + } + return -1; +} + +int +chmod_files (const char *mode, uid_t user, gid_t group, + char *single_file, GSList *filelist, GSList *constraints) +{ + struct mode_change *changes; + int errors = 0; + glob_t result; + char *filename = NULL; + int flags = GLOB_NOCHECK; + int i, rc; + + changes = mode_compile (mode, + MODE_MASK_EQUALS | MODE_MASK_PLUS | MODE_MASK_MINUS); + if (changes == MODE_INVALID) DIE(1) + else if (changes == MODE_MEMORY_EXHAUSTED) DIE(1) + + for (; filelist; filelist = filelist->next) + { + filename = filelist->data; + rc = glob(filename, flags, glob_errfn, &result); + if (rc == GLOB_NOSPACE) DIE(1) + flags |= GLOB_APPEND; + } + if(single_file) { + rc = glob(single_file, flags, glob_errfn, &result); + if (rc == GLOB_NOSPACE) DIE(1) + } + + for (i = 0; i < result.gl_pathc; i++) { + if (!match_files(constraints, result.gl_pathv[i])) { + errors |= change_file (result.gl_pathv[i], changes, 1, user, group); +#if 0 + _pam_log(LOG_DEBUG, TRUE, + "file %s (%d): mode %s\n", result.gl_pathv[i], user, mode); +#endif + } + } + + globfree(&result); + + return (errors); +} diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/chmod.h Linux-PAM-1.1.3/modules/pam_console/chmod.h --- Linux-PAM-1.1.3.orig/modules/pam_console/chmod.h 1969-12-31 19:00:00.000000000 -0500 +++ Linux-PAM-1.1.3/modules/pam_console/chmod.h 2011-01-26 22:14:52.059406906 -0500 @@ -0,0 +1,11 @@ +#include + +#ifndef _CHMOD_H +#define _CHMOD_H + +int +chmod_files(const char *mode, uid_t user, gid_t group, char *fname, GSList *filelist, GSList *constraints); +void +chmod_set_fstab(const char *fstab); + +#endif /* _CHMOD_H */ diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/configfile.c Linux-PAM-1.1.3/modules/pam_console/configfile.c --- Linux-PAM-1.1.3.orig/modules/pam_console/configfile.c 1969-12-31 19:00:00.000000000 -0500 +++ Linux-PAM-1.1.3/modules/pam_console/configfile.c 2011-01-26 22:14:52.062657563 -0500 @@ -0,0 +1,58 @@ +#include +#include +#include "configfile.h" + +void * +_do_malloc(size_t req) +{ + void *ret; + ret = malloc(req); + if (!ret) abort(); + return ret; +} + +GSList * +g_slist_prepend(GSList *l, void *d) +{ + GSList *memb; + memb = _do_malloc(sizeof(*memb)); + memb->next = l; + memb->data = d; + return memb; +} + +GSList * +g_slist_append(GSList *l, void *d) +{ + GSList *memb, *n; + memb = _do_malloc(sizeof(*memb)); + memb->next = NULL; + memb->data = d; + + if (l == NULL) { + return memb; + } + + n = l; + while (n->next != NULL) { + n = n->next; + } + n->next = memb; + + return l; +} + +void +g_slist_free(GSList *l) +{ + GSList *n; + while (l != NULL) { + n = l->next; + free(l); + l = n; + } +} + +#include "configfile.lex.c" +#include "configfile.tab.c" + diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/configfile.h Linux-PAM-1.1.3/modules/pam_console/configfile.h --- Linux-PAM-1.1.3.orig/modules/pam_console/configfile.h 1969-12-31 19:00:00.000000000 -0500 +++ Linux-PAM-1.1.3/modules/pam_console/configfile.h 2011-01-26 22:14:52.062657563 -0500 @@ -0,0 +1,64 @@ +/* Copyright 1999, 2005 Red Hat, Inc. + * This software may be used under the terms of the GNU General Public + * License, available in the file COPYING accompanying this file. + */ +#ifndef _CONFIGFILE_H +#define _CONFIGFILE_H +#define STATIC static + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +/* GSList reimplementation */ + +typedef struct GSList_s GSList; +struct GSList_s { + void *data; + GSList *next; +}; + +typedef struct class_s class; +struct class_s { + char* name; + GSList* list; +}; + +typedef struct config_s config; +struct config_s { + class* console_class; + char* mode; + class* device_class; + char* revert_mode; + char* revert_owner; + char* revert_group; +}; + +GSList * +g_slist_prepend(GSList *l, void *d); + +GSList * +g_slist_append(GSList *l, void *d); + +void +g_slist_free(GSList *l); + +void +parse_file(const char *name); + +int +check_console_name (const char *consolename); + +int +set_permissions(const char *consolename, const char *username, GSList *files); + +int +reset_permissions(const char *consolename, GSList *files); + +void * +_do_malloc(size_t req); + +#endif /* _CONFIGFILE_H */ diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/configfile.l Linux-PAM-1.1.3/modules/pam_console/configfile.l --- Linux-PAM-1.1.3.orig/modules/pam_console/configfile.l 1969-12-31 19:00:00.000000000 -0500 +++ Linux-PAM-1.1.3/modules/pam_console/configfile.l 2011-01-26 22:14:52.062657563 -0500 @@ -0,0 +1,66 @@ +%option noyywrap +%{ +/* Copyright 1999,2000 Red Hat, Inc. + * This software may be used under the terms of the GNU General Public + * License, available in the file COPYING accompanying this file + */ +/* get around an apparant bug in bison; YYSTYPE not copied into config.tab.h */ +#define YYSTYPE void * +#include "configfile.h" +#include "configfile.tab.h" +#include +#include +#include + +#include "pam_console.h" + +static int lineno; +static const char *filename; + +STATIC char * +strip_slash(const char *); +%} +%% +\n { lineno++; return EOL; } +\\\n { lineno++; } + /* do not return EOL, eat up escaped newline */ +[ \t]+ /* ignore whitespace */ +\< { return OBRACKET; } +\>= { return CBEQUALS; } +\> { return CBRACKET; } +([^\t\n #\<\>]|(\\#|\\\<|\\\>))+ { _pc_yylval=strip_slash(yytext); return STRING; } +#.*\n { lineno++; return EOL; } /* ignore comments */ +%% + +static void +lex_file (FILE *in) { + /* yy_flex_debug = 1; */ + yyin = in; + lineno = 1; +} + +static void +lex_set_filename(const char *name) { + filename = name; +} + +static int +_pc_yyerror (const char *s) { + _pam_log(NULL, LOG_ERR, 0, "%s line %d: %s: at `%s'\n", + filename, lineno, s, (char *)_pc_yylval); + return 0; +} + +STATIC char * +strip_slash(const char *s) { + char *r, *t; + + t = r = strdup(s); + while ((t = strchr(t, '\\')) != NULL) { + if (t[1] == '#' || t[1] == '<' || t[1] == '>') { + memmove(t, t+1, strlen(t)); + } + t++; + } + return r; +} diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/configfile.y Linux-PAM-1.1.3/modules/pam_console/configfile.y --- Linux-PAM-1.1.3.orig/modules/pam_console/configfile.y 1969-12-31 19:00:00.000000000 -0500 +++ Linux-PAM-1.1.3/modules/pam_console/configfile.y 2011-01-26 22:14:52.062657563 -0500 @@ -0,0 +1,336 @@ +%{ +/* Copyright 1999,2000 Red Hat, Inc. + * This software may be used under the terms of the GNU General Public + * License, available in the file COPYING accompanying this file + */ +#define YYSTYPE void * + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +typedef struct hashtable GHashTable; + +static GHashTable *namespace = NULL; +static GSList *configList = NULL; +static GSList *configListEnd = NULL; +static GSList *consoleClassList = NULL; +static GSList *consoleClassListEnd = NULL; +static const char *consoleNameCache = NULL; +static GHashTable *consoleHash = NULL; + +static void +do_yyerror(const char *format, ...); + +static void +empty_class(class *c); + +static unsigned int +str_hash(unsigned char *s) +{ + unsigned int hash = 5381; + int c; + + while ((c = *s++)) + hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ + + return hash; +} + +static int +str_equal(void *a, void *b) +{ + return strcmp(a, b) == 0; +} + +static unsigned int +ptr_hash(void *p) +{ + return (unsigned long)p >> 3; +} + +static int +ptr_equal(void *a, void *b) +{ + return a == b; +} + +%} + +%token EOL +%token OBRACKET +%token CBEQUALS +%token CBRACKET +%token STRING + +%% +lines: lines line + | /* empty */ + ; + +line: config + | classdef + | EOL + | error + ; + +classdef: + OBRACKET string CBEQUALS stringlist EOL { + class *c; + + c = hashtable_search(namespace, $2); + if (c) { + empty_class(c); + } else { + c = malloc(sizeof(class)); + hashtable_insert(namespace, strdup($2), c); + } + c->name = $2; + c->list = $4; + } + ; + +config: classlist STRING classlist optstring optstring EOL { + config *conf = malloc(sizeof(config)); + conf->console_class = $1; + conf->mode = $2; + conf->device_class = $3; + conf->revert_mode = $4; + conf->revert_owner = $5; + if (conf->revert_owner != NULL) { + conf->revert_group = strchr (conf->revert_owner, ':'); + if (conf->revert_group == NULL) + conf->revert_group = strchr (conf->revert_owner, '.'); + if (conf->revert_group != NULL) { + *(conf->revert_group) = '\0'; + conf->revert_group++; + if (*(conf->revert_group) == '\0') + conf->revert_group = NULL; + if (*(conf->revert_owner) == '\0') + conf->revert_owner = NULL; + } + } else { + conf->revert_group = NULL; + } + configListEnd = g_slist_append(configListEnd, conf); + if (configListEnd->next) configListEnd = configListEnd->next; + if (!configList) configList = configListEnd; + consoleClassListEnd = + g_slist_append(consoleClassListEnd, conf->console_class); + if (consoleClassListEnd->next) + consoleClassListEnd = consoleClassListEnd->next; + if (!consoleClassList) consoleClassList = consoleClassListEnd; + } + ; + +classlist: OBRACKET string CBRACKET { + class *c = hashtable_search(namespace, $2); + if(!c) { + _pam_log(NULL, LOG_ERR, FALSE, + "unknown class \"%s\" at line %d in %s\n", + (const char *)$2, lineno, filename); + YYERROR; + } + $$ = c; + } + | string { + class *c = malloc(sizeof(class)); + c->name = $1; + c->list = NULL; + $$ = c; + } + ; + + +stringlist: string {$$ = g_slist_append(NULL, $1);} + | stringlist string {$$ = g_slist_append($1, $2);} + ; + +optstring: string {$$=$1;} + | /* empty */ {$$=NULL;} + ; + +string: STRING {$$=$1;} ; + +%% + +/* exported functions */ + +/* parse a file given by a name */ +void +parse_file(const char *name) { + FILE *infile; + + _pam_log(NULL, LOG_DEBUG, TRUE, "parsing config file %s", name); + infile = fopen(name, "r"); + if (!infile) { + _pam_log(NULL, LOG_ERR, FALSE, "could not parse required file %s", name); + return; + } + + if (!namespace) namespace = create_hashtable(128, (unsigned int (*)(void *))str_hash, str_equal); + + lex_set_filename(name); + lex_file(infile); + + yyparse(); + fclose(infile); +} + +static int +check_one_console_name (const char *name, char *classComponent) { + regex_t p; + int r_err; + char *class_exp; + + class_exp = _do_malloc(strlen(classComponent) + 3); + sprintf(class_exp, "^%s$", classComponent); + r_err = regcomp(&p, class_exp, REG_EXTENDED|REG_NOSUB); + if (r_err) do_regerror(r_err, &p); + r_err = regexec(&p, name, 0, NULL, 0); + regfree(&p); + free (class_exp); + return !r_err; +} + +int +check_console_name (const char *consolename) { + GSList *this_class; + GSList *this_list; + class *c; + int found = 0; + + _pam_log(NULL, LOG_DEBUG, TRUE, "check console %s", consolename); + if (consoleNameCache != consolename) { + consoleNameCache = consolename; + if (consoleHash) hashtable_destroy(consoleHash, 0); + consoleHash = create_hashtable(128, ptr_hash, ptr_equal); + } + for (this_class = consoleClassList; this_class; + this_class = this_class->next) { + c = this_class->data; + if (c->list) { + for (this_list = c->list; this_list; this_list = this_list->next) { + if (check_one_console_name(consolename, this_list->data)) { + hashtable_insert(consoleHash, c, c); + found = 1; + } + } + } else { + if (check_one_console_name(consolename, c->name)) { + hashtable_insert(consoleHash, c, c); + found = 1; + } + } + } + + if (found) + return 1; + + /* not found */ + _pam_log(NULL, LOG_INFO, TRUE, "did not find console %s", consolename); + if (consoleHash) { + hashtable_destroy(consoleHash, 0); + consoleHash = NULL; + } + return 0; +} + +int +set_permissions(const char *consolename, const char *username, GSList *files) { + struct passwd *pwd; + config *c; + GSList *cl; + + if (!consoleNameCache || strcmp(consolename, consoleNameCache)) { + if (!check_console_name(consolename)) return -1; + } + + pwd = getpwnam(username); + if (pwd == NULL) { + _pam_log(NULL, LOG_ERR, FALSE, "getpwnam failed for \"%s\"", username); + return -1; + } + + for (cl = configList; cl; cl = cl->next) { + c = cl->data; + if (hashtable_search(consoleHash, c->console_class)) { + if (c->device_class->list) + chmod_files(c->mode, pwd->pw_uid, -1, NULL, c->device_class->list, files); + else + chmod_files(c->mode, pwd->pw_uid, -1, c->device_class->name, NULL, files); + } + } + return 0; +} + +int +reset_permissions(const char *consolename, GSList *files) { + struct passwd *pwd; + struct group *grp; + config *c; + GSList *cl; + + if (!consoleNameCache || strcmp(consolename, consoleNameCache)) { + if (!check_console_name(consolename)) return -1; + } + + for (cl = configList; cl; cl = cl->next) { + c = cl->data; + if (hashtable_search(consoleHash, c->console_class)) { + pwd = getpwnam(c->revert_owner ? c->revert_owner : "root"); + if (pwd == NULL) { + _pam_log(NULL, LOG_ERR, FALSE, "getpwnam failed for %s", + c->revert_owner ? c->revert_owner : "root"); + return -1; + } + grp = getgrnam(c->revert_group ? c->revert_group : "root"); + if (grp == NULL) { + _pam_log(NULL, LOG_ERR, FALSE, "getgrnam failed for %s", + c->revert_group ? c->revert_group : "root"); + return -1; + } + if (c->device_class->list) + chmod_files(c->revert_mode ? c->revert_mode : "0600", + pwd->pw_uid, grp->gr_gid, NULL, c->device_class->list, files); + else + chmod_files(c->revert_mode ? c->revert_mode : "0600", + pwd->pw_uid, grp->gr_gid, c->device_class->name, NULL, files); + } + } + return 0; +} + + + + +/* local, static functions */ + +static void +do_yyerror(const char *format, ...) { + va_list ap; + + va_start(ap, format); + openlog("pam_console", LOG_CONS|LOG_PID, LOG_AUTHPRIV); + vsyslog(LOG_PID|LOG_AUTHPRIV|LOG_ERR, format, ap); + va_end(ap); +} + +static void +empty_class(class *c) { + free(c->name); + c->name = NULL; + g_slist_free(c->list); + c->list = NULL; +} diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/console.apps.5 Linux-PAM-1.1.3/modules/pam_console/console.apps.5 --- Linux-PAM-1.1.3.orig/modules/pam_console/console.apps.5 1969-12-31 19:00:00.000000000 -0500 +++ Linux-PAM-1.1.3/modules/pam_console/console.apps.5 2011-01-26 22:14:52.062657563 -0500 @@ -0,0 +1,18 @@ +.\" Copyright 1999 Red Hat Software, Inc. +.\" Written by Michael K. Johnson +.TH console.apps 5 1999/2/4 "Red Hat Software" "System Administrator's Manual" +.SH NAME +console.apps \- specify console-accessible privileged applications +.SH DESCRIPTION +The /etc/security/console.apps/ directory should contain one file +per application that wishes to allow access to console users. +The filename should be the same as the servicename, and the +contents are irrelevant; the file may be a zero-length file. +The application that the file is used by is free to specify the +contents in any way that is useful for it. +.SH "SEE ALSO" +.BR pam_console (8) +.br +.BR console.perms (5) +.SH AUTHOR +Michael K. Johnson diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/console.handlers Linux-PAM-1.1.3/modules/pam_console/console.handlers --- Linux-PAM-1.1.3.orig/modules/pam_console/console.handlers 1969-12-31 19:00:00.000000000 -0500 +++ Linux-PAM-1.1.3/modules/pam_console/console.handlers 2011-01-26 22:14:52.062657563 -0500 @@ -0,0 +1,22 @@ +# /etc/security/console.handlers +# +# This file is provided for configuration of handlers which will be +# executed when user obtains console lock and when he loses it. +# Additionally it is used for a configuration of console device names. +# +# Format: +# name consoledevs regex regex ... +# binary lock|unlock flag flag ... +# See man console.handlers +# +# Example: +# console consoledevs tty[0-9][0-9]* vc/[0-9][0-9]* :[0-9]\.[0-9] :[0-9] +# echo lock wait Locking console for user on tty +# touch unlock wait /var/run/console-unlocked + +console consoledevs tty[0-9][0-9]* vc/[0-9][0-9]* :[0-9]\.[0-9] :[0-9] +/sbin/pam_console_apply lock logfail wait -t tty -s +/sbin/pam_console_apply unlock logfail wait -r -t tty -s +# initialize dmix for alsa sound +/usr/bin/ainit lock user start +/usr/bin/ainit unlock user stop diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/console.handlers.5 Linux-PAM-1.1.3/modules/pam_console/console.handlers.5 --- Linux-PAM-1.1.3.orig/modules/pam_console/console.handlers.5 1969-12-31 19:00:00.000000000 -0500 +++ Linux-PAM-1.1.3/modules/pam_console/console.handlers.5 2011-01-26 22:14:52.062657563 -0500 @@ -0,0 +1,46 @@ +.\" Copyright 2005 Red Hat Software, Inc. +.\" Written by Tomas Mraz +.TH console.handlers 5 2005/3/18 "Red Hat" "System Administrator's Manual" +.SH NAME +console.handlers \- file specifying handlers of console lock and unlock events +.SH DESCRIPTION +/etc/security/console.handlers determines which programs will be run when an +user obtains the console lock at login time, and when the user loses it +on log out. It is read by the pam_console module. + +The format is: + +\fBhandler-filename\fP \fBlock\fP\fI|\fP\fBunlock\fP \fI[\fP\fBflag ...\fP\fI]\fP + +Where \fBhandler-filename\fP is a name of the executable to be run, \fBlock\fP or +\fBunlock\fP specifies on which event it should be run, and flags specify how +should pam_console call it. + +Additionally there should be a line which specifies glob patterns of console devices. + +The format of this line is: +\fBconsole-name\fP \fBconsoledevs\fP \fBregex\fP \fI[\fP\fBregex ...\fP\fI]\fP + +Where \fBconsole-name\fP is a name of the console class - currently ignored - and +regexes are regular expression patterns which specify the name of the tty device. +Only the first such line is consulted. + +.SH FLAGS +.IP logfail +The pam_console module should log error to the system log if the return value of the +handler is not zero or if the handler can not be executed. +.IP wait +The pam_console should wait for the handler to exit before continuing. +.IP setuid +The handler should be executed with uid/gid of the user which obtained the +console lock. +.IP tty +The handler will get a tty name as obtained from PAM as a parameter. +.IP user +The handler will get an user name as obtained from PAM as a parameter. +.PP +Anything else will be added directly as a parameter to the handler executable. +.SH "SEE ALSO" +.BR pam_console (8) +.SH AUTHOR +Tomas Mraz diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/console.perms Linux-PAM-1.1.3/modules/pam_console/console.perms --- Linux-PAM-1.1.3.orig/modules/pam_console/console.perms 1969-12-31 19:00:00.000000000 -0500 +++ Linux-PAM-1.1.3/modules/pam_console/console.perms 2011-01-26 22:14:52.062657563 -0500 @@ -0,0 +1,25 @@ +# /etc/security/console.perms +# +# This file determines 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. + +# format is: +# =list of regexps specifying consoles or globs specifying files +# file-glob| perm dev-regex| \ +# revert-mode revert-owner[.revert-group] +# the revert-mode, revert-owner, and revert-group are optional, and default +# to 0600, root, and root, respectively. +# +# 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 -- see console.perms.d/50-default.perms +# permission definitions -- see console.perms.d/50-default.perms diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/console.perms.5 Linux-PAM-1.1.3/modules/pam_console/console.perms.5 --- Linux-PAM-1.1.3.orig/modules/pam_console/console.perms.5 1969-12-31 19:00:00.000000000 -0500 +++ Linux-PAM-1.1.3/modules/pam_console/console.perms.5 2011-01-26 22:14:52.062657563 -0500 @@ -0,0 +1,50 @@ +.\" Copyright 1999,2005 Red Hat Software, Inc. +.\" Written by Michael K. Johnson +.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 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. They are +read by the pam_console_apply helper executable. + +The format is: + +\f(CR<\fBclass\fR\f(CR>=\fBspace-separated list of words\fR + +\fBlogin-regexp\fR\fI|\fR\f(CR<\fBlogin-class\fR\f(CR> \fBperm dev-glob\fR\fI|\fR\f(CR<\fBdev-class\fR\f(CR> \e +.br +\f(CR \fBrevert-mode revert-owner\fR\fI[\fR\fP.revert-group\fI]\fR + +The \fBrevert-mode\fP, \fBrevert-owner\fP, and revert-group fields are optional, +and default to \fB0600\fP, \fBroot\fP, and \fBroot\fP, respectively. + +The words in a class definition are evaluated as globs if they +refer to files, but as regular expressions if they apply to a +console definition. Do not mix them. + +Any line can be broken and continued on the next line by using a +\e character as the last character on the line. + +The \fBlogin-class\fP class and the \fBlogin-regexp\fP word are evaluated as +regular expressions. +The \fBdev-class\fP and the \fBdev-glob\fP word are evaluated as +shell-style globs. If a name given corresponds to a directory, and +if it is a mount point listed in \fI/etc/fstab\fP, the device node +associated with the filesystem mounted at that point will be +substituted in its place. + +Classes are denoted by being contained in \f(CR<\fR angle bracket \f(CR>\fR +characters; a lack of \f(CR<\fR angle brackets \f(CR>\fR indicates that +the string is to be taken literally as a \fBlogin-regexp\fP or a +\fBdev-glob\fP, depending on its input position. +.SH "SEE ALSO" +.BR pam_console (8) +.br +.BR pam_console_apply (8) +.br +.BR console.apps (5) +.SH AUTHOR +Michael K. Johnson diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/handlers.c Linux-PAM-1.1.3/modules/pam_console/handlers.c --- Linux-PAM-1.1.3.orig/modules/pam_console/handlers.c 1969-12-31 19:00:00.000000000 -0500 +++ Linux-PAM-1.1.3/modules/pam_console/handlers.c 2011-01-26 22:14:52.062657563 -0500 @@ -0,0 +1,312 @@ +/* handlers.c -- execute handlers specified in handlers configuration file + Copyright (c) 2005 Red Hat, Inc. + Written by Tomas Mraz + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "handlers.h" +#include "pam_console.h" + +enum types { UNKNOWN, LOCK, UNLOCK, CONSOLEDEVS }; +enum flags { HF_LOGFAIL, HF_WAIT, HF_SETUID, HF_TTY, HF_USER, HF_PARAM }; + +struct console_handler { + char *executable; + enum types type; + char *flags; /* this is a double zero terminated array + allocated in one blob with executable */ + struct console_handler *next; +}; + +static struct console_handler *first_handler; + +static void +console_free_handlers (struct console_handler *handler) { + if (handler != NULL) { + console_free_handlers(handler->next); + free(handler->executable); + free(handler); + } +} + +int +console_parse_handlers (pam_handle_t *pamh, const char *handlers_name) { + FILE *fh; + char linebuf[HANDLERS_MAXLINELEN+1]; + int forget; + int skip = 0; + int rv = PAM_SESSION_ERR; + struct console_handler **previous_handler_ptr; + + fh = fopen(handlers_name, "r"); + if (fh == NULL) { + _pam_log(pamh, LOG_ERR, FALSE, "cannot open file %s for reading", handlers_name); + return rv; + } + + previous_handler_ptr = &first_handler; + + while (fgets(linebuf, sizeof(linebuf), fh) != NULL) + { + int len; + char *ptr; + char *tokptr; + char *temp; + char *destptr = NULL; /* needed to silence warning */ + struct console_handler *handler; + enum states { EXECUTABLE, TYPE, FLAGS } state; + + len = strlen(linebuf); + if (linebuf[len-1] != '\n') { + _pam_log(pamh, LOG_INFO, FALSE, "line too long or not ending with new line char - will be ignored"); + skip = 1; + continue; + } + if (skip) { + skip = 0; + continue; + } + linebuf[len-1] = '\0'; + if ((ptr=strchr(linebuf, '#')) != NULL) { + *ptr = '\0'; + } + for (ptr = linebuf; isspace(*ptr); ptr++); + if (*ptr == '\0') + continue; + + /* something on the line */ + if ((handler=calloc(sizeof(*handler), 1)) == NULL) + goto fail_exit; + *previous_handler_ptr = handler; + previous_handler_ptr = &handler->next; + + if ((handler->executable=malloc(len-(ptr-linebuf)+1)) == NULL) { + goto fail_exit; + } + + state = EXECUTABLE; + handler->type = UNKNOWN; + while ((tokptr=strtok_r(ptr, " \t", &temp)) != NULL) { + if (state == EXECUTABLE) { + strcpy(handler->executable, tokptr); + ptr = NULL; + handler->flags = destptr = handler->executable + strlen(handler->executable) + 1; + } + else if (state == TYPE) { + if (strcmp(tokptr, "lock") == 0) { + handler->type = LOCK; + } + else if (strcmp(tokptr, "unlock") == 0) { + handler->type = UNLOCK; + } + else if (strcmp(tokptr, "consoledevs") == 0) { + handler->type = CONSOLEDEVS; + } + } + + if (state == FLAGS) { + strcpy(destptr, tokptr); + destptr += strlen(destptr) + 1; + } + else { + state++; + } + } + *destptr = '\0'; + } + forget = fclose(fh); + + return PAM_SUCCESS; + +fail_exit: + console_free_handlers(first_handler); + return rv; +} + +static enum flags testflag(const char *flag) { + if (strcmp(flag, "logfail") == 0) { + return HF_LOGFAIL; + } + if (strcmp(flag, "wait") == 0) { + return HF_WAIT; + } + if (strcmp(flag, "setuid") == 0) { + return HF_SETUID; + } + if (strcmp(flag, "tty") == 0) { + return HF_TTY; + } + if (strcmp(flag, "user") == 0) { + return HF_USER; + } + return HF_PARAM; +} + +static void +call_exec(struct console_handler *handler, int nparams, const char *user, const char *tty) { + const char *flagptr; + const char **argv; + int i = 0; + argv = malloc(sizeof(*argv)*nparams+2); + + if (argv == NULL) + return; + + argv[i++] = handler->executable; + + for (flagptr = handler->flags; *flagptr != '\0'; flagptr += strlen(flagptr)+1) { + switch (testflag(flagptr)) { + case HF_LOGFAIL: + case HF_WAIT: + case HF_SETUID: + break; + case HF_TTY: + argv[i++] = tty; + break; + case HF_USER: + argv[i++] = user; + break; + case HF_PARAM: + argv[i++] = flagptr; + } + } + argv[i] = NULL; + execvp(handler->executable, (char * const *)argv); +} + +static int +execute_handler(pam_handle_t *pamh, struct console_handler *handler, const char *user, const char *tty) { + const char *flagptr; + int nparams = 0; + int logfail = 0; + int wait_exit = 0; + int set_uid = 0; + int child; + int rv = 0; + int max_fd; + int fd; + sighandler_t sighandler; + + for (flagptr = handler->flags; *flagptr != '\0'; flagptr += strlen(flagptr)+1) { + switch (testflag(flagptr)) { + case HF_LOGFAIL: + logfail = 1; + break; + case HF_WAIT: + wait_exit = 1; + break; + case HF_SETUID: + set_uid = 1; + break; + case HF_TTY: + case HF_USER: + case HF_PARAM: + nparams++; + } + } + + sighandler = signal(SIGCHLD, SIG_DFL); + + child = fork(); + switch (child) { + case -1: + _pam_log(pamh, LOG_ERR, !logfail, "fork failed when executing handler '%s'", + handler->executable); + return -1; + case 0: + /* close all descriptors except std* */ + max_fd = getdtablesize(); + for(fd = 3; fd < max_fd; fd++) + rv = close(fd); /* rv will be ignored */ + if (!wait_exit) { + switch(fork()) { + case 0: + exit(0); + case -1: + exit(255); + default: + if(setsid() == -1) { + exit(255); + } + } + } + if (set_uid) { + struct passwd *pw; + pw = getpwnam(user); + if (pw == NULL) + exit(255); + if (setgid(pw->pw_gid) == -1 || + setuid(pw->pw_uid) == -1) + exit(255); + } + call_exec(handler, nparams, user, tty); + exit(255); + default: + break; + } + + waitpid(child, &rv, 0); + + if (sighandler != SIG_ERR) + signal(SIGCHLD, sighandler); + + if (WIFEXITED(rv) && WEXITSTATUS(rv) != 0) + _pam_log(pamh, LOG_ERR, !logfail, "handler '%s' returned %d on exit", + handler->executable, (int)WEXITSTATUS(rv)); + else if (WIFSIGNALED(rv)) + _pam_log(pamh, LOG_ERR, !logfail, "handler '%s' caught a signal %d", + handler->executable, (int)WTERMSIG(rv)); + + return 0; +} + +void +console_run_handlers(pam_handle_t *pamh, int lock, const char *user, const char *tty) { + struct console_handler *handler; + + for (handler = first_handler; handler != NULL; handler = handler->next) { + if (lock && handler->type == LOCK) { + execute_handler(pamh, handler, user, tty); + } + else if (!lock && handler->type == UNLOCK) { + execute_handler(pamh, handler, user, tty); + } + } +} + +const char * +console_get_regexes(void) { + struct console_handler *handler; + + for (handler = first_handler; handler != NULL; handler = handler->next) { + if (handler->type == CONSOLEDEVS) { + return handler->flags; + } + } + return NULL; +} diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/handlers.h Linux-PAM-1.1.3/modules/pam_console/handlers.h --- Linux-PAM-1.1.3.orig/modules/pam_console/handlers.h 1969-12-31 19:00:00.000000000 -0500 +++ Linux-PAM-1.1.3/modules/pam_console/handlers.h 2011-01-26 22:14:52.062657563 -0500 @@ -0,0 +1,16 @@ +/* Copyright 2005 Red Hat, Inc. + * This software may be used under the terms of the GNU General Public + * License, available in the file COPYING accompanying this file. + */ +#ifndef _HANDLERS_H +#define _HANDLERS_H + +#include + +#define HANDLERS_MAXLINELEN 2000 + +int console_parse_handlers (pam_handle_t *pamh, const char *filename); +void console_run_handlers(pam_handle_t *pamh, int lock, const char *user, const char *tty); +const char *console_get_regexes(void); + +#endif /* _HANDLERS_H */ diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/hashtable.c Linux-PAM-1.1.3/modules/pam_console/hashtable.c --- Linux-PAM-1.1.3.orig/modules/pam_console/hashtable.c 1969-12-31 19:00:00.000000000 -0500 +++ Linux-PAM-1.1.3/modules/pam_console/hashtable.c 2011-01-26 22:14:52.062657563 -0500 @@ -0,0 +1,255 @@ +/* Copyright (C) 2004 Christopher Clark */ + +#include "hashtable.h" +#include "hashtable_private.h" +#include +#include +#include +#include + +/* +Credit for primes table: Aaron Krowne + http://br.endernet.org/~akrowne/ + http://planetmath.org/encyclopedia/GoodHashTablePrimes.html +*/ +static const unsigned int primes[] = { +53, 97, 193, 389, +769, 1543, 3079, 6151, +12289, 24593, 49157, 98317, +196613, 393241, 786433, 1572869, +3145739, 6291469, 12582917, 25165843, +50331653, 100663319, 201326611, 402653189, +805306457, 1610612741 +}; +const unsigned int prime_table_length = sizeof(primes)/sizeof(primes[0]); +const float max_load_factor = 0.65; + +/*****************************************************************************/ +struct hashtable * +create_hashtable(unsigned int minsize, + unsigned int (*hashf) (void*), + int (*eqf) (void*,void*)) +{ + struct hashtable *h; + unsigned int pindex, size = primes[0]; + /* Check requested hashtable isn't too large */ + if (minsize > (1u << 30)) return NULL; + /* Enforce size as prime */ + for (pindex=0; pindex < prime_table_length; pindex++) { + if (primes[pindex] > minsize) { size = primes[pindex]; break; } + } + h = (struct hashtable *)malloc(sizeof(struct hashtable)); + if (NULL == h) return NULL; /*oom*/ + h->table = (struct entry **)malloc(sizeof(struct entry*) * size); + if (NULL == h->table) { free(h); return NULL; } /*oom*/ + memset(h->table, 0, size * sizeof(struct entry *)); + h->tablelength = size; + h->primeindex = pindex; + h->entrycount = 0; + h->hashfn = hashf; + h->eqfn = eqf; + h->loadlimit = (unsigned int)(size * max_load_factor) + 1; + return h; +} + +/*****************************************************************************/ + +#define hash(h, k) h->hashfn(k) + +/*****************************************************************************/ +static int +hashtable_expand(struct hashtable *h) +{ + /* Double the size of the table to accomodate more entries */ + struct entry **newtable; + struct entry *e; + struct entry **pE; + unsigned int newsize, i, index; + /* Check we're not hitting max capacity */ + if (h->primeindex == (prime_table_length - 1)) return 0; + newsize = primes[++(h->primeindex)]; + + newtable = (struct entry **)malloc(sizeof(struct entry*) * newsize); + if (NULL != newtable) + { + memset(newtable, 0, newsize * sizeof(struct entry *)); + /* This algorithm is not 'stable'. ie. it reverses the list + * when it transfers entries between the tables */ + for (i = 0; i < h->tablelength; i++) { + while (NULL != (e = h->table[i])) { + h->table[i] = e->next; + index = indexFor(newsize,e->h); + e->next = newtable[index]; + newtable[index] = e; + } + } + free(h->table); + h->table = newtable; + } + /* Plan B: realloc instead */ + else + { + newtable = (struct entry **) + realloc(h->table, newsize * sizeof(struct entry *)); + if (NULL == newtable) { (h->primeindex)--; return 0; } + h->table = newtable; + memset(newtable[h->tablelength], 0, newsize - h->tablelength); + for (i = 0; i < h->tablelength; i++) { + for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) { + index = indexFor(newsize,e->h); + if (index == i) + { + pE = &(e->next); + } + else + { + *pE = e->next; + e->next = newtable[index]; + newtable[index] = e; + } + } + } + } + h->tablelength = newsize; + h->loadlimit = (unsigned int)(newsize * max_load_factor) + 1; + return -1; +} + +/*****************************************************************************/ +unsigned int +hashtable_count(struct hashtable *h) +{ + return h->entrycount; +} + +/*****************************************************************************/ +int +hashtable_insert(struct hashtable *h, void *k, void *v) +{ + /* This method allows duplicate keys - but they shouldn't be used */ + unsigned int index; + struct entry *e; + if (++(h->entrycount) > h->loadlimit) + { + /* Ignore the return value. If expand fails, we should + * still try cramming just this value into the existing table + * -- we may not have memory for a larger table, but one more + * element may be ok. Next time we insert, we'll try expanding again.*/ + hashtable_expand(h); + } + e = (struct entry *)malloc(sizeof(struct entry)); + if (NULL == e) { --(h->entrycount); return 0; } /*oom*/ + e->h = hash(h,k); + index = indexFor(h->tablelength,e->h); + e->k = k; + e->v = v; + e->next = h->table[index]; + h->table[index] = e; + return -1; +} + +/*****************************************************************************/ +void * /* returns value associated with key */ +hashtable_search(struct hashtable *h, void *k) +{ + struct entry *e; + unsigned int hashvalue, index; + hashvalue = hash(h,k); + index = indexFor(h->tablelength,hashvalue); + e = h->table[index]; + while (NULL != e) + { + /* Check hash value to short circuit heavier comparison */ + if ((hashvalue == e->h) && (h->eqfn(k, e->k))) return e->v; + e = e->next; + } + return NULL; +} + +/*****************************************************************************/ +void * /* returns value associated with key */ +hashtable_remove(struct hashtable *h, void *k, int free_key) +{ + /* TODO: consider compacting the table when the load factor drops enough, + * or provide a 'compact' method. */ + + struct entry *e; + struct entry **pE; + void *v; + unsigned int hashvalue, index; + + hashvalue = hash(h,k); + index = indexFor(h->tablelength,hash(h,k)); + pE = &(h->table[index]); + e = *pE; + while (NULL != e) + { + /* Check hash value to short circuit heavier comparison */ + if ((hashvalue == e->h) && (h->eqfn(k, e->k))) + { + *pE = e->next; + h->entrycount--; + v = e->v; + if (free_key) freekey(e->k); + free(e); + return v; + } + pE = &(e->next); + e = e->next; + } + return NULL; +} + +/*****************************************************************************/ +/* destroy */ +void +hashtable_destroy(struct hashtable *h, int free_kv) +{ + unsigned int i; + struct entry *e, *f; + struct entry **table = h->table; + if (free_kv) + { + for (i = 0; i < h->tablelength; i++) + { + e = table[i]; + while (NULL != e) + { f = e; e = e->next; freekey(f->k); free(f->v); free(f); } + } + } + free(h->table); + free(h); +} + +/* + * Copyright (c) 2002, Christopher Clark + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 COPYRIGHT OWNER + * OR CONTRIBUTORS 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. +*/ diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/hashtable.h Linux-PAM-1.1.3/modules/pam_console/hashtable.h --- Linux-PAM-1.1.3.orig/modules/pam_console/hashtable.h 1969-12-31 19:00:00.000000000 -0500 +++ Linux-PAM-1.1.3/modules/pam_console/hashtable.h 2011-01-26 22:14:52.062657563 -0500 @@ -0,0 +1,199 @@ +/* Copyright (C) 2002 Christopher Clark */ + +#ifndef __HASHTABLE_CWC22_H__ +#define __HASHTABLE_CWC22_H__ + +struct hashtable; + +/* Example of use: + * + * struct hashtable *h; + * struct some_key *k; + * struct some_value *v; + * + * static unsigned int hash_from_key_fn( void *k ); + * static int keys_equal_fn ( void *key1, void *key2 ); + * + * h = create_hashtable(16, hash_from_key_fn, keys_equal_fn); + * k = (struct some_key *) malloc(sizeof(struct some_key)); + * v = (struct some_value *) malloc(sizeof(struct some_value)); + * + * (initialise k and v to suitable values) + * + * if (! hashtable_insert(h,k,v) ) + * { exit(-1); } + * + * if (NULL == (found = hashtable_search(h,k) )) + * { printf("not found!"); } + * + * if (NULL == (found = hashtable_remove(h,k) )) + * { printf("Not found\n"); } + * + */ + +/* Macros may be used to define type-safe(r) hashtable access functions, with + * methods specialized to take known key and value types as parameters. + * + * Example: + * + * Insert this at the start of your file: + * + * DEFINE_HASHTABLE_INSERT(insert_some, struct some_key, struct some_value); + * DEFINE_HASHTABLE_SEARCH(search_some, struct some_key, struct some_value); + * DEFINE_HASHTABLE_REMOVE(remove_some, struct some_key, struct some_value); + * + * This defines the functions 'insert_some', 'search_some' and 'remove_some'. + * These operate just like hashtable_insert etc., with the same parameters, + * but their function signatures have 'struct some_key *' rather than + * 'void *', and hence can generate compile time errors if your program is + * supplying incorrect data as a key (and similarly for value). + * + * Note that the hash and key equality functions passed to create_hashtable + * still take 'void *' parameters instead of 'some key *'. This shouldn't be + * a difficult issue as they're only defined and passed once, and the other + * functions will ensure that only valid keys are supplied to them. + * + * The cost for this checking is increased code size and runtime overhead + * - if performance is important, it may be worth switching back to the + * unsafe methods once your program has been debugged with the safe methods. + * This just requires switching to some simple alternative defines - eg: + * #define insert_some hashtable_insert + * + */ + +/***************************************************************************** + * create_hashtable + + * @name create_hashtable + * @param minsize minimum initial size of hashtable + * @param hashfunction function for hashing keys + * @param key_eq_fn function for determining key equality + * @return newly created hashtable or NULL on failure + */ + +struct hashtable * +create_hashtable(unsigned int minsize, + unsigned int (*hashfunction) (void*), + int (*key_eq_fn) (void*,void*)); + +/***************************************************************************** + * hashtable_insert + + * @name hashtable_insert + * @param h the hashtable to insert into + * @param k the key - hashtable claims ownership and will free on removal + * @param v the value - does not claim ownership + * @return non-zero for successful insertion + * + * This function will cause the table to expand if the insertion would take + * the ratio of entries to table size over the maximum load factor. + * + * This function does not check for repeated insertions with a duplicate key. + * The value returned when using a duplicate key is undefined -- when + * the hashtable changes size, the order of retrieval of duplicate key + * entries is reversed. + * If in doubt, remove before insert. + */ + +int +hashtable_insert(struct hashtable *h, void *k, void *v); + +#define DEFINE_HASHTABLE_INSERT(fnname, keytype, valuetype) \ +int fnname (struct hashtable *h, keytype *k, valuetype *v) \ +{ \ + return hashtable_insert(h,k,v); \ +} + +/***************************************************************************** + * hashtable_search + + * @name hashtable_search + * @param h the hashtable to search + * @param k the key to search for - does not claim ownership + * @return the value associated with the key, or NULL if none found + */ + +void * +hashtable_search(struct hashtable *h, void *k); + +#define DEFINE_HASHTABLE_SEARCH(fnname, keytype, valuetype) \ +valuetype * fnname (struct hashtable *h, keytype *k) \ +{ \ + return (valuetype *) (hashtable_search(h,k)); \ +} + +/***************************************************************************** + * hashtable_remove + + * @name hashtable_remove + * @param h the hashtable to remove the item from + * @param k the key to search for - does not claim ownership + * @return the value associated with the key, or NULL if none found + */ + +void * /* returns value */ +hashtable_remove(struct hashtable *h, void *k, int free_key); + +#define DEFINE_HASHTABLE_REMOVE(fnname, keytype, valuetype) \ +valuetype * fnname (struct hashtable *h, keytype *k) \ +{ \ + return (valuetype *) (hashtable_remove(h,k)); \ +} + + +/***************************************************************************** + * hashtable_count + + * @name hashtable_count + * @param h the hashtable + * @return the number of items stored in the hashtable + */ +unsigned int +hashtable_count(struct hashtable *h); + + +/***************************************************************************** + * hashtable_destroy + + * @name hashtable_destroy + * @param h the hashtable + * @param free_values whether to call 'free' on the remaining values + */ + +void +hashtable_destroy(struct hashtable *h, int free_values); + +#endif /* __HASHTABLE_CWC22_H__ */ + +/* + * Copyright (c) 2002, Christopher Clark + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 COPYRIGHT OWNER + * OR CONTRIBUTORS 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. +*/ diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/hashtable_private.h Linux-PAM-1.1.3/modules/pam_console/hashtable_private.h --- Linux-PAM-1.1.3.orig/modules/pam_console/hashtable_private.h 1969-12-31 19:00:00.000000000 -0500 +++ Linux-PAM-1.1.3/modules/pam_console/hashtable_private.h 2011-01-26 22:14:52.062657563 -0500 @@ -0,0 +1,85 @@ +/* Copyright (C) 2002, 2004 Christopher Clark */ + +#ifndef __HASHTABLE_PRIVATE_CWC22_H__ +#define __HASHTABLE_PRIVATE_CWC22_H__ + +#include "hashtable.h" + +/*****************************************************************************/ +struct entry +{ + void *k, *v; + unsigned int h; + struct entry *next; +}; + +struct hashtable { + unsigned int tablelength; + struct entry **table; + unsigned int entrycount; + unsigned int loadlimit; + unsigned int primeindex; + unsigned int (*hashfn) (void *k); + int (*eqfn) (void *k1, void *k2); +}; + +/*****************************************************************************/ +unsigned int +hash(struct hashtable *h, void *k); + +/*****************************************************************************/ +/* indexFor */ +static inline unsigned int +indexFor(unsigned int tablelength, unsigned int hashvalue) { + return (hashvalue % tablelength); +}; + +/* Only works if tablelength == 2^N */ +/*static inline unsigned int +indexFor(unsigned int tablelength, unsigned int hashvalue) +{ + return (hashvalue & (tablelength - 1u)); +} +*/ + +/*****************************************************************************/ +#define freekey(X) free(X) +/*define freekey(X) ; */ + + +/*****************************************************************************/ + +#endif /* __HASHTABLE_PRIVATE_CWC22_H__*/ + +/* + * Copyright (c) 2002, Christopher Clark + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 COPYRIGHT OWNER + * OR CONTRIBUTORS 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. +*/ diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/modechange.c Linux-PAM-1.1.3/modules/pam_console/modechange.c --- Linux-PAM-1.1.3.orig/modules/pam_console/modechange.c 1969-12-31 19:00:00.000000000 -0500 +++ Linux-PAM-1.1.3/modules/pam_console/modechange.c 2011-01-26 22:14:52.062657563 -0500 @@ -0,0 +1,324 @@ +/* This file is derived from modechange.c included in the GNU fileutils + distribution. It has been changed to be a library specifically + for use within pam_console + Changes Copyright 1999 Red Hat Software, Inc. + */ + +/* modechange.c -- file mode manipulation + Copyright (C) 1989, 1990 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by David MacKenzie */ + +/* The ASCII mode string is compiled into a linked list of `struct + modechange', which can then be applied to each file to be changed. + We do this instead of re-parsing the ASCII string for each file + because the compiled form requires less computation to use; when + changing the mode of many files, this probably results in a + performance gain. */ + +#include "config.h" +#include +#include +#include "modechange.h" + +#include + +/* Return newly allocated memory to hold one element of type TYPE. */ +#define talloc(type) ((type *) malloc (sizeof (type))) + +#define isodigit(c) ((c) >= '0' && (c) <= '7') + +/* Return a positive integer containing the value of the ASCII + octal number S. If S is not an octal number, return -1. */ + +static int +oatoi (const char *s) +{ + register int i; + + if (*s == 0) + return -1; + for (i = 0; isodigit (*s); ++s) + i = i * 8 + *s - '0'; + if (*s) + return -1; + return i; +} + +/* Return a linked list of file mode change operations created from + MODE_STRING, an ASCII string that contains either an octal number + specifying an absolute mode, or symbolic mode change operations with + the form: + [ugoa...][[+-=][rwxXstugo...]...][,...] + MASKED_OPS is a bitmask indicating which symbolic mode operators (=+-) + should not affect bits set in the umask when no users are given. + Operators not selected in MASKED_OPS ignore the umask. + + Return MODE_INVALID if `mode_string' does not contain a valid + representation of file mode change operations; + return MODE_MEMORY_EXHAUSTED if there is insufficient memory. */ + +STATIC struct mode_change * +mode_compile (mode_string, masked_ops) + const char *mode_string; + unsigned masked_ops; +{ + struct mode_change *head; /* First element of the linked list. */ + struct mode_change *change; /* An element of the linked list. */ + int i; /* General purpose temporary. */ + int umask_value; /* The umask value (surprise). */ + unsigned short affected_bits; /* Which bits in the mode are operated on. */ + unsigned short affected_masked; /* `affected_bits' modified by umask. */ + unsigned ops_to_mask; /* Operators to actually use umask on. */ + + i = oatoi (mode_string); + if (i >= 0) + { + if (i > 07777) + return MODE_INVALID; + head = talloc (struct mode_change); + if (head == NULL) + return MODE_MEMORY_EXHAUSTED; + head->next = NULL; + head->op = '='; + head->flags = 0; + head->value = i; + head->affected = 07777; /* Affect all permissions. */ + return head; + } + + umask_value = umask (0); + umask (umask_value); /* Restore the old value. */ + + head = NULL; + change = NULL; + --mode_string; + + /* One loop iteration for each "ugoa...=+-rwxXstugo...[=+-rwxXstugo...]". */ + do + { + affected_bits = 0; + ops_to_mask = 0; + /* Turn on all the bits in `affected_bits' for each group given. */ + for (++mode_string;; ++mode_string) + switch (*mode_string) + { + case 'u': + affected_bits |= 04700; + break; + case 'g': + affected_bits |= 02070; + break; + case 'o': + affected_bits |= 01007; + break; + case 'a': + affected_bits |= 07777; + break; + default: + goto no_more_affected; + } + + no_more_affected: + /* If none specified, affect all bits, except perhaps those + set in the umask. */ + if (affected_bits == 0) + { + affected_bits = 07777; + ops_to_mask = masked_ops; + } + + while (*mode_string == '=' || *mode_string == '+' || *mode_string == '-') + { + /* Add the element to the tail of the list, so the operations + are performed in the correct order. */ + if (head == NULL) + { + head = talloc (struct mode_change); + if (head == NULL) + return MODE_MEMORY_EXHAUSTED; + change = head; + } + else + { + change->next = talloc (struct mode_change); + if (change->next == NULL) + { + mode_free (change); + return MODE_MEMORY_EXHAUSTED; + } + change = change->next; + } + + change->next = NULL; + change->op = *mode_string; /* One of "=+-". */ + affected_masked = affected_bits; + if (ops_to_mask & (*mode_string == '=' ? MODE_MASK_EQUALS + : *mode_string == '+' ? MODE_MASK_PLUS + : MODE_MASK_MINUS)) + affected_masked &= ~umask_value; + change->affected = affected_masked; + change->value = 0; + change->flags = 0; + + /* Set `value' according to the bits set in `affected_masked'. */ + for (++mode_string;; ++mode_string) + switch (*mode_string) + { + case 'r': + change->value |= 00444 & affected_masked; + break; + case 'w': + change->value |= 00222 & affected_masked; + break; + case 'X': + change->flags |= MODE_X_IF_ANY_X; + /* Fall through. */ + case 'x': + change->value |= 00111 & affected_masked; + break; + case 's': + /* Set the setuid/gid bits if `u' or `g' is selected. */ + change->value |= 06000 & affected_masked; + break; + case 't': + /* Set the "save text image" bit if `o' is selected. */ + change->value |= 01000 & affected_masked; + break; + case 'u': + /* Set the affected bits to the value of the `u' bits + on the same file. */ + if (change->value) + goto invalid; + change->value = 00700; + change->flags |= MODE_COPY_EXISTING; + break; + case 'g': + /* Set the affected bits to the value of the `g' bits + on the same file. */ + if (change->value) + goto invalid; + change->value = 00070; + change->flags |= MODE_COPY_EXISTING; + break; + case 'o': + /* Set the affected bits to the value of the `o' bits + on the same file. */ + if (change->value) + goto invalid; + change->value = 00007; + change->flags |= MODE_COPY_EXISTING; + break; + default: + goto no_more_values; + } + no_more_values:; + } + } while (*mode_string == ','); + if (*mode_string == 0) + return head; +invalid: + mode_free (head); + return MODE_INVALID; +} + +/* Return file mode OLDMODE, adjusted as indicated by the list of change + operations CHANGES. If OLDMODE is a directory, the type `X' + change affects it even if no execute bits were set in OLDMODE. + The returned value has the S_IFMT bits cleared. */ + +STATIC unsigned short +mode_adjust (oldmode, changes) + unsigned oldmode; + const struct mode_change *changes; +{ + unsigned short newmode; /* The adjusted mode and one operand. */ + unsigned short value; /* The other operand. */ + + newmode = oldmode & 07777; + + for (; changes; changes = changes->next) + { + if (changes->flags & MODE_COPY_EXISTING) + { + /* Isolate in `value' the bits in `newmode' to copy, given in + the mask `changes->value'. */ + value = newmode & changes->value; + + if (changes->value & 00700) + /* Copy `u' permissions onto `g' and `o'. */ + value |= (value >> 3) | (value >> 6); + else if (changes->value & 00070) + /* Copy `g' permissions onto `u' and `o'. */ + value |= (value << 3) | (value >> 3); + else + /* Copy `o' permissions onto `u' and `g'. */ + value |= (value << 3) | (value << 6); + + /* In order to change only `u', `g', or `o' permissions, + or some combination thereof, clear unselected bits. + This can not be done in mode_compile because the value + to which the `changes->affected' mask is applied depends + on the old mode of each file. */ + value &= changes->affected; + } + else + { + value = changes->value; + /* If `X', do not affect the execute bits if the file is not a + directory and no execute bits are already set. */ + if ((changes->flags & MODE_X_IF_ANY_X) + && !S_ISDIR (oldmode) + && (newmode & 00111) == 0) + value &= ~00111; /* Clear the execute bits. */ + } + + switch (changes->op) + { + case '=': + /* Preserve the previous values in `newmode' of bits that are + not affected by this change operation. */ + newmode = (newmode & ~changes->affected) | value; + break; + case '+': + newmode |= value; + break; + case '-': + newmode &= ~value; + break; + } + } + return newmode; +} + +/* Free the memory used by the list of file mode change operations + CHANGES. */ + +STATIC void +mode_free (changes) + register struct mode_change *changes; +{ + register struct mode_change *next; + + while (changes) + { + next = changes->next; + free (changes); + changes = next; + } +} + diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/modechange.h Linux-PAM-1.1.3/modules/pam_console/modechange.h --- Linux-PAM-1.1.3.orig/modules/pam_console/modechange.h 1969-12-31 19:00:00.000000000 -0500 +++ Linux-PAM-1.1.3/modules/pam_console/modechange.h 2011-01-26 22:14:52.062657563 -0500 @@ -0,0 +1,67 @@ +/* modechange.h -- definitions for file mode manipulation + Copyright (C) 1989, 1990 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _MODECHANGE_H +#define _MODECHANGE_H + +#ifndef STATIC +#define STATIC +#endif + + +/* Masks for the `flags' field in a `struct mode_change'. */ + +/* Affect the execute bits only if at least one execute bit is set already, + or if the file is a directory. */ +#define MODE_X_IF_ANY_X 01 + +/* If set, copy some existing permissions for u, g, or o onto the other two. + Which of u, g, or o is copied is determined by which bits are set in the + `value' field. */ +#define MODE_COPY_EXISTING 02 + +struct mode_change +{ + char op; /* One of "=+-". */ + char flags; /* Special operations. */ + unsigned short affected; /* Set for u/g/o/s/s/t, if to be affected. */ + unsigned short value; /* Bits to add/remove. */ + struct mode_change *next; /* Link to next change in list. */ +}; + +/* Masks for mode_compile argument. */ +#define MODE_MASK_EQUALS 1 +#define MODE_MASK_PLUS 2 +#define MODE_MASK_MINUS 4 + +/* Error return values for mode_compile. */ +#define MODE_INVALID (struct mode_change *) 0 +#define MODE_MEMORY_EXHAUSTED (struct mode_change *) 1 + +#ifndef __P +# if defined (__GNUC__) || (defined (__STDC__) && __STDC__) +# define __P(Args) Args +# else +# define __P(Args) () +# endif +#endif + +STATIC struct mode_change *mode_compile __P ((const char *, unsigned)); +STATIC unsigned short mode_adjust __P ((unsigned, const struct mode_change *)); +STATIC void mode_free __P ((struct mode_change *)); + +#endif /* _MODECHANGE_H */ diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/pam_console.8 Linux-PAM-1.1.3/modules/pam_console/pam_console.8 --- Linux-PAM-1.1.3.orig/modules/pam_console/pam_console.8 1969-12-31 19:00:00.000000000 -0500 +++ Linux-PAM-1.1.3/modules/pam_console/pam_console.8 2011-01-26 22:14:52.062657563 -0500 @@ -0,0 +1,105 @@ +.\" Copyright 1999 Red Hat Software, Inc. +.\" Written by Michael K. Johnson +.TH pam_console 8 2005/10/4 "Red Hat" "System Administrator's Manual" +.SH NAME +pam_console \- determine user owning the system console +.SH SYNOPSIS +.B session optional pam_console.so +.br +.B auth required pam_console.so +.SH DESCRIPTION +pam_console.so is designed to give users at the physical console +(virtual terminals and local xdm-managed X sessions by default, but +that is configurable) capabilities that they would not otherwise have, +and to take those capabilities away when the are no longer logged in at +the console. It provides two main kinds of capabilities: file permissions +and authentication. + +When a user logs in at the console and \fBno other user is currently +logged in at the console\fP, pam_console.so will run handler programs +specified in the file /etc/security/console.handlers such as +pam_console_apply which changes permissions and ownership of files as +described in the file /etc/security/console.perms. +That user may then log in on other terminals that are considered part +of the console, and as long as the user is still logged in at any one +of those terminals, that user will own those devices. When the user +logs out of the last terminal, the console may be taken by the next +user to log in. Other users who have logged in at the console during +the time that the first user was logged in will not be given ownership +of the devices unless they log in on one of the terminals; having done +so on any one terminal, the next user will own those devices until +he or she has logged out of every terminal that is part of the physical +console. Then the race can start for the next user. In practice, this +is not a problem; the physical console is not generally in use by many +people at the same time, and pam_console.so just tries to do the right +thing in weird cases. + +When an application attempts to authenticate the user \fBand this user +is already logged in at the console\fP, pam_console.so checks whether +there is a file in /etc/security/console.apps/ directory with the same name +as the application servicename, and if such a file exists, authentication +succeeds. This way pam_console may be utilized to run some system +applications (reboots, config tools) without root password, +or to enter user password on the first system login only. + +.SH ARGUMENTS +.IP debug +turns on debugging +.IP allow_nonroot_tty +gain console locks and change permissions even if the TTY's owner is not root. +.IP handlersfile=\fIfilename\fP +tells pam_console.so to get the list of the handlers from a different +file than /etc/security/console.handlers +.\" .IP glob +.\" \fBnot yet implemented\fP interpret strings as globs instead of +.\" regexp expressions. +.SH EXAMPLE +\fB/etc/pam.d/some-system-tool\fP: +.br +auth sufficient pam_rootok.so +.br +auth required pam_console.so +.br + +.br +\fB/etc/pam.d/some-login-service\fP: +.br +auth sufficient pam_console.so +.br +auth required pam_unix.so +.br +session required pam_unix.so +.br +session optional pam_console.so +.br +.SH FILES +\fI/var/run/console/\fP +.br +\fI/var/run/console/console.lock\fP +.br +\fI/etc/security/console.apps\fP +.br +\fI/etc/security/console.handlers\fP +.SH SECURITY NOTES +When pam_console "auth" is used for login services which provide +possibility of remote login, it is necessary to make sure the application +correctly sets PAM_RHOST variable, or to deny remote logins completely. +Currently, /bin/login (invoked from telnetd) and gdm is OK, others may be not. +.SH "SEE ALSO" +.BR console.perms (5) +.br +.BR console.apps (5) +.br +.BR console.handlers (5) +.br +.BR pam_console_apply (8) +.br +\fI/usr/share/doc/pam*/html/index.html\fP +.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 AUTHORS +Michael K. Johnson +.br +Support of console.handlers and other improvements by +Tomas Mraz diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/pam_console.c Linux-PAM-1.1.3/modules/pam_console/pam_console.c --- Linux-PAM-1.1.3.orig/modules/pam_console/pam_console.c 1969-12-31 19:00:00.000000000 -0500 +++ Linux-PAM-1.1.3/modules/pam_console/pam_console.c 2011-01-26 22:14:52.062657563 -0500 @@ -0,0 +1,669 @@ +/* Copyright 1999, 2005 Red Hat, Inc. + * This software may be used under the terms of the GNU General Public + * License, available in the file COPYING accompanying this file. + * + * /var/run/console/console.lock is the file used to control access to + * devices. It is created when the first console user logs in, + * and that user has the control of the console until they have + * logged out of all concurrent login sessions. That is, + * user A logs in on console 1 (gets access to console devices) + * user B logs in on console 2 (does not get access) + * user A logs in on console 3 (already has access) + * user A logs out of console 1 (still has access on console 3) + * user A logs out of console 3 (access revoked; user B does NOT get access) + * Note that all console users (both A and B in this situation) + * should be able to run console access programs (that is, + * pam_sm_authenticate() should return PAM_SUCCESS) even if + * console access to files/devices is not available to any one of + * the users (B in this case). + * + * /var/run/console/ is used for reference counting + * and to make console authentication easy -- if it exists, then + * has console access. + * + * A system startup script should remove /var/run/console/console.lock + * and everything in /var/run/console/ + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pam_console.h" +#include "handlers.h" +#include +#include +#include +#include + +/* In order to avoid errors in pam_get_item(), we need a very + * unfortunate cast. This is a terrible design error in PAM + * that Linux-PAM slavishly follows. :-( + */ +#define CAST_ME_HARDER (const void**) + +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; +static int allow_nonroot_tty = 0; + +/* some syslogging */ + +void +_pam_log(pam_handle_t *pamh, int err, int debug_p, const char *format, ...) +{ + va_list args; + + if (debug_p && !debug) return; + + va_start(args, format); + pam_vsyslog(pamh, err, format, args); + closelog(); +} + +static void * +_do_malloc(size_t req) +{ + void *ret; + + ret = malloc(req); + if (!ret) abort(); + return ret; +} + +static void +_args_parse(pam_handle_t *pamh, int argc, const char **argv) +{ + for (; argc-- > 0; ++argv) { + if (!strcmp(*argv,"debug")) + debug = 1; + else if (!strcmp(*argv,"allow_nonroot_tty")) + allow_nonroot_tty = 1; + else if (!strncmp(*argv,"handlersfile=",13)) + if (strlen(*argv+13) < PATH_MAX) + strcpy(consolehandlers,*argv+13); + else + _pam_log(pamh, LOG_ERR, FALSE, + "_args_parse: handlersfile filename too long"); + else { + _pam_log(pamh, LOG_ERR, FALSE, + "_args_parse: unknown option; %s",*argv); + } + } +} + +static int +is_root(pam_handle_t *pamh, const char *username) { + /* this should correspond to suser() in the kernel, since the + * whole point of this is to avoid doing unnecessary file ops + */ + struct passwd *pwd; + + pwd = pam_modutil_getpwnam(pamh, username); + if (pwd == NULL) { + _pam_log(pamh, LOG_ERR, FALSE, "getpwnam failed for %s", username); + return 0; + } + return !pwd->pw_uid; +} + +static int +check_one_console_name(const char *name, const char *cregex) { + regex_t p; + int r_err; + char *class_exp; + + class_exp = _do_malloc(strlen(cregex) + 3); + sprintf(class_exp, "^%s$", cregex); + r_err = regcomp(&p, class_exp, REG_EXTENDED|REG_NOSUB); + if (r_err) do_regerror(r_err, &p); + r_err = regexec(&p, name, 0, NULL, 0); + regfree(&p); + free (class_exp); + return !r_err; +} + +static int +check_console_name(pam_handle_t *pamh, const char *consolename, int nonroot_ok, int on_set) { + int found = 0; + int statted = 0; + struct stat st; + char full_path[PATH_MAX]; + const char *consoleregex; + + _pam_log(pamh, LOG_DEBUG, TRUE, "check console %s", consolename); + + if ((consoleregex = console_get_regexes()) == NULL) { + /* probably a broken configuration */ + _pam_log(pamh, LOG_INFO, FALSE, "no console regexes in console.handlers config"); + return 0; + } + for (; *consoleregex != '\0'; consoleregex += strlen(consoleregex)+1) { + if (check_one_console_name(consolename, consoleregex)) { + found = 1; + break; + } + } + + if (!found) { + /* not found */ + _pam_log(pamh, LOG_INFO, TRUE, "no matching console regex found"); + return 0; + } + + /* add some policy here -- not really the PAM way of doing things, but + it gives us an extra measure of security in case of misconfiguration */ + memset(&st, 0, sizeof(st)); + statted = 0; + + _pam_log(pamh, LOG_DEBUG, TRUE, "checking possible console \"%s\"", consolename); + if (lstat(consolename, &st) != -1) { + statted = 1; + } + if (!statted) { + strcpy(full_path, "/dev/"); + strncat(full_path, consolename, + sizeof(full_path) - 1 - strlen(full_path)); + full_path[sizeof(full_path) - 1] = '\0'; + _pam_log(pamh, LOG_DEBUG, TRUE, "checking possible console \"%s\"", + full_path); + if (lstat(full_path, &st) != -1) { + statted = 1; + } + } + if (!statted && (consolename[0] == ':')) { + int l; + char *dot = NULL; + strcpy(full_path, "/tmp/.X11-unix/X"); + l = sizeof(full_path) - 1 - strlen(full_path); + dot = strchr(consolename + 1, '.'); + if (dot != NULL) { + l = (l < dot - consolename - 1) ? l : dot - consolename - 1; + } + strncat(full_path, consolename + 1, l); + full_path[sizeof(full_path) - 1] = '\0'; + _pam_log(pamh, LOG_DEBUG, TRUE, "checking possible console \"%s\"", + full_path); + if (lstat(full_path, &st) != -1) { + statted = 1; + } + else if (!on_set) { /* there is no X11 socket in case of X11 crash */ + _pam_log(pamh, LOG_DEBUG, TRUE, "can't find X11 socket to examine for %s probably due to X crash", consolename); + statted = 1; /* this will work because st.st_uid is 0 */ + } + } + + if (statted) { + int ok = 0; + if (st.st_uid == 0) { + _pam_log(pamh, LOG_DEBUG, TRUE, "console %s is owned by UID 0", consolename); + ok = 1; + } + if (S_ISCHR(st.st_mode)) { + _pam_log(pamh, LOG_DEBUG, TRUE, "console %s is a character device", consolename); + ok = 1; + } + if (!ok && !nonroot_ok) { + _pam_log(pamh, LOG_INFO, TRUE, "%s is not a valid console device because it is owned by UID %d and the allow_nonroot flag was not set", consolename, st.st_uid); + found = 0; + } + } else { + _pam_log(pamh, LOG_INFO, TRUE, "can't find device or X11 socket to examine for %s", consolename); + found = 0; + } + + if (found) + return 1; + + /* not found */ + _pam_log(pamh, LOG_INFO, TRUE, "did not find console %s", consolename); + return 0; +} + +static int +lock_console(pam_handle_t *pamh, const char *id) +{ + int fd, ret_val; + + fd = open(consolelock, O_RDWR|O_CREAT|O_EXCL, 0600); + if (fd < 0) { + _pam_log(pamh, LOG_INFO, TRUE, + "console file lock already in place %s", consolelock); + return -1; + } + ret_val = pam_modutil_write (fd, id, strlen(id)); + if (ret_val == -1) { + close(fd); + } + else { + ret_val = close(fd); + } + if (ret_val == -1) { + unlink(consolelock); + return -1; + } + return 0; +} + +/* warning, the following function uses goto for error recovery. + * If you can't stand goto, don't read this function. :-P + */ +static int +use_count(pam_handle_t *pamh, char *filename, int increment, int delete) +{ + int fd, err, val; + static int cache_fd = 0; + struct stat st; + struct flock lockinfo; + char *buf = NULL; + + if (cache_fd) { + fd = cache_fd; + cache_fd = 0; + /* the cached fd is always already locked */ + } else { +top: + fd = open(filename, O_RDWR|O_CREAT, 0600); + if (fd < 0) { + _pam_log(pamh, LOG_ERR, FALSE, + "Could not open lock file %s, disallowing console access", + filename); + return -1; + } + + lockinfo.l_type = F_WRLCK; + lockinfo.l_whence = SEEK_SET; + lockinfo.l_start = 0; + lockinfo.l_len = 0; + alarm(20); /* FIXME: what if caller has sigalrm masked? */ + err = fcntl(fd, F_SETLKW, &lockinfo); + alarm(0); + if (err == EAGAIN) { + /* if someone has locked the file and not written to it in + * at least 20 seconds, we assume they either forgot to unlock + * it or are catatonic -- chances are slim that they are in + * the middle of a read-write cycle and I don't want to make + * us lock users out. Perhaps I should just return PAM_SUCCESS + * instead and log the event? Kill the process holding the + * lock? Options abound... For now, we ignore it. + */ + fcntl(fd, F_GETLK, &lockinfo); + /* now lockinfo.l_pid == 0 implies that the lock was released + * by the other process between returning from the 20 second + * wait and calling fcntl again, not likely to ever happen, and + * not a problem other than cosmetics even if it does. + */ + _pam_log(pamh, LOG_ERR, FALSE, + "ignoring stale lock on file %s by process %d", + lockinfo.l_pid, filename); + } + + /* it is possible at this point that the file has been removed + * by a previous login; if this happens, we need to start over. + * Unfortunately, the only way to do this without potential stack + * trashing is a goto. + */ + if (access (filename, F_OK) < 0) { + close (fd); + goto top; + } + } + + + if (fstat (fd, &st)) { + _pam_log(pamh, LOG_ERR, FALSE, + "\"impossible\" fstat error on open fd for %s", filename); + err = -1; goto return_error; + } + buf = _do_malloc(st.st_size+2); /* size will never grow by more than one */ + if (st.st_size) { + buf[0] = '\0'; /* if read returns eof, need atoi to give us 0 */ + if (pam_modutil_read (fd, buf, st.st_size) == -1) { + _pam_log(pamh, LOG_ERR, FALSE, + "\"impossible\" read error on %s", filename); + err = -1; goto return_error; + } + if (lseek(fd, 0, SEEK_SET) == -1) { + _pam_log(pamh, LOG_ERR, FALSE, + "\"impossible\" lseek error on %s", filename); + err = -1; goto return_error; + } + buf[st.st_size] = '\0'; + val = atoi(buf); + } else { + val = 0; + } + + if (increment) { /* increment == 0 implies query */ + val += increment; + if (val <= 0 && delete) { + if (unlink (filename)) { + _pam_log(pamh, LOG_ERR, FALSE, + "\"impossible\" unlink error on %s", filename); + err = -1; goto return_error; + } + err = 0; goto return_error; + } + + sprintf(buf, "%d", val); + if (pam_modutil_write(fd, buf, strlen(buf)) == -1) { + _pam_log(pamh, LOG_ERR, FALSE, + "\"impossible\" write error on %s", filename); + err = -1; goto return_error; + } + } + + err = val; + + if (!increment) { + cache_fd = fd; + } else { +return_error: + close (fd); + } + if (buf) free (buf); + return err; +} + +PAM_EXTERN int +pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + /* getuid() must return an id that maps to a username as a filename in + * /var/run/console/ + * and the service name must be listed in + * /etc/security/console-apps + */ + struct passwd *pwd; + char *lockfile = NULL; + char *appsfile = NULL; + const char *service; + int ret = PAM_AUTH_ERR; + + D(("called.")); + _args_parse(pamh, argc, argv); + + if (getuid() == 0) { + /* Obtain user name by pam_get_user() . + * We must make sure that the user sits on the local console + */ + const char *user = NULL; + const char *host = NULL; + const char *user_prompt; + + D(("invoked under root.")); + + ret = pam_get_item(pamh, PAM_RHOST, (const void **) &host); + if (ret == PAM_SUCCESS && host && *host) { + _pam_log(pamh, LOG_ERR, TRUE, + "PAM_RHOST is set - not invoked from console."); + return PAM_AUTH_ERR; + } + + D(("Obtain user name.")); + if (pam_get_item(pamh, PAM_USER_PROMPT, (const void **) &user_prompt) + != PAM_SUCCESS) { + user_prompt = "login: "; + } + ret = pam_get_user(pamh, &user, user_prompt); + if (ret != PAM_SUCCESS) { + _pam_log(pamh, LOG_ERR, FALSE, "could not obtain user name"); + return ret; + } + + pwd = pam_modutil_getpwnam(pamh, user); + if (pwd == NULL) { + _pam_log(pamh, LOG_ERR, FALSE, "user '%s' unknown for this system", user); + return PAM_AUTH_ERR; + } + + if (pwd->pw_uid == 0) { + _pam_log(pamh, LOG_ERR, TRUE, "user '%s' is not allowed to " + "authenticate by pam_console", pwd->pw_name); + return PAM_AUTH_ERR; + } + + } else { + pwd = pam_modutil_getpwuid(pamh, getuid()); + if (pwd == NULL) { + _pam_log(pamh, LOG_ERR, FALSE, "user with id %d not found", getuid()); + return PAM_AUTH_ERR; + } + } + + lockfile = _do_malloc(strlen(consolerefs) + strlen(pwd->pw_name) + 2); + sprintf(lockfile, "%s%s", consolerefs, pwd->pw_name); /* trusted data */ + + pam_get_item(pamh, PAM_SERVICE, CAST_ME_HARDER &service); + appsfile = _do_malloc(strlen(consoleapps) + strlen(service) + 2); + sprintf(appsfile, "%s%s", consoleapps, service); /* trusted data */ + + if (access(lockfile, F_OK) < 0) { + _pam_log(pamh, LOG_ERR, TRUE, + "user %s not a console user", pwd->pw_name); + ret = PAM_AUTH_ERR; goto error_return; + } + + if (access(appsfile, F_OK) < 0) { + _pam_log(pamh, LOG_ERR, TRUE, + "console access disallowed for service %s", service); + ret = PAM_AUTH_ERR; goto error_return; + } + + /* all checks OK, must be OK */ + ret = PAM_SUCCESS; + +error_return: + if (lockfile) free (lockfile); + if (appsfile) free (appsfile); + return ret; +} + +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) +{ + /* Create /var/run/console/console.lock if it does not exist + * Create /var/run/console/ if it does not exist + * Increment its use count + * Change file ownerships and permissions as given in + * /etc/security/console.perms IFF returned use count was 0 + * and we created /var/run/console/console.lock + */ + int got_console = 0; + int count = 0; + int ret = PAM_SESSION_ERR; + const char *username = NULL, *user_prompt; + char *lockfile; + const char *tty = NULL; + + D(("called.")); + _pam_log(pamh, LOG_ERR, TRUE, "pam_console open_session"); + _args_parse(pamh, argc, argv); + if(pam_get_item(pamh, PAM_USER_PROMPT, (const void **) &user_prompt) + != PAM_SUCCESS) { + user_prompt = "user name: "; + } + username = NULL; + pam_get_user(pamh, &username, user_prompt); + _pam_log(pamh, LOG_DEBUG, TRUE, "user is \"%s\"", + username ? username : "(null)"); + if (!username || !username[0]) { + _pam_log(pamh, LOG_DEBUG, TRUE, "user is \"%s\"", + username ? username : "(null)"); + return PAM_SESSION_ERR; + } + if (is_root(pamh, username)) { + _pam_log(pamh, LOG_DEBUG, TRUE, "user \"%s\" is root", username); + return PAM_SUCCESS; + } + pam_get_item(pamh, PAM_TTY, CAST_ME_HARDER &tty); + if (!tty || !tty[0]) { + _pam_log(pamh, LOG_ERR, TRUE, "TTY not defined"); + return PAM_SESSION_ERR; + } + + /* get configuration */ + if (!configfileparsed) { + console_parse_handlers(pamh, consolehandlers); + configfileparsed = 1; + } + + /* return success quietly if not a terminal login */ + if (!check_console_name(pamh, tty, allow_nonroot_tty, TRUE)) return PAM_SUCCESS; + + if (!lock_console(pamh, username)) got_console = 1; + + lockfile = _do_malloc(strlen(consolerefs) + strlen(username) + 2); + sprintf(lockfile, "%s%s", consolerefs, username); /* trusted data */ + count = use_count(pamh, lockfile , 1, 0); + if (count < 0) { + ret = PAM_SESSION_ERR; + } + else if (got_console) { + _pam_log(pamh, LOG_DEBUG, TRUE, "%s is console user", username); + /* errors will be logged and are not critical */ + console_run_handlers(pamh, TRUE, username, tty); + } + + free(lockfile); + return ret; +} + +PAM_EXTERN int +pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + /* Get /var/run/console/ use count, leave it locked + * If use count is now 1: + * If /var/run/console/console.lock contains " + * Revert file ownerships and permissions as given in + * /etc/security/console.perms + * Decrement /var/run/console/, removing both it and + * /var/run/console/console.lock if 0, unlocking /var/run/console/ + * in any case. + */ + int fd; + int count = 0; + int err; + int delete_consolelock = 0; + const char *username = NULL, *user_prompt; + char *lockfile = NULL; + char *consoleuser = NULL; + const char *tty = NULL; + struct stat st; + + D(("called.")); + _args_parse(pamh, argc, argv); + if(pam_get_item(pamh, PAM_USER_PROMPT, (const void **) &user_prompt) + != PAM_SUCCESS) { + user_prompt = "user name: "; + } + pam_get_user(pamh, &username, user_prompt); + + if (!username || !username[0]) return PAM_SESSION_ERR; + if (is_root(pamh, username)) return PAM_SUCCESS; + pam_get_item(pamh, PAM_TTY, CAST_ME_HARDER &tty); + if (!tty || !tty[0]) return PAM_SESSION_ERR; + + /* get configuration */ + if (!configfileparsed) { + console_parse_handlers(pamh, consolehandlers); + configfileparsed = 1; + } + + /* return success quietly if not a terminal login */ + if (!check_console_name(pamh, tty, allow_nonroot_tty, FALSE)) return PAM_SUCCESS; + + lockfile = _do_malloc(strlen(consolerefs) + strlen(username) + 2); + sprintf(lockfile, "%s%s", consolerefs, username); /* trusted data */ + count = use_count(pamh, lockfile, 0, 0); + if (count < 0) { + err = PAM_SESSION_ERR; + goto return_error; + } + + if (count == 1) { + fd = open(consolelock, O_RDONLY); + if (fd != -1) { + if (fstat (fd, &st)) { + _pam_log(pamh, 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); + if (st.st_size) { + if (pam_modutil_read (fd, consoleuser, st.st_size) == -1) { + _pam_log(pamh, LOG_ERR, FALSE, + "\"impossible\" read error on %s", consolelock); + err = PAM_SESSION_ERR; + close(fd); + goto return_error; + } + consoleuser[st.st_size] = '\0'; + } + close (fd); + + if (!strcmp(username, consoleuser)) { + delete_consolelock = 1; + /* errors will be logged and at this stage we cannot do + * anything about them... + */ + console_run_handlers(pamh, FALSE, username, tty); + } + } else { + /* didn't open file */ + err = PAM_SESSION_ERR; + goto return_error; + } + } + + count = use_count(pamh, lockfile, -1, 1); + if (count < 1 && delete_consolelock) { + if (unlink(consolelock)) { + _pam_log(pamh, LOG_ERR, FALSE, + "\"impossible\" unlink error on %s", consolelock); + err = PAM_SESSION_ERR; goto return_error; + } + } + + err = PAM_SUCCESS; +return_error: + if (lockfile) free(lockfile); + if (consoleuser) free (consoleuser); + return err; +} + +#ifdef PAM_STATIC + +/* static module data */ + +struct pam_module _pam_console_modstruct = { + "pam_console", + pam_sm_authenticate, + pam_sm_setcred, + NULL, + pam_sm_open_session, + pam_sm_close_session, + NULL, +}; + +#endif + +/* end of module definition */ diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/pam_console.h Linux-PAM-1.1.3/modules/pam_console/pam_console.h --- Linux-PAM-1.1.3.orig/modules/pam_console/pam_console.h 1969-12-31 19:00:00.000000000 -0500 +++ Linux-PAM-1.1.3/modules/pam_console/pam_console.h 2011-01-26 22:14:52.062657563 -0500 @@ -0,0 +1,25 @@ +/* Copyright 1999, 2005 Red Hat, Inc. + * This software may be used under the terms of the GNU General Public + * License, available in the file COPYING accompanying this file. + */ +#ifndef _PAM_CONSOLE_H +#define _PAM_CONSOLE_H +#include +#include + +#define LOCKFILE "console.lock" + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +void +_pam_log(pam_handle_t *pamh, int err, int debug_p, const char *format, ...); + +void +do_regerror(int errcode, const regex_t *preg); + +#endif /* _PAM_CONSOLE_H */ diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/pam_console_apply.8 Linux-PAM-1.1.3/modules/pam_console/pam_console_apply.8 --- Linux-PAM-1.1.3.orig/modules/pam_console/pam_console_apply.8 1969-12-31 19:00:00.000000000 -0500 +++ Linux-PAM-1.1.3/modules/pam_console/pam_console_apply.8 2011-01-26 22:14:52.062657563 -0500 @@ -0,0 +1,62 @@ +.\" Copyright 2001 Red Hat, Inc. +.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 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 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. +.IP -f +Load other fstab file than the default one (\fI/etc/fstab\fP). +.IP -r +Signals \fBpam_console_apply\fP to reset permissions. The default is to set +permissions so that the user listed in \fI/var/run/console.lock\fP has access +to the devices, and to reset permissions if no such file exists. +.IP -t +Use to match console class in console.perms file. The default is tty0. +.IP -s +Write error messages to the system log instead of stderr. +.IP -d +Log/display messages useful for debugging. +.PP +The optional arguments constrain what files should be affected +by \fBpam_console_apply\fP. If they aren't specified permissions are +changed on all files specified in the \fIconsole.perms\fP file. +.SH FILES +\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 +.BR console.perms(5) +.br +.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 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 -Naur Linux-PAM-1.1.3.orig/modules/pam_console/pam_console_apply.c Linux-PAM-1.1.3/modules/pam_console/pam_console_apply.c --- Linux-PAM-1.1.3.orig/modules/pam_console/pam_console_apply.c 1969-12-31 19:00:00.000000000 -0500 +++ Linux-PAM-1.1.3/modules/pam_console/pam_console_apply.c 2011-01-26 22:14:52.062657563 -0500 @@ -0,0 +1,175 @@ +/* + * Read in the file, and grant ownerships to whoever has the lock. + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define STATIC static +#include "configfile.h" +#include "chmod.h" +#include "pam_console.h" + +#include + +#define CAST_ME_HARDER (const void**) +#define DEFAULT_PERMSFILE "/etc/security/console.perms" +#define PERMS_GLOB "/etc/security/console.perms.d/*.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; + +void +_pam_log(pam_handle_t *pamh, int err, int debug_p, const char *format, ...) +{ + va_list args; + if (debug_p && !debug) return; + va_start(args, format); + if (syslogging) { + openlog("pam_console_apply", LOG_CONS|LOG_PID, LOG_AUTHPRIV); + vsyslog(err, format, args); + closelog(); + } + 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) +{ + int fd; + int i, c; + struct stat st; + char *consoleuser = NULL; + enum {Set, Reset} sense = Set; + GSList *files = NULL; + + while((c = getopt(argc, argv, "c:f:t:rsd")) != -1) { + switch(c) { + 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': 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': + sense = Reset; + break; + case 's': + syslogging = TRUE; + break; + case 'd': + debug = TRUE; + break; + default: + fprintf(stderr, "usage: %s [-f /etc/fstab] " + "[-c %s] [-t tty] [-r] [-s] [-d] [ ...]\n", argv[0], + consoleperms); + exit(1); + } + } + + for (i = argc-1; i >= optind; i--) { + files = g_slist_prepend(files, argv[i]); + } + + if (*consoleperms == '\0') + parse_files(); + else + parse_file(consoleperms); + + fd = open(consolelock, O_RDONLY); + if (fd != -1) { + if (fstat (fd, &st)) { + _pam_log(NULL, LOG_ERR, FALSE, + "\"impossible\" fstat error on %s", consolelock); + close(fd); + goto return_error; + } + if (st.st_size) { + consoleuser = _do_malloc(st.st_size+1); + memset(consoleuser, '\0', st.st_size); + if ((i = read (fd, consoleuser, st.st_size)) == -1) { + _pam_log(NULL, LOG_ERR, FALSE, + "\"impossible\" read error on %s", + consolelock); + goto return_error; + } + consoleuser[i] = '\0'; + } + close(fd); + } else { + sense = Reset; + } + if((sense == Set) && (consoleuser != NULL)) { + set_permissions(tty, consoleuser, files); + } + if(sense == Reset) { + reset_permissions(tty, files); + } + return 0; + +return_error: + return 1; +} diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/regerr.c Linux-PAM-1.1.3/modules/pam_console/regerr.c --- Linux-PAM-1.1.3.orig/modules/pam_console/regerr.c 1969-12-31 19:00:00.000000000 -0500 +++ Linux-PAM-1.1.3/modules/pam_console/regerr.c 2011-01-26 22:14:52.062657563 -0500 @@ -0,0 +1,32 @@ +/* Copyright 1999 Red Hat Software, Inc. + * This software may be used under the terms of the GNU General Public + * License, available in the file COPYING accompanying this file + */ +#include "config.h" +#include +#include +#include +#include +#include +#include "pam_console.h" + +#ifndef STATIC +#define STATIC +#endif + +STATIC void +do_regerror(int errcode, const regex_t *preg) { + char *errbuf; + size_t errbuf_size; + + errbuf_size = regerror(errcode, preg, NULL, 0); /* missing ; */ + errbuf = alloca(errbuf_size); + if(!errbuf) { + perror("alloca"); + return; + } + + regerror(errcode, preg, errbuf, errbuf_size); + pam_syslog(NULL, LOG_ERR, + "regular expression error %s", errbuf); +} diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/sed-static Linux-PAM-1.1.3/modules/pam_console/sed-static --- Linux-PAM-1.1.3.orig/modules/pam_console/sed-static 1969-12-31 19:00:00.000000000 -0500 +++ Linux-PAM-1.1.3/modules/pam_console/sed-static 2011-01-26 22:14:52.062657563 -0500 @@ -0,0 +1,19 @@ +#!/bin/sh + +[ -n "$1" ] || { echo $0: 'sed what file?' 1>&2 ; exit 1 ; } + +sed ' +/^YY_BUFFER_STATE yy_create_buffer/s/^/STATIC / +/^void yy_delete_buffer/s/^/STATIC / +/^void yy_flush_buffer/s/^/STATIC / +/^void yy_init_buffer/s/^/STATIC / +/^void yy_load_buffer_state/s/^/STATIC / +/^void YY_BUFFER_STATE yy_scan_buffer/s/^/STATIC / +/^YY_BUFFER_STATE yy_scan_bytes/s/^/STATIC / +/^YY_BUFFER_STATE yy_scan_buffer/s/^/STATIC / +/^YY_BUFFER_STATE yy_scan_string/s/^/STATIC / +/^void yy_switch_to_buffer/s/^/STATIC / +/define YY_DECL int yylex/s/YY_DECL /YY_DECL STATIC / +/^int yyparse/s/^/STATIC / +/^void yyrestart/s/^/STATIC / +' < $1 > sedtmp.$$ && mv sedtmp.$$ $1