summaryrefslogtreecommitdiffstats
path: root/doc
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--doc/HOWTO1918
-rw-r--r--doc/Makefile.am5
-rw-r--r--doc/Makefile.in481
-rw-r--r--doc/README.limits66
-rw-r--r--doc/README.platforms33
-rw-r--r--doc/WISHLIST40
-rw-r--r--doc/console.c.spec.txt36
-rw-r--r--doc/cracklib26.diff340
8 files changed, 2919 insertions, 0 deletions
diff --git a/doc/HOWTO b/doc/HOWTO
new file mode 100644
index 0000000..01a90ed
--- /dev/null
+++ b/doc/HOWTO
@@ -0,0 +1,1918 @@
+[ Note: the installation instructions in this document are somewhat
+ out of date - the package now uses GNU autoconf and is configured
+ just like most GNU packages: run ./configure then make. --marekm ]
+
+ Linux Shadow Password HOWTO
+ Michael H. Jackson, mhjack@tscnet.com
+ v1.3, 3 April 1996
+
+ This document aims to describe how to obtain, install, and configure
+ the Linux password Shadow Suite. It also discusses obtaining, and
+ reinstalling other software and network daemons that require access to
+ user passwords. This other software is not actually part of the
+ Shadow Suite, but these programs will need to be recompiled to support
+ the Shadow Suite. This document also contains a programming example
+ for adding shadow support to a program. Answers to some of the more
+ frequently asked questions are included near the end of this document.
+
+ 1. Introduction.
+
+ This is the Linux Shadow-Password-HOWTO. This document describes why
+ and how to add shadow password support on a Linux system. Some
+ examples of how to use some of the Shadow Suite's features is also
+ included.
+
+ When installing the Shadow Suite and when using many of the utility
+ programs, you must be logged in as root. When installing the Shadow
+ Suite you will be making changes to system software, and it is highly
+ recommended that you make backup copies of programs as indicated. I
+ also recommend that you read and understand all the instructions
+ before you begin.
+
+ 1.1. Changes from the previous release.
+
+ Additions:
+ Added a sub-section on why you might not want to install shadow
+ Added a sub-section on updating the xdm program
+ Added a section on how to put Shadow Suite features to work
+ Added a section containing frequently asked questions
+
+ Corrections/Updates:
+ Corrected html references on Sunsite
+ Corrected section on wu-ftp to reflect adding -lshadow to the Makefile
+ Corrected minor spelling and verbiage errors
+ Changed section on wu-ftpd to support ELF
+ Updated to reflect security problems in various login programs
+ Updated to recommend the Linux Shadow Suite by Marek Michalkiewicz
+
+ 1.2. New versions of this document.
+
+ The latest released version of this document can always be retrieved
+ by anonymous FTP from:
+
+ sunsite.unc.edu
+
+ /pub/Linux/docs/HOWTO/Shadow-Password-HOWTO
+
+ or:
+
+ /pub/Linux/docs/HOWTO/other-formats/Shadow-Password-HOWTO{-html.tar,ps,dvi}.gz
+
+ or via the World Wide Web from the Linux Documentation Project Web
+ Server <http://sunsite.unc.edu/mdw/linux.html>, at page: Shadow-
+ Password-HOWTO <http://sunsite.unc.edu/linux/HOWTO/Shadow-Password-
+ HOWTO.html> or directly from me, <mhjack@tscnet.com>. It will also be
+ posted to the newsgroup: comp.os.linux.answers
+
+ This document is now packaged with the Shadow-YYDDMM packages.
+
+ 1.3. Feedback.
+
+ Please send any comments, updates, or suggestions to me: Michael H.
+ Jackson <mhjack@tscnet.com> The sooner I get feedback, the sooner I
+ can update and correct this document. If you find any problems with
+ it, please mail me directly as I very rarely stay up-to-date on the
+ newsgroups.
+
+ 2. Why shadow your passwd file?
+
+ By default, most current Linux distributions do not contain the Shadow
+ Suite installed. This includes Slackware 2.3, Slackware 3.0, and
+ other popular distributions. One of the reasons for this is that the
+ copyright notices in the original Shadow Suite were not clear on
+ redistribution if a fee was charged. Linux uses a GNU Copyright
+ (sometimes refereed to as a Copyleft) that allows people to package it
+ into a convenient package (like a CD-ROM distribution) and charge a
+ fee for it.
+
+ The current maintainer of the Shadow Suite, Marek Michalkiewicz
+ <marekm@i17linuxb.ists.pwr.wroc.pl> received the source code from the
+ original author under a BSD style copyright that allowed
+ redistribution. Now that the copyright issues are resolved, it is
+ expected that future distributions will contain password shadowing by
+ default. Until then, you will need to install it yourself.
+
+ If you installed your distribution from a CD-ROM, you may find that,
+ even though the distribution did not have the Shadow Suite installed,
+ some of the files you need to install the Shadow Suite may be on the
+ CD-ROM.
+
+ However, Shadow Suite versions 3.3.1, 3.3.1-2, and shadow-mk all have
+ security problems with their login program and several other suid root
+ programs that came with them, and should no longer be used.
+
+ All of the necessary files may be obtained via anonymous FTP or
+ through the World Wide Web.
+
+ On a Linux system without the Shadow Suite installed, user information
+ including passwords is stored in the /etc/passwd file. The password
+ is stored in an encrypted format. If you ask a cryptography expert,
+ however, he or she will tell you that the password is actually in an
+ encoded rather than encrypted format because when using crypt(3), the
+ text is set to null and the password is the key. Therefore, from here
+ on, I will use the term encoded in this document.
+
+ The algorithm used to encode the password field is technically
+ referred to as a one way hash function. This is an algorithm that is
+ easy to compute in one direction, but very difficult to calculate in
+ the reverse direction. More about the actual algorithm used can be
+ found in section 2.4 or your crypt(3) manual page.
+
+ When a user picks or is assigned a password, it is encoded with a
+ randomly generated value called the salt. This means that any
+ particular password could be stored in 4096 different ways. The salt
+ value is then stored with the encoded password.
+
+ When a user logs in and supplies a password, the salt is first
+ retrieved from the stored encoded password. Then the supplied
+ password is encoded with the salt value, and then compared with the
+ encoded password. If there is a match, then the user is
+ authenticated.
+
+ It is computationally difficult (but not impossible) to take a
+ randomly encoded password and recover the original password. However,
+ on any system with more than just a few users, at least some of the
+ passwords will be common words (or simple variations of common words).
+
+ System crackers know all this, and will simply encrypt a dictionary of
+ words and common passwords using all possible 4096 salt values. Then
+ they will compare the encoded passwords in your /etc/passwd file with
+ their database. Once they have found a match, they have the password
+ for another account. This is referred to as a dictionary attack, and
+ is one of the most common methods for gaining or expanding
+ unauthorized access to a system.
+
+ If you think about it, an 8 character password encodes to 4096 * 13
+ character strings. So a dictionary of say 400,000 common words,
+ names, passwords, and simple variations would easily fit on a 4GB hard
+ drive. The attacker need only sort them, and then check for matches.
+ Since a 4GB hard drive can be had for under $1000.00, this is well
+ within the means of most system crackers.
+
+ Also, if a cracker obtains your /etc/passwd file first, they only need
+ to encode the dictionary with the salt values actually contained in
+ your /etc/passwd file. This method is usable by your average teenager
+ with a couple of hundred spare Megabytes and a 486 class computer.
+
+ Even without lots of drive space, utilities like crack(1) can usually
+ break at least a couple of passwords on a system with enough users
+ (assuming the users of the system are allowed to pick their own
+ passwords).
+
+ The /etc/passwd file also contains information like user ID's and
+ group ID's that are used by many system programs. Therefore, the
+ /etc/passwd file must remain world readable. If you were to change
+ the /etc/passwd file so that nobody can read it, the first thing that
+ you would notice is that the ls -l command now displays user ID's
+ instead of names!
+
+ The Shadow Suite solves the problem by relocating the passwords to
+ another file (usually /etc/shadow). The /etc/shadow file is set so
+ that it cannot be read by just anyone. Only root will be able to read
+ and write to the /etc/shadow file. Some programs (like xlock) don't
+ need to be able to change passwords, they only need to be able to
+ verify them. These programs can either be run suid root or you can
+ set up a group shadow that is allowed read only access to the
+ /etc/shadow file. Then the program can be run sgid shadow.
+
+ By moving the passwords to the /etc/shadow file, we are effectively
+ keeping the attacker from having access to the encoded passwords with
+ which to perform a dictionary attack.
+
+ Additionally, the Shadow Suite adds lots of other nice features:
+
+ · A configuration file to set login defaults (/etc/login.defs)
+
+ · Utilities for adding, modifying, and deleting user accounts and
+ groups
+
+ · Password aging and expiration
+
+ · Account expiration and locking
+
+ · Shadowed group passwords (optional)
+
+ · Double length passwords (16 character passwords) NOT RECOMMENDED
+
+ · Better control over user's password selection
+
+ · Dial-up passwords
+
+ · Secondary authentication programs NOT RECOMMENDED
+
+ Installing the Shadow Suite contributes toward a more secure system,
+ but there are many other things that can also be done to improve the
+ security of a Linux system, and there will eventually be a series of
+ Linux Security HOWTO's that will discuss other security measures and
+ related issues.
+
+ For current information on other Linux security issues, including
+ warnings on known vulnerabilities see the Linux Security home page.
+ <http://bach.cis.temple.edu/linux/linux-security/>
+
+ 2.1. Why you might NOT want to shadow your passwd file.
+
+ There are a few circumstances and configurations in which installing
+ the Shadow Suite would NOT be a good idea:
+
+ · The machine does not contain user accounts.
+
+ · Your machine is running on a LAN and is using NIS (Network
+ Information Services) to get or supply user names and passwords to
+ other machines on the network. (This can actually be done, but is
+ beyond the scope of this document, and really won't increase
+ security much anyway)
+
+ · Your machine is being used by terminal servers to verify users via
+ NFS (Network File System), NIS, or some other method.
+
+ · Your machine runs other software that validates users, and there is
+ no shadow version available, and you don't have the source code.
+
+ 2.2. Format of the /etc/passwd file
+
+ A non-shadowed /etc/passwd file has the following format:
+
+ username:passwd:UID:GID:full_name:directory:shell
+
+ Where:
+
+ username
+ The user (login) name
+
+ passwd
+ The encoded password
+
+ UID
+ Numerical user ID
+
+ GID
+ Numerical default group ID
+
+ full_name
+ The user's full name - Actually this field is called the GECOS
+ (General Electric Comprehensive Operating System) field and can
+ store information other than just the full name. The Shadow
+ commands and manual pages refer to this field as the comment
+ field.
+
+ directory
+ User's home directory (Full pathname)
+
+ shell
+ User's login shell (Full Pathname)
+
+ For example:
+
+ username:Npge08pfz4wuk:503:100:Full Name:/home/username:/bin/sh
+
+ Where Np is the salt and ge08pfz4wuk is the encoded password. The
+ encoded salt/password could just as easily have been kbeMVnZM0oL7I and
+ the two are exactly the same password. There are 4096 possible encod­
+ ings for the same password. (The example password in this case is
+ 'password', a really bad password).
+
+ Once the shadow suite is installed, the /etc/passwd file would instead
+ contain:
+
+ username:x:503:100:Full Name:/home/username:/bin/sh
+
+ The x in the second field in this case is now just a place holder.
+ The format of the /etc/passwd file really didn't change, it just no
+ longer contains the encoded password. This means that any program
+ that reads the /etc/passwd file but does not actually need to verify
+ passwords will still operate correctly.
+
+ The passwords are now relocated to the shadow file (usually
+ /etc/shadow file).
+
+ 2.3. Format of the shadow file
+
+ The /etc/shadow file contains the following information:
+
+ username:passwd:last:may:must:warn:expire:disable:reserved
+
+ Where:
+
+ username
+ The User Name
+
+ passwd
+ The Encoded password
+ last
+ Days since Jan 1, 1970 that password was last changed
+
+ may
+ Days before password may be changed
+
+ must
+ Days after which password must be changed
+
+ warn
+ Days before password is to expire that user is warned
+
+ expire
+ Days after password expires that account is disabled
+
+ disable
+ Days since Jan 1, 1970 that account is disabled
+
+ reserved
+ A reserved field
+
+ The previous example might then be:
+
+ username:Npge08pfz4wuk:9479:0:10000::::
+
+ 2.4. Review of crypt(3).
+
+ From the crypt(3) manual page:
+
+ "crypt is the password encryption function. It is based on the Data
+ Encryption Standard algorithm with variations intended (among other
+ things) to discourage use of hardware implementations of a key search.
+
+ The key is a user's typed password. The encoded string is all NULLs
+
+ The salt is a two-character string chosen from the set a-zA-Z0-9./.
+ This string is used to perturb the algorithm in one of 4096 different
+ ways.
+
+ By taking the lowest 7 bits of each character of the key, a 56-bit key
+ is obtained. This 56-bit key is used to encrypt repeatedly a constant
+ string (usually a string consisting of all zeros). The returned value
+ points to the encrypted password, a series of 13 printable ASCII
+ characters (the first two characters represent the salt itself). The
+ return value points to static data whose content is overwritten by
+ each call.
+
+ Warning: The key space consists of 2**56 equal 7.2e16 possible values.
+ Exhaustive searches of this key space are possible using massively
+ parallel computers. Software, such as crack(1), is available which
+ will search the portion of this key space that is generally used by
+ humans for passwords. Hence, password selection should, at minimum,
+ avoid common words and names. The use of a passwd(1) program that
+ checks for crackable passwords during the selection process is
+ recommended.
+
+ The DES algorithm itself has a few quirks which make the use of the
+ crypt(3) interface a very poor choice for anything other than password
+ authentication. If you are planning on using the crypt(3) interface
+ for a cryptography project, don't do it: get a good book on encryption
+ and one of the widely available DES libraries."
+
+ Most Shadow Suites contain code for doubling the length of the
+ password to 16 characters. Experts in des recommend against this, as
+ the encoding is simply applied first to the left half and then to the
+ right half of the longer password. Because of the way crypt works,
+ this may make for a less secure encoded password then if double length
+ passwords were not used in the first place. Additionally, it is less
+ likely that a user will be able to remember a 16 character password.
+
+ There is development work under way that would allow the
+ authentication algorithm to be replaced with something more secure and
+ with support for longer passwords (specifically the MD5 algorithm) and
+ retain compatibility with the crypt method.
+
+ If you are looking for a good book on encryption, I recommend:
+
+ "Applied Cryptography: Protocols, Algorithms, and Source Code in C"
+ by Bruce Schneier <schneier@chinet.com>
+ ISBN: 0-471-59756-2
+
+ 3. Getting the Shadow Suite.
+
+ 3.1. History of the Shadow Suite for Linux
+
+ DO NOT USE THE PACKAGES IN THIS SECTION, THEY HAVE SECURITY PROBLEMS
+
+ The original Shadow Suite was written by Julianne F. Haugh
+
+ There are several versions that have been used on Linux systems:
+
+ · shadow-3.3.1 is the original.
+
+ · shadow-3.3.1-2 is Linux specific patch made by Florian La Roche
+ <flla@stud.uni-sb.de> and contains some further enhancements.
+
+ · shadow-mk was specifically packaged for Linux.
+
+ The shadow-mk package contains the shadow-3.3.1 package distributed by
+ Julianne F. Haugh with the shadow-3.3.1-2 patch installed, a few fixes
+ made by Mohan Kokal <magnus@texas.net> that make installation a lot
+ easier, a patch by Joseph R.M. Zbiciak for login1.c (login.secure)
+ that eliminates the -f, -h security holes in /bin/login, and some
+ other miscellaneous patches.
+
+ The shadow.mk package was the previously recommended package, but
+ should be replaced due to a security problem with the login program.
+
+ There are security problems with Shadow versions 3.3.1, 3.3.1-2, and
+ shadow-mk involving the login program. This login bug involves not
+ checking the length of a login name. This causes the buffer to
+ overflow causing crashes or worse. It has been rumored that this
+ buffer overflow can allow someone with an account on the system to use
+ this bug and the shared libraries to gain root access. I won't
+ discuss exactly how this is possible because there are a lot of Linux
+ systems that are affected, but systems with these Shadow Suites
+ installed, and most pre-ELF distributions without the Shadow Suite are
+ vulnerable!
+
+ For more information on this and other Linux security issues, see the
+ Linux Security home page (Shared Libraries and login Program
+ Vulnerability) <http://bach.cis.temple.edu/linux/linux-security/Linux-
+ Security-FAQ/Linux-telnetd.html>
+
+ 3.2. Where to get the Shadow Suite.
+
+ The only recommended Shadow Suite is still in BETA testing, however
+ the latest versions are safe in a production environment and don't
+ contain a vulnerable login program.
+
+ The package uses the following naming convention:
+
+ shadow-YYMMDD.tar.gz
+
+ where YYMMDD is the issue date of the Suite.
+
+ This version will eventually be Version 3.3.3 when it is released from
+ Beta testing, and is maintained by Marek Michalkiewicz
+ <marekm@i17linuxb.ists.pwr.wroc.pl>. It's available as: shadow-
+ current.tar.gz
+ <ftp://i17linuxb.ists.pwr.wroc.pl/pub/linux/shadow/shadow-
+ current.tar.gz>.
+
+ The following mirror sites have also been established:
+
+ · ftp://ftp.icm.edu.pl/pub/Linux/shadow/shadow-current.tar.gz
+
+ · ftp://iguana.hut.fi/pub/linux/shadow/shadow-current.tar.gz
+
+ · ftp://ftp.cin.net/usr/ggallag/shadow/shadow-current.tar.gz
+
+ · ftp://ftp.netural.com/pub/linux/shadow/shadow-current.tar.gz
+
+ You should use the currently available version.
+
+ You should NOT use a version older than shadow-960129 as they also
+ have the login security problem discussed above.
+
+ When this document refers to the Shadow Suite I am referring to the
+ this package. It is assumed that this is the package that you are
+ using.
+
+ For reference, I used shadow-960129 to make these installation
+ instructions.
+
+ If you were previously using shadow-mk, you should upgrade to this
+ version and rebuild everything that you originally compiled.
+
+ 3.3. What is included with the Shadow Suite.
+
+ The Shadow Suite contains replacement programs for:
+
+ su, login, passwd, newgrp, chfn, chsh, and id
+
+ The package also contains the new programs:
+
+ chage, newusers, dpasswd, gpasswd, useradd, userdel, usermod,
+ groupadd, groupdel, groupmod, groups, pwck, grpck, lastlog, pwconv,
+ and pwunconv
+
+ Additionally, the library: libshadow.a is included for writing and/or
+ compiling programs that need to access user passwords.
+
+ Also, manual pages for the programs are also included.
+
+ There is also a configuration file for the login program which will be
+ installed as /etc/login.defs.
+
+ 4. Compiling the programs.
+
+ 4.1. Unpacking the archive.
+
+ The first step after retrieving the package is unpacking it. The
+ package is in the tar (tape archive) format and compressed using gzip,
+ so first move it to /usr/src, then type:
+
+ tar -xzvf shadow-current.tar.gz
+
+ This will unpack it into the directory: /usr/src/shadow-YYMMDD
+
+ 4.2. Configuring with the config.h file
+
+ The first thing that you need to do is to copy over the Makefile and
+ the config.h file:
+
+ cd /usr/src/shadow-YYMMDD
+ cp Makefile.linux Makefile
+ cp config.h.linux config.h
+
+ You should then take a look at the config.h file. This file contains
+ definitions for some of the configuration options. If you are using
+ the recommended package, I recommend that you disable group shadow
+ support for your first time around.
+
+ By default shadowed group passwords are enabled. To disable these
+ edit the config.h file, and change the #define SHADOWGRP to #undef
+ SHADOWGRP. I recommend that you disable them to start with, and then
+ if you really want group passwords and group administrators that you
+ enable it later and recompile. If you leave it enabled, you must
+ create the file /etc/gshadow.
+
+ Enabling the long passwords option is NOT recommended as discussed
+ above.
+
+ Do NOT change the setting: #undef AUTOSHADOW
+
+ The AUTOSHADOW option was originally designed so that programs that
+ were shadow ignorant would still function. This sounds good in
+ theory, but does not work correctly. If you enable this option, and
+ the program runs as root, it may call getpwnam() as root, and later
+ write the modified entry back to the /etc/passwd file (with the no-
+ longer-shadowed password). Such programs include chfn and chsh. (You
+ can't get around this by swapping real and effective uid before
+ calling getpwnam() because root may use chfn and chsh too.)
+
+ The same warning is also valid if you are building libc, it has a
+ SHADOW_COMPAT option which does the same thing. It should NOT be
+ used! If you start getting encoded passwords back in your /etc/passwd
+ file, this is the problem.
+
+ If you are using a libc version prior to 4.6.27, you will need to make
+ a couple more changes to config.h and the Makefile. To config.h edit
+ and change:
+
+ #define HAVE_BASENAME
+
+ to:
+
+ #undef HAVE_BASENAME
+
+ And then in the Makefile, change:
+
+ SOBJS = smain.o env.o entry.o susetup.o shell.o \
+ sub.o mail.o motd.o sulog.o age.o tz.o hushed.o
+
+ SSRCS = smain.c env.c entry.c setup.c shell.c \
+ pwent.c sub.c mail.c motd.c sulog.c shadow.c age.c pwpack.c rad64.c \
+ tz.c hushed.c
+
+ SOBJS = smain.o env.o entry.o susetup.o shell.o \
+ sub.o mail.o motd.o sulog.o age.o tz.o hushed.o basename.o
+
+ SSRCS = smain.c env.c entry.c setup.c shell.c \
+ pwent.c sub.c mail.c motd.c sulog.c shadow.c age.c pwpack.c rad64.c \
+ tz.c hushed.c basename.c
+
+ These changes add the code contained in basename.c which is contained
+ in libc 4.6.27 and later.
+
+ 4.3. Making backup copies of your original programs.
+
+ It would also be a good idea to track down and make backup copies of
+ the programs that the shadow suite will replace. On a Slackware 3.0
+ system these are:
+
+ · /bin/su
+
+ · /bin/login
+
+ · /usr/bin/passwd
+
+ · /usr/bin/newgrp
+
+ · /usr/bin/chfn
+
+ · /usr/bin/chsh
+
+ · /usr/bin/id
+
+ The BETA package has a save target in the Makefile, but it's commented
+ out because different distributions place the programs in different
+ places.
+
+ You should also make a backup copy of your /etc/passwd file, but be
+ careful to name it something else if you place it in the same
+ directory so you don't overwrite the passwd command.
+
+ 4.4. Running make
+
+ You need to be logged as root to do most of the installation.
+
+ Run make to compile the executables in the package:
+
+ make all
+
+ You may see the warning: rcsid defined but not used. This is fine, it
+ just happens because the author is using a version control package.
+
+ 5. Installing
+
+ 5.1. Have a boot disk handy in case you break anything.
+
+ If something goes terribly wrong, it would be handy to have a boot
+ disk. If you have a boot/root combination from your installation,
+ that will work, otherwise see the Bootdisk-HOWTO
+ <http://sunsite.unc.edu/mdw/HOWTO/Bootdisk-HOWTO.html>, which
+ describes how to make a bootable disk.
+
+ 5.2. Removing duplicate man pages
+
+ You should also move the manual pages that are about to be replaced.
+ Even if you are brave enough install the Shadow Suite without making
+ backups, you will still want to remove the old manual pages. The new
+ manual pages won't normally overwrite the old ones because the old
+ ones are probably compressed.
+
+ You can use a combination of: man -aW command and locate command to
+ locate the manual pages that need to be (re)moved. It's generally
+ easier to figure out which are the older pages before you run make
+ install.
+
+ If you are using the Slackware 3.0 distribution, then the manual pages
+ you want to remove are:
+
+ · /usr/man/man1/chfn.1.gz
+
+ · /usr/man/man1/chsh.1.gz
+
+ · /usr/man/man1/id.1.gz
+
+ · /usr/man/man1/login.1.gz
+
+ · /usr/man/man1/passwd.1.gz
+
+ · /usr/man/man1/su.1.gz
+
+ · /usr/man/man5/passwd.5.gz
+
+ There may also be man pages of the same name in the /var/man/cat[1-9]
+ subdirectories that should also be deleted.
+
+ 5.3. Running make install
+
+ You are now ready to type: (do this as root)
+
+ make install
+
+ This will install the new and replacement programs and fix-up the file
+ permissions. It will also install the man pages.
+
+ This also takes care of installing the Shadow Suite include files in
+ the correct places in /usr/include/shadow.
+
+ Using the BETA package you must manually copy the file login.defs to
+ the /etc subdirectory and make sure that only root can make changes to
+ it.
+
+ cp login.defs /etc
+ chmod 700 /etc/login.defs
+
+ This file is the configuration file for the login program. You should
+ review and make changes to this file for your particular system. This
+ is where you decide which tty's root can login from, and set other
+ security policy settings (like password expiration defaults).
+
+ 5.4. Running pwconv
+
+ The next step is to run pwconv. This must also be done as root, and
+ is best done from the /etc subdirectory:
+
+ cd /etc
+ /usr/sbin/pwconv
+
+ pwconv takes your /etc/passwd file and strips out the fields to create
+ two files: /etc/npasswd and /etc/nshadow.
+
+ A pwunconv program is also provided if you need to make a normal
+ /etc/passwd file out of an /etc/passwd and /etc/shadow combination.
+
+ 5.5. Renaming npasswd and nshadow
+
+ Now that you have run pwconv you have created the files /etc/npasswd
+ and /etc/nshadow. These need to be copied over to /etc/passwd and
+ /etc/shadow. We also want to make a backup copy of the original
+ /etc/passwd file, and make sure only root can read it. We'll put the
+ backup in root's home directory:
+
+ cd /etc
+ cp passwd ~passwd
+ chmod 600 ~passwd
+ mv npasswd passwd
+ mv nshadow shadow
+
+ You should also ensure that the file ownerships and permissions are
+ correct. If you are going to be using X-Windows, the xlock and xdm
+ programs need to be able to read the shadow file (but not write it).
+
+ There are two ways that this can be done. You can set xlock to suid
+ root (xdm is usually run as root anyway). Or you can make the shadow
+ file owned by root with a group of shadow, but before you do this,
+ make sure that you have a shadow group (look in /etc/group). None of
+ the users on the system should actually be in the shadow group.
+
+ chown root.root passwd
+ chown root.shadow shadow
+ chmod 0644 passwd
+ chmod 0640 shadow
+
+ Your system now has the password file shadowed. You should now pop
+ over to another virtual terminal and verify that you can login.
+
+ Really, do this now!
+
+ If you can't, then something is wrong! To get back to a non-shadowed
+ state, do the following the following:
+
+ cd /etc
+ cp ~passwd passwd
+ chmod 644 passwd
+
+ You would then restore the files that you saved earlier to their
+ proper locations.
+
+ 6. Other programs you may need to upgrade or patch
+
+ Even though the shadow suite contains replacement programs for most
+ programs that need to access passwords, there are a few additional
+ programs on most systems that require access to passwords.
+
+ If you are running a Debian Distribution (or even if you are not), you
+ can obtain Debian sources for the programs that need to be rebuild
+ from: ftp://ftp.debian.org/debian/stable/source/
+
+ The remainder of this section discusses how to upgrade adduser,
+ wu_ftpd, ftpd, pop3d, xlock, xdm and sudo so that they support the
+ shadow suite.
+
+ See the section ``Adding Shadow Support to a C program'' for a
+ discussion on how to put shadow support into any other program that
+ needs it (although the program must then be run SUID root or SGID
+ shadow to be able to actually access the shadow file).
+
+ 6.1. Slackware adduser program
+
+ Slackware distributions (and possibly some others) contain a
+ interactive program for adding users called /sbin/adduser. A shadow
+ version of this program can be obtained from
+ ftp://sunsite.unc.edu/pub/Linux/
+ system/Admin/accounts/adduser.shadow-1.4.tar.gz.
+
+ I would encourage you to use the programs that are supplied with the
+ Shadow Suite (useradd, usermod, and userdel) instead of the slackware
+ adduser program. They take a little time to learn how to use, but
+ it's well worth the effort because you have much more control and they
+ perform proper file locking on the /etc/passwd and /etc/shadow file
+ (adduser doesn't).
+
+ See the section on ``Putting the Shadow Suite to use'' for more
+ information.
+
+ But if you gotta have it, here is what you do:
+
+ tar -xzvf adduser.shadow-1.4.tar.gz
+ cd adduser
+ make clean
+ make adduser
+ chmod 700 adduser
+ cp adduser /sbin
+
+ 6.2. The wu_ftpd Server
+
+ Most Linux systems some with the wu_ftpd server. If your distribution
+ does not come with shadow installed, then your wu_ftpd will not be
+ compiled for shadow. wu_ftpd is launched from inetd/tcpd as a root
+ process. If you are running an old wu_ftpd daemon, you will want to
+ upgrade it anyway because older ones had a bug that would allow the
+ root account to be compromised (For more info see the Linux security
+ home page <http://bach.cis.temple.edu/linux/linux-security/Linux-
+ Security-FAQ/Linux-wu.ftpd-2.4-Update.html>).
+
+ Fortunately, you only need to get the source code and recompile it
+ with shadow enabled.
+
+ If you are not running an ELF system, The wu_ftp server can be found
+ on Sunsite as wu-ftp-2.4-fixed.tar.gz
+ <ftp://sunsite.unc.edu/pub/Linux/system/Network/file-transfer/wu-
+ ftpd-2.4-fixed.tar.gz>
+
+ Once you retrieve the server, put it in /usr/src, then type:
+
+ cd /usr/src
+ tar -xzvf wu-ftpd-2.4-fixed.tar.gz
+ cd wu-ftpd-2.4-fixed
+ cp ./src/config/config.lnx.shadow ./src/config/config.lnx
+
+ Then edit ./src/makefiles/Makefile.lnx, and change the line:
+
+ LIBES = -lbsd -support
+
+ to:
+
+ LIBES = -lbsd -support -lshadow
+
+ Now you are ready to run the build script and install:
+
+ cd /usr/src/wu-ftpd-2.4-fixed
+ /usr/src/wu-ftp-2.4.fixed/build lnx
+ cp /usr/sbin/wu.ftpd /usr/sbin/wu.ftpd.old
+ cp ./bin/ftpd /usr/sbin/wu.ftpd
+
+ This uses the Linux shadow configuration file, compiles and installs
+ the server.
+
+ On my Slackware 2.3 system I also had to do the following before
+ running build:
+
+ cd /usr/include/netinet
+ ln -s in_systm.h in_system.h
+ cd -
+
+ Problems have been reported compiling this package under ELF systems,
+ but the Beta version of the next release works fine. It can be found
+ as wu-ftp-2.4.2-beta-10.tar.gz
+ <ftp://tscnet.com/pub/linux/network/ftp/wu-ftpd-2.4.2-beta-10.tar.gz>
+
+ Once you retrieve the server, put it in /usr/src, then type:
+
+ cd /usr/src
+ tar -xzvf wu-ftpd-2.4.2-beta-9.tar.gz
+ cd wu-ftpd-beta-9
+ cd ./src/config
+
+ Then edit config.lnx, and change:
+
+ #undef SHADOW.PASSWORD
+
+ to:
+
+ #define SHADOW.PASSWORD
+
+ Then,
+
+ cd ../Makefiles
+
+ and edit the file Makefile.lnx and change:
+
+ LIBES = -lsupport -lbsd # -lshadow
+
+ to:
+
+ LIBES = -lsupport -lbsd -lshadow
+
+ Then build and install:
+
+ cd ..
+ build lnx
+ cp /usr/sbin/wu.ftpd /usr/sbin/wu.ftpd.old
+ cp ./bin/ftpd /usr/sbin/wu.ftpd
+
+ Note that you should check your /etc/inetd.conf file to make sure that
+ this is where your wu.ftpd server really lives. It has been reported
+ that some distributions place the server daemons in different places,
+ and then wu.ftpd in particular may be named something else.
+
+ 6.3. Standard ftpd
+
+ If you are running the standard ftpd server, I would recommend that
+ you upgrade to the wu_ftpd server. Aside from the known bug discussed
+ above, it's generally thought to be more secure.
+
+ If you insist on the standard one, or you need NIS support, Sunsite
+ has ftpd-shadow-nis.tgz
+ <ftp://sunsite.unc.edu/pub/Linux/system/Network/file-transfer/ftpd-
+ shadow-nis.tgz>
+
+ 6.4. pop3d (Post Office Protocol 3)
+
+ If you need to support the third Post Office Protocol (POP3), you will
+ need to recompile a pop3d program. pop3d is normally run by
+ inetd/tcpd as root.
+
+ There are two versions available from Sunsite:
+ pop3d-1.00.4.linux.shadow.tar.gz
+ <ftp://sunsite.unc.edu/pub/Linux/system/Mail/pop/pop3d-1.00.4.linux.shadow.tar.gz>
+ and pop3d+shadow+elf.tar.gz
+ <ftp://sunsite.unc.edu/pub/Linux/system/Mail/pop/pop3d+shadow+elf.tar.gz>
+
+ Both of these are fairly straight forward to install.
+
+ 6.5. xlock
+
+ If you install the shadow suite, and then run X Windows System and
+ lock the screen without upgrading your xlock, you will have to use
+ CNTL-ALT-Fx to switch to another tty, login, and kill the xlock
+ process (or use CNTL-ALT-BS to kill the X server). Fortunately it's
+ fairly easy to upgrade your xlock program.
+
+ If you are running XFree86 Versions 3.x.x, you are probably using
+ xlockmore (which is a great screen-saver in addition to a lock). This
+ package supports shadow with a recompile. If you have an older xlock,
+ I recommend that you upgrade to this one.
+
+ xlockmore-3.5.tgz is available at:
+ <ftp://sunsite.unc.edu/pub/Linux/X11/xutils/screensavers/xlockmore-3.7.tgz>
+
+ Basically, this is what you need to do:
+
+ Get the xlockmore-3.7.tgz file and put it in /usr/src unpack it:
+
+ tar -xzvf xlockmore-3.7.tgz
+
+ Edit the file: /usr/X11R6/lib/X11/config/linux.cf, and change the
+ line:
+
+ #define HasShadowPasswd NO
+
+ to
+
+ #define HasShadowPasswd YES
+
+ Then build the executables:
+
+ cd /usr/src/xlockmore
+ xmkmf
+ make depend
+ make
+
+ Then move everything into place and update file ownerships and
+ permissions:
+
+ cp xlock /usr/X11R6/bin/
+ cp XLock /var/X11R6/lib/app-defaults/
+ chown root.shadow /usr/X11R6/bin/xlock
+ chmod 2755 /usr/X11R6/bin/xlock
+ chown root.shadow /etc/shadow
+ chmod 640 /etc/shadow
+
+ Your xlock will now work correctly.
+
+ 6.6. xdm
+
+ xdm is a program that presents a login screen for X-Windows. Some
+ systems start xdm when the system is told to goto a specified run
+ level (see /etc/inittab.
+
+ With the Shadow Suite install, xdm will need to be updated.
+ Fortunately it's fairly easy to upgrade your xdm program.
+
+ xdm.tar.gz is available at:
+ <ftp://sunsite.unc.edu/pub/Linux/X11/xutils/xdm.tar.gz>
+
+ Get the xdm.tar.gz file and put it in /usr/src, then to unpack it:
+
+ tar -xzvf xdm.tar.gz
+
+ Edit the file: /usr/X11R6/lib/X11/config/linux.cf, and change the
+ line:
+
+ #define HasShadowPasswd NO
+
+ to
+
+ #define HasShadowPasswd YES
+
+ Then build the executables:
+
+ cd /usr/src/xdm
+ xmkmf
+ make depend
+ make
+
+ Then move everything into place:
+
+ cp xdm /usr/X11R6/bin/
+
+ xdm is run as root so you don't need to change it file permissions.
+
+ 6.7. sudo
+
+ The program sudo allows a system administrator to let users run
+ programs that would normally require root access. This is handy
+ because it lets the administrator limit access to the root account
+ itself while still allowing users to do things like mounting drives.
+
+ sudo needs to read passwords because it verifies the users password
+ when it's invoked. sudo already runs SUID root, so accessing the
+ /etc/shadow file is not a problem.
+
+ sudo for the shadow suite, is available as at:
+ <ftp://sunsite.unc.edu/pub/Linux/system/Admin/sudo-1.2-shadow.tgz>
+
+ Warning: When you install sudo your /etc/sudoers file will be replaced
+ with a default one, so you need to make a backup of it if you have
+ added anything to the default one. (you could also edit the Makefile
+ and remove the line that copies the default file to /etc).
+
+ The package is already setup for shadow, so all that's required is to
+ recompile the package (put it in /usr/src):
+
+ cd /usr/src
+ tar -xzvf sudo-1.2-shadow.tgz
+ cd sudo-1.2-shadow
+ make all
+ make install
+
+ 6.8. imapd (E-Mail pine package)
+
+ imapd is an e-mail server similar to pop3d. imapd comes with the Pine
+ E-mail package. The documentation that comes with the package states
+ that the default for Linux systems is to include support for shadow.
+ However, I have found that this is not true. Furthermore, the build
+ script / Makefile combination on this package is makes it very
+ difficult to add the libshadow.a library at compile time, so I was
+ unable to add shadow support for imapd.
+
+ If anyone has this figured out, please E-mail me, and I'll include the
+ solution here.
+
+ 6.9. pppd (Point-to-Point Protocol Server)
+
+ The pppd server can be setup to use several types of authentication:
+ Password Authentication Protocol (PAP) and Cryptographic Handshake
+ Authentication Protocol (CHAP). The pppd server usually reads the
+ password strings that it uses from /etc/ppp/chap-secrets and/or
+ /etc/ppp/pap-secrets. If you are using this default behavior of pppd,
+ it is not necessary to reinstall pppd.
+
+ pppd also allows you to use the login parameter (either on the command
+ line, or in the configuration or options file). If the login option
+ is given, then pppd will use the /etc/passwd file for the username and
+ passwords for the PAP. This, of course, will no longer work now that
+ our password file is shadowed. For pppd-1.2.1d this requires adding
+ code for shadow support.
+
+ The example given in the next section is adding shadow support to
+ pppd-1.2.1d (an older version of pppd).
+
+ pppd-2.2.0 already contains shadow support.
+
+ 7. Putting the Shadow Suite to use.
+
+ This section discusses some of the things that you will want to know
+ now that you have the Shadow Suite installed on your system. More
+ information is contained in the manual pages for each command.
+
+ 7.1. Adding, Modifying, and deleting users
+
+ The Shadow Suite added the following command line oriented commands
+ for adding, modifying, and deleting users. You may also have
+ installed the adduser program.
+
+ 7.1.1. useradd
+
+ The useradd command can be used to add users to the system. You also
+ invoke this command to change the default settings.
+
+ The first thing that you should do is to examine the default settings
+ and make changes specific to your system:
+
+ useradd -D
+
+ ______________________________________________________________________
+ GROUP=1
+ HOME=/home
+ INACTIVE=0
+ EXPIRE=0
+ SHELL=
+ SKEL=/etc/skel
+ ______________________________________________________________________
+
+ The defaults are probably not what you want, so if you started adding
+ users now you would have to specify all the information for each user.
+ However, we can and should change the default values.
+
+ On my system:
+
+ · I want the default group to be 100
+
+ · I want passwords to expire every 60 days
+
+ · I don't want to lock an account because the password is expired
+
+ · I want to default shell to be /bin/bash
+
+ To make these changes I would use:
+
+ useradd -D -g100 -e60 -f0 -s/bin/bash
+
+ Now running useradd -D will give:
+
+ ______________________________________________________________________
+ GROUP=100
+ HOME=/home
+ INACTIVE=0
+ EXPIRE=60
+ SHELL=/bin/bash
+ SKEL=/etc/skel
+ ______________________________________________________________________
+
+ Just in case you wanted to know, these defaults are stored in the file
+ /etc/default/useradd.
+
+ Now you can use useradd to add users to the system. For example, to
+ add the user fred, using the defaults, you would use the following:
+
+ useradd -m -c "Fred Flintstone" fred
+
+ This will create the following entry in the /etc/passwd file:
+
+ fred:*:505:100:Fred Flintstone:/home/fred:/bin/bash
+
+ And the following entry in the /etc/shadow file:
+
+ fred:!:0:0:60:0:0:0:0
+
+ fred's home directory will be created and the contents of /etc/skel
+ will be copied there because of the -m switch.
+
+ Also, since we did not specify a UID, the next available one was used.
+
+ fred's account is created, but fred still won't be able to login until
+ we unlock the account. We do this by changing the password.
+
+ passwd fred
+
+ ______________________________________________________________________
+ Changing password for fred
+ Enter the new password (minimum of 5 characters)
+ Please use a combination of upper and lower case letters and numbers.
+ New Password: *******
+ Re-enter new password: *******
+ ______________________________________________________________________
+
+ Now the /etc/shadow will contain:
+
+ fred:J0C.WDR1amIt6:9559:0:60:0:0:0:0
+
+ And fred will now be able to login and use the system. The nice thing
+ about useradd and the other programs that come with the Shadow Suite
+ is that they make changes to the /etc/passwd and /etc/shadow files
+ atomically. So if you are adding a user, and another user is changing
+ their password at the same time, both operations will be performed
+ correctly.
+
+ You should use the supplied commands rather than directly editing
+ /etc/passwd and /etc/shadow. If you were editing the /etc/shadow
+ file, and a user were to change his password while you are editing,
+ and then you were to save the file you were editing, the user's
+ password change would be lost.
+
+ Here is a small interactive script that adds users using useradd and
+ passwd:
+
+ ______________________________________________________________________
+ #!/bin/bash
+ #
+ # /sbin/newuser - A script to add users to the system using the Shadow
+ # Suite's useradd and passwd commands.
+ #
+ # Written my Mike Jackson <mhjack@tscnet.com> as an example for the Linux
+ # Shadow Password Howto. Permission to use and modify is expressly granted.
+ #
+ # This could be modified to show the defaults and allow modification similar
+ # to the Slackware Adduser program. It could also be modified to disallow
+ # stupid entries. (i.e. better error checking).
+ #
+ ##
+ # Defaults for the useradd command
+ ##
+ GROUP=100 # Default Group
+ HOME=/home # Home directory location (/home/username)
+ SKEL=/etc/skel # Skeleton Directory
+ INACTIVE=0 # Days after password expires to disable account (0=never)
+ EXPIRE=60 # Days that a passwords lasts
+ SHELL=/bin/bash # Default Shell (full path)
+ ##
+ # Defaults for the passwd command
+ ##
+ PASSMIN=0 # Days between password changes
+ PASSWARN=14 # Days before password expires that a warning is given
+ ##
+ # Ensure that root is running the script.
+ ##
+ WHOAMI=`/usr/bin/whoami`
+ if [ $WHOAMI != "root" ]; then
+ echo "You must be root to add news users!"
+ exit 1
+ fi
+ ##
+ # Ask for username and fullname.
+ ##
+ echo ""
+ echo -n "Username: "
+ read USERNAME
+ echo -n "Full name: "
+ read FULLNAME
+ #
+ echo "Adding user: $USERNAME."
+ #
+ # Note that the "" around $FULLNAME is required because this field is
+ # almost always going to contain at least on space, and without the "'s
+ # the useradd command would think that you we moving on to the next
+ # parameter when it reached the SPACE character.
+ #
+ /usr/sbin/useradd -c"$FULLNAME" -d$HOME/$USERNAME -e$EXPIRE \
+ -f$INACTIVE -g$GROUP -m -k$SKEL -s$SHELL $USERNAME
+ ##
+ # Set password defaults
+ ##
+ /bin/passwd -n $PASSMIN -w $PASSWARN $USERNAME >/dev/null 2>&1
+ ##
+ # Let the passwd command actually ask for password (twice)
+ ##
+ /bin/passwd $USERNAME
+ ##
+ # Show what was done.
+ ##
+ echo ""
+ echo "Entry from /etc/passwd:"
+ echo -n " "
+ grep "$USERNAME:" /etc/passwd
+ echo "Entry from /etc/shadow:"
+ echo -n " "
+ grep "$USERNAME:" /etc/shadow
+ echo "Summary output of the passwd command:"
+ echo -n " "
+ passwd -S $USERNAME
+ echo ""
+ ______________________________________________________________________
+
+ Using a script to add new users is really much more preferable than
+ editing the /etc/passwd or /etc/shadow files directly or using a
+ program like the Slackware adduser program. Feel free to use and
+ modify this script for your particular system.
+
+ For more information on the useradd see the online manual page.
+
+ 7.1.2. usermod
+
+ The usermod program is used to modify the information on a user. The
+ switches are similar to the useradd program.
+
+ Let's say that you want to change fred's shell, you would do the
+ following:
+
+ usermod -s /bin/tcsh fred
+
+ Now fred's /etc/passwd file entry would be change to this:
+
+ fred:*:505:100:Fred Flintstone:/home/fred:/bin/tcsh
+
+ Let's make fred's account expire on 09/15/97:
+
+ usermod -e 09/15/97 fred
+
+ Now fred's entry in /etc/shadow becomes:
+
+ fred:J0C.WDR1amIt6:9559:0:60:0:0:10119:0
+
+ For more information on the usermod command see the online manual
+ page.
+
+ 7.1.3. userdel
+
+ userdel does just what you would expect, it deletes the user's
+ account. You simply use:
+
+ userdel -r username
+
+ The -r causes all files in the user's home directory to be removed
+ along with the home directory itself. Files located in other file
+ system will have to be searched for and deleted manually.
+
+ If you want to simply lock the account rather than delete it, use the
+ passwd command instead.
+
+ 7.2. The passwd command and passwd aging.
+
+ The passwd command has the obvious use of changing passwords.
+ Additionally, it is used by the root user to:
+
+ · Lock and unlock accounts (-l and -u)
+
+ · Set the maximum number of days that a password remains valid (-x)
+
+ · Set the minimum days between password changes (-n)
+
+ · Sets the number of days of warning that a password is about to
+ expire (-w)
+
+ · Sets the number of days after the password expires before the
+ account is locked (-i)
+
+ · Allow viewing of account information in a clearer format (-S)
+
+ For example, let look again at fred
+
+ passwd -S fred
+ fred P 03/04/96 0 60 0 0
+
+ This means that fred's password is valid, it was last changed on
+ 03/04/96, it can be changed at any time, it expires after 60 days,
+ fred will not be warned, and and the account won't be disabled when
+ the password expires.
+
+ This simply means that if fred logs in after the password expires, he
+ will be prompted for a new password at login.
+
+ If we decide that we want to warn fred 14 days before his password
+ expires and make his account inactive 14 days after he lets it expire,
+ we would need to do the following:
+
+ passwd -w14 -i14 fred
+
+ Now fred is changed to:
+ fred P 03/04/96 0 60 14 14
+
+ For more information on the passwd command see the online manual page.
+
+ 7.3. The login.defs file.
+
+ The file /etc/login is the configuration file for the login program
+ and also for the Shadow Suite as a whole.
+
+ /etc/login contains settings from what the prompts will look like to
+ what the default expiration will be when a user changes his password.
+
+ The /etc/login.defs file is quite well documented just by the comments
+ that are contained within it. However, there are a few things to
+ note:
+
+ · It contains flags that can be turned on or off that determine the
+ amount of logging that takes place.
+
+ · It contains pointers to other configuration files.
+
+ · It contains defaults assignments for things like password aging.
+
+ From the above list you can see that this is a rather important file,
+ and you should make sure that it is present, and that the settings are
+ what you desire for your system.
+
+ 7.4. Group passwords.
+
+ The /etc/groups file may contain passwords that permit a user to
+ become a member of a particular group. This function is enabled if
+ you define the constant SHADOWGRP in the /usr/src/shadow-
+ YYMMDD/config.h file.
+
+ If you define this constant and then compile, you must create an
+ /etc/gshadow file to hold the group passwords and the group
+ administrator information.
+
+ When you created the /etc/shadow, you used a program called pwconv,
+ there no equivalent program to create the /etc/gshadow file, but it
+ really doesn't matter, it takes care of itself.
+
+ To create the initial /etc/gshadow file do the following:
+
+ touch /etc/gshadow
+ chown root.root /etc/gshadow
+ chmod 700 /etc/gshadow
+
+ Once you create new groups, they will be added to the /etc/group and
+ the /etc/gshadow files. If you modify a group by adding or removing
+ users or changing the group password, the /etc/gshadow file will be
+ changed.
+
+ The programs groups, groupadd, groupmod, and groupdel are provided as
+ part of the Shadow Suite to modify groups.
+
+ The format of the /etc/group file is as follows:
+
+ groupname:!:GID:member,member,...
+
+ Where:
+
+ groupname
+ The name of the group
+
+ ! The field that normally holds the password, but that is now
+ relocated to the /etc/gshadow file.
+
+ GID
+ The numerical group ID number
+
+ member
+ List of group members
+
+ The format of the /etc/gshadow file is as follows:
+
+ groupname:password:admin,admin,...:member,member,...
+
+ Where:
+
+ groupname
+ The name of the group
+
+ password
+ The encoded group password.
+
+ admin
+ List of group administrators
+
+ member
+ List of group members
+
+ The command gpasswd is used only for adding or removing administrators
+ and members to or from a group. root or someone in the list of
+ administrators may add or remove group members.
+
+ The groups password can be changed using the passwd command by root or
+ anyone listed as an administrator for the group.
+
+ Despite the fact that there is not currently a manual page for
+ gpasswd, typing gpasswd without any parameters gives a listing of
+ options. It's fairly easy to grasp how it all works once you
+ understand the file formats and the concepts.
+
+ 7.5. Consistency checking programs
+
+ 7.5.1. pwck
+
+ The program pwck is provided to provide a consistency check on the
+ /etc/passwd and /etc/shadow files. It will check each username and
+ verify that it has the following:
+
+ · the correct number of fields
+
+ · unique user name
+
+ · valid user and group identifier
+
+ · valid primary group
+
+ · valid home directory
+
+ · valid login shell
+
+ It will also warn of any account that has no password.
+
+ It's a good idea to run pwck after installing the Shadow Suite. It's
+ also a good idea to run it periodically, perhaps weekly or monthly.
+ If you use the -r option, you can use cron to run it on a regular
+ basis and have the report mailed to you.
+
+ 7.5.2. grpck
+
+ grpck is the consistency checking program for the /etc/group and
+ /etc/gshadow files. It performs the following checks:
+
+ · the correct number of fields
+
+ · unique group name
+
+ · valid list of members and administrators
+
+ It also has the -r option for automated reports.
+
+ 7.6. Dial-up passwords.
+
+ Dial-up passwords are another optional line of defense for systems
+ that allow dial-in access. If you have a system that allows many
+ people to connect locally or via a network, but you want to limit who
+ can dial in and connect, then dial-up passwords are for you. To
+ enable dial-up passwords, you must edit the file /etc/login.defs and
+ ensure that DIALUPS_CHECK_ENAB is set to yes.
+
+ Two files contain the dial-up information, /etc/dialups which contains
+ the ttys (one per line, with the leading "/dev/" removed). If a tty
+ is listed then dial-up checks are performed.
+
+ The second file is the /etc/d_passwd file. This file contains the
+ fully qualified path name of a shell, followed by an optional
+ password.
+
+ If a user logs into a line that is listed in /etc/dialups, and his
+ shell is listed in the file /etc/d_passwd he will be allowed access
+ only by suppling the correct password.
+
+ Another useful purpose for using dial-up passwords might be to setup a
+ line that only allows a certain type of connect (perhaps a PPP or UUCP
+ connection). If a user tries to get another type of connection (i.e.
+ a list of shells), he must know a password to use the line.
+
+ Before you can use the dial-up feature, you must create the files.
+
+ The command dpasswd is provided to assign passwords to the shells in
+ the /etc/d_passwd file. See the manual page for more information.
+ 8. Adding shadow support to a C program
+
+ Adding shadow support to a program is actually fairly straightforward.
+ The only problem is that the program must be run by root (or SUID
+ root) in order for the the program to be able to access the
+ /etc/shadow file.
+
+ This presents one big problem: very careful programming practices must
+ be followed when creating SUID programs. For instance, if a program
+ has a shell escape, this must not occur as root if the program is SUID
+ root.
+
+ For adding shadow support to a program so that it can check passwords,
+ but otherwise does need to run as root, it's a lot safer to run the
+ program SUID shadow instead. The xlock program is an example of this.
+
+ In the example given below, pppd-1.2.1d already runs SUID as root, so
+ adding shadow support should not make the program any more vulnerable.
+
+ 8.1. Header files
+
+ The header files should reside in /usr/include/shadow. There should
+ also be a /usr/include/shadow.h, but it will be a symbolic link to
+ /usr/include/shadow/shadow.h.
+
+ To add shadow support to a program, you need to include the header
+ files:
+
+ #include <shadow/shadow.h>
+ #include <shadow/pwauth.h>
+
+ It might be a good idea to use compiler directives to conditionally
+ compile the shadow code (I do in the example below).
+
+ 8.2. libshadow.a library
+
+ When you installed the Shadow Suite the libshadow.a file was created
+ and installed in /usr/lib.
+
+ When compiling shadow support into a program, the linker needs to be
+ told to include the libshadow.a library into the link.
+
+ This is done by:
+
+ gcc program.c -o program -lshadow
+
+ However, as we will see in the example below, most large programs use
+ a Makefile, and usually have a variable called LIBS=... that we will
+ modify.
+
+ 8.3. Shadow Structure
+
+ The libshadow.a library uses a structure called spwd for the
+ information it retrieves from the /etc/shadow file. This is the
+ definition of the spwd structure from the /usr/include/shadow/shadow.h
+ header file:
+
+ ______________________________________________________________________
+ struct spwd
+ {
+ char *sp_namp; /* login name */
+ char *sp_pwdp; /* encrypted password */
+ sptime sp_lstchg; /* date of last change */
+ sptime sp_min; /* minimum number of days between changes */
+ sptime sp_max; /* maximum number of days between changes */
+ sptime sp_warn; /* number of days of warning before password
+ expires */
+ sptime sp_inact; /* number of days after password expires
+ until the account becomes unusable. */
+ sptime sp_expire; /* days since 1/1/70 until account expires
+ */
+ unsigned long sp_flag; /* reserved for future use */
+ };
+ ______________________________________________________________________
+
+ The Shadow Suite can put things into the sp_pwdp field besides just
+ the encoded passwd. The password field could contain:
+
+ username:Npge08pfz4wuk;@/sbin/extra:9479:0:10000::::
+
+ This means that in addition to the password, the program /sbin/extra
+ should be called for further authentication. The program called will
+ get passed the username and a switch that indicates why it's being
+ called. See the file /usr/include/shadow/pwauth.h and the source code
+ for pwauth.c for more information.
+
+ What this means is that we should use the function pwauth to perform
+ the actual authentication, as it will take care of the secondary
+ authentication as well. The example below does this.
+
+ The author of the Shadow Suite indicates that since most programs in
+ existence don't do this, and that it may be removed or changed in
+ future versions of the Shadow Suite.
+
+ 8.4. Shadow Functions
+
+ The shadow.h file also contains the function prototypes for the
+ functions contained in the libshadow.a library:
+
+ ______________________________________________________________________
+ extern void setspent __P ((void));
+ extern void endspent __P ((void));
+ extern struct spwd *sgetspent __P ((__const char *__string));
+ extern struct spwd *fgetspent __P ((FILE *__fp));
+ extern struct spwd *getspent __P ((void));
+ extern struct spwd *getspnam __P ((__const char *__name));
+ extern int putspent __P ((__const struct spwd *__sp, FILE *__fp));
+ ______________________________________________________________________
+
+ The function that we are going to use in the example is: getspnam
+ which will retrieve for us a spwd structure for the supplied name.
+
+ 8.5. Example
+
+ This is an example of adding shadow support to a program that needs
+ it, but does not have it by default.
+
+ This example uses the Point-to-Point Protocol Server (pppd-1.2.1d),
+ which has a mode in which it performs PAP authentication using user
+ names and passwords from the /etc/passwd file instead of the PAP or
+ CHAP files. You would not need to add this code to pppd-2.2.0 because
+ it's already there.
+
+ This feature of pppd probably isn't used very much, but if you
+ installed the Shadow Suite, it won't work anymore because the
+ passwords are no longer stored in /etc/passwd.
+
+ The code for authenticating users under pppd-1.2.1d is located in the
+ /usr/src/pppd-1.2.1d/pppd/auth.c file.
+
+ The following code needs to be added to the top of the file where all
+ the other #include directives are. We have surrounded the #includes
+ with conditional directives (i.e. only include if we are compiling for
+ shadow support).
+
+ ______________________________________________________________________
+ #ifdef HAS_SHADOW
+ #include <shadow.h>
+ #include <shadow/pwauth.h>
+ #endif
+ ______________________________________________________________________
+
+ The next thing to do is to modify the actual code. We are still
+ making changes to the auth.c file.
+
+ Function auth.c before modifications:
+
+ ______________________________________________________________________
+ /*
+ * login - Check the user name and password against the system
+ * password database, and login the user if OK.
+ *
+ * returns:
+ * UPAP_AUTHNAK: Login failed.
+ * UPAP_AUTHACK: Login succeeded.
+ * In either case, msg points to an appropriate message.
+ */
+ static int
+ login(user, passwd, msg, msglen)
+ char *user;
+ char *passwd;
+ char **msg;
+ int *msglen;
+ {
+ struct passwd *pw;
+ char *epasswd;
+ char *tty;
+
+ if ((pw = getpwnam(user)) == NULL) {
+ return (UPAP_AUTHNAK);
+ }
+ /*
+ * XXX If no passwd, let them login without one.
+ */
+ if (pw->pw_passwd == '\0') {
+ return (UPAP_AUTHACK);
+ }
+
+ epasswd = crypt(passwd, pw->pw_passwd);
+ if (strcmp(epasswd, pw->pw_passwd)) {
+ return (UPAP_AUTHNAK);
+ }
+
+ syslog(LOG_INFO, "user %s logged in", user);
+
+ /*
+ * Write a wtmp entry for this user.
+ */
+ tty = strrchr(devname, '/');
+ if (tty == NULL)
+ tty = devname;
+ else
+ tty++;
+ logwtmp(tty, user, ""); /* Add wtmp login entry */
+ logged_in = TRUE;
+
+ return (UPAP_AUTHACK);
+ }
+ ______________________________________________________________________
+
+ The user's password is placed into pw->pw_passwd, so all we really
+ need to do is add the function getspnam. This will put the password
+ into spwd->sp_pwdp.
+
+ We will add the function pwauth to perform the actual authentication.
+ This will automatically perform secondary authentication if the shadow
+ file is setup for it.
+
+ Function auth.c after modifications to support shadow:
+
+ ______________________________________________________________________
+ /*
+ * login - Check the user name and password against the system
+ * password database, and login the user if OK.
+ *
+ * This function has been modified to support the Linux Shadow Password
+ * Suite if USE_SHADOW is defined.
+ *
+ * returns:
+ * UPAP_AUTHNAK: Login failed.
+ * UPAP_AUTHACK: Login succeeded.
+ * In either case, msg points to an appropriate message.
+ */
+ static int
+ login(user, passwd, msg, msglen)
+ char *user;
+ char *passwd;
+ char **msg;
+ int *msglen;
+ {
+ struct passwd *pw;
+ char *epasswd;
+ char *tty;
+
+ #ifdef USE_SHADOW
+ struct spwd *spwd;
+ struct spwd *getspnam();
+ #endif
+
+ if ((pw = getpwnam(user)) == NULL) {
+ return (UPAP_AUTHNAK);
+ }
+
+ #ifdef USE_SHADOW
+ spwd = getspnam(user);
+ if (spwd)
+ pw->pw_passwd = spwd->sp-pwdp;
+ #endif
+
+ /*
+ * XXX If no passwd, let NOT them login without one.
+ */
+ if (pw->pw_passwd == '\0') {
+ return (UPAP_AUTHNAK);
+ }
+ #ifdef HAS_SHADOW
+ if ((pw->pw_passwd && pw->pw_passwd[0] == '@'
+ && pw_auth (pw->pw_passwd+1, pw->pw_name, PW_LOGIN, NULL))
+ || !valid (passwd, pw)) {
+ return (UPAP_AUTHNAK);
+ }
+ #else
+ epasswd = crypt(passwd, pw->pw_passwd);
+ if (strcmp(epasswd, pw->pw_passwd)) {
+ return (UPAP_AUTHNAK);
+ }
+ #endif
+
+ syslog(LOG_INFO, "user %s logged in", user);
+
+ /*
+ * Write a wtmp entry for this user.
+ */
+ tty = strrchr(devname, '/');
+ if (tty == NULL)
+ tty = devname;
+ else
+ tty++;
+ logwtmp(tty, user, ""); /* Add wtmp login entry */
+ logged_in = TRUE;
+
+ return (UPAP_AUTHACK);
+ }
+ ______________________________________________________________________
+
+ Careful examination will reveal that we made another change as well.
+ The original version allowed access (returned UPAP_AUTHACK if there
+ was NO password in the /etc/passwd file. This is not good, because a
+ common use of this login feature is to use one account to allow access
+ to the PPP process and then check the username and password supplied
+ by PAP with the username in the /etc/passwd file and the password in
+ the /etc/shadow file.
+
+ So if we had set the original version up to run as the shell for a
+ user i.e. ppp, then anyone could get a ppp connection by setting
+ their PAP to user ppp and a password of null.
+
+ We fixed this also by returning UPAP_AUTHNAK instead of UPAP_AUTHACK
+ if the password field was empty.
+
+ Interestingly enough, pppd-2.2.0 has the same problem.
+
+ Next we need to modify the Makefile so that two things occur:
+ USE_SHADOW must be defined, and libshadow.a needs to be added to the
+ linking process.
+
+ Edit the Makefile, and add:
+
+ LIBS = -lshadow
+
+ Then we find the line:
+
+ COMPILE_FLAGS = -I.. -D_linux_=1 -DGIDSET_TYPE=gid_t
+
+ And change it to:
+
+ COMPILE_FLAGS = -I.. -D_linux_=1 -DGIDSET_TYPE=gid_t -DUSE_SHADOW
+
+ Now make and install.
+
+ 9. Frequently Asked Questions.
+
+ Q: I used to control which tty's root could log into using the file
+ /etc/securettys, but it doesn't seem to work anymore, what's going on?
+
+ A: The file /etc/securettys does absolutely nothing now that the
+ Shadow Suite is installed. The tty's that root can use are now
+ located in the login configuration file /etc/login.defs. The entry in
+ this file may point to another file.
+
+ Q: I installed the Shadow Suite, but now I can't login, what did I
+ miss?
+
+ A: You probably installed the Shadow programs, but didn't run pwconv
+ or you forgot to copy /etc/npasswd to /etc/passwd and /etc/nshadow to
+ /etc/shadow. Also, you may need to copy login.defs to /etc.
+
+ Q: In the section on xlock, it said to change the group ownership of
+ the /etc/shadow file to shadow. I don't have a shadow group, what do
+ I do?
+
+ A: You can add one. Simply edit the /etc/group file, and insert a
+ line for the shadow group. You need to ensure that the group number
+ is not used by another group, and you need to insert it before the
+ nogroup entry. Or you can simply suid xlock to root.
+
+ Q: Is there a mailing list for the Linux Shadow Password Suite?
+
+ A: Yes, but it's for the development and beta testing of the next
+ Shadow Suite for Linux. You can get added to the list by mailing to:
+ shadow-list-request@neptune.cin.net with a subject of: subscribe. The
+ list is actually for discussions of the Linux shadow-YYMMSS series of
+ releases. You should join if you want to get involved in further
+ development or if you install the Suite on your system and want to get
+ information on newer releases.
+
+ Q: I installed the Shadow Suite, but when I use the userdel command, I
+ get "userdel: cannot open shadow group file", what did I do wrong?
+
+ A: You compiled the Shadow Suite with the SHADOWGRP option enabled,
+ but you don't have an /etc/gshadow file. You need to either edit the
+ config.h file and recompile, or create an /etc/group file. See the
+ section on shadow groups.
+
+ Q: I installed the Shadow Suite but now I'm getting encoded passwords
+ back in my /etc/passwd file, what's wrong?
+
+ A: You either enabled the AUTOSHADOW option in the Shadow config.h
+ file, or your libc was compiled with the SAHDOW_COMPAT option. You
+ need to determine which is the problem, and recompile.
+
+ 10. Copyright Message.
+
+ The Linux Shadow Password HOWTO is Copyright (c) 1996 Michael H.
+ Jackson.
+
+ Permission is granted to make and distribute verbatim copies of this
+ document provided the copyright notice and this permission notice are
+ preserved on all copies.
+
+ Permission is granted to copy and distribute modified versions of this
+ document under the conditions for verbatim copies above, provided a
+ notice clearly stating that the document is a modified version is also
+ included in the modified document.
+
+ Permission is granted to copy and distribute translations of this
+ document into another language, under the conditions specified above
+ for modified versions.
+
+ Permission is granted to convert this document into another media
+ under the conditions specified above for modified versions provided
+ the requirement to acknowledge the source document is fulfilled by
+ inclusion of an obvious reference to the source document in the new
+ media. Where there is any doubt as to what defines 'obvious' the
+ copyright owner reserves the right to decide.
+
+ 11. Miscellaneous and Acknowledgments.
+
+ The code examples for auth.c are taken from pppd-1.2.1d and
+ ppp-2.1.0e, Copyright (c) 1993 and The Australian National University
+ and Copyright (c) 1989 Carnegie Mellon University.
+
+ Thanks to Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl> for
+ writing and maintaining the Shadow Suite for Linux, and for his review
+ and comments on this document.
+
+ Thanks to Ron Tidd <rtidd@tscnet.com> for his helpful review and
+ testing.
+
+ Thanks to everyone who has sent me feedback to help improve this
+ document.
+
+ Please, if you have any comments or suggestions then mail them to me.
+
+ regards
+
+ Michael H. Jackson <mhjack@tscnet.com>
+
diff --git a/doc/Makefile.am b/doc/Makefile.am
new file mode 100644
index 0000000..85f2248
--- /dev/null
+++ b/doc/Makefile.am
@@ -0,0 +1,5 @@
+# This is a dummy Makefile.am to get automake work flawlessly,
+# and also cooperate to make a distribution for `make dist'
+
+EXTRA_DIST = HOWTO README.limits \
+ README.platforms WISHLIST console.c.spec.txt cracklib26.diff
diff --git a/doc/Makefile.in b/doc/Makefile.in
new file mode 100644
index 0000000..0323749
--- /dev/null
+++ b/doc/Makefile.in
@@ -0,0 +1,481 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# This is a dummy Makefile.am to get automake work flawlessly,
+# and also cooperate to make a distribution for `make dist'
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = doc
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+am__DIST_COMMON = $(srcdir)/Makefile.in
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+ECONF_CPPFLAGS = @ECONF_CPPFLAGS@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GREP = @GREP@
+GROUP_NAME_MAX_LENGTH = @GROUP_NAME_MAX_LENGTH@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBACL = @LIBACL@
+LIBATTR = @LIBATTR@
+LIBAUDIT = @LIBAUDIT@
+LIBCRACK = @LIBCRACK@
+LIBCRYPT = @LIBCRYPT@
+LIBECONF = @LIBECONF@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBMD = @LIBMD@
+LIBOBJS = @LIBOBJS@
+LIBPAM = @LIBPAM@
+LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
+LIBSEMANAGE = @LIBSEMANAGE@
+LIBSKEY = @LIBSKEY@
+LIBTCB = @LIBTCB@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+POSUB = @POSUB@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VENDORDIR = @VENDORDIR@
+VERSION = @VERSION@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+XMLCATALOG = @XMLCATALOG@
+XML_CATALOG_FILE = @XML_CATALOG_FILE@
+XSLTPROC = @XSLTPROC@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+capcmd = @capcmd@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+EXTRA_DIST = HOWTO README.limits \
+ README.platforms WISHLIST console.c.spec.txt cracklib26.diff
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign doc/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+tags TAGS:
+
+ctags CTAGS:
+
+cscope cscopelist:
+
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+ cscopelist-am ctags-am distclean distclean-generic \
+ distclean-libtool distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags-am uninstall uninstall-am
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/doc/README.limits b/doc/README.limits
new file mode 100644
index 0000000..80ed940
--- /dev/null
+++ b/doc/README.limits
@@ -0,0 +1,66 @@
+
+ABOUT shadow-login limits:
+
+This code is merged into shadow login program from the original LShell 2.01
+written by Joel Katz. The port and some additional features have been added
+by Cristian Gafton (gafton@sorosis.ro).
+
+
+Changes:
+ - 96/04/16
+ - {spaces,tabs} allowed within limits string
+ - Warn via syslog multiple default limits
+ - added few paragraphs to the login man page
+ - 96/04/14
+ - code merged into lmain.c --cristiang
+
+TODO: - support groups in the limits file
+ (only usernames are supported at this moment :-( )
+
+Setting user limits for shadow login program
+
+First, make a root-only-readable file (/etc/limits by default or LIMITS_FILE
+defined config.h) that describes the resource limits you wish to impose. By
+default no quotas are imposed on 'root'. In fact, there is no way to impose
+limits via this procedure to root-equiv accounts (accounts with UID 0).
+
+Each line describes a limit for a user in the form:
+
+ user LIMITS_STRING
+
+The LIMITS_STRING is a string of a concatenated list of resource limits.
+Each limit consists of a letter identifier followed by a numerical limit.
+The valid identifiers are:
+
+ A: max address space (KB)
+ C: max core file size (KB)
+ D: max data size (KB)
+ F: maximum filesize (KB)
+ M: max locked-in-memory address space (KB)
+ N: max number of open files
+ R: max resident set size (KB)
+ S: max stack size (KB)
+ T: max CPU time (MIN)
+ U: max number of processes
+ L: max number of logins for this user
+
+For example, L2D2048N5 is a valid LIMITS_STRING. For reading convenience,
+the following entries are equivalent:
+
+username L2D2048N5
+username L2 D2048 N5
+
+Be aware that after <username> the rest of the line is considered a limit
+string, thus comments are not allowed. A invalid limits string will be
+rejected (not considered) by the login program.
+
+The default entry is denoted by username '*'. If you have multiple 'default'
+entries in your LIMITS_FILE, then the last one will be used as the default
+entry.
+
+To completely disable limits for a user, a single dash (-) will do.
+
+Also, please note that all limit settings are set PER LOGIN. They are
+not global, nor are they permanent. Perhaps global limits will come, but
+for now this will have to do ;)
+
diff --git a/doc/README.platforms b/doc/README.platforms
new file mode 100644
index 0000000..295d125
--- /dev/null
+++ b/doc/README.platforms
@@ -0,0 +1,33 @@
+# $Id$
+#
+# This is the current (still incomplete) list of platforms this
+# package has been verified to work on. Additions (preferably
+# in the format as described below) are welcome. Thanks!
+#
+# V: last version reported to work
+# H: host type
+# L: Linux libc version
+# D: Linux distribution, or other OS name and version
+# C: changes (if any)
+# R: reported by
+
+V: 980529
+H: sparc-unknown-linux-gnu
+L: glibc-2.0.7
+D: Ultrapenguin-1.0.9
+C: had to explicitly disable desrpc.
+R: Bjorn Christianson <bjorn@cascade.psychology.mcmaster.ca>
+
+V: 980724
+H: i486-pc-linux-gnulibc1
+L: libc-5.4.33
+D: Debian-1.3.1.r6
+C: none (use dpkg-buildpackage)
+R: Marek Michalkiewicz <marekm@linux.org.pl>
+
+V: current
+H: i686-pc-linux-gnu
+L: glibc-2.0.7.19981211
+D: Debian-2.1
+C: none (use dpkg-buildpackage)
+R: Marek Michalkiewicz <marekm@linux.org.pl>
diff --git a/doc/WISHLIST b/doc/WISHLIST
new file mode 100644
index 0000000..61390bd
--- /dev/null
+++ b/doc/WISHLIST
@@ -0,0 +1,40 @@
+$Id$
+
+This is my wishlist for the shadow suite, in no particular order. Feel
+free to do anything from this list and mail me the diffs :-).
+
+Patches in diff -u format, against the latest version (sometimes in the
+"beta" directory) are preferred and make my job easier. Please, no
+MIME, base64, quoted-printable, or HTML. For very big patches, or if
+your mailer can corrupt them, please use gzip and uuencode. Thanks!
+
+New ideas to add to this list are welcome, too. --marekm
+
+- fix all the bugs, of course
+- implement "su only" accounts (no logins, only su from other account)
+- rewrite getdef.c to be more general? (no hardcoded names)
+- patch for rlogind/telnetd to create utmp entry and fill in ut_addr
+- option to specify encrypted password in passwd (for yppasswdd, so it
+ doesn't need to know about shadow/non-shadow); should probably use a pipe
+ (less insecure than command line arguments)
+- add support for changing NIS passwords
+- add option to check passwords by piping them to external programs
+- add functionality of the contrib/rpasswd.c wrapper to passwd
+- option to generate pronounceable passwords (like on SCO), external program?
+- poppassd (remote password change for eudora etc.)
+- add support for passwd/shadow db files (glibc)
+- vipw: check password files for errors after editing
+- add "maximum time users allowed to stay logged in" limit option to logoutd
+- handle quotes in /etc/environment like the shell does (but sshd doesn't...)
+- better utmpx support (logoutd, ...)
+- better OPIE support (report number of logins left, etc.)
+- new option for /etc/suauth: don't load user's environment (force "su -")
+ suggested by Ulisses Alonso Camaro
+- find out why recent releases won't compile on Solaris
+- newusers should be able to copy /etc/skel to the new home directory
+ (like useradd)
+- add directories where other packages can add hooks for package-specific
+ per-user configuration, to be executed with run-parts. Some hooks should
+ be executed at package install time for existing users, likewise for
+ package removal and possibly modification. (Debian Bug#36019)
+
diff --git a/doc/console.c.spec.txt b/doc/console.c.spec.txt
new file mode 100644
index 0000000..b7c0d0d
--- /dev/null
+++ b/doc/console.c.spec.txt
@@ -0,0 +1,36 @@
+$Id$
+
+Specification for console.c source file --
+
+input values --
+ tty -- character pointer to device name with leading "/dev/"
+ removed.
+
+return values --
+ 0 -- false
+ 1 -- true
+
+int console (char * tty)
+ if "CONSOLE" string value is not present in login.defs
+ return true
+
+ if the first character of "CONSOLE" string value is not "/"
+ treat the string as a ":" delimited list of device
+ names and search for the value of tty in that
+ tokenized list.
+
+ if a match is found
+ return true
+
+ return false
+
+ if the file named by "CONSOLE" cannot be opened
+ return true
+
+ scan the file looking for a match between the input line
+ and the value of tty
+
+ if a match is found
+ return true
+
+ return false
diff --git a/doc/cracklib26.diff b/doc/cracklib26.diff
new file mode 100644
index 0000000..09160b8
--- /dev/null
+++ b/doc/cracklib26.diff
@@ -0,0 +1,340 @@
+diff -ur orig/cracklib26_small/cracklib/fascist.c cracklib26_small/cracklib/fascist.c
+--- orig/cracklib26_small/cracklib/fascist.c Mon Dec 15 02:56:55 1997
++++ cracklib26_small/cracklib/fascist.c Sat Apr 4 22:14:45 1998
+@@ -12,6 +12,7 @@
+ #include <ctype.h>
+ #include <sys/types.h>
+ #include <pwd.h>
++#include <string.h>
+
+ #define ISSKIP(x) (isspace(x) || ispunct(x))
+
+@@ -460,28 +461,27 @@
+ }
+
+ char *
+-FascistGecos(password, uid)
++FascistGecosPw(password, pwd)
+ char *password;
+- int uid;
++ struct passwd *pwd;
+ {
+ int i;
+ int j;
+ int wc;
+ char *ptr;
+- struct passwd *pwp;
+ char gbuffer[STRINGSIZE];
+ char tbuffer[STRINGSIZE];
+ char *uwords[STRINGSIZE];
+ char longbuffer[STRINGSIZE * 2];
+
+- if (!(pwp = getpwuid(uid)))
++ if (!pwd)
+ {
+ return ("you are not registered in the password file");
+ }
+
+ /* lets get really paranoid and assume a dangerously long gecos entry */
+
+- strncpy(tbuffer, pwp->pw_name, STRINGSIZE);
++ strncpy(tbuffer, pwd->pw_name, STRINGSIZE);
+ tbuffer[STRINGSIZE-1] = '\0';
+ if (GTry(tbuffer, password))
+ {
+@@ -490,12 +490,13 @@
+
+ /* it never used to be that you got passwd strings > 1024 chars, but now... */
+
+- strncpy(tbuffer, pwp->pw_gecos, STRINGSIZE);
++ strncpy(tbuffer, pwd->pw_gecos, STRINGSIZE);
+ tbuffer[STRINGSIZE-1] = '\0';
+ strcpy(gbuffer, Lowercase(tbuffer));
+
+ wc = 0;
+ ptr = gbuffer;
++ uwords[0] = (char *) 0;
+
+ while (*ptr)
+ {
+@@ -530,6 +531,8 @@
+ *(ptr++) = '\0';
+ }
+ }
++ if (!uwords[0])
++ return ((char *) 0); /* empty gecos */
+ #ifdef DEBUG
+ for (i = 0; uwords[i]; i++)
+ {
+@@ -586,9 +589,10 @@
+ }
+
+ char *
+-FascistLook(pwp, instring)
++FascistLookPw(pwp, instring, pwd)
+ PWDICT *pwp;
+ char *instring;
++ struct passwd *pwd;
+ {
+ int i;
+ char *ptr;
+@@ -667,7 +671,7 @@
+ return ("it looks like a National Insurance number.");
+ }
+
+- if (ptr = FascistGecos(password, getuid()))
++ if (ptr = FascistGecosPw(password, pwd ? pwd : getpwuid(getuid())))
+ {
+ return (ptr);
+ }
+@@ -715,9 +719,10 @@
+ }
+
+ char *
+-FascistCheck(password, path)
++FascistCheckPw(password, path, pwd)
+ char *password;
+ char *path;
++ struct passwd *pwd;
+ {
+ static char lastpath[STRINGSIZE];
+ static PWDICT *pwp;
+@@ -750,5 +755,29 @@
+ strncpy(lastpath, path, STRINGSIZE);
+ }
+
+- return (FascistLook(pwp, pwtrunced));
++ return (FascistLookPw(pwp, pwtrunced, pwd));
++}
++
++char *
++FascistGecos(password, uid)
++ char *password;
++ int uid;
++{
++ return (FascistGecosPw(password, getpwuid(uid)));
++}
++
++char *
++FascistLook(pwp, instring)
++ PWDICT *pwp;
++ char *instring;
++{
++ return (FascistLookPw(pwp, instring, (char *) 0));
++}
++
++char *
++FascistCheck(password, path)
++ char *password;
++ char *path;
++{
++ return (FascistCheckPw(password, path, (char *) 0));
+ }
+diff -ur orig/cracklib26_small/cracklib/packer.h cracklib26_small/cracklib/packer.h
+--- orig/cracklib26_small/cracklib/packer.h Mon Dec 15 00:09:30 1997
++++ cracklib26_small/cracklib/packer.h Sat Jan 10 22:13:46 1998
+@@ -34,6 +34,7 @@
+ FILE *dfp;
+ FILE *wfp;
+
++ int canfree;
+ int32 flags;
+ #define PFOR_WRITE 0x0001
+ #define PFOR_FLUSH 0x0002
+diff -ur orig/cracklib26_small/cracklib/packlib.c cracklib26_small/cracklib/packlib.c
+--- orig/cracklib26_small/cracklib/packlib.c Fri Jul 9 22:22:58 1993
++++ cracklib26_small/cracklib/packlib.c Sat Jan 10 22:28:49 1998
+@@ -16,7 +16,7 @@
+ char *mode;
+ {
+ int32 i;
+- static PWDICT pdesc;
++ PWDICT *pdesc;
+ char iname[STRINGSIZE];
+ char dname[STRINGSIZE];
+ char wname[STRINGSIZE];
+@@ -25,92 +25,94 @@
+ FILE *ifp;
+ FILE *wfp;
+
+- if (pdesc.header.pih_magic == PIH_MAGIC)
+- {
+- fprintf(stderr, "%s: another dictionary already open\n", prefix);
++ if ((pdesc = (PWDICT *) malloc(sizeof(PWDICT))) == 0)
+ return ((PWDICT *) 0);
+- }
+
+- memset(&pdesc, '\0', sizeof(pdesc));
++ memset(pdesc, '\0', sizeof(*pdesc));
+
+ sprintf(iname, "%s.pwi", prefix);
+ sprintf(dname, "%s.pwd", prefix);
+ sprintf(wname, "%s.hwm", prefix);
+
+- if (!(pdesc.dfp = fopen(dname, mode)))
++ if (!(pdesc->dfp = fopen(dname, mode)))
+ {
+ perror(dname);
++ free(pdesc);
+ return ((PWDICT *) 0);
+ }
+
+- if (!(pdesc.ifp = fopen(iname, mode)))
++ if (!(pdesc->ifp = fopen(iname, mode)))
+ {
+- fclose(pdesc.dfp);
++ fclose(pdesc->dfp);
+ perror(iname);
++ free(pdesc);
+ return ((PWDICT *) 0);
+ }
+
+- if (pdesc.wfp = fopen(wname, mode))
++ if (pdesc->wfp = fopen(wname, mode))
+ {
+- pdesc.flags |= PFOR_USEHWMS;
++ pdesc->flags |= PFOR_USEHWMS;
+ }
+
+- ifp = pdesc.ifp;
+- dfp = pdesc.dfp;
+- wfp = pdesc.wfp;
++ ifp = pdesc->ifp;
++ dfp = pdesc->dfp;
++ wfp = pdesc->wfp;
+
+ if (mode[0] == 'w')
+ {
+- pdesc.flags |= PFOR_WRITE;
+- pdesc.header.pih_magic = PIH_MAGIC;
+- pdesc.header.pih_blocklen = NUMWORDS;
+- pdesc.header.pih_numwords = 0;
++ pdesc->flags |= PFOR_WRITE;
++ pdesc->header.pih_magic = PIH_MAGIC;
++ pdesc->header.pih_blocklen = NUMWORDS;
++ pdesc->header.pih_numwords = 0;
+
+- fwrite((char *) &pdesc.header, sizeof(pdesc.header), 1, ifp);
++ fwrite((char *) &pdesc->header, sizeof(pdesc->header), 1, ifp);
+ } else
+ {
+- pdesc.flags &= ~PFOR_WRITE;
++ pdesc->flags &= ~PFOR_WRITE;
+
+- if (!fread((char *) &pdesc.header, sizeof(pdesc.header), 1, ifp))
++ if (!fread((char *) &pdesc->header, sizeof(pdesc->header), 1, ifp))
+ {
+ fprintf(stderr, "%s: error reading header\n", prefix);
+
+- pdesc.header.pih_magic = 0;
++ pdesc->header.pih_magic = 0;
+ fclose(ifp);
+ fclose(dfp);
++ free(pdesc);
+ return ((PWDICT *) 0);
+ }
+
+- if (pdesc.header.pih_magic != PIH_MAGIC)
++ if (pdesc->header.pih_magic != PIH_MAGIC)
+ {
+ fprintf(stderr, "%s: magic mismatch\n", prefix);
+
+- pdesc.header.pih_magic = 0;
++ pdesc->header.pih_magic = 0;
+ fclose(ifp);
+ fclose(dfp);
++ free(pdesc);
+ return ((PWDICT *) 0);
+ }
+
+- if (pdesc.header.pih_blocklen != NUMWORDS)
++ if (pdesc->header.pih_blocklen != NUMWORDS)
+ {
+ fprintf(stderr, "%s: size mismatch\n", prefix);
+
+- pdesc.header.pih_magic = 0;
++ pdesc->header.pih_magic = 0;
+ fclose(ifp);
+ fclose(dfp);
++ free(pdesc);
+ return ((PWDICT *) 0);
+ }
+
+- if (pdesc.flags & PFOR_USEHWMS)
++ if (pdesc->flags & PFOR_USEHWMS)
+ {
+- if (fread(pdesc.hwms, 1, sizeof(pdesc.hwms), wfp) != sizeof(pdesc.hwms))
++ if (fread(pdesc->hwms, 1, sizeof(pdesc->hwms), wfp) != sizeof(pdesc->hwms))
+ {
+- pdesc.flags &= ~PFOR_USEHWMS;
++ pdesc->flags &= ~PFOR_USEHWMS;
+ }
+ }
+ }
+-
+- return (&pdesc);
++ pdesc->canfree = 1;
++ return (pdesc);
+ }
+
+ int
+@@ -159,8 +161,13 @@
+
+ fclose(pwp->ifp);
+ fclose(pwp->dfp);
++ if (pwp->wfp)
++ fclose(pwp->wfp);
+
+- pwp->header.pih_magic = 0;
++ if (pwp->canfree)
++ free(pwp);
++ else
++ pwp->header.pih_magic = 0;
+
+ return (0);
+ }
+@@ -307,6 +314,11 @@
+ register char *this;
+ int idx;
+
++/*
++ * comment in npasswd-2.0beta4 says this:
++ * This does not work under all circumstances, so don't bother
++ */
++#if 0
+ if (pwp->flags & PFOR_USEHWMS)
+ {
+ idx = string[0] & 0xff;
+@@ -317,6 +329,10 @@
+ lwm = 0;
+ hwm = PW_WORDS(pwp) - 1;
+ }
++#else
++ lwm = 0;
++ hwm = PW_WORDS(pwp);
++#endif
+
+ #ifdef DEBUG
+ printf("---- %lu, %lu ----\n", lwm, hwm);
+diff -ur orig/cracklib26_small/util/mkdict cracklib26_small/util/mkdict
+--- orig/cracklib26_small/util/mkdict Fri Jul 9 22:23:03 1993
++++ cracklib26_small/util/mkdict Sat Apr 4 22:31:45 1998
+@@ -14,9 +14,16 @@
+ SORT="sort"
+ ###SORT="sort -T /tmp"
+
+-cat $* |
++### Use zcat to read compressed (as well as uncompressed) dictionaries.
++### Compressed dictionaries can save quite a lot of disk space.
++
++CAT="gzip -cdf"
++###CAT="zcat"
++###CAT="cat"
++
++$CAT $* |
+ tr '[A-Z]' '[a-z]' |
+- tr -cd '[\012a-z0-9]' |
++ tr -cd '\012[a-z][0-9]' |
+ $SORT |
+ uniq |
+ grep -v '^#' |