The previous article in this series examined an authentication method known as OTP (or One Time Passwords). Your FreeBSD system supports several types of authentication methods; you can choose which type your users are subject to by configuring something known as PAM, or Pluggable Authentication Modules.
As the name suggests, PAM consists of many modules. You can see which modules were installed with your system by issuing this command:
$ ls /usr/lib |grep pam_
Note that each module ends in
so and has a name that gives
some indication of what that module is responsible for.
"Pluggable" means you have great flexibility. The entire framework already exists; you merely choose which portions of the framework you wish to implement. It also implies that one can "plug in" the desired module. Each module can be added or removed by simply adding or deleting a remark or changing a keyword in a configuration file.
If you are new to PAM, you will find excellent information regarding FreeBSD's implementation, written by the very person
in charge of the implementation. Alternatively, if you installed the
docs/ directory when you installed FreeBSD, you'll find the same
information on your hard drive:
$ ls /usr/share/doc/en_US.ISO8859-1/articles/pam
PAM uses some terminology that I've summarized into the following tables. First, PAM has been divided into four groups known as facilities. Each group provides at least one function, known as a primitive. Table 1 matches each primitive to its facility and includes a brief description of the functionality provided by that primitive:
|Establishes UID, GID, resource limits.|
|Time of day, server load.|
entry in |
|Same as above, but when session closes.|
|Check for password expiry, easily-guessable password.|
Next, PAM uses control flags to determine which authentication scheme or schemes to apply to a user. For now, I've summarized these flags in Table 2. Don't worry if this doesn't make sense; it will become more clear when we work through a configuration example.
|This line must succeed.|
|Request is immediately denied if this line fails.|
|Request is immediately allowed if this line succeeds.|
|It's okay if this line fails.|
Now that we're aware of the terminology used by PAM, we're ready to take a closer look at its configuration. This will vary depending upon whether you are using FreeBSD 4.x or 5.x, so I will demonstrate both. As of the time of this writing, FreeBSD 4.7 is considered STABLE and 5.0 is considered CURRENT. If you're unfamiliar with the difference between the two, an explanation can be found here and in the early adopter's guide.
Also in FreeBSD Basics:
The upshot is that you don't want to install version 5.0 on your main machine until it has become STABLE and the number has changed to at least 5.1. The FreeBSD site will have an announcement when this occurs. Until then, you'll notice that my articles will mention both FreeBSD 4.x and 5.x, to help you through the transition period. If you are lucky enough to have a spare computer to use as a test machine, install FreeBSD 5.0 to give yourself time to play with its many new features. However, if you only have one computer, you can install FreeBSD on, wait until FreeBSD 5.1 before upgrading from version 4.x.
Having said all of that, one of the features of FreeBSD 5.x is greatly-improved PAM support. For one, the type of PAM has changed from Linux-PAM to OpenPAM.
I'll start by showing you how to configure PAM on a FreeBSD 4.x system, then move on to show you the changes with 5.0.
In FreeBSD 4.x, the PAM configuration file is /etc/pam.conf. I won't display the entire file here, as it starts off with about two pages of comments. Even though the comments repeat the information in the above tables, they are well worth reading on your own. Once you get past the comments, you'll see this section:
# If the user can authenticate with S/Key, that's sufficient; # allow clear password. Try kerberos, then try plain unix password. login auth sufficient pam_skey.so login auth sufficient pam_opie.so no_fake_prompts #login auth required pam_opieaccess.so login auth requisite pam_cleartext_pass_ok.so #login auth sufficient pam_kerberosIV.so try_first_pass #login auth sufficient pam_krb5.so try_first_pass login auth required pam_unix.so try_first_pass login account required pam_unix.so login password required pam_permit.so login session required pam_permit.so
Each line in this section starts with the word
login, as this
section affects the
login service. This section configures how a
person will authenticate when they receive a
login prompt. Let's
see if we can work out the syntax.
First, three of those lines are commented out, as they begin with a
#. This means that
opieaccess and both versions of
Kerberos aren't used by default. Second, each line in the
pam.conf file is divided up as follows:
service facility control flag module name module arguments
Notice that the
login, which supports
all four facilities:
session. Let's concentrate on the
auth facility for a moment. There are seven listed ways a user can
be authenticated: with s/key, OPIE, opie_access, a cleartext password, Kerberos
IV, Kerberos 5, and the traditional Unix password authentication system.
The control flags determine which of the seven authentication methods a user is subject to. It's important to understand how these control flags interact with each other before you start editing this file. The lines are read in order, but some control flags tell PAM to read on to the next line, while other control flags tell PAM to stop reading.
For example, in the default configuration,
requisite. Notice from the chart that authentication will fail if
a user doesn't meet
requisite. That is, if a user types in the
incorrect cleartext password, the login will fail. However, if the user types
in the correct cleartext password, PAM will continue reading. Since there
aren't any other
requisite lines and Unix password authentication
required, the correct cleartext password will be accepted as
the user's authentication method.
Now, note the lines that use
sufficient. If a user chooses to
use an authentication method labeled as
sufficient and their login
attempt succeeds, PAM will stop reading and accept the authentication. However,
a user is not
required to authenticate using a method marked as
sufficient. We saw this behavior when we configured OPIE. Since
sufficient, the user can log in with
their OTP, if they choose to do so. If they give the correct challenge, the
login will be successful and they won't be prompted for any further login
information. If the user instead decides not to use OTP, she will be prompted
to input the
requisite cleartext password.
Now move down to the last four lines in this section. Notice there is a
line for each facility and each line is
required. If you ever
change a line in a PAM configuration file, double check that
the last line for each listed facility is
If you take a quick peek through the rest of
you'll see sections for various services:
other. This gives you
the flexibility of specifying different authentication schemes for different
services. If a user happens to connect to a FreeBSD system using a service not
mentioned in the file, they will be subject to the
which by default requires a Unix password:
# If we don't match anything else, default to using getpwnam(). other auth required pam_unix.so try_first_pass other account required pam_unix.so try_first_pass
The OpenPAM used in FreeBSD 5.x follows the same logic, but adds more modules and lays out the configuration slightly differently. If you try this command on a FreeBSD 5.0 system, you'll receive many more PAM modules:
ls /usr/lib |grep pam_
You'll also find that the 4.x modules have been included for backwards compatibility:
ls /usr/lib/compat |grep pam_
OpenPAM also supports
/etc/pam.conf for backwards
compatibility; however, this file isn't included for you. Instead, you should
use the new layout:
$ ls /etc/pam.d README imap other rsh xdm ftp kde passwd sshd xserver ftpd login pop3 su gdm rexecd telnetd
Notice that each service in the old style
/etc/pam.conf is now
a separate file in the
pam.d directory. The
file is the former comment section, and it has changed slightly, so yes, you
should read it. In addition to the many new modules, more services have been
added. The files themselves are identical to
the service name is missing as it is now the name of the file. For example,
this line in
login auth sufficient pam_opie.so no_fake_prompts
is now this line in
auth sufficient pam_opie.so no_warn no_fake_prompts
Before you go about changing the default files for either type of PAM, you should be aware that PAM is a work in progress. I would highly recommend that you create a test account and be prepared for some experimentation. From one virtual terminal, make a change to the configuration file as the superuser. Then try to log in to another virtual terminal as the test user to see if your changes yield the intended result. This way if you come across any unexpected behavior, you can simply go back to the terminal where you changed the configuration file and undo the change.
As an example, let's see how one would go about always forcing users to use
their OTP password at the login prompt.
man pam_opieaccess gives a
hint on how to take away a user's choice and force them to log in using OTP:
To properly use this module, pam_opie(8) should be marked ``sufficient'', and pam_opieaccess should be listed right below it and marked ``requisite''.
It also indicates how this change will affect your users:
The authentication component (pam_sm_authenticate()), returns PAM_SUCCESS in two cases: 1. The user does not have OPIE enabled. 2. The user has OPIE enabled, and the remote host is listed as a trusted host in /etc/opieaccess, and the user does not have a file named opiealways in his home directory. Otherwise, it returns PAM_AUTH_ERR.
Let's compare those manpage hints to the relevant lines in
/etc/pam.conf on a FreeBSD 4.7 system:
login auth sufficient pam_skey.so login auth sufficient pam_opie.so no_fake_prompts #login auth required pam_opieaccess.so login auth requisite pam_cleartext_pass_ok.so login auth required pam_unix.so try_first_pass
Depending upon when you installed FreeBSD, your
pam_opieaccess.so line may say
required instead of
requisite. This is a typo in
pam.conf, as the
manpage is correct. I'll change that line so it now looks like this:
login auth requisite pam_opieaccess.so
Now, from another terminal, I'll try to log in as the
user. Instead of giving the OTP password, I'll try to give the reusable
password for this account:
login: test otp-md5 497 dh0908 ext Password: (here I typed in the reusable password) $
Hmmmm. At first glance, it looks like the configuration change failed to enforce OTP passwords, as the user successfully logged in using a reusable password. Better take another look at that section of the manpage:
2. The user has OPIE enabled, and the remote host is listed as a trusted host in /etc/opieaccess, and the user does not have a file named opiealways in his home directory.
I wonder if it has something to do with that file
There's no manpage for it, so I went to my good friend www.google.ca and searched for
opiealways. The very first hit brought me to the diary of OpenPAM's
implementer, which explained that the presence of this file will always
force a user to use OTP. So, as the test user, I created that empty file in my
home directory. Then I logged out and tried to log back in without using OTP:
$ touch .opiealways $ exit login: test otp-md5 497 dh0908 ext Password: (here I typed in the reusable password) pam_opieaccess: pam_sm_authenticate: Refused; remote host is not in opieaccess Login incorrect
Voila, by simply removing a remark in the PAM configuration file and
instructing the user to
touch .opiealways, that user will now
always be forced to use OTP.
Being the paranoid type, I also tested that the configuration change didn't
adversely affect users who don't use OTP. I logged in as a regular user,
received the regular login prompt, and successfully logged in after inputting
the correct reusable password. I carried the test one step further by creating
.opiealways file in a regular user's home directory. Since the
user wasn't in the OTP database, that file did not affect the user's login.
However, should the user in the future add themselves to the OTP database, the
presence of that file will force them to use OTP.
This behavior can simplify things, if you plan on creating new user accounts that may decide to use OTP. Create the following file:
$ touch /usr/share/skel/dot.opiealways
Note that this skeleton file will only be inherited by new users you create. It won't affect existing user accounts.
This should get you started on your own PAM experiments. I will be writing about some of the new PAM modules later on this year, once FreeBSD 5.x has gone stable.
Dru Lavigne is a network and systems administrator, IT instructor, author and international speaker. She has over a decade of experience administering and teaching Netware, Microsoft, Cisco, Checkpoint, SCO, Solaris, Linux, and BSD systems. A prolific author, she pens the popular FreeBSD Basics column for O'Reilly and is author of BSD Hacks and The Best of FreeBSD Basics.
Read more FreeBSD Basics columns.
Return to the BSD DevCenter.
Copyright © 2009 O'Reilly Media, Inc.