Magellan Linux

Annotation of /trunk/pam/patches/pam-1.1.4-pam-console.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1461 - (hide annotations) (download)
Tue Aug 2 09:12:06 2011 UTC (12 years, 10 months ago) by niro
File size: 136951 byte(s)
-added RH pam_console patch
1 niro 1461 Submitted By: Jim Gifford (jim at linuxfromscratch dot org)
2     Date: 2007-01-21
3     Initial Package Version: 0.99.7.0
4     Origin: http://redhat.download.fedoraproject.org/pub/fedora/linux/core/updates/6/SRPMS/pam-0.99.6.2-3.9.fc6.src.rpm
5     Upstream Status: From Fedora/Redhat
6     Description: Adds pam_console module
7     Rediffed against 1.1.0 by Joe Ciccone <jciccone@gmail.com> on 2009-07-09
8     Rediffed against 1.1.3 by Joe Ciccone <jciccone@gmail.com> on 2011-01-26
9    
10     diff -Naur Linux-PAM-1.1.3.orig/configure.in Linux-PAM-1.1.3/configure.in
11     --- Linux-PAM-1.1.3.orig/configure.in 2010-10-27 09:19:13.000000000 -0400
12     +++ Linux-PAM-1.1.3/configure.in 2011-01-26 22:14:52.059406906 -0500
13     @@ -568,7 +568,7 @@
14     AC_CONFIG_FILES([Makefile libpam/Makefile libpamc/Makefile libpamc/test/Makefile \
15     libpam_misc/Makefile conf/Makefile conf/pam_conv1/Makefile \
16     po/Makefile.in \
17     - modules/Makefile \
18     + modules/Makefile modules/pam_console/Makefile \
19     modules/pam_access/Makefile modules/pam_cracklib/Makefile \
20     modules/pam_debug/Makefile modules/pam_deny/Makefile \
21     modules/pam_echo/Makefile modules/pam_env/Makefile \
22     diff -Naur Linux-PAM-1.1.3.orig/modules/Makefile.am Linux-PAM-1.1.3/modules/Makefile.am
23     --- Linux-PAM-1.1.3.orig/modules/Makefile.am 2008-11-28 09:29:12.000000000 -0500
24     +++ Linux-PAM-1.1.3/modules/Makefile.am 2011-01-26 22:14:52.059406906 -0500
25     @@ -2,7 +2,7 @@
26     # Copyright (c) 2005, 2006, 2008 Thorsten Kukuk <kukuk@thkukuk.de>
27     #
28    
29     -SUBDIRS = pam_access pam_cracklib pam_debug pam_deny pam_echo \
30     +SUBDIRS = pam_access pam_cracklib pam_console pam_debug pam_deny pam_echo \
31     pam_env pam_exec pam_faildelay pam_filter pam_ftp \
32     pam_group pam_issue pam_keyinit pam_lastlog pam_limits \
33     pam_listfile pam_localuser pam_loginuid pam_mail \
34     diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/.cvsignore Linux-PAM-1.1.3/modules/pam_console/.cvsignore
35     --- Linux-PAM-1.1.3.orig/modules/pam_console/.cvsignore 1969-12-31 19:00:00.000000000 -0500
36     +++ Linux-PAM-1.1.3/modules/pam_console/.cvsignore 2011-01-26 22:14:52.062657563 -0500
37     @@ -0,0 +1,3 @@
38     +configfile.tab.c
39     +configfile.tab.h
40     +configfile.lex.c
41     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
42     --- Linux-PAM-1.1.3.orig/modules/pam_console/50-default.perms 1969-12-31 19:00:00.000000000 -0500
43     +++ Linux-PAM-1.1.3/modules/pam_console/50-default.perms 2011-01-26 22:14:52.059406906 -0500
44     @@ -0,0 +1,61 @@
45     +# device classes -- these are shell-style globs
46     +<floppy>=/dev/fd[0-1]* \
47     + /dev/floppy* /mnt/floppy*
48     +<sound>=/dev/dsp* /dev/audio* /dev/midi* \
49     + /dev/mixer* /dev/sequencer* \
50     + /dev/sound/* /dev/beep \
51     + /dev/snd/*
52     +<cdrom>=/dev/cdrom* /dev/cdroms/* /dev/cdwriter* /mnt/cdrom*
53     +<pilot>=/dev/pilot
54     +<jaz>=/mnt/jaz*
55     +<zip>=/mnt/pocketzip* /mnt/zip* /dev/zip*
56     +<ls120>=/dev/ls120 /mnt/ls120*
57     +<scanner>=/dev/scanner* /dev/usb/scanner*
58     +<rio500>=/dev/usb/rio500
59     +<camera>=/mnt/camera* /dev/usb/dc2xx* /dev/usb/mdc800*
60     +<memstick>=/mnt/memstick*
61     +<flash>=/mnt/flash* /dev/flash*
62     +<diskonkey>=/mnt/diskonkey*
63     +<rem_ide>=/mnt/microdrive*
64     +<fb>=/dev/fb /dev/fb[0-9]* \
65     + /dev/fb/*
66     +<kbd>=/dev/kbd
67     +<joystick>=/dev/js[0-9]*
68     +<v4l>=/dev/video* /dev/radio* /dev/winradio* /dev/vtx* /dev/vbi* \
69     + /dev/video/*
70     +<gpm>=/dev/gpmctl
71     +<dri>=/dev/nvidia* /dev/3dfx* /dev/dri/card*
72     +<mainboard>=/dev/apm_bios
73     +<pmu>=/dev/pmu
74     +<bluetooth>=/dev/rfcomm*
75     +<raw1394>=/dev/raw1394
76     +<irda>=/dev/ircomm*
77     +
78     +# permission definitions
79     +<console> 0660 <floppy> 0660 root.floppy
80     +<console> 0600 <sound> 0600 root
81     +<console> 0600 <cdrom> 0660 root.disk
82     +<console> 0600 <pilot> 0660 root.uucp
83     +<console> 0600 <jaz> 0660 root.disk
84     +<console> 0600 <zip> 0660 root.disk
85     +<console> 0600 <ls120> 0660 root.disk
86     +<console> 0600 <scanner> 0600 root
87     +<console> 0600 <camera> 0600 root.disk
88     +<console> 0600 <memstick> 0600 root.disk
89     +<console> 0600 <flash> 0600 root.disk
90     +<console> 0600 <diskonkey> 0660 root.disk
91     +<console> 0600 <rem_ide> 0660 root.disk
92     +<console> 0600 <fb> 0600 root
93     +<console> 0600 <kbd> 0600 root
94     +<console> 0600 <joystick> 0600 root
95     +<console> 0600 <v4l> 0600 root
96     +<console> 0700 <gpm> 0700 root
97     +<console> 0600 <mainboard> 0600 root
98     +<console> 0600 <rio500> 0600 root
99     +<console> 0600 <pmu> 0600 root
100     +<console> 0600 <bluetooth> 0600 root
101     +<console> 0600 <raw1394> 0600 root
102     +<console> 0600 <irda> 0600 root
103     +
104     +<xconsole> 0600 /dev/console 0600 root.root
105     +<console> 0600 <dri> 0600 root
106     diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/COPYING Linux-PAM-1.1.3/modules/pam_console/COPYING
107     --- Linux-PAM-1.1.3.orig/modules/pam_console/COPYING 1969-12-31 19:00:00.000000000 -0500
108     +++ Linux-PAM-1.1.3/modules/pam_console/COPYING 2011-01-26 22:14:52.062657563 -0500
109     @@ -0,0 +1,340 @@
110     + GNU GENERAL PUBLIC LICENSE
111     + Version 2, June 1991
112     +
113     + Copyright (C) 1989, 1991 Free Software Foundation, Inc.
114     + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
115     + Everyone is permitted to copy and distribute verbatim copies
116     + of this license document, but changing it is not allowed.
117     +
118     + Preamble
119     +
120     + The licenses for most software are designed to take away your
121     +freedom to share and change it. By contrast, the GNU General Public
122     +License is intended to guarantee your freedom to share and change free
123     +software--to make sure the software is free for all its users. This
124     +General Public License applies to most of the Free Software
125     +Foundation's software and to any other program whose authors commit to
126     +using it. (Some other Free Software Foundation software is covered by
127     +the GNU Library General Public License instead.) You can apply it to
128     +your programs, too.
129     +
130     + When we speak of free software, we are referring to freedom, not
131     +price. Our General Public Licenses are designed to make sure that you
132     +have the freedom to distribute copies of free software (and charge for
133     +this service if you wish), that you receive source code or can get it
134     +if you want it, that you can change the software or use pieces of it
135     +in new free programs; and that you know you can do these things.
136     +
137     + To protect your rights, we need to make restrictions that forbid
138     +anyone to deny you these rights or to ask you to surrender the rights.
139     +These restrictions translate to certain responsibilities for you if you
140     +distribute copies of the software, or if you modify it.
141     +
142     + For example, if you distribute copies of such a program, whether
143     +gratis or for a fee, you must give the recipients all the rights that
144     +you have. You must make sure that they, too, receive or can get the
145     +source code. And you must show them these terms so they know their
146     +rights.
147     +
148     + We protect your rights with two steps: (1) copyright the software, and
149     +(2) offer you this license which gives you legal permission to copy,
150     +distribute and/or modify the software.
151     +
152     + Also, for each author's protection and ours, we want to make certain
153     +that everyone understands that there is no warranty for this free
154     +software. If the software is modified by someone else and passed on, we
155     +want its recipients to know that what they have is not the original, so
156     +that any problems introduced by others will not reflect on the original
157     +authors' reputations.
158     +
159     + Finally, any free program is threatened constantly by software
160     +patents. We wish to avoid the danger that redistributors of a free
161     +program will individually obtain patent licenses, in effect making the
162     +program proprietary. To prevent this, we have made it clear that any
163     +patent must be licensed for everyone's free use or not licensed at all.
164     +
165     + The precise terms and conditions for copying, distribution and
166     +modification follow.
167     +
168     + GNU GENERAL PUBLIC LICENSE
169     + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
170     +
171     + 0. This License applies to any program or other work which contains
172     +a notice placed by the copyright holder saying it may be distributed
173     +under the terms of this General Public License. The "Program", below,
174     +refers to any such program or work, and a "work based on the Program"
175     +means either the Program or any derivative work under copyright law:
176     +that is to say, a work containing the Program or a portion of it,
177     +either verbatim or with modifications and/or translated into another
178     +language. (Hereinafter, translation is included without limitation in
179     +the term "modification".) Each licensee is addressed as "you".
180     +
181     +Activities other than copying, distribution and modification are not
182     +covered by this License; they are outside its scope. The act of
183     +running the Program is not restricted, and the output from the Program
184     +is covered only if its contents constitute a work based on the
185     +Program (independent of having been made by running the Program).
186     +Whether that is true depends on what the Program does.
187     +
188     + 1. You may copy and distribute verbatim copies of the Program's
189     +source code as you receive it, in any medium, provided that you
190     +conspicuously and appropriately publish on each copy an appropriate
191     +copyright notice and disclaimer of warranty; keep intact all the
192     +notices that refer to this License and to the absence of any warranty;
193     +and give any other recipients of the Program a copy of this License
194     +along with the Program.
195     +
196     +You may charge a fee for the physical act of transferring a copy, and
197     +you may at your option offer warranty protection in exchange for a fee.
198     +
199     + 2. You may modify your copy or copies of the Program or any portion
200     +of it, thus forming a work based on the Program, and copy and
201     +distribute such modifications or work under the terms of Section 1
202     +above, provided that you also meet all of these conditions:
203     +
204     + a) You must cause the modified files to carry prominent notices
205     + stating that you changed the files and the date of any change.
206     +
207     + b) You must cause any work that you distribute or publish, that in
208     + whole or in part contains or is derived from the Program or any
209     + part thereof, to be licensed as a whole at no charge to all third
210     + parties under the terms of this License.
211     +
212     + c) If the modified program normally reads commands interactively
213     + when run, you must cause it, when started running for such
214     + interactive use in the most ordinary way, to print or display an
215     + announcement including an appropriate copyright notice and a
216     + notice that there is no warranty (or else, saying that you provide
217     + a warranty) and that users may redistribute the program under
218     + these conditions, and telling the user how to view a copy of this
219     + License. (Exception: if the Program itself is interactive but
220     + does not normally print such an announcement, your work based on
221     + the Program is not required to print an announcement.)
222     +
223     +These requirements apply to the modified work as a whole. If
224     +identifiable sections of that work are not derived from the Program,
225     +and can be reasonably considered independent and separate works in
226     +themselves, then this License, and its terms, do not apply to those
227     +sections when you distribute them as separate works. But when you
228     +distribute the same sections as part of a whole which is a work based
229     +on the Program, the distribution of the whole must be on the terms of
230     +this License, whose permissions for other licensees extend to the
231     +entire whole, and thus to each and every part regardless of who wrote it.
232     +
233     +Thus, it is not the intent of this section to claim rights or contest
234     +your rights to work written entirely by you; rather, the intent is to
235     +exercise the right to control the distribution of derivative or
236     +collective works based on the Program.
237     +
238     +In addition, mere aggregation of another work not based on the Program
239     +with the Program (or with a work based on the Program) on a volume of
240     +a storage or distribution medium does not bring the other work under
241     +the scope of this License.
242     +
243     + 3. You may copy and distribute the Program (or a work based on it,
244     +under Section 2) in object code or executable form under the terms of
245     +Sections 1 and 2 above provided that you also do one of the following:
246     +
247     + a) Accompany it with the complete corresponding machine-readable
248     + source code, which must be distributed under the terms of Sections
249     + 1 and 2 above on a medium customarily used for software interchange; or,
250     +
251     + b) Accompany it with a written offer, valid for at least three
252     + years, to give any third party, for a charge no more than your
253     + cost of physically performing source distribution, a complete
254     + machine-readable copy of the corresponding source code, to be
255     + distributed under the terms of Sections 1 and 2 above on a medium
256     + customarily used for software interchange; or,
257     +
258     + c) Accompany it with the information you received as to the offer
259     + to distribute corresponding source code. (This alternative is
260     + allowed only for noncommercial distribution and only if you
261     + received the program in object code or executable form with such
262     + an offer, in accord with Subsection b above.)
263     +
264     +The source code for a work means the preferred form of the work for
265     +making modifications to it. For an executable work, complete source
266     +code means all the source code for all modules it contains, plus any
267     +associated interface definition files, plus the scripts used to
268     +control compilation and installation of the executable. However, as a
269     +special exception, the source code distributed need not include
270     +anything that is normally distributed (in either source or binary
271     +form) with the major components (compiler, kernel, and so on) of the
272     +operating system on which the executable runs, unless that component
273     +itself accompanies the executable.
274     +
275     +If distribution of executable or object code is made by offering
276     +access to copy from a designated place, then offering equivalent
277     +access to copy the source code from the same place counts as
278     +distribution of the source code, even though third parties are not
279     +compelled to copy the source along with the object code.
280     +
281     + 4. You may not copy, modify, sublicense, or distribute the Program
282     +except as expressly provided under this License. Any attempt
283     +otherwise to copy, modify, sublicense or distribute the Program is
284     +void, and will automatically terminate your rights under this License.
285     +However, parties who have received copies, or rights, from you under
286     +this License will not have their licenses terminated so long as such
287     +parties remain in full compliance.
288     +
289     + 5. You are not required to accept this License, since you have not
290     +signed it. However, nothing else grants you permission to modify or
291     +distribute the Program or its derivative works. These actions are
292     +prohibited by law if you do not accept this License. Therefore, by
293     +modifying or distributing the Program (or any work based on the
294     +Program), you indicate your acceptance of this License to do so, and
295     +all its terms and conditions for copying, distributing or modifying
296     +the Program or works based on it.
297     +
298     + 6. Each time you redistribute the Program (or any work based on the
299     +Program), the recipient automatically receives a license from the
300     +original licensor to copy, distribute or modify the Program subject to
301     +these terms and conditions. You may not impose any further
302     +restrictions on the recipients' exercise of the rights granted herein.
303     +You are not responsible for enforcing compliance by third parties to
304     +this License.
305     +
306     + 7. If, as a consequence of a court judgment or allegation of patent
307     +infringement or for any other reason (not limited to patent issues),
308     +conditions are imposed on you (whether by court order, agreement or
309     +otherwise) that contradict the conditions of this License, they do not
310     +excuse you from the conditions of this License. If you cannot
311     +distribute so as to satisfy simultaneously your obligations under this
312     +License and any other pertinent obligations, then as a consequence you
313     +may not distribute the Program at all. For example, if a patent
314     +license would not permit royalty-free redistribution of the Program by
315     +all those who receive copies directly or indirectly through you, then
316     +the only way you could satisfy both it and this License would be to
317     +refrain entirely from distribution of the Program.
318     +
319     +If any portion of this section is held invalid or unenforceable under
320     +any particular circumstance, the balance of the section is intended to
321     +apply and the section as a whole is intended to apply in other
322     +circumstances.
323     +
324     +It is not the purpose of this section to induce you to infringe any
325     +patents or other property right claims or to contest validity of any
326     +such claims; this section has the sole purpose of protecting the
327     +integrity of the free software distribution system, which is
328     +implemented by public license practices. Many people have made
329     +generous contributions to the wide range of software distributed
330     +through that system in reliance on consistent application of that
331     +system; it is up to the author/donor to decide if he or she is willing
332     +to distribute software through any other system and a licensee cannot
333     +impose that choice.
334     +
335     +This section is intended to make thoroughly clear what is believed to
336     +be a consequence of the rest of this License.
337     +
338     + 8. If the distribution and/or use of the Program is restricted in
339     +certain countries either by patents or by copyrighted interfaces, the
340     +original copyright holder who places the Program under this License
341     +may add an explicit geographical distribution limitation excluding
342     +those countries, so that distribution is permitted only in or among
343     +countries not thus excluded. In such case, this License incorporates
344     +the limitation as if written in the body of this License.
345     +
346     + 9. The Free Software Foundation may publish revised and/or new versions
347     +of the General Public License from time to time. Such new versions will
348     +be similar in spirit to the present version, but may differ in detail to
349     +address new problems or concerns.
350     +
351     +Each version is given a distinguishing version number. If the Program
352     +specifies a version number of this License which applies to it and "any
353     +later version", you have the option of following the terms and conditions
354     +either of that version or of any later version published by the Free
355     +Software Foundation. If the Program does not specify a version number of
356     +this License, you may choose any version ever published by the Free Software
357     +Foundation.
358     +
359     + 10. If you wish to incorporate parts of the Program into other free
360     +programs whose distribution conditions are different, write to the author
361     +to ask for permission. For software which is copyrighted by the Free
362     +Software Foundation, write to the Free Software Foundation; we sometimes
363     +make exceptions for this. Our decision will be guided by the two goals
364     +of preserving the free status of all derivatives of our free software and
365     +of promoting the sharing and reuse of software generally.
366     +
367     + NO WARRANTY
368     +
369     + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
370     +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
371     +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
372     +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
373     +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
374     +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
375     +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
376     +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
377     +REPAIR OR CORRECTION.
378     +
379     + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
380     +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
381     +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
382     +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
383     +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
384     +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
385     +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
386     +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
387     +POSSIBILITY OF SUCH DAMAGES.
388     +
389     + END OF TERMS AND CONDITIONS
390     +
391     + How to Apply These Terms to Your New Programs
392     +
393     + If you develop a new program, and you want it to be of the greatest
394     +possible use to the public, the best way to achieve this is to make it
395     +free software which everyone can redistribute and change under these terms.
396     +
397     + To do so, attach the following notices to the program. It is safest
398     +to attach them to the start of each source file to most effectively
399     +convey the exclusion of warranty; and each file should have at least
400     +the "copyright" line and a pointer to where the full notice is found.
401     +
402     + <one line to give the program's name and a brief idea of what it does.>
403     + Copyright (C) 19yy <name of author>
404     +
405     + This program is free software; you can redistribute it and/or modify
406     + it under the terms of the GNU General Public License as published by
407     + the Free Software Foundation; either version 2 of the License, or
408     + (at your option) any later version.
409     +
410     + This program is distributed in the hope that it will be useful,
411     + but WITHOUT ANY WARRANTY; without even the implied warranty of
412     + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
413     + GNU General Public License for more details.
414     +
415     + You should have received a copy of the GNU General Public License
416     + along with this program; if not, write to the Free Software
417     + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
418     +
419     +
420     +Also add information on how to contact you by electronic and paper mail.
421     +
422     +If the program is interactive, make it output a short notice like this
423     +when it starts in an interactive mode:
424     +
425     + Gnomovision version 69, Copyright (C) 19yy name of author
426     + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
427     + This is free software, and you are welcome to redistribute it
428     + under certain conditions; type `show c' for details.
429     +
430     +The hypothetical commands `show w' and `show c' should show the appropriate
431     +parts of the General Public License. Of course, the commands you use may
432     +be called something other than `show w' and `show c'; they could even be
433     +mouse-clicks or menu items--whatever suits your program.
434     +
435     +You should also get your employer (if you work as a programmer) or your
436     +school, if any, to sign a "copyright disclaimer" for the program, if
437     +necessary. Here is a sample; alter the names:
438     +
439     + Yoyodyne, Inc., hereby disclaims all copyright interest in the program
440     + `Gnomovision' (which makes passes at compilers) written by James Hacker.
441     +
442     + <signature of Ty Coon>, 1 April 1989
443     + Ty Coon, President of Vice
444     +
445     +This General Public License does not permit incorporating your program into
446     +proprietary programs. If your program is a subroutine library, you may
447     +consider it more useful to permit linking proprietary applications with the
448     +library. If this is what you want to do, use the GNU Library General
449     +Public License instead of this License.
450     diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/Makefile.am Linux-PAM-1.1.3/modules/pam_console/Makefile.am
451     --- Linux-PAM-1.1.3.orig/modules/pam_console/Makefile.am 1969-12-31 19:00:00.000000000 -0500
452     +++ Linux-PAM-1.1.3/modules/pam_console/Makefile.am 2011-01-26 22:14:52.062657563 -0500
453     @@ -0,0 +1,64 @@
454     +#
455     +# Copyright (c) 2005 Thorsten Kukuk <kukuk@suse.de>
456     +# Copyright (c) 2005 Red Hat, Inc.
457     +#
458     +
459     +CLEANFILES = *~
460     +
461     +CONFFILES = console.perms console.handlers 50-default.perms
462     +MAN5 = console.apps.5 console.perms.5 console.handlers.5
463     +MAN8 = pam_console.8 pam_console_apply.8
464     +
465     +man_MANS = $(MAN5) $(MAN8)
466     +
467     +EXTRA_DIST = README $(man_MANS) $(CONFFILES) sed-static configfile.y configfile.l
468     +
469     +LOCKDIR = /var/run/console
470     +LOCKMODE = 755
471     +
472     +securelibdir = $(SECUREDIR)
473     +secureconfdir = $(SCONFIGDIR)
474     +permsddir = $(SCONFIGDIR)/console.perms.d
475     +
476     +noinst_HEADERS = chmod.h configfile.h configfile.tab.h handlers.h modechange.h pam_console.h
477     +
478     +AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
479     + $(GLIB_CFLAGS) -DLOCKDIR=\"$(LOCKDIR)\"
480     +
481     +pam_console_la_LDFLAGS = -no-undefined -avoid-version -module
482     +if HAVE_VERSIONING
483     + pam_console_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
484     +endif
485     +pam_console_la_LIBADD = -L$(top_builddir)/libpam -lpam
486     +
487     +pam_console_apply_LDADD = -L$(top_builddir)/libpam -lpam
488     +
489     +securelib_LTLIBRARIES = pam_console.la
490     +sbin_PROGRAMS = pam_console_apply
491     +
492     +
493     +secureconf_DATA = console.perms console.handlers
494     +
495     +FLEX_OPTS = -Cr
496     +BISON_OPTS = -d
497     +
498     +pam_console_la_SOURCES = pam_console.c pam_console.h regerr.c handlers.c handlers.h
499     +pam_console_apply_SOURCES = pam_console_apply.c pam_console.h chmod.c modechange.c regerr.c \
500     + configfile.c configfile.h hashtable.c hashtable.h hashtable_private.h
501     +
502     +pam_console_la_CFLAGS = $(AM_CFLAGS)
503     +pam_console_apply_CFLAGS = $(AM_CFLAGS)
504     +
505     +configfile.tab.c: configfile.y
506     + $(YACC) $(BISON_OPTS) -o $@ -p _pc_yy $<
507     + sh $(srcdir)/sed-static $@
508     +
509     +configfile.lex.c: configfile.l configfile.tab.c
510     + $(LEX) $(FLEX_OPTS) -o$@ -P_pc_yy $<
511     + sh $(srcdir)/sed-static $@
512     +
513     +configfile.c: configfile.tab.c configfile.lex.c
514     +
515     +install-data-local:
516     + mkdir -p $(DESTDIR)$(secureconfdir)/console.apps
517     + mkdir -m $(LOCKMODE) -p -p $(DESTDIR)$(LOCKDIR)
518     diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/README Linux-PAM-1.1.3/modules/pam_console/README
519     --- Linux-PAM-1.1.3.orig/modules/pam_console/README 1969-12-31 19:00:00.000000000 -0500
520     +++ Linux-PAM-1.1.3/modules/pam_console/README 2011-01-26 22:14:52.062657563 -0500
521     @@ -0,0 +1,45 @@
522     +README for pam_console
523     +======================
524     +
525     +NOTE: This software is very powerful. Incautious use could leave your
526     +system open to attack, or difficult to use.
527     +
528     +pam_console is distributed in the hope that it will be useful,
529     +but WITHOUT ANY WARRANTY; without even the implied warranty of
530     +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
531     +
532     +Because pam_console integrates GPL-licensed code, all of pam_console
533     +is licensed only under the GPL, unlike most PAM modules. See the
534     +file COPYING for the license terms under which this software is
535     +licensed.
536     +
537     +(If this software breaks your system, you get to keep all the pieces.)
538     +
539     +The pam_console module exists to change file permissions when users
540     +log on at the console, and to change them back when they log out of
541     +the console. It also cooperates with the pam_listfile module to
542     +make it possible to allow users who are at the console to run
543     +various programs that would otherwise be restricted to root only.
544     +
545     +The pam_console.8 and pam_console_apply.8 man pages explain this
546     +software in more detail.
547     +
548     +Please note: the current version depends on too many external tools
549     +and libraries, making it big and hard to evaluate for security.
550     +This is only a bootstrap stage; I'll be fixing it later. I'm using
551     +lex/yacc right now so that it is trivial to change the grammar, and
552     +I'm using glib because I didn't want to write my own hashtables
553     +while I was busy thinking about file locking. Don't report those
554     +as bugs, I'll fix them later once I've ironed out the important
555     +details...
556     +
557     +Michael K. Johnson
558     +Red Hat Software, Inc.
559     +
560     +Additional note: the current version is improved so that the functionality
561     +of changing the ownership and permissions of the devices is split out
562     +of the pam_console.so module to the pam_console_apply executable,
563     +which is called from the pam_console module when the lock is obtained.
564     +Thus the module doesn't depend on the glib.
565     +
566     +Copyright 1999, 2005 Red Hat, Inc.
567     diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/chmod.c Linux-PAM-1.1.3/modules/pam_console/chmod.c
568     --- Linux-PAM-1.1.3.orig/modules/pam_console/chmod.c 1969-12-31 19:00:00.000000000 -0500
569     +++ Linux-PAM-1.1.3/modules/pam_console/chmod.c 2011-01-26 22:14:52.059406906 -0500
570     @@ -0,0 +1,240 @@
571     +/* This file is derived from chmod.c and stpcpy.c, included
572     + in the GNU fileutils distribution. It has been changed to be a
573     + library specifically for use within the Red Hat pam_console module.
574     + Changes Copyright 1999,2001 Red Hat, Inc.
575     + */
576     +
577     +/* chmod -- change permission modes of files
578     + Copyright (C) 89, 90, 91, 95, 1996 Free Software Foundation, Inc.
579     +
580     + This program is free software; you can redistribute it and/or modify
581     + it under the terms of the GNU General Public License as published by
582     + the Free Software Foundation; either version 2, or (at your option)
583     + any later version.
584     +
585     + This program is distributed in the hope that it will be useful,
586     + but WITHOUT ANY WARRANTY; without even the implied warranty of
587     + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
588     + GNU General Public License for more details.
589     +
590     + You should have received a copy of the GNU General Public License
591     + along with this program; if not, write to the Free Software Foundation,
592     + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
593     +
594     +#include "config.h"
595     +#include <errno.h>
596     +#include <glob.h>
597     +#include <fnmatch.h>
598     +#include <stdio.h>
599     +#include <stdlib.h>
600     +#include <string.h>
601     +#include <sys/stat.h>
602     +#include <sys/types.h>
603     +#include <unistd.h>
604     +#include <dirent.h>
605     +#include <mntent.h>
606     +#define NAMLEN(dirent) strlen((dirent)->d_name)
607     +
608     +#include "configfile.h"
609     +#include "chmod.h"
610     +#include "modechange.h"
611     +
612     +#define CLOSEDIR(d) closedir (d)
613     +
614     +#ifdef _D_NEED_STPCPY
615     +/* stpcpy.c -- copy a string and return pointer to end of new string
616     + Copyright (C) 1989, 1990 Free Software Foundation.
617     +
618     + This program is free software; you can redistribute it and/or modify
619     + it under the terms of the GNU General Public License as published by
620     + the Free Software Foundation; either version 2, or (at your option)
621     + any later version.
622     +
623     + This program is distributed in the hope that it will be useful,
624     + but WITHOUT ANY WARRANTY; without even the implied warranty of
625     + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
626     + GNU General Public License for more details.
627     +
628     + You should have received a copy of the GNU General Public License
629     + along with this program; if not, write to the Free Software Foundation,
630     + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
631     +
632     +/* Copy SRC to DEST, returning the address of the terminating '\0' in DEST. */
633     +
634     +static char *
635     +stpcpy (char *dest, const char *src)
636     +{
637     + while ((*dest++ = *src++) != '\0')
638     + /* Do nothing. */ ;
639     + return dest - 1;
640     +}
641     +#endif /* _D_NEED_STPCPY */
642     +
643     +/* end included files */
644     +
645     +static const char *fstab_filename = "/etc/fstab";
646     +
647     +static int change_via_fstab __P ((const char *dir,
648     + const struct mode_change *changes,
649     + uid_t user, gid_t group));
650     +
651     +/* Change the mode of FILE according to the list of operations CHANGES.
652     + If DEREF_SYMLINK is nonzero and FILE is a symbolic link, change the
653     + mode of the referenced file. If DEREF_SYMLINK is zero, ignore symbolic
654     + links. Return 0 if successful, 1 if errors occurred. */
655     +
656     +static int
657     +change_file (const char *file, const struct mode_change *changes,
658     + const int deref_symlink, uid_t user, gid_t group)
659     +{
660     + struct stat file_stats;
661     + unsigned short newmode;
662     + int errors = 0;
663     +
664     + if (lstat (file, &file_stats) == -1)
665     + {
666     + if (errno == ENOENT)
667     + {
668     + /* doesn't exist, check fstab */
669     + errors |= change_via_fstab (file, changes, user, group);
670     + return errors;
671     + }
672     + else
673     + {
674     + return 1;
675     + }
676     + }
677     +
678     + if (S_ISLNK (file_stats.st_mode))
679     + {
680     + /* don't bother with dangling symlinks */
681     + if (stat (file, &file_stats))
682     + {
683     + return 1;
684     + }
685     + }
686     +
687     + newmode = mode_adjust (file_stats.st_mode, changes);
688     +
689     + if (S_ISDIR (file_stats.st_mode))
690     + errors |= change_via_fstab (file, changes, user, group);
691     + else
692     + {
693     + if (newmode != (file_stats.st_mode & 07777))
694     + {
695     + if (chmod (file, (int) newmode) == -1)
696     + {
697     + errors = 1;
698     + }
699     + }
700     + errors |= chown (file, user, group);
701     + }
702     +
703     + return errors;
704     +}
705     +
706     +void
707     +chmod_set_fstab(const char *fstab)
708     +{
709     + fstab_filename = strdup(fstab);
710     +}
711     +
712     +
713     +/* If the directory spec given matches a filesystem listed in /etc/fstab,
714     + * modify the device special associated with that filesystem. */
715     +static int
716     +change_via_fstab (const char *dir, const struct mode_change *changes,
717     + uid_t user, gid_t group)
718     +{
719     + int errors = 0;
720     + FILE *fstab;
721     + struct mntent *mntent;
722     +
723     + fstab = setmntent(fstab_filename, "r");
724     +
725     + if (fstab == NULL)
726     + {
727     + return 1;
728     + }
729     +
730     + for(mntent = getmntent(fstab); mntent != NULL; mntent = getmntent(fstab))
731     + {
732     + if(mntent->mnt_dir &&
733     + mntent->mnt_fsname &&
734     + (fnmatch(dir, mntent->mnt_dir, 0) == 0))
735     + {
736     + errors |= change_file(mntent->mnt_fsname, changes, TRUE, user, group);
737     + }
738     + }
739     +
740     + endmntent(fstab);
741     +
742     + return errors;
743     +}
744     +
745     +/* Parse the ASCII mode into a linked list
746     + of `struct mode_change' and apply that to each file argument. */
747     +
748     +
749     +static int
750     +glob_errfn(const char *pathname, int theerr) {
751     + /* silently ignore inaccessible files */
752     + return 0;
753     +}
754     +
755     +#define DIE(n) {fprintf(stderr, "chmod failure\n"); return (n);}
756     +
757     +static int
758     +match_files(GSList *files, const char *filename) {
759     +
760     + if (!files)
761     + return 0; /* empty list matches */
762     + for (; files; files = files->next) {
763     + if (!fnmatch(files->data, filename, FNM_PATHNAME))
764     + return 0;
765     + }
766     + return -1;
767     +}
768     +
769     +int
770     +chmod_files (const char *mode, uid_t user, gid_t group,
771     + char *single_file, GSList *filelist, GSList *constraints)
772     +{
773     + struct mode_change *changes;
774     + int errors = 0;
775     + glob_t result;
776     + char *filename = NULL;
777     + int flags = GLOB_NOCHECK;
778     + int i, rc;
779     +
780     + changes = mode_compile (mode,
781     + MODE_MASK_EQUALS | MODE_MASK_PLUS | MODE_MASK_MINUS);
782     + if (changes == MODE_INVALID) DIE(1)
783     + else if (changes == MODE_MEMORY_EXHAUSTED) DIE(1)
784     +
785     + for (; filelist; filelist = filelist->next)
786     + {
787     + filename = filelist->data;
788     + rc = glob(filename, flags, glob_errfn, &result);
789     + if (rc == GLOB_NOSPACE) DIE(1)
790     + flags |= GLOB_APPEND;
791     + }
792     + if(single_file) {
793     + rc = glob(single_file, flags, glob_errfn, &result);
794     + if (rc == GLOB_NOSPACE) DIE(1)
795     + }
796     +
797     + for (i = 0; i < result.gl_pathc; i++) {
798     + if (!match_files(constraints, result.gl_pathv[i])) {
799     + errors |= change_file (result.gl_pathv[i], changes, 1, user, group);
800     +#if 0
801     + _pam_log(LOG_DEBUG, TRUE,
802     + "file %s (%d): mode %s\n", result.gl_pathv[i], user, mode);
803     +#endif
804     + }
805     + }
806     +
807     + globfree(&result);
808     +
809     + return (errors);
810     +}
811     diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/chmod.h Linux-PAM-1.1.3/modules/pam_console/chmod.h
812     --- Linux-PAM-1.1.3.orig/modules/pam_console/chmod.h 1969-12-31 19:00:00.000000000 -0500
813     +++ Linux-PAM-1.1.3/modules/pam_console/chmod.h 2011-01-26 22:14:52.059406906 -0500
814     @@ -0,0 +1,11 @@
815     +#include <unistd.h>
816     +
817     +#ifndef _CHMOD_H
818     +#define _CHMOD_H
819     +
820     +int
821     +chmod_files(const char *mode, uid_t user, gid_t group, char *fname, GSList *filelist, GSList *constraints);
822     +void
823     +chmod_set_fstab(const char *fstab);
824     +
825     +#endif /* _CHMOD_H */
826     diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/configfile.c Linux-PAM-1.1.3/modules/pam_console/configfile.c
827     --- Linux-PAM-1.1.3.orig/modules/pam_console/configfile.c 1969-12-31 19:00:00.000000000 -0500
828     +++ Linux-PAM-1.1.3/modules/pam_console/configfile.c 2011-01-26 22:14:52.062657563 -0500
829     @@ -0,0 +1,58 @@
830     +#include <string.h>
831     +#include <stdlib.h>
832     +#include "configfile.h"
833     +
834     +void *
835     +_do_malloc(size_t req)
836     +{
837     + void *ret;
838     + ret = malloc(req);
839     + if (!ret) abort();
840     + return ret;
841     +}
842     +
843     +GSList *
844     +g_slist_prepend(GSList *l, void *d)
845     +{
846     + GSList *memb;
847     + memb = _do_malloc(sizeof(*memb));
848     + memb->next = l;
849     + memb->data = d;
850     + return memb;
851     +}
852     +
853     +GSList *
854     +g_slist_append(GSList *l, void *d)
855     +{
856     + GSList *memb, *n;
857     + memb = _do_malloc(sizeof(*memb));
858     + memb->next = NULL;
859     + memb->data = d;
860     +
861     + if (l == NULL) {
862     + return memb;
863     + }
864     +
865     + n = l;
866     + while (n->next != NULL) {
867     + n = n->next;
868     + }
869     + n->next = memb;
870     +
871     + return l;
872     +}
873     +
874     +void
875     +g_slist_free(GSList *l)
876     +{
877     + GSList *n;
878     + while (l != NULL) {
879     + n = l->next;
880     + free(l);
881     + l = n;
882     + }
883     +}
884     +
885     +#include "configfile.lex.c"
886     +#include "configfile.tab.c"
887     +
888     diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/configfile.h Linux-PAM-1.1.3/modules/pam_console/configfile.h
889     --- Linux-PAM-1.1.3.orig/modules/pam_console/configfile.h 1969-12-31 19:00:00.000000000 -0500
890     +++ Linux-PAM-1.1.3/modules/pam_console/configfile.h 2011-01-26 22:14:52.062657563 -0500
891     @@ -0,0 +1,64 @@
892     +/* Copyright 1999, 2005 Red Hat, Inc.
893     + * This software may be used under the terms of the GNU General Public
894     + * License, available in the file COPYING accompanying this file.
895     + */
896     +#ifndef _CONFIGFILE_H
897     +#define _CONFIGFILE_H
898     +#define STATIC static
899     +
900     +#ifndef FALSE
901     +#define FALSE 0
902     +#endif
903     +#ifndef TRUE
904     +#define TRUE (!FALSE)
905     +#endif
906     +
907     +/* GSList reimplementation */
908     +
909     +typedef struct GSList_s GSList;
910     +struct GSList_s {
911     + void *data;
912     + GSList *next;
913     +};
914     +
915     +typedef struct class_s class;
916     +struct class_s {
917     + char* name;
918     + GSList* list;
919     +};
920     +
921     +typedef struct config_s config;
922     +struct config_s {
923     + class* console_class;
924     + char* mode;
925     + class* device_class;
926     + char* revert_mode;
927     + char* revert_owner;
928     + char* revert_group;
929     +};
930     +
931     +GSList *
932     +g_slist_prepend(GSList *l, void *d);
933     +
934     +GSList *
935     +g_slist_append(GSList *l, void *d);
936     +
937     +void
938     +g_slist_free(GSList *l);
939     +
940     +void
941     +parse_file(const char *name);
942     +
943     +int
944     +check_console_name (const char *consolename);
945     +
946     +int
947     +set_permissions(const char *consolename, const char *username, GSList *files);
948     +
949     +int
950     +reset_permissions(const char *consolename, GSList *files);
951     +
952     +void *
953     +_do_malloc(size_t req);
954     +
955     +#endif /* _CONFIGFILE_H */
956     diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/configfile.l Linux-PAM-1.1.3/modules/pam_console/configfile.l
957     --- Linux-PAM-1.1.3.orig/modules/pam_console/configfile.l 1969-12-31 19:00:00.000000000 -0500
958     +++ Linux-PAM-1.1.3/modules/pam_console/configfile.l 2011-01-26 22:14:52.062657563 -0500
959     @@ -0,0 +1,66 @@
960     +%option noyywrap
961     +%{
962     +/* Copyright 1999,2000 Red Hat, Inc.
963     + * This software may be used under the terms of the GNU General Public
964     + * License, available in the file COPYING accompanying this file
965     + */
966     +/* get around an apparant bug in bison; YYSTYPE not copied into config.tab.h */
967     +#define YYSTYPE void *
968     +#include "configfile.h"
969     +#include "configfile.tab.h"
970     +#include <stdio.h>
971     +#include <string.h>
972     +#include <syslog.h>
973     +
974     +#include "pam_console.h"
975     +
976     +static int lineno;
977     +static const char *filename;
978     +
979     +STATIC char *
980     +strip_slash(const char *);
981     +%}
982     +%%
983     +\n { lineno++; return EOL; }
984     +\\\n { lineno++; }
985     + /* do not return EOL, eat up escaped newline */
986     +[ \t]+ /* ignore whitespace */
987     +\< { return OBRACKET; }
988     +\>= { return CBEQUALS; }
989     +\> { return CBRACKET; }
990     +([^\t\n #\<\>]|(\\#|\\\<|\\\>))+ { _pc_yylval=strip_slash(yytext); return STRING; }
991     +#.*\n { lineno++; return EOL; } /* ignore comments */
992     +%%
993     +
994     +static void
995     +lex_file (FILE *in) {
996     + /* yy_flex_debug = 1; */
997     + yyin = in;
998     + lineno = 1;
999     +}
1000     +
1001     +static void
1002     +lex_set_filename(const char *name) {
1003     + filename = name;
1004     +}
1005     +
1006     +static int
1007     +_pc_yyerror (const char *s) {
1008     + _pam_log(NULL, LOG_ERR, 0, "%s line %d: %s: at `%s'\n",
1009     + filename, lineno, s, (char *)_pc_yylval);
1010     + return 0;
1011     +}
1012     +
1013     +STATIC char *
1014     +strip_slash(const char *s) {
1015     + char *r, *t;
1016     +
1017     + t = r = strdup(s);
1018     + while ((t = strchr(t, '\\')) != NULL) {
1019     + if (t[1] == '#' || t[1] == '<' || t[1] == '>') {
1020     + memmove(t, t+1, strlen(t));
1021     + }
1022     + t++;
1023     + }
1024     + return r;
1025     +}
1026     diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/configfile.y Linux-PAM-1.1.3/modules/pam_console/configfile.y
1027     --- Linux-PAM-1.1.3.orig/modules/pam_console/configfile.y 1969-12-31 19:00:00.000000000 -0500
1028     +++ Linux-PAM-1.1.3/modules/pam_console/configfile.y 2011-01-26 22:14:52.062657563 -0500
1029     @@ -0,0 +1,336 @@
1030     +%{
1031     +/* Copyright 1999,2000 Red Hat, Inc.
1032     + * This software may be used under the terms of the GNU General Public
1033     + * License, available in the file COPYING accompanying this file
1034     + */
1035     +#define YYSTYPE void *
1036     +
1037     +#include <errno.h>
1038     +#include <grp.h>
1039     +#include <limits.h>
1040     +#include <regex.h>
1041     +#include <stdio.h>
1042     +#include <stdarg.h>
1043     +#include <sys/types.h>
1044     +#include <sys/stat.h>
1045     +#include <pwd.h>
1046     +#include <chmod.h>
1047     +#include <hashtable.h>
1048     +
1049     +#include <security/pam_modules.h>
1050     +#include <security/pam_modutil.h>
1051     +
1052     +typedef struct hashtable GHashTable;
1053     +
1054     +static GHashTable *namespace = NULL;
1055     +static GSList *configList = NULL;
1056     +static GSList *configListEnd = NULL;
1057     +static GSList *consoleClassList = NULL;
1058     +static GSList *consoleClassListEnd = NULL;
1059     +static const char *consoleNameCache = NULL;
1060     +static GHashTable *consoleHash = NULL;
1061     +
1062     +static void
1063     +do_yyerror(const char *format, ...);
1064     +
1065     +static void
1066     +empty_class(class *c);
1067     +
1068     +static unsigned int
1069     +str_hash(unsigned char *s)
1070     +{
1071     + unsigned int hash = 5381;
1072     + int c;
1073     +
1074     + while ((c = *s++))
1075     + hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
1076     +
1077     + return hash;
1078     +}
1079     +
1080     +static int
1081     +str_equal(void *a, void *b)
1082     +{
1083     + return strcmp(a, b) == 0;
1084     +}
1085     +
1086     +static unsigned int
1087     +ptr_hash(void *p)
1088     +{
1089     + return (unsigned long)p >> 3;
1090     +}
1091     +
1092     +static int
1093     +ptr_equal(void *a, void *b)
1094     +{
1095     + return a == b;
1096     +}
1097     +
1098     +%}
1099     +
1100     +%token EOL
1101     +%token OBRACKET
1102     +%token CBEQUALS
1103     +%token CBRACKET
1104     +%token STRING
1105     +
1106     +%%
1107     +lines: lines line
1108     + | /* empty */
1109     + ;
1110     +
1111     +line: config
1112     + | classdef
1113     + | EOL
1114     + | error
1115     + ;
1116     +
1117     +classdef:
1118     + OBRACKET string CBEQUALS stringlist EOL {
1119     + class *c;
1120     +
1121     + c = hashtable_search(namespace, $2);
1122     + if (c) {
1123     + empty_class(c);
1124     + } else {
1125     + c = malloc(sizeof(class));
1126     + hashtable_insert(namespace, strdup($2), c);
1127     + }
1128     + c->name = $2;
1129     + c->list = $4;
1130     + }
1131     + ;
1132     +
1133     +config: classlist STRING classlist optstring optstring EOL {
1134     + config *conf = malloc(sizeof(config));
1135     + conf->console_class = $1;
1136     + conf->mode = $2;
1137     + conf->device_class = $3;
1138     + conf->revert_mode = $4;
1139     + conf->revert_owner = $5;
1140     + if (conf->revert_owner != NULL) {
1141     + conf->revert_group = strchr (conf->revert_owner, ':');
1142     + if (conf->revert_group == NULL)
1143     + conf->revert_group = strchr (conf->revert_owner, '.');
1144     + if (conf->revert_group != NULL) {
1145     + *(conf->revert_group) = '\0';
1146     + conf->revert_group++;
1147     + if (*(conf->revert_group) == '\0')
1148     + conf->revert_group = NULL;
1149     + if (*(conf->revert_owner) == '\0')
1150     + conf->revert_owner = NULL;
1151     + }
1152     + } else {
1153     + conf->revert_group = NULL;
1154     + }
1155     + configListEnd = g_slist_append(configListEnd, conf);
1156     + if (configListEnd->next) configListEnd = configListEnd->next;
1157     + if (!configList) configList = configListEnd;
1158     + consoleClassListEnd =
1159     + g_slist_append(consoleClassListEnd, conf->console_class);
1160     + if (consoleClassListEnd->next)
1161     + consoleClassListEnd = consoleClassListEnd->next;
1162     + if (!consoleClassList) consoleClassList = consoleClassListEnd;
1163     + }
1164     + ;
1165     +
1166     +classlist: OBRACKET string CBRACKET {
1167     + class *c = hashtable_search(namespace, $2);
1168     + if(!c) {
1169     + _pam_log(NULL, LOG_ERR, FALSE,
1170     + "unknown class \"%s\" at line %d in %s\n",
1171     + (const char *)$2, lineno, filename);
1172     + YYERROR;
1173     + }
1174     + $$ = c;
1175     + }
1176     + | string {
1177     + class *c = malloc(sizeof(class));
1178     + c->name = $1;
1179     + c->list = NULL;
1180     + $$ = c;
1181     + }
1182     + ;
1183     +
1184     +
1185     +stringlist: string {$$ = g_slist_append(NULL, $1);}
1186     + | stringlist string {$$ = g_slist_append($1, $2);}
1187     + ;
1188     +
1189     +optstring: string {$$=$1;}
1190     + | /* empty */ {$$=NULL;}
1191     + ;
1192     +
1193     +string: STRING {$$=$1;} ;
1194     +
1195     +%%
1196     +
1197     +/* exported functions */
1198     +
1199     +/* parse a file given by a name */
1200     +void
1201     +parse_file(const char *name) {
1202     + FILE *infile;
1203     +
1204     + _pam_log(NULL, LOG_DEBUG, TRUE, "parsing config file %s", name);
1205     + infile = fopen(name, "r");
1206     + if (!infile) {
1207     + _pam_log(NULL, LOG_ERR, FALSE, "could not parse required file %s", name);
1208     + return;
1209     + }
1210     +
1211     + if (!namespace) namespace = create_hashtable(128, (unsigned int (*)(void *))str_hash, str_equal);
1212     +
1213     + lex_set_filename(name);
1214     + lex_file(infile);
1215     +
1216     + yyparse();
1217     + fclose(infile);
1218     +}
1219     +
1220     +static int
1221     +check_one_console_name (const char *name, char *classComponent) {
1222     + regex_t p;
1223     + int r_err;
1224     + char *class_exp;
1225     +
1226     + class_exp = _do_malloc(strlen(classComponent) + 3);
1227     + sprintf(class_exp, "^%s$", classComponent);
1228     + r_err = regcomp(&p, class_exp, REG_EXTENDED|REG_NOSUB);
1229     + if (r_err) do_regerror(r_err, &p);
1230     + r_err = regexec(&p, name, 0, NULL, 0);
1231     + regfree(&p);
1232     + free (class_exp);
1233     + return !r_err;
1234     +}
1235     +
1236     +int
1237     +check_console_name (const char *consolename) {
1238     + GSList *this_class;
1239     + GSList *this_list;
1240     + class *c;
1241     + int found = 0;
1242     +
1243     + _pam_log(NULL, LOG_DEBUG, TRUE, "check console %s", consolename);
1244     + if (consoleNameCache != consolename) {
1245     + consoleNameCache = consolename;
1246     + if (consoleHash) hashtable_destroy(consoleHash, 0);
1247     + consoleHash = create_hashtable(128, ptr_hash, ptr_equal);
1248     + }
1249     + for (this_class = consoleClassList; this_class;
1250     + this_class = this_class->next) {
1251     + c = this_class->data;
1252     + if (c->list) {
1253     + for (this_list = c->list; this_list; this_list = this_list->next) {
1254     + if (check_one_console_name(consolename, this_list->data)) {
1255     + hashtable_insert(consoleHash, c, c);
1256     + found = 1;
1257     + }
1258     + }
1259     + } else {
1260     + if (check_one_console_name(consolename, c->name)) {
1261     + hashtable_insert(consoleHash, c, c);
1262     + found = 1;
1263     + }
1264     + }
1265     + }
1266     +
1267     + if (found)
1268     + return 1;
1269     +
1270     + /* not found */
1271     + _pam_log(NULL, LOG_INFO, TRUE, "did not find console %s", consolename);
1272     + if (consoleHash) {
1273     + hashtable_destroy(consoleHash, 0);
1274     + consoleHash = NULL;
1275     + }
1276     + return 0;
1277     +}
1278     +
1279     +int
1280     +set_permissions(const char *consolename, const char *username, GSList *files) {
1281     + struct passwd *pwd;
1282     + config *c;
1283     + GSList *cl;
1284     +
1285     + if (!consoleNameCache || strcmp(consolename, consoleNameCache)) {
1286     + if (!check_console_name(consolename)) return -1;
1287     + }
1288     +
1289     + pwd = getpwnam(username);
1290     + if (pwd == NULL) {
1291     + _pam_log(NULL, LOG_ERR, FALSE, "getpwnam failed for \"%s\"", username);
1292     + return -1;
1293     + }
1294     +
1295     + for (cl = configList; cl; cl = cl->next) {
1296     + c = cl->data;
1297     + if (hashtable_search(consoleHash, c->console_class)) {
1298     + if (c->device_class->list)
1299     + chmod_files(c->mode, pwd->pw_uid, -1, NULL, c->device_class->list, files);
1300     + else
1301     + chmod_files(c->mode, pwd->pw_uid, -1, c->device_class->name, NULL, files);
1302     + }
1303     + }
1304     + return 0;
1305     +}
1306     +
1307     +int
1308     +reset_permissions(const char *consolename, GSList *files) {
1309     + struct passwd *pwd;
1310     + struct group *grp;
1311     + config *c;
1312     + GSList *cl;
1313     +
1314     + if (!consoleNameCache || strcmp(consolename, consoleNameCache)) {
1315     + if (!check_console_name(consolename)) return -1;
1316     + }
1317     +
1318     + for (cl = configList; cl; cl = cl->next) {
1319     + c = cl->data;
1320     + if (hashtable_search(consoleHash, c->console_class)) {
1321     + pwd = getpwnam(c->revert_owner ? c->revert_owner : "root");
1322     + if (pwd == NULL) {
1323     + _pam_log(NULL, LOG_ERR, FALSE, "getpwnam failed for %s",
1324     + c->revert_owner ? c->revert_owner : "root");
1325     + return -1;
1326     + }
1327     + grp = getgrnam(c->revert_group ? c->revert_group : "root");
1328     + if (grp == NULL) {
1329     + _pam_log(NULL, LOG_ERR, FALSE, "getgrnam failed for %s",
1330     + c->revert_group ? c->revert_group : "root");
1331     + return -1;
1332     + }
1333     + if (c->device_class->list)
1334     + chmod_files(c->revert_mode ? c->revert_mode : "0600",
1335     + pwd->pw_uid, grp->gr_gid, NULL, c->device_class->list, files);
1336     + else
1337     + chmod_files(c->revert_mode ? c->revert_mode : "0600",
1338     + pwd->pw_uid, grp->gr_gid, c->device_class->name, NULL, files);
1339     + }
1340     + }
1341     + return 0;
1342     +}
1343     +
1344     +
1345     +
1346     +
1347     +/* local, static functions */
1348     +
1349     +static void
1350     +do_yyerror(const char *format, ...) {
1351     + va_list ap;
1352     +
1353     + va_start(ap, format);
1354     + openlog("pam_console", LOG_CONS|LOG_PID, LOG_AUTHPRIV);
1355     + vsyslog(LOG_PID|LOG_AUTHPRIV|LOG_ERR, format, ap);
1356     + va_end(ap);
1357     +}
1358     +
1359     +static void
1360     +empty_class(class *c) {
1361     + free(c->name);
1362     + c->name = NULL;
1363     + g_slist_free(c->list);
1364     + c->list = NULL;
1365     +}
1366     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
1367     --- Linux-PAM-1.1.3.orig/modules/pam_console/console.apps.5 1969-12-31 19:00:00.000000000 -0500
1368     +++ Linux-PAM-1.1.3/modules/pam_console/console.apps.5 2011-01-26 22:14:52.062657563 -0500
1369     @@ -0,0 +1,18 @@
1370     +.\" Copyright 1999 Red Hat Software, Inc.
1371     +.\" Written by Michael K. Johnson <johnsonm@redhat.com>
1372     +.TH console.apps 5 1999/2/4 "Red Hat Software" "System Administrator's Manual"
1373     +.SH NAME
1374     +console.apps \- specify console-accessible privileged applications
1375     +.SH DESCRIPTION
1376     +The /etc/security/console.apps/ directory should contain one file
1377     +per application that wishes to allow access to console users.
1378     +The filename should be the same as the servicename, and the
1379     +contents are irrelevant; the file may be a zero-length file.
1380     +The application that the file is used by is free to specify the
1381     +contents in any way that is useful for it.
1382     +.SH "SEE ALSO"
1383     +.BR pam_console (8)
1384     +.br
1385     +.BR console.perms (5)
1386     +.SH AUTHOR
1387     +Michael K. Johnson <johnsonm@redhat.com>
1388     diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/console.handlers Linux-PAM-1.1.3/modules/pam_console/console.handlers
1389     --- Linux-PAM-1.1.3.orig/modules/pam_console/console.handlers 1969-12-31 19:00:00.000000000 -0500
1390     +++ Linux-PAM-1.1.3/modules/pam_console/console.handlers 2011-01-26 22:14:52.062657563 -0500
1391     @@ -0,0 +1,22 @@
1392     +# /etc/security/console.handlers
1393     +#
1394     +# This file is provided for configuration of handlers which will be
1395     +# executed when user obtains console lock and when he loses it.
1396     +# Additionally it is used for a configuration of console device names.
1397     +#
1398     +# Format:
1399     +# name consoledevs regex regex ...
1400     +# binary lock|unlock flag flag ...
1401     +# See man console.handlers
1402     +#
1403     +# Example:
1404     +# console consoledevs tty[0-9][0-9]* vc/[0-9][0-9]* :[0-9]\.[0-9] :[0-9]
1405     +# echo lock wait Locking console for user on tty
1406     +# touch unlock wait /var/run/console-unlocked
1407     +
1408     +console consoledevs tty[0-9][0-9]* vc/[0-9][0-9]* :[0-9]\.[0-9] :[0-9]
1409     +/sbin/pam_console_apply lock logfail wait -t tty -s
1410     +/sbin/pam_console_apply unlock logfail wait -r -t tty -s
1411     +# initialize dmix for alsa sound
1412     +/usr/bin/ainit lock user start
1413     +/usr/bin/ainit unlock user stop
1414     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
1415     --- Linux-PAM-1.1.3.orig/modules/pam_console/console.handlers.5 1969-12-31 19:00:00.000000000 -0500
1416     +++ Linux-PAM-1.1.3/modules/pam_console/console.handlers.5 2011-01-26 22:14:52.062657563 -0500
1417     @@ -0,0 +1,46 @@
1418     +.\" Copyright 2005 Red Hat Software, Inc.
1419     +.\" Written by Tomas Mraz <tmraz@redhat.com>
1420     +.TH console.handlers 5 2005/3/18 "Red Hat" "System Administrator's Manual"
1421     +.SH NAME
1422     +console.handlers \- file specifying handlers of console lock and unlock events
1423     +.SH DESCRIPTION
1424     +/etc/security/console.handlers determines which programs will be run when an
1425     +user obtains the console lock at login time, and when the user loses it
1426     +on log out. It is read by the pam_console module.
1427     +
1428     +The format is:
1429     +
1430     +\fBhandler-filename\fP \fBlock\fP\fI|\fP\fBunlock\fP \fI[\fP\fBflag ...\fP\fI]\fP
1431     +
1432     +Where \fBhandler-filename\fP is a name of the executable to be run, \fBlock\fP or
1433     +\fBunlock\fP specifies on which event it should be run, and flags specify how
1434     +should pam_console call it.
1435     +
1436     +Additionally there should be a line which specifies glob patterns of console devices.
1437     +
1438     +The format of this line is:
1439     +\fBconsole-name\fP \fBconsoledevs\fP \fBregex\fP \fI[\fP\fBregex ...\fP\fI]\fP
1440     +
1441     +Where \fBconsole-name\fP is a name of the console class - currently ignored - and
1442     +regexes are regular expression patterns which specify the name of the tty device.
1443     +Only the first such line is consulted.
1444     +
1445     +.SH FLAGS
1446     +.IP logfail
1447     +The pam_console module should log error to the system log if the return value of the
1448     +handler is not zero or if the handler can not be executed.
1449     +.IP wait
1450     +The pam_console should wait for the handler to exit before continuing.
1451     +.IP setuid
1452     +The handler should be executed with uid/gid of the user which obtained the
1453     +console lock.
1454     +.IP tty
1455     +The handler will get a tty name as obtained from PAM as a parameter.
1456     +.IP user
1457     +The handler will get an user name as obtained from PAM as a parameter.
1458     +.PP
1459     +Anything else will be added directly as a parameter to the handler executable.
1460     +.SH "SEE ALSO"
1461     +.BR pam_console (8)
1462     +.SH AUTHOR
1463     +Tomas Mraz <tmraz@redhat.com>
1464     diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/console.perms Linux-PAM-1.1.3/modules/pam_console/console.perms
1465     --- Linux-PAM-1.1.3.orig/modules/pam_console/console.perms 1969-12-31 19:00:00.000000000 -0500
1466     +++ Linux-PAM-1.1.3/modules/pam_console/console.perms 2011-01-26 22:14:52.062657563 -0500
1467     @@ -0,0 +1,25 @@
1468     +# /etc/security/console.perms
1469     +#
1470     +# This file determines the permissions that will be given to priviledged
1471     +# users of the console at login time, and the permissions to which to
1472     +# revert when the users log out.
1473     +
1474     +# format is:
1475     +# <class>=list of regexps specifying consoles or globs specifying files
1476     +# file-glob|<class> perm dev-regex|<dev-class> \
1477     +# revert-mode revert-owner[.revert-group]
1478     +# the revert-mode, revert-owner, and revert-group are optional, and default
1479     +# to 0600, root, and root, respectively.
1480     +#
1481     +# For more information:
1482     +# man 5 console.perms
1483     +#
1484     +# This file should not be modified.
1485     +# Rather a new file in the console.perms.d directory should be created.
1486     +
1487     +# file classes -- these are regular expressions
1488     +<console>=tty[0-9][0-9]* vc/[0-9][0-9]* :[0-9]\.[0-9] :[0-9]
1489     +<xconsole>=:[0-9]\.[0-9] :[0-9]
1490     +
1491     +# device classes -- see console.perms.d/50-default.perms
1492     +# permission definitions -- see console.perms.d/50-default.perms
1493     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
1494     --- Linux-PAM-1.1.3.orig/modules/pam_console/console.perms.5 1969-12-31 19:00:00.000000000 -0500
1495     +++ Linux-PAM-1.1.3/modules/pam_console/console.perms.5 2011-01-26 22:14:52.062657563 -0500
1496     @@ -0,0 +1,50 @@
1497     +.\" Copyright 1999,2005 Red Hat Software, Inc.
1498     +.\" Written by Michael K. Johnson <johnsonm@redhat.com>
1499     +.TH console.perms 5 2005/5/2 "Red Hat Software" "System Administrator's Manual"
1500     +.SH NAME
1501     +console.perms \- permissions control file for users at the system console
1502     +.SH DESCRIPTION
1503     +/etc/security/console.perms and .perms files in the
1504     +/etc/security/console.perms.d directory determine the permissions that will be
1505     +given to priviledged users of the console at login time, and the
1506     +permissions to which to revert when the users log out. They are
1507     +read by the pam_console_apply helper executable.
1508     +
1509     +The format is:
1510     +
1511     +\f(CR<\fBclass\fR\f(CR>=\fBspace-separated list of words\fR
1512     +
1513     +\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
1514     +.br
1515     +\f(CR \fBrevert-mode revert-owner\fR\fI[\fR\fP.revert-group\fI]\fR
1516     +
1517     +The \fBrevert-mode\fP, \fBrevert-owner\fP, and revert-group fields are optional,
1518     +and default to \fB0600\fP, \fBroot\fP, and \fBroot\fP, respectively.
1519     +
1520     +The words in a class definition are evaluated as globs if they
1521     +refer to files, but as regular expressions if they apply to a
1522     +console definition. Do not mix them.
1523     +
1524     +Any line can be broken and continued on the next line by using a
1525     +\e character as the last character on the line.
1526     +
1527     +The \fBlogin-class\fP class and the \fBlogin-regexp\fP word are evaluated as
1528     +regular expressions.
1529     +The \fBdev-class\fP and the \fBdev-glob\fP word are evaluated as
1530     +shell-style globs. If a name given corresponds to a directory, and
1531     +if it is a mount point listed in \fI/etc/fstab\fP, the device node
1532     +associated with the filesystem mounted at that point will be
1533     +substituted in its place.
1534     +
1535     +Classes are denoted by being contained in \f(CR<\fR angle bracket \f(CR>\fR
1536     +characters; a lack of \f(CR<\fR angle brackets \f(CR>\fR indicates that
1537     +the string is to be taken literally as a \fBlogin-regexp\fP or a
1538     +\fBdev-glob\fP, depending on its input position.
1539     +.SH "SEE ALSO"
1540     +.BR pam_console (8)
1541     +.br
1542     +.BR pam_console_apply (8)
1543     +.br
1544     +.BR console.apps (5)
1545     +.SH AUTHOR
1546     +Michael K. Johnson <johnsonm@redhat.com>
1547     diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/handlers.c Linux-PAM-1.1.3/modules/pam_console/handlers.c
1548     --- Linux-PAM-1.1.3.orig/modules/pam_console/handlers.c 1969-12-31 19:00:00.000000000 -0500
1549     +++ Linux-PAM-1.1.3/modules/pam_console/handlers.c 2011-01-26 22:14:52.062657563 -0500
1550     @@ -0,0 +1,312 @@
1551     +/* handlers.c -- execute handlers specified in handlers configuration file
1552     + Copyright (c) 2005 Red Hat, Inc.
1553     + Written by Tomas Mraz <tmraz@redhat.com>
1554     +
1555     + This program is free software; you can redistribute it and/or modify
1556     + it under the terms of the GNU General Public License as published by
1557     + the Free Software Foundation; either version 2, or (at your option)
1558     + any later version.
1559     +
1560     + This program is distributed in the hope that it will be useful,
1561     + but WITHOUT ANY WARRANTY; without even the implied warranty of
1562     + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1563     + GNU General Public License for more details.
1564     +
1565     + You should have received a copy of the GNU General Public License
1566     + along with this program; if not, write to the Free Software Foundation,
1567     + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
1568     +
1569     +#include "config.h"
1570     +#include <errno.h>
1571     +#include <stdio.h>
1572     +#include <stdlib.h>
1573     +#include <string.h>
1574     +#include <ctype.h>
1575     +#include <unistd.h>
1576     +#include <signal.h>
1577     +#include <sys/wait.h>
1578     +#include <sys/types.h>
1579     +#include <pwd.h>
1580     +#include <syslog.h>
1581     +
1582     +#include "handlers.h"
1583     +#include "pam_console.h"
1584     +
1585     +enum types { UNKNOWN, LOCK, UNLOCK, CONSOLEDEVS };
1586     +enum flags { HF_LOGFAIL, HF_WAIT, HF_SETUID, HF_TTY, HF_USER, HF_PARAM };
1587     +
1588     +struct console_handler {
1589     + char *executable;
1590     + enum types type;
1591     + char *flags; /* this is a double zero terminated array
1592     + allocated in one blob with executable */
1593     + struct console_handler *next;
1594     +};
1595     +
1596     +static struct console_handler *first_handler;
1597     +
1598     +static void
1599     +console_free_handlers (struct console_handler *handler) {
1600     + if (handler != NULL) {
1601     + console_free_handlers(handler->next);
1602     + free(handler->executable);
1603     + free(handler);
1604     + }
1605     +}
1606     +
1607     +int
1608     +console_parse_handlers (pam_handle_t *pamh, const char *handlers_name) {
1609     + FILE *fh;
1610     + char linebuf[HANDLERS_MAXLINELEN+1];
1611     + int forget;
1612     + int skip = 0;
1613     + int rv = PAM_SESSION_ERR;
1614     + struct console_handler **previous_handler_ptr;
1615     +
1616     + fh = fopen(handlers_name, "r");
1617     + if (fh == NULL) {
1618     + _pam_log(pamh, LOG_ERR, FALSE, "cannot open file %s for reading", handlers_name);
1619     + return rv;
1620     + }
1621     +
1622     + previous_handler_ptr = &first_handler;
1623     +
1624     + while (fgets(linebuf, sizeof(linebuf), fh) != NULL)
1625     + {
1626     + int len;
1627     + char *ptr;
1628     + char *tokptr;
1629     + char *temp;
1630     + char *destptr = NULL; /* needed to silence warning */
1631     + struct console_handler *handler;
1632     + enum states { EXECUTABLE, TYPE, FLAGS } state;
1633     +
1634     + len = strlen(linebuf);
1635     + if (linebuf[len-1] != '\n') {
1636     + _pam_log(pamh, LOG_INFO, FALSE, "line too long or not ending with new line char - will be ignored");
1637     + skip = 1;
1638     + continue;
1639     + }
1640     + if (skip) {
1641     + skip = 0;
1642     + continue;
1643     + }
1644     + linebuf[len-1] = '\0';
1645     + if ((ptr=strchr(linebuf, '#')) != NULL) {
1646     + *ptr = '\0';
1647     + }
1648     + for (ptr = linebuf; isspace(*ptr); ptr++);
1649     + if (*ptr == '\0')
1650     + continue;
1651     +
1652     + /* something on the line */
1653     + if ((handler=calloc(sizeof(*handler), 1)) == NULL)
1654     + goto fail_exit;
1655     + *previous_handler_ptr = handler;
1656     + previous_handler_ptr = &handler->next;
1657     +
1658     + if ((handler->executable=malloc(len-(ptr-linebuf)+1)) == NULL) {
1659     + goto fail_exit;
1660     + }
1661     +
1662     + state = EXECUTABLE;
1663     + handler->type = UNKNOWN;
1664     + while ((tokptr=strtok_r(ptr, " \t", &temp)) != NULL) {
1665     + if (state == EXECUTABLE) {
1666     + strcpy(handler->executable, tokptr);
1667     + ptr = NULL;
1668     + handler->flags = destptr = handler->executable + strlen(handler->executable) + 1;
1669     + }
1670     + else if (state == TYPE) {
1671     + if (strcmp(tokptr, "lock") == 0) {
1672     + handler->type = LOCK;
1673     + }
1674     + else if (strcmp(tokptr, "unlock") == 0) {
1675     + handler->type = UNLOCK;
1676     + }
1677     + else if (strcmp(tokptr, "consoledevs") == 0) {
1678     + handler->type = CONSOLEDEVS;
1679     + }
1680     + }
1681     +
1682     + if (state == FLAGS) {
1683     + strcpy(destptr, tokptr);
1684     + destptr += strlen(destptr) + 1;
1685     + }
1686     + else {
1687     + state++;
1688     + }
1689     + }
1690     + *destptr = '\0';
1691     + }
1692     + forget = fclose(fh);
1693     +
1694     + return PAM_SUCCESS;
1695     +
1696     +fail_exit:
1697     + console_free_handlers(first_handler);
1698     + return rv;
1699     +}
1700     +
1701     +static enum flags testflag(const char *flag) {
1702     + if (strcmp(flag, "logfail") == 0) {
1703     + return HF_LOGFAIL;
1704     + }
1705     + if (strcmp(flag, "wait") == 0) {
1706     + return HF_WAIT;
1707     + }
1708     + if (strcmp(flag, "setuid") == 0) {
1709     + return HF_SETUID;
1710     + }
1711     + if (strcmp(flag, "tty") == 0) {
1712     + return HF_TTY;
1713     + }
1714     + if (strcmp(flag, "user") == 0) {
1715     + return HF_USER;
1716     + }
1717     + return HF_PARAM;
1718     +}
1719     +
1720     +static void
1721     +call_exec(struct console_handler *handler, int nparams, const char *user, const char *tty) {
1722     + const char *flagptr;
1723     + const char **argv;
1724     + int i = 0;
1725     + argv = malloc(sizeof(*argv)*nparams+2);
1726     +
1727     + if (argv == NULL)
1728     + return;
1729     +
1730     + argv[i++] = handler->executable;
1731     +
1732     + for (flagptr = handler->flags; *flagptr != '\0'; flagptr += strlen(flagptr)+1) {
1733     + switch (testflag(flagptr)) {
1734     + case HF_LOGFAIL:
1735     + case HF_WAIT:
1736     + case HF_SETUID:
1737     + break;
1738     + case HF_TTY:
1739     + argv[i++] = tty;
1740     + break;
1741     + case HF_USER:
1742     + argv[i++] = user;
1743     + break;
1744     + case HF_PARAM:
1745     + argv[i++] = flagptr;
1746     + }
1747     + }
1748     + argv[i] = NULL;
1749     + execvp(handler->executable, (char * const *)argv);
1750     +}
1751     +
1752     +static int
1753     +execute_handler(pam_handle_t *pamh, struct console_handler *handler, const char *user, const char *tty) {
1754     + const char *flagptr;
1755     + int nparams = 0;
1756     + int logfail = 0;
1757     + int wait_exit = 0;
1758     + int set_uid = 0;
1759     + int child;
1760     + int rv = 0;
1761     + int max_fd;
1762     + int fd;
1763     + sighandler_t sighandler;
1764     +
1765     + for (flagptr = handler->flags; *flagptr != '\0'; flagptr += strlen(flagptr)+1) {
1766     + switch (testflag(flagptr)) {
1767     + case HF_LOGFAIL:
1768     + logfail = 1;
1769     + break;
1770     + case HF_WAIT:
1771     + wait_exit = 1;
1772     + break;
1773     + case HF_SETUID:
1774     + set_uid = 1;
1775     + break;
1776     + case HF_TTY:
1777     + case HF_USER:
1778     + case HF_PARAM:
1779     + nparams++;
1780     + }
1781     + }
1782     +
1783     + sighandler = signal(SIGCHLD, SIG_DFL);
1784     +
1785     + child = fork();
1786     + switch (child) {
1787     + case -1:
1788     + _pam_log(pamh, LOG_ERR, !logfail, "fork failed when executing handler '%s'",
1789     + handler->executable);
1790     + return -1;
1791     + case 0:
1792     + /* close all descriptors except std* */
1793     + max_fd = getdtablesize();
1794     + for(fd = 3; fd < max_fd; fd++)
1795     + rv = close(fd); /* rv will be ignored */
1796     + if (!wait_exit) {
1797     + switch(fork()) {
1798     + case 0:
1799     + exit(0);
1800     + case -1:
1801     + exit(255);
1802     + default:
1803     + if(setsid() == -1) {
1804     + exit(255);
1805     + }
1806     + }
1807     + }
1808     + if (set_uid) {
1809     + struct passwd *pw;
1810     + pw = getpwnam(user);
1811     + if (pw == NULL)
1812     + exit(255);
1813     + if (setgid(pw->pw_gid) == -1 ||
1814     + setuid(pw->pw_uid) == -1)
1815     + exit(255);
1816     + }
1817     + call_exec(handler, nparams, user, tty);
1818     + exit(255);
1819     + default:
1820     + break;
1821     + }
1822     +
1823     + waitpid(child, &rv, 0);
1824     +
1825     + if (sighandler != SIG_ERR)
1826     + signal(SIGCHLD, sighandler);
1827     +
1828     + if (WIFEXITED(rv) && WEXITSTATUS(rv) != 0)
1829     + _pam_log(pamh, LOG_ERR, !logfail, "handler '%s' returned %d on exit",
1830     + handler->executable, (int)WEXITSTATUS(rv));
1831     + else if (WIFSIGNALED(rv))
1832     + _pam_log(pamh, LOG_ERR, !logfail, "handler '%s' caught a signal %d",
1833     + handler->executable, (int)WTERMSIG(rv));
1834     +
1835     + return 0;
1836     +}
1837     +
1838     +void
1839     +console_run_handlers(pam_handle_t *pamh, int lock, const char *user, const char *tty) {
1840     + struct console_handler *handler;
1841     +
1842     + for (handler = first_handler; handler != NULL; handler = handler->next) {
1843     + if (lock && handler->type == LOCK) {
1844     + execute_handler(pamh, handler, user, tty);
1845     + }
1846     + else if (!lock && handler->type == UNLOCK) {
1847     + execute_handler(pamh, handler, user, tty);
1848     + }
1849     + }
1850     +}
1851     +
1852     +const char *
1853     +console_get_regexes(void) {
1854     + struct console_handler *handler;
1855     +
1856     + for (handler = first_handler; handler != NULL; handler = handler->next) {
1857     + if (handler->type == CONSOLEDEVS) {
1858     + return handler->flags;
1859     + }
1860     + }
1861     + return NULL;
1862     +}
1863     diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/handlers.h Linux-PAM-1.1.3/modules/pam_console/handlers.h
1864     --- Linux-PAM-1.1.3.orig/modules/pam_console/handlers.h 1969-12-31 19:00:00.000000000 -0500
1865     +++ Linux-PAM-1.1.3/modules/pam_console/handlers.h 2011-01-26 22:14:52.062657563 -0500
1866     @@ -0,0 +1,16 @@
1867     +/* Copyright 2005 Red Hat, Inc.
1868     + * This software may be used under the terms of the GNU General Public
1869     + * License, available in the file COPYING accompanying this file.
1870     + */
1871     +#ifndef _HANDLERS_H
1872     +#define _HANDLERS_H
1873     +
1874     +#include <security/pam_modules.h>
1875     +
1876     +#define HANDLERS_MAXLINELEN 2000
1877     +
1878     +int console_parse_handlers (pam_handle_t *pamh, const char *filename);
1879     +void console_run_handlers(pam_handle_t *pamh, int lock, const char *user, const char *tty);
1880     +const char *console_get_regexes(void);
1881     +
1882     +#endif /* _HANDLERS_H */
1883     diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/hashtable.c Linux-PAM-1.1.3/modules/pam_console/hashtable.c
1884     --- Linux-PAM-1.1.3.orig/modules/pam_console/hashtable.c 1969-12-31 19:00:00.000000000 -0500
1885     +++ Linux-PAM-1.1.3/modules/pam_console/hashtable.c 2011-01-26 22:14:52.062657563 -0500
1886     @@ -0,0 +1,255 @@
1887     +/* Copyright (C) 2004 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */
1888     +
1889     +#include "hashtable.h"
1890     +#include "hashtable_private.h"
1891     +#include <stdlib.h>
1892     +#include <stdio.h>
1893     +#include <string.h>
1894     +#include <math.h>
1895     +
1896     +/*
1897     +Credit for primes table: Aaron Krowne
1898     + http://br.endernet.org/~akrowne/
1899     + http://planetmath.org/encyclopedia/GoodHashTablePrimes.html
1900     +*/
1901     +static const unsigned int primes[] = {
1902     +53, 97, 193, 389,
1903     +769, 1543, 3079, 6151,
1904     +12289, 24593, 49157, 98317,
1905     +196613, 393241, 786433, 1572869,
1906     +3145739, 6291469, 12582917, 25165843,
1907     +50331653, 100663319, 201326611, 402653189,
1908     +805306457, 1610612741
1909     +};
1910     +const unsigned int prime_table_length = sizeof(primes)/sizeof(primes[0]);
1911     +const float max_load_factor = 0.65;
1912     +
1913     +/*****************************************************************************/
1914     +struct hashtable *
1915     +create_hashtable(unsigned int minsize,
1916     + unsigned int (*hashf) (void*),
1917     + int (*eqf) (void*,void*))
1918     +{
1919     + struct hashtable *h;
1920     + unsigned int pindex, size = primes[0];
1921     + /* Check requested hashtable isn't too large */
1922     + if (minsize > (1u << 30)) return NULL;
1923     + /* Enforce size as prime */
1924     + for (pindex=0; pindex < prime_table_length; pindex++) {
1925     + if (primes[pindex] > minsize) { size = primes[pindex]; break; }
1926     + }
1927     + h = (struct hashtable *)malloc(sizeof(struct hashtable));
1928     + if (NULL == h) return NULL; /*oom*/
1929     + h->table = (struct entry **)malloc(sizeof(struct entry*) * size);
1930     + if (NULL == h->table) { free(h); return NULL; } /*oom*/
1931     + memset(h->table, 0, size * sizeof(struct entry *));
1932     + h->tablelength = size;
1933     + h->primeindex = pindex;
1934     + h->entrycount = 0;
1935     + h->hashfn = hashf;
1936     + h->eqfn = eqf;
1937     + h->loadlimit = (unsigned int)(size * max_load_factor) + 1;
1938     + return h;
1939     +}
1940     +
1941     +/*****************************************************************************/
1942     +
1943     +#define hash(h, k) h->hashfn(k)
1944     +
1945     +/*****************************************************************************/
1946     +static int
1947     +hashtable_expand(struct hashtable *h)
1948     +{
1949     + /* Double the size of the table to accomodate more entries */
1950     + struct entry **newtable;
1951     + struct entry *e;
1952     + struct entry **pE;
1953     + unsigned int newsize, i, index;
1954     + /* Check we're not hitting max capacity */
1955     + if (h->primeindex == (prime_table_length - 1)) return 0;
1956     + newsize = primes[++(h->primeindex)];
1957     +
1958     + newtable = (struct entry **)malloc(sizeof(struct entry*) * newsize);
1959     + if (NULL != newtable)
1960     + {
1961     + memset(newtable, 0, newsize * sizeof(struct entry *));
1962     + /* This algorithm is not 'stable'. ie. it reverses the list
1963     + * when it transfers entries between the tables */
1964     + for (i = 0; i < h->tablelength; i++) {
1965     + while (NULL != (e = h->table[i])) {
1966     + h->table[i] = e->next;
1967     + index = indexFor(newsize,e->h);
1968     + e->next = newtable[index];
1969     + newtable[index] = e;
1970     + }
1971     + }
1972     + free(h->table);
1973     + h->table = newtable;
1974     + }
1975     + /* Plan B: realloc instead */
1976     + else
1977     + {
1978     + newtable = (struct entry **)
1979     + realloc(h->table, newsize * sizeof(struct entry *));
1980     + if (NULL == newtable) { (h->primeindex)--; return 0; }
1981     + h->table = newtable;
1982     + memset(newtable[h->tablelength], 0, newsize - h->tablelength);
1983     + for (i = 0; i < h->tablelength; i++) {
1984     + for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) {
1985     + index = indexFor(newsize,e->h);
1986     + if (index == i)
1987     + {
1988     + pE = &(e->next);
1989     + }
1990     + else
1991     + {
1992     + *pE = e->next;
1993     + e->next = newtable[index];
1994     + newtable[index] = e;
1995     + }
1996     + }
1997     + }
1998     + }
1999     + h->tablelength = newsize;
2000     + h->loadlimit = (unsigned int)(newsize * max_load_factor) + 1;
2001     + return -1;
2002     +}
2003     +
2004     +/*****************************************************************************/
2005     +unsigned int
2006     +hashtable_count(struct hashtable *h)
2007     +{
2008     + return h->entrycount;
2009     +}
2010     +
2011     +/*****************************************************************************/
2012     +int
2013     +hashtable_insert(struct hashtable *h, void *k, void *v)
2014     +{
2015     + /* This method allows duplicate keys - but they shouldn't be used */
2016     + unsigned int index;
2017     + struct entry *e;
2018     + if (++(h->entrycount) > h->loadlimit)
2019     + {
2020     + /* Ignore the return value. If expand fails, we should
2021     + * still try cramming just this value into the existing table
2022     + * -- we may not have memory for a larger table, but one more
2023     + * element may be ok. Next time we insert, we'll try expanding again.*/
2024     + hashtable_expand(h);
2025     + }
2026     + e = (struct entry *)malloc(sizeof(struct entry));
2027     + if (NULL == e) { --(h->entrycount); return 0; } /*oom*/
2028     + e->h = hash(h,k);
2029     + index = indexFor(h->tablelength,e->h);
2030     + e->k = k;
2031     + e->v = v;
2032     + e->next = h->table[index];
2033     + h->table[index] = e;
2034     + return -1;
2035     +}
2036     +
2037     +/*****************************************************************************/
2038     +void * /* returns value associated with key */
2039     +hashtable_search(struct hashtable *h, void *k)
2040     +{
2041     + struct entry *e;
2042     + unsigned int hashvalue, index;
2043     + hashvalue = hash(h,k);
2044     + index = indexFor(h->tablelength,hashvalue);
2045     + e = h->table[index];
2046     + while (NULL != e)
2047     + {
2048     + /* Check hash value to short circuit heavier comparison */
2049     + if ((hashvalue == e->h) && (h->eqfn(k, e->k))) return e->v;
2050     + e = e->next;
2051     + }
2052     + return NULL;
2053     +}
2054     +
2055     +/*****************************************************************************/
2056     +void * /* returns value associated with key */
2057     +hashtable_remove(struct hashtable *h, void *k, int free_key)
2058     +{
2059     + /* TODO: consider compacting the table when the load factor drops enough,
2060     + * or provide a 'compact' method. */
2061     +
2062     + struct entry *e;
2063     + struct entry **pE;
2064     + void *v;
2065     + unsigned int hashvalue, index;
2066     +
2067     + hashvalue = hash(h,k);
2068     + index = indexFor(h->tablelength,hash(h,k));
2069     + pE = &(h->table[index]);
2070     + e = *pE;
2071     + while (NULL != e)
2072     + {
2073     + /* Check hash value to short circuit heavier comparison */
2074     + if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
2075     + {
2076     + *pE = e->next;
2077     + h->entrycount--;
2078     + v = e->v;
2079     + if (free_key) freekey(e->k);
2080     + free(e);
2081     + return v;
2082     + }
2083     + pE = &(e->next);
2084     + e = e->next;
2085     + }
2086     + return NULL;
2087     +}
2088     +
2089     +/*****************************************************************************/
2090     +/* destroy */
2091     +void
2092     +hashtable_destroy(struct hashtable *h, int free_kv)
2093     +{
2094     + unsigned int i;
2095     + struct entry *e, *f;
2096     + struct entry **table = h->table;
2097     + if (free_kv)
2098     + {
2099     + for (i = 0; i < h->tablelength; i++)
2100     + {
2101     + e = table[i];
2102     + while (NULL != e)
2103     + { f = e; e = e->next; freekey(f->k); free(f->v); free(f); }
2104     + }
2105     + }
2106     + free(h->table);
2107     + free(h);
2108     +}
2109     +
2110     +/*
2111     + * Copyright (c) 2002, Christopher Clark
2112     + * All rights reserved.
2113     + *
2114     + * Redistribution and use in source and binary forms, with or without
2115     + * modification, are permitted provided that the following conditions
2116     + * are met:
2117     + *
2118     + * * Redistributions of source code must retain the above copyright
2119     + * notice, this list of conditions and the following disclaimer.
2120     + *
2121     + * * Redistributions in binary form must reproduce the above copyright
2122     + * notice, this list of conditions and the following disclaimer in the
2123     + * documentation and/or other materials provided with the distribution.
2124     + *
2125     + * * Neither the name of the original author; nor the names of any contributors
2126     + * may be used to endorse or promote products derived from this software
2127     + * without specific prior written permission.
2128     + *
2129     + *
2130     + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2131     + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2132     + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2133     + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
2134     + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2135     + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2136     + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2137     + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2138     + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
2139     + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2140     + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2141     +*/
2142     diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/hashtable.h Linux-PAM-1.1.3/modules/pam_console/hashtable.h
2143     --- Linux-PAM-1.1.3.orig/modules/pam_console/hashtable.h 1969-12-31 19:00:00.000000000 -0500
2144     +++ Linux-PAM-1.1.3/modules/pam_console/hashtable.h 2011-01-26 22:14:52.062657563 -0500
2145     @@ -0,0 +1,199 @@
2146     +/* Copyright (C) 2002 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */
2147     +
2148     +#ifndef __HASHTABLE_CWC22_H__
2149     +#define __HASHTABLE_CWC22_H__
2150     +
2151     +struct hashtable;
2152     +
2153     +/* Example of use:
2154     + *
2155     + * struct hashtable *h;
2156     + * struct some_key *k;
2157     + * struct some_value *v;
2158     + *
2159     + * static unsigned int hash_from_key_fn( void *k );
2160     + * static int keys_equal_fn ( void *key1, void *key2 );
2161     + *
2162     + * h = create_hashtable(16, hash_from_key_fn, keys_equal_fn);
2163     + * k = (struct some_key *) malloc(sizeof(struct some_key));
2164     + * v = (struct some_value *) malloc(sizeof(struct some_value));
2165     + *
2166     + * (initialise k and v to suitable values)
2167     + *
2168     + * if (! hashtable_insert(h,k,v) )
2169     + * { exit(-1); }
2170     + *
2171     + * if (NULL == (found = hashtable_search(h,k) ))
2172     + * { printf("not found!"); }
2173     + *
2174     + * if (NULL == (found = hashtable_remove(h,k) ))
2175     + * { printf("Not found\n"); }
2176     + *
2177     + */
2178     +
2179     +/* Macros may be used to define type-safe(r) hashtable access functions, with
2180     + * methods specialized to take known key and value types as parameters.
2181     + *
2182     + * Example:
2183     + *
2184     + * Insert this at the start of your file:
2185     + *
2186     + * DEFINE_HASHTABLE_INSERT(insert_some, struct some_key, struct some_value);
2187     + * DEFINE_HASHTABLE_SEARCH(search_some, struct some_key, struct some_value);
2188     + * DEFINE_HASHTABLE_REMOVE(remove_some, struct some_key, struct some_value);
2189     + *
2190     + * This defines the functions 'insert_some', 'search_some' and 'remove_some'.
2191     + * These operate just like hashtable_insert etc., with the same parameters,
2192     + * but their function signatures have 'struct some_key *' rather than
2193     + * 'void *', and hence can generate compile time errors if your program is
2194     + * supplying incorrect data as a key (and similarly for value).
2195     + *
2196     + * Note that the hash and key equality functions passed to create_hashtable
2197     + * still take 'void *' parameters instead of 'some key *'. This shouldn't be
2198     + * a difficult issue as they're only defined and passed once, and the other
2199     + * functions will ensure that only valid keys are supplied to them.
2200     + *
2201     + * The cost for this checking is increased code size and runtime overhead
2202     + * - if performance is important, it may be worth switching back to the
2203     + * unsafe methods once your program has been debugged with the safe methods.
2204     + * This just requires switching to some simple alternative defines - eg:
2205     + * #define insert_some hashtable_insert
2206     + *
2207     + */
2208     +
2209     +/*****************************************************************************
2210     + * create_hashtable
2211     +
2212     + * @name create_hashtable
2213     + * @param minsize minimum initial size of hashtable
2214     + * @param hashfunction function for hashing keys
2215     + * @param key_eq_fn function for determining key equality
2216     + * @return newly created hashtable or NULL on failure
2217     + */
2218     +
2219     +struct hashtable *
2220     +create_hashtable(unsigned int minsize,
2221     + unsigned int (*hashfunction) (void*),
2222     + int (*key_eq_fn) (void*,void*));
2223     +
2224     +/*****************************************************************************
2225     + * hashtable_insert
2226     +
2227     + * @name hashtable_insert
2228     + * @param h the hashtable to insert into
2229     + * @param k the key - hashtable claims ownership and will free on removal
2230     + * @param v the value - does not claim ownership
2231     + * @return non-zero for successful insertion
2232     + *
2233     + * This function will cause the table to expand if the insertion would take
2234     + * the ratio of entries to table size over the maximum load factor.
2235     + *
2236     + * This function does not check for repeated insertions with a duplicate key.
2237     + * The value returned when using a duplicate key is undefined -- when
2238     + * the hashtable changes size, the order of retrieval of duplicate key
2239     + * entries is reversed.
2240     + * If in doubt, remove before insert.
2241     + */
2242     +
2243     +int
2244     +hashtable_insert(struct hashtable *h, void *k, void *v);
2245     +
2246     +#define DEFINE_HASHTABLE_INSERT(fnname, keytype, valuetype) \
2247     +int fnname (struct hashtable *h, keytype *k, valuetype *v) \
2248     +{ \
2249     + return hashtable_insert(h,k,v); \
2250     +}
2251     +
2252     +/*****************************************************************************
2253     + * hashtable_search
2254     +
2255     + * @name hashtable_search
2256     + * @param h the hashtable to search
2257     + * @param k the key to search for - does not claim ownership
2258     + * @return the value associated with the key, or NULL if none found
2259     + */
2260     +
2261     +void *
2262     +hashtable_search(struct hashtable *h, void *k);
2263     +
2264     +#define DEFINE_HASHTABLE_SEARCH(fnname, keytype, valuetype) \
2265     +valuetype * fnname (struct hashtable *h, keytype *k) \
2266     +{ \
2267     + return (valuetype *) (hashtable_search(h,k)); \
2268     +}
2269     +
2270     +/*****************************************************************************
2271     + * hashtable_remove
2272     +
2273     + * @name hashtable_remove
2274     + * @param h the hashtable to remove the item from
2275     + * @param k the key to search for - does not claim ownership
2276     + * @return the value associated with the key, or NULL if none found
2277     + */
2278     +
2279     +void * /* returns value */
2280     +hashtable_remove(struct hashtable *h, void *k, int free_key);
2281     +
2282     +#define DEFINE_HASHTABLE_REMOVE(fnname, keytype, valuetype) \
2283     +valuetype * fnname (struct hashtable *h, keytype *k) \
2284     +{ \
2285     + return (valuetype *) (hashtable_remove(h,k)); \
2286     +}
2287     +
2288     +
2289     +/*****************************************************************************
2290     + * hashtable_count
2291     +
2292     + * @name hashtable_count
2293     + * @param h the hashtable
2294     + * @return the number of items stored in the hashtable
2295     + */
2296     +unsigned int
2297     +hashtable_count(struct hashtable *h);
2298     +
2299     +
2300     +/*****************************************************************************
2301     + * hashtable_destroy
2302     +
2303     + * @name hashtable_destroy
2304     + * @param h the hashtable
2305     + * @param free_values whether to call 'free' on the remaining values
2306     + */
2307     +
2308     +void
2309     +hashtable_destroy(struct hashtable *h, int free_values);
2310     +
2311     +#endif /* __HASHTABLE_CWC22_H__ */
2312     +
2313     +/*
2314     + * Copyright (c) 2002, Christopher Clark
2315     + * All rights reserved.
2316     + *
2317     + * Redistribution and use in source and binary forms, with or without
2318     + * modification, are permitted provided that the following conditions
2319     + * are met:
2320     + *
2321     + * * Redistributions of source code must retain the above copyright
2322     + * notice, this list of conditions and the following disclaimer.
2323     + *
2324     + * * Redistributions in binary form must reproduce the above copyright
2325     + * notice, this list of conditions and the following disclaimer in the
2326     + * documentation and/or other materials provided with the distribution.
2327     + *
2328     + * * Neither the name of the original author; nor the names of any contributors
2329     + * may be used to endorse or promote products derived from this software
2330     + * without specific prior written permission.
2331     + *
2332     + *
2333     + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2334     + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2335     + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2336     + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
2337     + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2338     + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2339     + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2340     + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2341     + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
2342     + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2343     + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2344     +*/
2345     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
2346     --- Linux-PAM-1.1.3.orig/modules/pam_console/hashtable_private.h 1969-12-31 19:00:00.000000000 -0500
2347     +++ Linux-PAM-1.1.3/modules/pam_console/hashtable_private.h 2011-01-26 22:14:52.062657563 -0500
2348     @@ -0,0 +1,85 @@
2349     +/* Copyright (C) 2002, 2004 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */
2350     +
2351     +#ifndef __HASHTABLE_PRIVATE_CWC22_H__
2352     +#define __HASHTABLE_PRIVATE_CWC22_H__
2353     +
2354     +#include "hashtable.h"
2355     +
2356     +/*****************************************************************************/
2357     +struct entry
2358     +{
2359     + void *k, *v;
2360     + unsigned int h;
2361     + struct entry *next;
2362     +};
2363     +
2364     +struct hashtable {
2365     + unsigned int tablelength;
2366     + struct entry **table;
2367     + unsigned int entrycount;
2368     + unsigned int loadlimit;
2369     + unsigned int primeindex;
2370     + unsigned int (*hashfn) (void *k);
2371     + int (*eqfn) (void *k1, void *k2);
2372     +};
2373     +
2374     +/*****************************************************************************/
2375     +unsigned int
2376     +hash(struct hashtable *h, void *k);
2377     +
2378     +/*****************************************************************************/
2379     +/* indexFor */
2380     +static inline unsigned int
2381     +indexFor(unsigned int tablelength, unsigned int hashvalue) {
2382     + return (hashvalue % tablelength);
2383     +};
2384     +
2385     +/* Only works if tablelength == 2^N */
2386     +/*static inline unsigned int
2387     +indexFor(unsigned int tablelength, unsigned int hashvalue)
2388     +{
2389     + return (hashvalue & (tablelength - 1u));
2390     +}
2391     +*/
2392     +
2393     +/*****************************************************************************/
2394     +#define freekey(X) free(X)
2395     +/*define freekey(X) ; */
2396     +
2397     +
2398     +/*****************************************************************************/
2399     +
2400     +#endif /* __HASHTABLE_PRIVATE_CWC22_H__*/
2401     +
2402     +/*
2403     + * Copyright (c) 2002, Christopher Clark
2404     + * All rights reserved.
2405     + *
2406     + * Redistribution and use in source and binary forms, with or without
2407     + * modification, are permitted provided that the following conditions
2408     + * are met:
2409     + *
2410     + * * Redistributions of source code must retain the above copyright
2411     + * notice, this list of conditions and the following disclaimer.
2412     + *
2413     + * * Redistributions in binary form must reproduce the above copyright
2414     + * notice, this list of conditions and the following disclaimer in the
2415     + * documentation and/or other materials provided with the distribution.
2416     + *
2417     + * * Neither the name of the original author; nor the names of any contributors
2418     + * may be used to endorse or promote products derived from this software
2419     + * without specific prior written permission.
2420     + *
2421     + *
2422     + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2423     + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2424     + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2425     + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
2426     + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2427     + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2428     + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2429     + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2430     + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
2431     + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2432     + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2433     +*/
2434     diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/modechange.c Linux-PAM-1.1.3/modules/pam_console/modechange.c
2435     --- Linux-PAM-1.1.3.orig/modules/pam_console/modechange.c 1969-12-31 19:00:00.000000000 -0500
2436     +++ Linux-PAM-1.1.3/modules/pam_console/modechange.c 2011-01-26 22:14:52.062657563 -0500
2437     @@ -0,0 +1,324 @@
2438     +/* This file is derived from modechange.c included in the GNU fileutils
2439     + distribution. It has been changed to be a library specifically
2440     + for use within pam_console
2441     + Changes Copyright 1999 Red Hat Software, Inc.
2442     + */
2443     +
2444     +/* modechange.c -- file mode manipulation
2445     + Copyright (C) 1989, 1990 Free Software Foundation, Inc.
2446     +
2447     + This program is free software; you can redistribute it and/or modify
2448     + it under the terms of the GNU General Public License as published by
2449     + the Free Software Foundation; either version 2, or (at your option)
2450     + any later version.
2451     +
2452     + This program is distributed in the hope that it will be useful,
2453     + but WITHOUT ANY WARRANTY; without even the implied warranty of
2454     + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2455     + GNU General Public License for more details.
2456     +
2457     + You should have received a copy of the GNU General Public License
2458     + along with this program; if not, write to the Free Software Foundation,
2459     + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
2460     +
2461     +/* Written by David MacKenzie <djm@ai.mit.edu> */
2462     +
2463     +/* The ASCII mode string is compiled into a linked list of `struct
2464     + modechange', which can then be applied to each file to be changed.
2465     + We do this instead of re-parsing the ASCII string for each file
2466     + because the compiled form requires less computation to use; when
2467     + changing the mode of many files, this probably results in a
2468     + performance gain. */
2469     +
2470     +#include "config.h"
2471     +#include <sys/types.h>
2472     +#include <sys/stat.h>
2473     +#include "modechange.h"
2474     +
2475     +#include <stdlib.h>
2476     +
2477     +/* Return newly allocated memory to hold one element of type TYPE. */
2478     +#define talloc(type) ((type *) malloc (sizeof (type)))
2479     +
2480     +#define isodigit(c) ((c) >= '0' && (c) <= '7')
2481     +
2482     +/* Return a positive integer containing the value of the ASCII
2483     + octal number S. If S is not an octal number, return -1. */
2484     +
2485     +static int
2486     +oatoi (const char *s)
2487     +{
2488     + register int i;
2489     +
2490     + if (*s == 0)
2491     + return -1;
2492     + for (i = 0; isodigit (*s); ++s)
2493     + i = i * 8 + *s - '0';
2494     + if (*s)
2495     + return -1;
2496     + return i;
2497     +}
2498     +
2499     +/* Return a linked list of file mode change operations created from
2500     + MODE_STRING, an ASCII string that contains either an octal number
2501     + specifying an absolute mode, or symbolic mode change operations with
2502     + the form:
2503     + [ugoa...][[+-=][rwxXstugo...]...][,...]
2504     + MASKED_OPS is a bitmask indicating which symbolic mode operators (=+-)
2505     + should not affect bits set in the umask when no users are given.
2506     + Operators not selected in MASKED_OPS ignore the umask.
2507     +
2508     + Return MODE_INVALID if `mode_string' does not contain a valid
2509     + representation of file mode change operations;
2510     + return MODE_MEMORY_EXHAUSTED if there is insufficient memory. */
2511     +
2512     +STATIC struct mode_change *
2513     +mode_compile (mode_string, masked_ops)
2514     + const char *mode_string;
2515     + unsigned masked_ops;
2516     +{
2517     + struct mode_change *head; /* First element of the linked list. */
2518     + struct mode_change *change; /* An element of the linked list. */
2519     + int i; /* General purpose temporary. */
2520     + int umask_value; /* The umask value (surprise). */
2521     + unsigned short affected_bits; /* Which bits in the mode are operated on. */
2522     + unsigned short affected_masked; /* `affected_bits' modified by umask. */
2523     + unsigned ops_to_mask; /* Operators to actually use umask on. */
2524     +
2525     + i = oatoi (mode_string);
2526     + if (i >= 0)
2527     + {
2528     + if (i > 07777)
2529     + return MODE_INVALID;
2530     + head = talloc (struct mode_change);
2531     + if (head == NULL)
2532     + return MODE_MEMORY_EXHAUSTED;
2533     + head->next = NULL;
2534     + head->op = '=';
2535     + head->flags = 0;
2536     + head->value = i;
2537     + head->affected = 07777; /* Affect all permissions. */
2538     + return head;
2539     + }
2540     +
2541     + umask_value = umask (0);
2542     + umask (umask_value); /* Restore the old value. */
2543     +
2544     + head = NULL;
2545     + change = NULL;
2546     + --mode_string;
2547     +
2548     + /* One loop iteration for each "ugoa...=+-rwxXstugo...[=+-rwxXstugo...]". */
2549     + do
2550     + {
2551     + affected_bits = 0;
2552     + ops_to_mask = 0;
2553     + /* Turn on all the bits in `affected_bits' for each group given. */
2554     + for (++mode_string;; ++mode_string)
2555     + switch (*mode_string)
2556     + {
2557     + case 'u':
2558     + affected_bits |= 04700;
2559     + break;
2560     + case 'g':
2561     + affected_bits |= 02070;
2562     + break;
2563     + case 'o':
2564     + affected_bits |= 01007;
2565     + break;
2566     + case 'a':
2567     + affected_bits |= 07777;
2568     + break;
2569     + default:
2570     + goto no_more_affected;
2571     + }
2572     +
2573     + no_more_affected:
2574     + /* If none specified, affect all bits, except perhaps those
2575     + set in the umask. */
2576     + if (affected_bits == 0)
2577     + {
2578     + affected_bits = 07777;
2579     + ops_to_mask = masked_ops;
2580     + }
2581     +
2582     + while (*mode_string == '=' || *mode_string == '+' || *mode_string == '-')
2583     + {
2584     + /* Add the element to the tail of the list, so the operations
2585     + are performed in the correct order. */
2586     + if (head == NULL)
2587     + {
2588     + head = talloc (struct mode_change);
2589     + if (head == NULL)
2590     + return MODE_MEMORY_EXHAUSTED;
2591     + change = head;
2592     + }
2593     + else
2594     + {
2595     + change->next = talloc (struct mode_change);
2596     + if (change->next == NULL)
2597     + {
2598     + mode_free (change);
2599     + return MODE_MEMORY_EXHAUSTED;
2600     + }
2601     + change = change->next;
2602     + }
2603     +
2604     + change->next = NULL;
2605     + change->op = *mode_string; /* One of "=+-". */
2606     + affected_masked = affected_bits;
2607     + if (ops_to_mask & (*mode_string == '=' ? MODE_MASK_EQUALS
2608     + : *mode_string == '+' ? MODE_MASK_PLUS
2609     + : MODE_MASK_MINUS))
2610     + affected_masked &= ~umask_value;
2611     + change->affected = affected_masked;
2612     + change->value = 0;
2613     + change->flags = 0;
2614     +
2615     + /* Set `value' according to the bits set in `affected_masked'. */
2616     + for (++mode_string;; ++mode_string)
2617     + switch (*mode_string)
2618     + {
2619     + case 'r':
2620     + change->value |= 00444 & affected_masked;
2621     + break;
2622     + case 'w':
2623     + change->value |= 00222 & affected_masked;
2624     + break;
2625     + case 'X':
2626     + change->flags |= MODE_X_IF_ANY_X;
2627     + /* Fall through. */
2628     + case 'x':
2629     + change->value |= 00111 & affected_masked;
2630     + break;
2631     + case 's':
2632     + /* Set the setuid/gid bits if `u' or `g' is selected. */
2633     + change->value |= 06000 & affected_masked;
2634     + break;
2635     + case 't':
2636     + /* Set the "save text image" bit if `o' is selected. */
2637     + change->value |= 01000 & affected_masked;
2638     + break;
2639     + case 'u':
2640     + /* Set the affected bits to the value of the `u' bits
2641     + on the same file. */
2642     + if (change->value)
2643     + goto invalid;
2644     + change->value = 00700;
2645     + change->flags |= MODE_COPY_EXISTING;
2646     + break;
2647     + case 'g':
2648     + /* Set the affected bits to the value of the `g' bits
2649     + on the same file. */
2650     + if (change->value)
2651     + goto invalid;
2652     + change->value = 00070;
2653     + change->flags |= MODE_COPY_EXISTING;
2654     + break;
2655     + case 'o':
2656     + /* Set the affected bits to the value of the `o' bits
2657     + on the same file. */
2658     + if (change->value)
2659     + goto invalid;
2660     + change->value = 00007;
2661     + change->flags |= MODE_COPY_EXISTING;
2662     + break;
2663     + default:
2664     + goto no_more_values;
2665     + }
2666     + no_more_values:;
2667     + }
2668     + } while (*mode_string == ',');
2669     + if (*mode_string == 0)
2670     + return head;
2671     +invalid:
2672     + mode_free (head);
2673     + return MODE_INVALID;
2674     +}
2675     +
2676     +/* Return file mode OLDMODE, adjusted as indicated by the list of change
2677     + operations CHANGES. If OLDMODE is a directory, the type `X'
2678     + change affects it even if no execute bits were set in OLDMODE.
2679     + The returned value has the S_IFMT bits cleared. */
2680     +
2681     +STATIC unsigned short
2682     +mode_adjust (oldmode, changes)
2683     + unsigned oldmode;
2684     + const struct mode_change *changes;
2685     +{
2686     + unsigned short newmode; /* The adjusted mode and one operand. */
2687     + unsigned short value; /* The other operand. */
2688     +
2689     + newmode = oldmode & 07777;
2690     +
2691     + for (; changes; changes = changes->next)
2692     + {
2693     + if (changes->flags & MODE_COPY_EXISTING)
2694     + {
2695     + /* Isolate in `value' the bits in `newmode' to copy, given in
2696     + the mask `changes->value'. */
2697     + value = newmode & changes->value;
2698     +
2699     + if (changes->value & 00700)
2700     + /* Copy `u' permissions onto `g' and `o'. */
2701     + value |= (value >> 3) | (value >> 6);
2702     + else if (changes->value & 00070)
2703     + /* Copy `g' permissions onto `u' and `o'. */
2704     + value |= (value << 3) | (value >> 3);
2705     + else
2706     + /* Copy `o' permissions onto `u' and `g'. */
2707     + value |= (value << 3) | (value << 6);
2708     +
2709     + /* In order to change only `u', `g', or `o' permissions,
2710     + or some combination thereof, clear unselected bits.
2711     + This can not be done in mode_compile because the value
2712     + to which the `changes->affected' mask is applied depends
2713     + on the old mode of each file. */
2714     + value &= changes->affected;
2715     + }
2716     + else
2717     + {
2718     + value = changes->value;
2719     + /* If `X', do not affect the execute bits if the file is not a
2720     + directory and no execute bits are already set. */
2721     + if ((changes->flags & MODE_X_IF_ANY_X)
2722     + && !S_ISDIR (oldmode)
2723     + && (newmode & 00111) == 0)
2724     + value &= ~00111; /* Clear the execute bits. */
2725     + }
2726     +
2727     + switch (changes->op)
2728     + {
2729     + case '=':
2730     + /* Preserve the previous values in `newmode' of bits that are
2731     + not affected by this change operation. */
2732     + newmode = (newmode & ~changes->affected) | value;
2733     + break;
2734     + case '+':
2735     + newmode |= value;
2736     + break;
2737     + case '-':
2738     + newmode &= ~value;
2739     + break;
2740     + }
2741     + }
2742     + return newmode;
2743     +}
2744     +
2745     +/* Free the memory used by the list of file mode change operations
2746     + CHANGES. */
2747     +
2748     +STATIC void
2749     +mode_free (changes)
2750     + register struct mode_change *changes;
2751     +{
2752     + register struct mode_change *next;
2753     +
2754     + while (changes)
2755     + {
2756     + next = changes->next;
2757     + free (changes);
2758     + changes = next;
2759     + }
2760     +}
2761     +
2762     diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/modechange.h Linux-PAM-1.1.3/modules/pam_console/modechange.h
2763     --- Linux-PAM-1.1.3.orig/modules/pam_console/modechange.h 1969-12-31 19:00:00.000000000 -0500
2764     +++ Linux-PAM-1.1.3/modules/pam_console/modechange.h 2011-01-26 22:14:52.062657563 -0500
2765     @@ -0,0 +1,67 @@
2766     +/* modechange.h -- definitions for file mode manipulation
2767     + Copyright (C) 1989, 1990 Free Software Foundation, Inc.
2768     +
2769     + This program is free software; you can redistribute it and/or modify
2770     + it under the terms of the GNU General Public License as published by
2771     + the Free Software Foundation; either version 2, or (at your option)
2772     + any later version.
2773     +
2774     + This program is distributed in the hope that it will be useful,
2775     + but WITHOUT ANY WARRANTY; without even the implied warranty of
2776     + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2777     + GNU General Public License for more details.
2778     +
2779     + You should have received a copy of the GNU General Public License
2780     + along with this program; if not, write to the Free Software Foundation,
2781     + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
2782     +
2783     +#ifndef _MODECHANGE_H
2784     +#define _MODECHANGE_H
2785     +
2786     +#ifndef STATIC
2787     +#define STATIC
2788     +#endif
2789     +
2790     +
2791     +/* Masks for the `flags' field in a `struct mode_change'. */
2792     +
2793     +/* Affect the execute bits only if at least one execute bit is set already,
2794     + or if the file is a directory. */
2795     +#define MODE_X_IF_ANY_X 01
2796     +
2797     +/* If set, copy some existing permissions for u, g, or o onto the other two.
2798     + Which of u, g, or o is copied is determined by which bits are set in the
2799     + `value' field. */
2800     +#define MODE_COPY_EXISTING 02
2801     +
2802     +struct mode_change
2803     +{
2804     + char op; /* One of "=+-". */
2805     + char flags; /* Special operations. */
2806     + unsigned short affected; /* Set for u/g/o/s/s/t, if to be affected. */
2807     + unsigned short value; /* Bits to add/remove. */
2808     + struct mode_change *next; /* Link to next change in list. */
2809     +};
2810     +
2811     +/* Masks for mode_compile argument. */
2812     +#define MODE_MASK_EQUALS 1
2813     +#define MODE_MASK_PLUS 2
2814     +#define MODE_MASK_MINUS 4
2815     +
2816     +/* Error return values for mode_compile. */
2817     +#define MODE_INVALID (struct mode_change *) 0
2818     +#define MODE_MEMORY_EXHAUSTED (struct mode_change *) 1
2819     +
2820     +#ifndef __P
2821     +# if defined (__GNUC__) || (defined (__STDC__) && __STDC__)
2822     +# define __P(Args) Args
2823     +# else
2824     +# define __P(Args) ()
2825     +# endif
2826     +#endif
2827     +
2828     +STATIC struct mode_change *mode_compile __P ((const char *, unsigned));
2829     +STATIC unsigned short mode_adjust __P ((unsigned, const struct mode_change *));
2830     +STATIC void mode_free __P ((struct mode_change *));
2831     +
2832     +#endif /* _MODECHANGE_H */
2833     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
2834     --- Linux-PAM-1.1.3.orig/modules/pam_console/pam_console.8 1969-12-31 19:00:00.000000000 -0500
2835     +++ Linux-PAM-1.1.3/modules/pam_console/pam_console.8 2011-01-26 22:14:52.062657563 -0500
2836     @@ -0,0 +1,105 @@
2837     +.\" Copyright 1999 Red Hat Software, Inc.
2838     +.\" Written by Michael K. Johnson <johnsonm@redhat.com>
2839     +.TH pam_console 8 2005/10/4 "Red Hat" "System Administrator's Manual"
2840     +.SH NAME
2841     +pam_console \- determine user owning the system console
2842     +.SH SYNOPSIS
2843     +.B session optional pam_console.so
2844     +.br
2845     +.B auth required pam_console.so
2846     +.SH DESCRIPTION
2847     +pam_console.so is designed to give users at the physical console
2848     +(virtual terminals and local xdm-managed X sessions by default, but
2849     +that is configurable) capabilities that they would not otherwise have,
2850     +and to take those capabilities away when the are no longer logged in at
2851     +the console. It provides two main kinds of capabilities: file permissions
2852     +and authentication.
2853     +
2854     +When a user logs in at the console and \fBno other user is currently
2855     +logged in at the console\fP, pam_console.so will run handler programs
2856     +specified in the file /etc/security/console.handlers such as
2857     +pam_console_apply which changes permissions and ownership of files as
2858     +described in the file /etc/security/console.perms.
2859     +That user may then log in on other terminals that are considered part
2860     +of the console, and as long as the user is still logged in at any one
2861     +of those terminals, that user will own those devices. When the user
2862     +logs out of the last terminal, the console may be taken by the next
2863     +user to log in. Other users who have logged in at the console during
2864     +the time that the first user was logged in will not be given ownership
2865     +of the devices unless they log in on one of the terminals; having done
2866     +so on any one terminal, the next user will own those devices until
2867     +he or she has logged out of every terminal that is part of the physical
2868     +console. Then the race can start for the next user. In practice, this
2869     +is not a problem; the physical console is not generally in use by many
2870     +people at the same time, and pam_console.so just tries to do the right
2871     +thing in weird cases.
2872     +
2873     +When an application attempts to authenticate the user \fBand this user
2874     +is already logged in at the console\fP, pam_console.so checks whether
2875     +there is a file in /etc/security/console.apps/ directory with the same name
2876     +as the application servicename, and if such a file exists, authentication
2877     +succeeds. This way pam_console may be utilized to run some system
2878     +applications (reboots, config tools) without root password,
2879     +or to enter user password on the first system login only.
2880     +
2881     +.SH ARGUMENTS
2882     +.IP debug
2883     +turns on debugging
2884     +.IP allow_nonroot_tty
2885     +gain console locks and change permissions even if the TTY's owner is not root.
2886     +.IP handlersfile=\fIfilename\fP
2887     +tells pam_console.so to get the list of the handlers from a different
2888     +file than /etc/security/console.handlers
2889     +.\" .IP glob
2890     +.\" \fBnot yet implemented\fP interpret strings as globs instead of
2891     +.\" regexp expressions.
2892     +.SH EXAMPLE
2893     +\fB/etc/pam.d/some-system-tool\fP:
2894     +.br
2895     +auth sufficient pam_rootok.so
2896     +.br
2897     +auth required pam_console.so
2898     +.br
2899     +
2900     +.br
2901     +\fB/etc/pam.d/some-login-service\fP:
2902     +.br
2903     +auth sufficient pam_console.so
2904     +.br
2905     +auth required pam_unix.so
2906     +.br
2907     +session required pam_unix.so
2908     +.br
2909     +session optional pam_console.so
2910     +.br
2911     +.SH FILES
2912     +\fI/var/run/console/\fP
2913     +.br
2914     +\fI/var/run/console/console.lock\fP
2915     +.br
2916     +\fI/etc/security/console.apps\fP
2917     +.br
2918     +\fI/etc/security/console.handlers\fP
2919     +.SH SECURITY NOTES
2920     +When pam_console "auth" is used for login services which provide
2921     +possibility of remote login, it is necessary to make sure the application
2922     +correctly sets PAM_RHOST variable, or to deny remote logins completely.
2923     +Currently, /bin/login (invoked from telnetd) and gdm is OK, others may be not.
2924     +.SH "SEE ALSO"
2925     +.BR console.perms (5)
2926     +.br
2927     +.BR console.apps (5)
2928     +.br
2929     +.BR console.handlers (5)
2930     +.br
2931     +.BR pam_console_apply (8)
2932     +.br
2933     +\fI/usr/share/doc/pam*/html/index.html\fP
2934     +.SH BUGS
2935     +Let's hope not, but if you find any, please report them via the "Bug Track"
2936     +link at http://bugzilla.redhat.com/bugzilla/
2937     +.SH AUTHORS
2938     +Michael K. Johnson <johnsonm@redhat.com>
2939     +.br
2940     +Support of console.handlers and other improvements by
2941     +Tomas Mraz <tmraz@redhat.com>
2942     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
2943     --- Linux-PAM-1.1.3.orig/modules/pam_console/pam_console.c 1969-12-31 19:00:00.000000000 -0500
2944     +++ Linux-PAM-1.1.3/modules/pam_console/pam_console.c 2011-01-26 22:14:52.062657563 -0500
2945     @@ -0,0 +1,669 @@
2946     +/* Copyright 1999, 2005 Red Hat, Inc.
2947     + * This software may be used under the terms of the GNU General Public
2948     + * License, available in the file COPYING accompanying this file.
2949     + *
2950     + * /var/run/console/console.lock is the file used to control access to
2951     + * devices. It is created when the first console user logs in,
2952     + * and that user has the control of the console until they have
2953     + * logged out of all concurrent login sessions. That is,
2954     + * user A logs in on console 1 (gets access to console devices)
2955     + * user B logs in on console 2 (does not get access)
2956     + * user A logs in on console 3 (already has access)
2957     + * user A logs out of console 1 (still has access on console 3)
2958     + * user A logs out of console 3 (access revoked; user B does NOT get access)
2959     + * Note that all console users (both A and B in this situation)
2960     + * should be able to run console access programs (that is,
2961     + * pam_sm_authenticate() should return PAM_SUCCESS) even if
2962     + * console access to files/devices is not available to any one of
2963     + * the users (B in this case).
2964     + *
2965     + * /var/run/console/<username> is used for reference counting
2966     + * and to make console authentication easy -- if it exists, then
2967     + * <username> has console access.
2968     + *
2969     + * A system startup script should remove /var/run/console/console.lock
2970     + * and everything in /var/run/console/
2971     + */
2972     +
2973     +#include "config.h"
2974     +#include <errno.h>
2975     +#include <pwd.h>
2976     +#include <stdlib.h>
2977     +#include <string.h>
2978     +#include <syslog.h>
2979     +#include <sys/types.h>
2980     +#include <sys/stat.h>
2981     +#include <sys/param.h>
2982     +#include <fcntl.h>
2983     +#include <unistd.h>
2984     +#include <stdio.h>
2985     +#include <regex.h>
2986     +#include "pam_console.h"
2987     +#include "handlers.h"
2988     +#include <security/pam_modules.h>
2989     +#include <security/_pam_macros.h>
2990     +#include <security/pam_modutil.h>
2991     +#include <security/pam_ext.h>
2992     +
2993     +/* In order to avoid errors in pam_get_item(), we need a very
2994     + * unfortunate cast. This is a terrible design error in PAM
2995     + * that Linux-PAM slavishly follows. :-(
2996     + */
2997     +#define CAST_ME_HARDER (const void**)
2998     +
2999     +static char consolelock[] = LOCKDIR "/" LOCKFILE;
3000     +static char consolerefs[] = LOCKDIR "/";
3001     +static char consoleapps[] = "/etc/security/console.apps/";
3002     +static char consolehandlers[PATH_MAX] = "/etc/security/console.handlers";
3003     +static int configfileparsed = 0;
3004     +static int debug = 0;
3005     +static int allow_nonroot_tty = 0;
3006     +
3007     +/* some syslogging */
3008     +
3009     +void
3010     +_pam_log(pam_handle_t *pamh, int err, int debug_p, const char *format, ...)
3011     +{
3012     + va_list args;
3013     +
3014     + if (debug_p && !debug) return;
3015     +
3016     + va_start(args, format);
3017     + pam_vsyslog(pamh, err, format, args);
3018     + closelog();
3019     +}
3020     +
3021     +static void *
3022     +_do_malloc(size_t req)
3023     +{
3024     + void *ret;
3025     +
3026     + ret = malloc(req);
3027     + if (!ret) abort();
3028     + return ret;
3029     +}
3030     +
3031     +static void
3032     +_args_parse(pam_handle_t *pamh, int argc, const char **argv)
3033     +{
3034     + for (; argc-- > 0; ++argv) {
3035     + if (!strcmp(*argv,"debug"))
3036     + debug = 1;
3037     + else if (!strcmp(*argv,"allow_nonroot_tty"))
3038     + allow_nonroot_tty = 1;
3039     + else if (!strncmp(*argv,"handlersfile=",13))
3040     + if (strlen(*argv+13) < PATH_MAX)
3041     + strcpy(consolehandlers,*argv+13);
3042     + else
3043     + _pam_log(pamh, LOG_ERR, FALSE,
3044     + "_args_parse: handlersfile filename too long");
3045     + else {
3046     + _pam_log(pamh, LOG_ERR, FALSE,
3047     + "_args_parse: unknown option; %s",*argv);
3048     + }
3049     + }
3050     +}
3051     +
3052     +static int
3053     +is_root(pam_handle_t *pamh, const char *username) {
3054     + /* this should correspond to suser() in the kernel, since the
3055     + * whole point of this is to avoid doing unnecessary file ops
3056     + */
3057     + struct passwd *pwd;
3058     +
3059     + pwd = pam_modutil_getpwnam(pamh, username);
3060     + if (pwd == NULL) {
3061     + _pam_log(pamh, LOG_ERR, FALSE, "getpwnam failed for %s", username);
3062     + return 0;
3063     + }
3064     + return !pwd->pw_uid;
3065     +}
3066     +
3067     +static int
3068     +check_one_console_name(const char *name, const char *cregex) {
3069     + regex_t p;
3070     + int r_err;
3071     + char *class_exp;
3072     +
3073     + class_exp = _do_malloc(strlen(cregex) + 3);
3074     + sprintf(class_exp, "^%s$", cregex);
3075     + r_err = regcomp(&p, class_exp, REG_EXTENDED|REG_NOSUB);
3076     + if (r_err) do_regerror(r_err, &p);
3077     + r_err = regexec(&p, name, 0, NULL, 0);
3078     + regfree(&p);
3079     + free (class_exp);
3080     + return !r_err;
3081     +}
3082     +
3083     +static int
3084     +check_console_name(pam_handle_t *pamh, const char *consolename, int nonroot_ok, int on_set) {
3085     + int found = 0;
3086     + int statted = 0;
3087     + struct stat st;
3088     + char full_path[PATH_MAX];
3089     + const char *consoleregex;
3090     +
3091     + _pam_log(pamh, LOG_DEBUG, TRUE, "check console %s", consolename);
3092     +
3093     + if ((consoleregex = console_get_regexes()) == NULL) {
3094     + /* probably a broken configuration */
3095     + _pam_log(pamh, LOG_INFO, FALSE, "no console regexes in console.handlers config");
3096     + return 0;
3097     + }
3098     + for (; *consoleregex != '\0'; consoleregex += strlen(consoleregex)+1) {
3099     + if (check_one_console_name(consolename, consoleregex)) {
3100     + found = 1;
3101     + break;
3102     + }
3103     + }
3104     +
3105     + if (!found) {
3106     + /* not found */
3107     + _pam_log(pamh, LOG_INFO, TRUE, "no matching console regex found");
3108     + return 0;
3109     + }
3110     +
3111     + /* add some policy here -- not really the PAM way of doing things, but
3112     + it gives us an extra measure of security in case of misconfiguration */
3113     + memset(&st, 0, sizeof(st));
3114     + statted = 0;
3115     +
3116     + _pam_log(pamh, LOG_DEBUG, TRUE, "checking possible console \"%s\"", consolename);
3117     + if (lstat(consolename, &st) != -1) {
3118     + statted = 1;
3119     + }
3120     + if (!statted) {
3121     + strcpy(full_path, "/dev/");
3122     + strncat(full_path, consolename,
3123     + sizeof(full_path) - 1 - strlen(full_path));
3124     + full_path[sizeof(full_path) - 1] = '\0';
3125     + _pam_log(pamh, LOG_DEBUG, TRUE, "checking possible console \"%s\"",
3126     + full_path);
3127     + if (lstat(full_path, &st) != -1) {
3128     + statted = 1;
3129     + }
3130     + }
3131     + if (!statted && (consolename[0] == ':')) {
3132     + int l;
3133     + char *dot = NULL;
3134     + strcpy(full_path, "/tmp/.X11-unix/X");
3135     + l = sizeof(full_path) - 1 - strlen(full_path);
3136     + dot = strchr(consolename + 1, '.');
3137     + if (dot != NULL) {
3138     + l = (l < dot - consolename - 1) ? l : dot - consolename - 1;
3139     + }
3140     + strncat(full_path, consolename + 1, l);
3141     + full_path[sizeof(full_path) - 1] = '\0';
3142     + _pam_log(pamh, LOG_DEBUG, TRUE, "checking possible console \"%s\"",
3143     + full_path);
3144     + if (lstat(full_path, &st) != -1) {
3145     + statted = 1;
3146     + }
3147     + else if (!on_set) { /* there is no X11 socket in case of X11 crash */
3148     + _pam_log(pamh, LOG_DEBUG, TRUE, "can't find X11 socket to examine for %s probably due to X crash", consolename);
3149     + statted = 1; /* this will work because st.st_uid is 0 */
3150     + }
3151     + }
3152     +
3153     + if (statted) {
3154     + int ok = 0;
3155     + if (st.st_uid == 0) {
3156     + _pam_log(pamh, LOG_DEBUG, TRUE, "console %s is owned by UID 0", consolename);
3157     + ok = 1;
3158     + }
3159     + if (S_ISCHR(st.st_mode)) {
3160     + _pam_log(pamh, LOG_DEBUG, TRUE, "console %s is a character device", consolename);
3161     + ok = 1;
3162     + }
3163     + if (!ok && !nonroot_ok) {
3164     + _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);
3165     + found = 0;
3166     + }
3167     + } else {
3168     + _pam_log(pamh, LOG_INFO, TRUE, "can't find device or X11 socket to examine for %s", consolename);
3169     + found = 0;
3170     + }
3171     +
3172     + if (found)
3173     + return 1;
3174     +
3175     + /* not found */
3176     + _pam_log(pamh, LOG_INFO, TRUE, "did not find console %s", consolename);
3177     + return 0;
3178     +}
3179     +
3180     +static int
3181     +lock_console(pam_handle_t *pamh, const char *id)
3182     +{
3183     + int fd, ret_val;
3184     +
3185     + fd = open(consolelock, O_RDWR|O_CREAT|O_EXCL, 0600);
3186     + if (fd < 0) {
3187     + _pam_log(pamh, LOG_INFO, TRUE,
3188     + "console file lock already in place %s", consolelock);
3189     + return -1;
3190     + }
3191     + ret_val = pam_modutil_write (fd, id, strlen(id));
3192     + if (ret_val == -1) {
3193     + close(fd);
3194     + }
3195     + else {
3196     + ret_val = close(fd);
3197     + }
3198     + if (ret_val == -1) {
3199     + unlink(consolelock);
3200     + return -1;
3201     + }
3202     + return 0;
3203     +}
3204     +
3205     +/* warning, the following function uses goto for error recovery.
3206     + * If you can't stand goto, don't read this function. :-P
3207     + */
3208     +static int
3209     +use_count(pam_handle_t *pamh, char *filename, int increment, int delete)
3210     +{
3211     + int fd, err, val;
3212     + static int cache_fd = 0;
3213     + struct stat st;
3214     + struct flock lockinfo;
3215     + char *buf = NULL;
3216     +
3217     + if (cache_fd) {
3218     + fd = cache_fd;
3219     + cache_fd = 0;
3220     + /* the cached fd is always already locked */
3221     + } else {
3222     +top:
3223     + fd = open(filename, O_RDWR|O_CREAT, 0600);
3224     + if (fd < 0) {
3225     + _pam_log(pamh, LOG_ERR, FALSE,
3226     + "Could not open lock file %s, disallowing console access",
3227     + filename);
3228     + return -1;
3229     + }
3230     +
3231     + lockinfo.l_type = F_WRLCK;
3232     + lockinfo.l_whence = SEEK_SET;
3233     + lockinfo.l_start = 0;
3234     + lockinfo.l_len = 0;
3235     + alarm(20); /* FIXME: what if caller has sigalrm masked? */
3236     + err = fcntl(fd, F_SETLKW, &lockinfo);
3237     + alarm(0);
3238     + if (err == EAGAIN) {
3239     + /* if someone has locked the file and not written to it in
3240     + * at least 20 seconds, we assume they either forgot to unlock
3241     + * it or are catatonic -- chances are slim that they are in
3242     + * the middle of a read-write cycle and I don't want to make
3243     + * us lock users out. Perhaps I should just return PAM_SUCCESS
3244     + * instead and log the event? Kill the process holding the
3245     + * lock? Options abound... For now, we ignore it.
3246     + */
3247     + fcntl(fd, F_GETLK, &lockinfo);
3248     + /* now lockinfo.l_pid == 0 implies that the lock was released
3249     + * by the other process between returning from the 20 second
3250     + * wait and calling fcntl again, not likely to ever happen, and
3251     + * not a problem other than cosmetics even if it does.
3252     + */
3253     + _pam_log(pamh, LOG_ERR, FALSE,
3254     + "ignoring stale lock on file %s by process %d",
3255     + lockinfo.l_pid, filename);
3256     + }
3257     +
3258     + /* it is possible at this point that the file has been removed
3259     + * by a previous login; if this happens, we need to start over.
3260     + * Unfortunately, the only way to do this without potential stack
3261     + * trashing is a goto.
3262     + */
3263     + if (access (filename, F_OK) < 0) {
3264     + close (fd);
3265     + goto top;
3266     + }
3267     + }
3268     +
3269     +
3270     + if (fstat (fd, &st)) {
3271     + _pam_log(pamh, LOG_ERR, FALSE,
3272     + "\"impossible\" fstat error on open fd for %s", filename);
3273     + err = -1; goto return_error;
3274     + }
3275     + buf = _do_malloc(st.st_size+2); /* size will never grow by more than one */
3276     + if (st.st_size) {
3277     + buf[0] = '\0'; /* if read returns eof, need atoi to give us 0 */
3278     + if (pam_modutil_read (fd, buf, st.st_size) == -1) {
3279     + _pam_log(pamh, LOG_ERR, FALSE,
3280     + "\"impossible\" read error on %s", filename);
3281     + err = -1; goto return_error;
3282     + }
3283     + if (lseek(fd, 0, SEEK_SET) == -1) {
3284     + _pam_log(pamh, LOG_ERR, FALSE,
3285     + "\"impossible\" lseek error on %s", filename);
3286     + err = -1; goto return_error;
3287     + }
3288     + buf[st.st_size] = '\0';
3289     + val = atoi(buf);
3290     + } else {
3291     + val = 0;
3292     + }
3293     +
3294     + if (increment) { /* increment == 0 implies query */
3295     + val += increment;
3296     + if (val <= 0 && delete) {
3297     + if (unlink (filename)) {
3298     + _pam_log(pamh, LOG_ERR, FALSE,
3299     + "\"impossible\" unlink error on %s", filename);
3300     + err = -1; goto return_error;
3301     + }
3302     + err = 0; goto return_error;
3303     + }
3304     +
3305     + sprintf(buf, "%d", val);
3306     + if (pam_modutil_write(fd, buf, strlen(buf)) == -1) {
3307     + _pam_log(pamh, LOG_ERR, FALSE,
3308     + "\"impossible\" write error on %s", filename);
3309     + err = -1; goto return_error;
3310     + }
3311     + }
3312     +
3313     + err = val;
3314     +
3315     + if (!increment) {
3316     + cache_fd = fd;
3317     + } else {
3318     +return_error:
3319     + close (fd);
3320     + }
3321     + if (buf) free (buf);
3322     + return err;
3323     +}
3324     +
3325     +PAM_EXTERN int
3326     +pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
3327     +{
3328     + /* getuid() must return an id that maps to a username as a filename in
3329     + * /var/run/console/
3330     + * and the service name must be listed in
3331     + * /etc/security/console-apps
3332     + */
3333     + struct passwd *pwd;
3334     + char *lockfile = NULL;
3335     + char *appsfile = NULL;
3336     + const char *service;
3337     + int ret = PAM_AUTH_ERR;
3338     +
3339     + D(("called."));
3340     + _args_parse(pamh, argc, argv);
3341     +
3342     + if (getuid() == 0) {
3343     + /* Obtain user name by pam_get_user() .
3344     + * We must make sure that the user sits on the local console
3345     + */
3346     + const char *user = NULL;
3347     + const char *host = NULL;
3348     + const char *user_prompt;
3349     +
3350     + D(("invoked under root."));
3351     +
3352     + ret = pam_get_item(pamh, PAM_RHOST, (const void **) &host);
3353     + if (ret == PAM_SUCCESS && host && *host) {
3354     + _pam_log(pamh, LOG_ERR, TRUE,
3355     + "PAM_RHOST is set - not invoked from console.");
3356     + return PAM_AUTH_ERR;
3357     + }
3358     +
3359     + D(("Obtain user name."));
3360     + if (pam_get_item(pamh, PAM_USER_PROMPT, (const void **) &user_prompt)
3361     + != PAM_SUCCESS) {
3362     + user_prompt = "login: ";
3363     + }
3364     + ret = pam_get_user(pamh, &user, user_prompt);
3365     + if (ret != PAM_SUCCESS) {
3366     + _pam_log(pamh, LOG_ERR, FALSE, "could not obtain user name");
3367     + return ret;
3368     + }
3369     +
3370     + pwd = pam_modutil_getpwnam(pamh, user);
3371     + if (pwd == NULL) {
3372     + _pam_log(pamh, LOG_ERR, FALSE, "user '%s' unknown for this system", user);
3373     + return PAM_AUTH_ERR;
3374     + }
3375     +
3376     + if (pwd->pw_uid == 0) {
3377     + _pam_log(pamh, LOG_ERR, TRUE, "user '%s' is not allowed to "
3378     + "authenticate by pam_console", pwd->pw_name);
3379     + return PAM_AUTH_ERR;
3380     + }
3381     +
3382     + } else {
3383     + pwd = pam_modutil_getpwuid(pamh, getuid());
3384     + if (pwd == NULL) {
3385     + _pam_log(pamh, LOG_ERR, FALSE, "user with id %d not found", getuid());
3386     + return PAM_AUTH_ERR;
3387     + }
3388     + }
3389     +
3390     + lockfile = _do_malloc(strlen(consolerefs) + strlen(pwd->pw_name) + 2);
3391     + sprintf(lockfile, "%s%s", consolerefs, pwd->pw_name); /* trusted data */
3392     +
3393     + pam_get_item(pamh, PAM_SERVICE, CAST_ME_HARDER &service);
3394     + appsfile = _do_malloc(strlen(consoleapps) + strlen(service) + 2);
3395     + sprintf(appsfile, "%s%s", consoleapps, service); /* trusted data */
3396     +
3397     + if (access(lockfile, F_OK) < 0) {
3398     + _pam_log(pamh, LOG_ERR, TRUE,
3399     + "user %s not a console user", pwd->pw_name);
3400     + ret = PAM_AUTH_ERR; goto error_return;
3401     + }
3402     +
3403     + if (access(appsfile, F_OK) < 0) {
3404     + _pam_log(pamh, LOG_ERR, TRUE,
3405     + "console access disallowed for service %s", service);
3406     + ret = PAM_AUTH_ERR; goto error_return;
3407     + }
3408     +
3409     + /* all checks OK, must be OK */
3410     + ret = PAM_SUCCESS;
3411     +
3412     +error_return:
3413     + if (lockfile) free (lockfile);
3414     + if (appsfile) free (appsfile);
3415     + return ret;
3416     +}
3417     +
3418     +PAM_EXTERN int
3419     +pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)
3420     +{
3421     + return PAM_SUCCESS;
3422     +}
3423     +
3424     +PAM_EXTERN int
3425     +pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv)
3426     +{
3427     + /* Create /var/run/console/console.lock if it does not exist
3428     + * Create /var/run/console/<username> if it does not exist
3429     + * Increment its use count
3430     + * Change file ownerships and permissions as given in
3431     + * /etc/security/console.perms IFF returned use count was 0
3432     + * and we created /var/run/console/console.lock
3433     + */
3434     + int got_console = 0;
3435     + int count = 0;
3436     + int ret = PAM_SESSION_ERR;
3437     + const char *username = NULL, *user_prompt;
3438     + char *lockfile;
3439     + const char *tty = NULL;
3440     +
3441     + D(("called."));
3442     + _pam_log(pamh, LOG_ERR, TRUE, "pam_console open_session");
3443     + _args_parse(pamh, argc, argv);
3444     + if(pam_get_item(pamh, PAM_USER_PROMPT, (const void **) &user_prompt)
3445     + != PAM_SUCCESS) {
3446     + user_prompt = "user name: ";
3447     + }
3448     + username = NULL;
3449     + pam_get_user(pamh, &username, user_prompt);
3450     + _pam_log(pamh, LOG_DEBUG, TRUE, "user is \"%s\"",
3451     + username ? username : "(null)");
3452     + if (!username || !username[0]) {
3453     + _pam_log(pamh, LOG_DEBUG, TRUE, "user is \"%s\"",
3454     + username ? username : "(null)");
3455     + return PAM_SESSION_ERR;
3456     + }
3457     + if (is_root(pamh, username)) {
3458     + _pam_log(pamh, LOG_DEBUG, TRUE, "user \"%s\" is root", username);
3459     + return PAM_SUCCESS;
3460     + }
3461     + pam_get_item(pamh, PAM_TTY, CAST_ME_HARDER &tty);
3462     + if (!tty || !tty[0]) {
3463     + _pam_log(pamh, LOG_ERR, TRUE, "TTY not defined");
3464     + return PAM_SESSION_ERR;
3465     + }
3466     +
3467     + /* get configuration */
3468     + if (!configfileparsed) {
3469     + console_parse_handlers(pamh, consolehandlers);
3470     + configfileparsed = 1;
3471     + }
3472     +
3473     + /* return success quietly if not a terminal login */
3474     + if (!check_console_name(pamh, tty, allow_nonroot_tty, TRUE)) return PAM_SUCCESS;
3475     +
3476     + if (!lock_console(pamh, username)) got_console = 1;
3477     +
3478     + lockfile = _do_malloc(strlen(consolerefs) + strlen(username) + 2);
3479     + sprintf(lockfile, "%s%s", consolerefs, username); /* trusted data */
3480     + count = use_count(pamh, lockfile , 1, 0);
3481     + if (count < 0) {
3482     + ret = PAM_SESSION_ERR;
3483     + }
3484     + else if (got_console) {
3485     + _pam_log(pamh, LOG_DEBUG, TRUE, "%s is console user", username);
3486     + /* errors will be logged and are not critical */
3487     + console_run_handlers(pamh, TRUE, username, tty);
3488     + }
3489     +
3490     + free(lockfile);
3491     + return ret;
3492     +}
3493     +
3494     +PAM_EXTERN int
3495     +pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv)
3496     +{
3497     + /* Get /var/run/console/<username> use count, leave it locked
3498     + * If use count is now 1:
3499     + * If /var/run/console/console.lock contains <username>"
3500     + * Revert file ownerships and permissions as given in
3501     + * /etc/security/console.perms
3502     + * Decrement /var/run/console/<username>, removing both it and
3503     + * /var/run/console/console.lock if 0, unlocking /var/run/console/<username>
3504     + * in any case.
3505     + */
3506     + int fd;
3507     + int count = 0;
3508     + int err;
3509     + int delete_consolelock = 0;
3510     + const char *username = NULL, *user_prompt;
3511     + char *lockfile = NULL;
3512     + char *consoleuser = NULL;
3513     + const char *tty = NULL;
3514     + struct stat st;
3515     +
3516     + D(("called."));
3517     + _args_parse(pamh, argc, argv);
3518     + if(pam_get_item(pamh, PAM_USER_PROMPT, (const void **) &user_prompt)
3519     + != PAM_SUCCESS) {
3520     + user_prompt = "user name: ";
3521     + }
3522     + pam_get_user(pamh, &username, user_prompt);
3523     +
3524     + if (!username || !username[0]) return PAM_SESSION_ERR;
3525     + if (is_root(pamh, username)) return PAM_SUCCESS;
3526     + pam_get_item(pamh, PAM_TTY, CAST_ME_HARDER &tty);
3527     + if (!tty || !tty[0]) return PAM_SESSION_ERR;
3528     +
3529     + /* get configuration */
3530     + if (!configfileparsed) {
3531     + console_parse_handlers(pamh, consolehandlers);
3532     + configfileparsed = 1;
3533     + }
3534     +
3535     + /* return success quietly if not a terminal login */
3536     + if (!check_console_name(pamh, tty, allow_nonroot_tty, FALSE)) return PAM_SUCCESS;
3537     +
3538     + lockfile = _do_malloc(strlen(consolerefs) + strlen(username) + 2);
3539     + sprintf(lockfile, "%s%s", consolerefs, username); /* trusted data */
3540     + count = use_count(pamh, lockfile, 0, 0);
3541     + if (count < 0) {
3542     + err = PAM_SESSION_ERR;
3543     + goto return_error;
3544     + }
3545     +
3546     + if (count == 1) {
3547     + fd = open(consolelock, O_RDONLY);
3548     + if (fd != -1) {
3549     + if (fstat (fd, &st)) {
3550     + _pam_log(pamh, LOG_ERR, FALSE,
3551     + "\"impossible\" fstat error on %s", consolelock);
3552     + close(fd);
3553     + err = PAM_SESSION_ERR; goto return_error;
3554     + }
3555     + consoleuser = _do_malloc(st.st_size+1);
3556     + if (st.st_size) {
3557     + if (pam_modutil_read (fd, consoleuser, st.st_size) == -1) {
3558     + _pam_log(pamh, LOG_ERR, FALSE,
3559     + "\"impossible\" read error on %s", consolelock);
3560     + err = PAM_SESSION_ERR;
3561     + close(fd);
3562     + goto return_error;
3563     + }
3564     + consoleuser[st.st_size] = '\0';
3565     + }
3566     + close (fd);
3567     +
3568     + if (!strcmp(username, consoleuser)) {
3569     + delete_consolelock = 1;
3570     + /* errors will be logged and at this stage we cannot do
3571     + * anything about them...
3572     + */
3573     + console_run_handlers(pamh, FALSE, username, tty);
3574     + }
3575     + } else {
3576     + /* didn't open file */
3577     + err = PAM_SESSION_ERR;
3578     + goto return_error;
3579     + }
3580     + }
3581     +
3582     + count = use_count(pamh, lockfile, -1, 1);
3583     + if (count < 1 && delete_consolelock) {
3584     + if (unlink(consolelock)) {
3585     + _pam_log(pamh, LOG_ERR, FALSE,
3586     + "\"impossible\" unlink error on %s", consolelock);
3587     + err = PAM_SESSION_ERR; goto return_error;
3588     + }
3589     + }
3590     +
3591     + err = PAM_SUCCESS;
3592     +return_error:
3593     + if (lockfile) free(lockfile);
3594     + if (consoleuser) free (consoleuser);
3595     + return err;
3596     +}
3597     +
3598     +#ifdef PAM_STATIC
3599     +
3600     +/* static module data */
3601     +
3602     +struct pam_module _pam_console_modstruct = {
3603     + "pam_console",
3604     + pam_sm_authenticate,
3605     + pam_sm_setcred,
3606     + NULL,
3607     + pam_sm_open_session,
3608     + pam_sm_close_session,
3609     + NULL,
3610     +};
3611     +
3612     +#endif
3613     +
3614     +/* end of module definition */
3615     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
3616     --- Linux-PAM-1.1.3.orig/modules/pam_console/pam_console.h 1969-12-31 19:00:00.000000000 -0500
3617     +++ Linux-PAM-1.1.3/modules/pam_console/pam_console.h 2011-01-26 22:14:52.062657563 -0500
3618     @@ -0,0 +1,25 @@
3619     +/* Copyright 1999, 2005 Red Hat, Inc.
3620     + * This software may be used under the terms of the GNU General Public
3621     + * License, available in the file COPYING accompanying this file.
3622     + */
3623     +#ifndef _PAM_CONSOLE_H
3624     +#define _PAM_CONSOLE_H
3625     +#include <security/pam_modules.h>
3626     +#include <regex.h>
3627     +
3628     +#define LOCKFILE "console.lock"
3629     +
3630     +#ifndef FALSE
3631     +#define FALSE 0
3632     +#endif
3633     +#ifndef TRUE
3634     +#define TRUE (!FALSE)
3635     +#endif
3636     +
3637     +void
3638     +_pam_log(pam_handle_t *pamh, int err, int debug_p, const char *format, ...);
3639     +
3640     +void
3641     +do_regerror(int errcode, const regex_t *preg);
3642     +
3643     +#endif /* _PAM_CONSOLE_H */
3644     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
3645     --- Linux-PAM-1.1.3.orig/modules/pam_console/pam_console_apply.8 1969-12-31 19:00:00.000000000 -0500
3646     +++ Linux-PAM-1.1.3/modules/pam_console/pam_console_apply.8 2011-01-26 22:14:52.062657563 -0500
3647     @@ -0,0 +1,62 @@
3648     +.\" Copyright 2001 Red Hat, Inc.
3649     +.TH pam_console_apply 8 2005/5/2 "Red Hat" "System Administrator's Manual"
3650     +.SH NAME
3651     +pam_console_apply \- set or revoke permissions for users at the system console
3652     +.SH SYNOPSIS
3653     +.B pam_console_apply
3654     +[-f <fstab file>] [-c <console.perms file>] [-r] [-t <tty>] [-s] [-d] [<device file> ...]
3655     +.SH DESCRIPTION
3656     +\fBpam_console_apply\fP is a helper executable which sets or resets permissions
3657     +on device nodes.
3658     +.br
3659     +If \fI/var/run/console.lock\fP exists, \fBpam_console_apply\fP will grant
3660     +permissions to the user listed therein. If the lock file does not exist,
3661     +permissions are reset according to defaults set in \fIconsole.perms\fP files,
3662     +normally configured to set permissions on devices so that \fBroot\fP
3663     +owns them.
3664     +
3665     +When initializing its configuration it first parses
3666     +the \fI/etc/security/console.perms\fP file and then it searches for files
3667     +ending with the \fI.perms\fP suffix in the \fI/etc/security/console.perms.d\fP
3668     +directory. These files are parsed in the lexical order in "C" locale.
3669     +Permission rules are appended to a global list, console and device class
3670     +definitions override previous definitions of the same class.
3671     +.SH ARGUMENTS
3672     +.IP -c
3673     +Load other console.perms file than the default one.
3674     +.IP -f
3675     +Load other fstab file than the default one (\fI/etc/fstab\fP).
3676     +.IP -r
3677     +Signals \fBpam_console_apply\fP to reset permissions. The default is to set
3678     +permissions so that the user listed in \fI/var/run/console.lock\fP has access
3679     +to the devices, and to reset permissions if no such file exists.
3680     +.IP -t
3681     +Use <tty> to match console class in console.perms file. The default is tty0.
3682     +.IP -s
3683     +Write error messages to the system log instead of stderr.
3684     +.IP -d
3685     +Log/display messages useful for debugging.
3686     +.PP
3687     +The optional <device file> arguments constrain what files should be affected
3688     +by \fBpam_console_apply\fP. If they aren't specified permissions are
3689     +changed on all files specified in the \fIconsole.perms\fP file.
3690     +.SH FILES
3691     +\fI/var/run/console.lock\fP
3692     +.br
3693     +\fI/etc/security/console.perms\fP
3694     +.br
3695     +\fI/etc/security/console.perms.d/50-default.perms\fP
3696     +.SH "SEE ALSO"
3697     +.BR pam_console(8)
3698     +.br
3699     +.BR console.perms(5)
3700     +.br
3701     +.SH BUGS
3702     +Let's hope not, but if you find any, please report them via the "Bug Track"
3703     +link at http://bugzilla.redhat.com/bugzilla/
3704     +.SH AUTHORS
3705     +Nalin Dahyabhai <nalin@redhat.com>, using code shamelessly stolen from parts of
3706     +pam_console.
3707     +.br
3708     +Support of console.perms.d and other improvements by
3709     +Tomas Mraz <tmraz@redhat.com>.
3710     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
3711     --- Linux-PAM-1.1.3.orig/modules/pam_console/pam_console_apply.c 1969-12-31 19:00:00.000000000 -0500
3712     +++ Linux-PAM-1.1.3/modules/pam_console/pam_console_apply.c 2011-01-26 22:14:52.062657563 -0500
3713     @@ -0,0 +1,175 @@
3714     +/*
3715     + * Read in the file, and grant ownerships to whoever has the lock.
3716     + */
3717     +
3718     +#include "config.h"
3719     +#include <errno.h>
3720     +#include <pwd.h>
3721     +#include <stdlib.h>
3722     +#include <string.h>
3723     +#include <syslog.h>
3724     +#include <sys/types.h>
3725     +#include <sys/stat.h>
3726     +#include <sys/param.h>
3727     +#include <fcntl.h>
3728     +#include <unistd.h>
3729     +#include <stdio.h>
3730     +#include <stdarg.h>
3731     +#include <glob.h>
3732     +#include <locale.h>
3733     +#define STATIC static
3734     +#include "configfile.h"
3735     +#include "chmod.h"
3736     +#include "pam_console.h"
3737     +
3738     +#include <security/_pam_macros.h>
3739     +
3740     +#define CAST_ME_HARDER (const void**)
3741     +#define DEFAULT_PERMSFILE "/etc/security/console.perms"
3742     +#define PERMS_GLOB "/etc/security/console.perms.d/*.perms"
3743     +
3744     +static const char consolelock[] = LOCKDIR "/" LOCKFILE;
3745     +static char consoleperms[PATH_MAX];
3746     +static char tty[PATH_MAX] = "tty0";
3747     +static int debug = 0;
3748     +static int syslogging = 0;
3749     +
3750     +void
3751     +_pam_log(pam_handle_t *pamh, int err, int debug_p, const char *format, ...)
3752     +{
3753     + va_list args;
3754     + if (debug_p && !debug) return;
3755     + va_start(args, format);
3756     + if (syslogging) {
3757     + openlog("pam_console_apply", LOG_CONS|LOG_PID, LOG_AUTHPRIV);
3758     + vsyslog(err, format, args);
3759     + closelog();
3760     + }
3761     + else {
3762     + vfprintf(stderr, format, args);
3763     + fprintf(stderr, "\n");
3764     + }
3765     + va_end(args);
3766     +}
3767     +
3768     +static int
3769     +pf_glob_errorfn(const char *epath, int eerrno)
3770     +{
3771     + return 0;
3772     +}
3773     +
3774     +static void
3775     +parse_files(void)
3776     +{
3777     + int rc;
3778     + glob_t globbuf;
3779     + int i;
3780     + const char *oldlocale;
3781     +
3782     + /* first we parse the console.perms file */
3783     + parse_file(DEFAULT_PERMSFILE);
3784     +
3785     + /* set the LC_COLLATE so the sorting order doesn't depend
3786     + on system locale */
3787     + oldlocale = setlocale(LC_COLLATE, "C");
3788     +
3789     + rc = glob(PERMS_GLOB, GLOB_NOCHECK, pf_glob_errorfn, &globbuf);
3790     + setlocale(LC_COLLATE, oldlocale);
3791     + if (rc == GLOB_NOSPACE) {
3792     + return;
3793     + }
3794     +
3795     + for (i = 0; globbuf.gl_pathv[i] != NULL; i++) {
3796     + parse_file(globbuf.gl_pathv[i]);
3797     + }
3798     + globfree(&globbuf);
3799     +}
3800     +
3801     +int
3802     +main(int argc, char **argv)
3803     +{
3804     + int fd;
3805     + int i, c;
3806     + struct stat st;
3807     + char *consoleuser = NULL;
3808     + enum {Set, Reset} sense = Set;
3809     + GSList *files = NULL;
3810     +
3811     + while((c = getopt(argc, argv, "c:f:t:rsd")) != -1) {
3812     + switch(c) {
3813     + case 'c': if (strlen(optarg) >= sizeof(consoleperms)) {
3814     + fprintf(stderr, "Console.perms filename too long\n");
3815     + exit(1);
3816     + }
3817     + strncpy(consoleperms, optarg, sizeof(consoleperms) - 1);
3818     + consoleperms[sizeof(consoleperms) - 1] = '\0';
3819     + break;
3820     + case 'f': chmod_set_fstab(optarg);
3821     + break;
3822     + case 't': if (strlen(optarg) >= sizeof(tty)) {
3823     + fprintf(stderr, "TTY name too long\n");
3824     + exit(1);
3825     + }
3826     + strncpy(tty, optarg, sizeof(tty) - 1);
3827     + tty[sizeof(tty) - 1] = '\0';
3828     + break;
3829     + case 'r':
3830     + sense = Reset;
3831     + break;
3832     + case 's':
3833     + syslogging = TRUE;
3834     + break;
3835     + case 'd':
3836     + debug = TRUE;
3837     + break;
3838     + default:
3839     + fprintf(stderr, "usage: %s [-f /etc/fstab] "
3840     + "[-c %s] [-t tty] [-r] [-s] [-d] [<device file> ...]\n", argv[0],
3841     + consoleperms);
3842     + exit(1);
3843     + }
3844     + }
3845     +
3846     + for (i = argc-1; i >= optind; i--) {
3847     + files = g_slist_prepend(files, argv[i]);
3848     + }
3849     +
3850     + if (*consoleperms == '\0')
3851     + parse_files();
3852     + else
3853     + parse_file(consoleperms);
3854     +
3855     + fd = open(consolelock, O_RDONLY);
3856     + if (fd != -1) {
3857     + if (fstat (fd, &st)) {
3858     + _pam_log(NULL, LOG_ERR, FALSE,
3859     + "\"impossible\" fstat error on %s", consolelock);
3860     + close(fd);
3861     + goto return_error;
3862     + }
3863     + if (st.st_size) {
3864     + consoleuser = _do_malloc(st.st_size+1);
3865     + memset(consoleuser, '\0', st.st_size);
3866     + if ((i = read (fd, consoleuser, st.st_size)) == -1) {
3867     + _pam_log(NULL, LOG_ERR, FALSE,
3868     + "\"impossible\" read error on %s",
3869     + consolelock);
3870     + goto return_error;
3871     + }
3872     + consoleuser[i] = '\0';
3873     + }
3874     + close(fd);
3875     + } else {
3876     + sense = Reset;
3877     + }
3878     + if((sense == Set) && (consoleuser != NULL)) {
3879     + set_permissions(tty, consoleuser, files);
3880     + }
3881     + if(sense == Reset) {
3882     + reset_permissions(tty, files);
3883     + }
3884     + return 0;
3885     +
3886     +return_error:
3887     + return 1;
3888     +}
3889     diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/regerr.c Linux-PAM-1.1.3/modules/pam_console/regerr.c
3890     --- Linux-PAM-1.1.3.orig/modules/pam_console/regerr.c 1969-12-31 19:00:00.000000000 -0500
3891     +++ Linux-PAM-1.1.3/modules/pam_console/regerr.c 2011-01-26 22:14:52.062657563 -0500
3892     @@ -0,0 +1,32 @@
3893     +/* Copyright 1999 Red Hat Software, Inc.
3894     + * This software may be used under the terms of the GNU General Public
3895     + * License, available in the file COPYING accompanying this file
3896     + */
3897     +#include "config.h"
3898     +#include <stdio.h>
3899     +#include <alloca.h>
3900     +#include <sys/types.h>
3901     +#include <syslog.h>
3902     +#include <security/pam_ext.h>
3903     +#include "pam_console.h"
3904     +
3905     +#ifndef STATIC
3906     +#define STATIC
3907     +#endif
3908     +
3909     +STATIC void
3910     +do_regerror(int errcode, const regex_t *preg) {
3911     + char *errbuf;
3912     + size_t errbuf_size;
3913     +
3914     + errbuf_size = regerror(errcode, preg, NULL, 0); /* missing ; */
3915     + errbuf = alloca(errbuf_size);
3916     + if(!errbuf) {
3917     + perror("alloca");
3918     + return;
3919     + }
3920     +
3921     + regerror(errcode, preg, errbuf, errbuf_size);
3922     + pam_syslog(NULL, LOG_ERR,
3923     + "regular expression error %s", errbuf);
3924     +}
3925     diff -Naur Linux-PAM-1.1.3.orig/modules/pam_console/sed-static Linux-PAM-1.1.3/modules/pam_console/sed-static
3926     --- Linux-PAM-1.1.3.orig/modules/pam_console/sed-static 1969-12-31 19:00:00.000000000 -0500
3927     +++ Linux-PAM-1.1.3/modules/pam_console/sed-static 2011-01-26 22:14:52.062657563 -0500
3928     @@ -0,0 +1,19 @@
3929     +#!/bin/sh
3930     +
3931     +[ -n "$1" ] || { echo $0: 'sed what file?' 1>&2 ; exit 1 ; }
3932     +
3933     +sed '
3934     +/^YY_BUFFER_STATE yy_create_buffer/s/^/STATIC /
3935     +/^void yy_delete_buffer/s/^/STATIC /
3936     +/^void yy_flush_buffer/s/^/STATIC /
3937     +/^void yy_init_buffer/s/^/STATIC /
3938     +/^void yy_load_buffer_state/s/^/STATIC /
3939     +/^void YY_BUFFER_STATE yy_scan_buffer/s/^/STATIC /
3940     +/^YY_BUFFER_STATE yy_scan_bytes/s/^/STATIC /
3941     +/^YY_BUFFER_STATE yy_scan_buffer/s/^/STATIC /
3942     +/^YY_BUFFER_STATE yy_scan_string/s/^/STATIC /
3943     +/^void yy_switch_to_buffer/s/^/STATIC /
3944     +/define YY_DECL int yylex/s/YY_DECL /YY_DECL STATIC /
3945     +/^int yyparse/s/^/STATIC /
3946     +/^void yyrestart/s/^/STATIC /
3947     +' < $1 > sedtmp.$$ && mv sedtmp.$$ $1