Many interactive commands are security sensitive.
An obvious example is
passwd
used to change a user's
password.
Such commands require users to authenticate themselves even though
they have successfully logged in to the system.
Also many server daemons carry out tasks on behalf of remote
users, and most of these require the daemon to authenticate
the remote user.
Early versions of Unix had such programs (applications and daemons)
directly read and parse the
/etc/passwd
file, so they
could authenticate users.
This became a problem when the format of /etc/passwd
changed to include aging information in the second field.
Every program that needed to authenticate users had to be updated
and re-compiled.
Sometime after that, single (remote) user databases became common
in large organizations, using technology such as
NIS.
This meant a second set of such commands (all NIS
commands start with the letters “yp”, as in
yppasswd
).
Soon shadow passwords became common, then Kerberos,
then different password encryption (actually, hashing)
algorithms (such as MD5), then LDAP, etc.
Every such change either requires custom versions of applications
and daemons, or a re-write of the existing versions.
And for every program that needed authentication!
At some point, someone came up with the idea that programs that need
authentication should use a standard library for that, which in turn
could be configured to use different databases and/or new algorithms
just by adding new DLLs
(shared object files).
This system became known as
PAM
(Pluggable Authentication Modules).
Using PAM, some new authentication DLL can be invoked
by the PAM library just by editing a text configuration file
(which says which authentication modules to use).
“PAM-ified” programs do not need to be changed in any
way to use different authentication modules.
Only a text configuration file (one for each program) needs to be
updated to change how some program authenticates users.
To see if some program is “PAM-ified” or not,
check if it has been compiled with the PAM library:
ldd cmd | grep libpam.so
Modern (and most legacy) applications and daemons that
need authentication have been re-written (hopefully for the
last time!) to use PAM.
There are many PAM modules (yes I know that's redundant but
saying “PAMs” or “PA modules” is awkward) available
for every system, each supporting a different authentication
method.
New ones can be easily found on the Internet, or created by
programmers.
A nice benefit of this design is that different programs can use
different PAM modules for authentication, all on the same
system.
(Each program's text configuration file may specify a different
set of PAM modules to use.)
In addition to authentication, PAM modules can be used for
session setup and tear-down, logging, and various other uses.
For example, there is a PAM module to display the
MOTD file.
Another module changes the owner, group, and permissions of various
files in
/dev
, to allow users logged in at the
console permission to use sound or access removable media.
The PAM configuration file for some program can list more than one
PAM module to try, and each is tried in the order listed.
So if the user fails to authenticate using the PAM module for (say)
local files (
/etc/passwd
and /etc/shadow
),
then PAM will try the next module listed, which can attempt
authentication using a different database such as NIS,
LDAP, or even Windows AD.
PAM modules don't only allow or deny access by authenticating
users.
They can check other things to determine access.
For instance, some PAM modules deny access if the resource is busy
with too many users already.
Others can allow or deny users based on criteria such as the
time of day.
Because of PAM's utility and flexibility, system administrators
should become familiar with the system and the set of PAM modules
available to them.
Then they can implement a wide range of security policies for
the various applications and services on their hosts.
PAM Overview:
In the PAM configuration file for some program (application or
daemon), the administrator lists all the PAM modules that should
be used to implement the access policy.
This list is called a stack.
When a program needs to authenticate a user, each PAM module
is invoked in the order listed in the configuration file for
that program.
Each module can return success or failure.
The results of all the modules are combined into a single result.
This process is controlled by the “control-flag” listed for
each module.
Generally, if any one module “fails”, then PAM informs the
application that access is denied.
The exact behavior of PAM in the event that one module fails can be
changed in the configuration file, allowing for complex policies to
be implemented.
For example you can configure some program to try to authenticate
with LDAP first, and if that fails try local files.
Then allow access if either module succeeds.
Take for example an application such as
hwbrowser
.
This is written to use PAM to see who is allowed to run that
command.
The exact set of modules is controlled by a text configuration
(or policy) file in the /etc/pam.d
directory;
the configuration file is called hwbrowser
.
(It is common but not required to use the application's name as
the configuration file's name.)
By editing this configuration file, you can enforce any access
policy desired.
Here's the default hwbrowser
PAM configuration file
from a Fedora Core Linux system:
/etc/pam.d# cat hwbrowser
#%PAM-1.0
auth sufficient pam_rootok.so
auth sufficient pam_timestamp.so
auth required pam_stack.so service=system-auth
session required pam_permit.so
session optional pam_xauth.so
account required pam_permit.so
As you can see, the file has a list of DLLs to use,
and some of them are passed extra arguments.
(The syntax of PAM configuration files is discussed below.)
If an application can't find a configuration file for itself, it defaults to using the
other
PAM configuration
file.
It is important for security reasons to have an
“other
” configuration file!
Typically this file should deny all access.
This is a deny by default policy.
The administrator will need to create (if missing) a PAM
configuration file for any “PAM-ified” program to be used
on the system.
By editing (or creating if missing) these files, a system administer implements access policy for the applications and servers on the host. Don't forget that other security systems may also require configuration to implement a host's access policies, including firewalls, TCP Wrappers, file permissions and ACLs, group memberships, SE Linux policy files, service configuration files, SASL, and so on.
SASL is a framework for authentication mechanism
negotiation.
A server can advertise one or more authentication mechanisms to
clients, and the two can agree on which one to use.
It is not uncommon to have SASL configured to use
PAM.
See
Cyrus SASL for System Administrators and
RFC-4422 for more information on SASL.
/lib/security
directory.
Do an “ls
” of this directory to see what PAM modules
have been installed on your system.
Additional modules may be put anywhere, but if so the configuration
file needs to list the complete pathname of the module.
Each PAM module is really just a DLL that defines one
or more of the six standard functions that PAM will use.
These functions are grouped into four types, or
contexts: account
, auth
,
session
, and password
.
Any given PAM module will implement the functions needed for
one or more of these types.
(So, a module that only implements session
functions
will do nothing if used in any other context.)
To see which functions a given PAM module implements, your first
thought should be to consult the documentation.
When that is lacking, you can run the command:
nm --dynamic --defined-only pam_module.so
and see which PAM functions are defined in that module. An “auth” module will define the function
and see which PAM functions are defined in that module. An “auth” module will define the function
pam_sm_authenticate()
, an “account”
module will define pam_sm_acct_mgmt()
, a “session”
module will define both pam_sm_open_session()
and
pam_sm_close_session()
, and
a “password” module will define pam_sm_chauthtok()
.
Any PAM module must define at least one set of these functions, and
may define several.
PAM Configuration (Policy) File Syntax:
This is documented in the
Each line contains a module context (or type), the
control flag, the module, and
module options (if any).
Blank lines and comment lines (starting with “
For determining authorization to run a command, only the lines that start with “
The relevant modules are run in order listed in the file. Modules are passed information about the request and user, plus any module options listed on the end of the line. Each module returns a result such as pass or fail. The modules are run until an overall decision is reached, which is either pass or fail. (In more sophisticated configurations, many different return values can occur, and the configuration file can say what to do for each.) The final result is passed back to the application.
pam.conf
man page.
Older versions of PAM used one large pam.conf
file,
with each line starting with the name of the service the line
applies to.
In modern PAM, each service has its own file in
/etc/pam.d
.
The syntax is the same except that first field is omitted, even
though the man page may still mention it.
If both the
/etc/pam.conf
file and the /etc/pam.d/
directory exist, PAM will ignore the file.
#
”)
are also allowed.
(Some implementations of PAM allow for long lines to be continued, using
the convention of ending a line with a backslash.
Don't rely on this unless you are certain your implementation
supports it!)
The context says when the module is used:
for authentication, for password updates, or for session
setup/cleanup.
The control flag tells PAM how to react to the module's
result (e.g., pass or fail).
For determining authorization to run a command, only the lines that start with “
auth
” and “account
”
matter.
The others can be ignored.
(They have other uses, such as initializing the environment
or logging the command's use.)
The auth
modules determine who the user is and if that user
has a valid account on this machine.
The account
modules determine if the user is allowed access.
Some possible account policies you can test for include: the account and
password are not expired, must be a system account, only 50 users may run this
command (say FTP) at once, access only allowed during certain hours,
access from the console (i.e. not a remote user), etc.
The relevant modules are run in order listed in the file. Modules are passed information about the request and user, plus any module options listed on the end of the line. Each module returns a result such as pass or fail. The modules are run until an overall decision is reached, which is either pass or fail. (In more sophisticated configurations, many different return values can occur, and the configuration file can say what to do for each.) The final result is passed back to the application.
Locating PAM Module Documentation:
A description of most standard PAM modules can be found in the
on-line
PAM Administrator's Guide, but often the name alone suggests what
a module does.
Not every module is listed in this one guide.
However many PAM modules have
man
pages (and
many don't), so if not listed in the guide try
“man pam_module
”.
(I.e. to find info on pam_console.so
module try
“man pam_console
”.)
If this doesn't work you must look on the Internet for information.
A good place to start is
The Linux-PAM web site.
Failing that you can always try a Google search.
For example, a search for “pam_timestamp
” easily
finds a
man page for pam_timestamp.
PAM Walk-through (I):
Enough with the theory!
Examine the first line from the
The “
The next “
This means that if you have successfully authenticated recently say by supplying your password, that will be remembered for several minutes and you can use the command without authenticating yourself again. (This module was invented for the use of the
Now look at the last
Now look at the last line:
Putting these lines together we get this policy: A user can run the
hwbrowser
example
above:
auth sufficient pam_rootok.so
A description of this “pam_rootok
” module can be
found in the on-line
PAM Administrator's Guide, but the name alone suggests what it
does:
If the user is root
, then that is sufficient to allow
access to this command.
The “
sufficient
” control-flag means that if the
module passes, that is if the user is root, no further
modules need to be tried.
But if the user is not root
then PAM
must try the other modules listed (if any) to decide whether
to allow access.
The next “
auth
” line is:
auth sufficient pam_timestamp.soWhat does this mean? Looking up this module in the guide we find... nothing! In this case the man page is locally installed and we find this information there: “... In a nutshell,
pam_timestamp
caches successful
authentication attempts, and allows you to use a recent successful
attempt as the basis for authentication. ...”
This means that if you have successfully authenticated recently say by supplying your password, that will be remembered for several minutes and you can use the command without authenticating yourself again. (This module was invented for the use of the
sudo
command.
The timestamp is the modification time on a file, by default
in /var/run/sudo/username/*
.
You can also determine for how long after that time your
credentials remain valid; default is 5 minutes.)
Now look at the last
auth
line:
auth required pam_stack.so service=system-authThe
pam_stack
module runs all the modules in
the file listed after service=
(another PAM config file),
and returns whatever result that file's modules return.
Modern Linux PAM no longer uses
The pam_stack
.
Instead two new keywords are available for use in the configuration
files, include
and substack
.
On a modern system, the above line would look like this:
auth include system-auth
pam_stack.so
line says that the user can use the
hwbrowser
command if they pass all the auth
modules listed in the PAM configuration file
“system-auth
”.
This is a Red Hat thing.
The folks at Red Hat decided to centralize a lot of security
policies into that one file.
If you look at some other configuration files in
/etc/pam.d
on a Red Hat based system,
you will see the same line.
(Note the system-auth
file is over-written each
time the “authconfig
” command is run, so
it is important to keep a backup copy of this file handy
if you edit it manually.)
Centralizing your default access policy in one PAM configuration file
is a good idea, so if and when it changes you need only update that
one file.
Now look at the last line:
account required pam_permit.soA quick check of this module says it merely always returns pass. I guess Red Hat just wanted to show an
account
module.
You can ignore such lines as they have no effect on PAM's overall
result.
Putting these lines together we get this policy: A user can run the
hwbrowser
command: if the user ID is zero
(root
), or if the user recently authenticated, or
(if neither of those) if the user passes the common policy
in the system-auth
file.
(The default system-auth
file is discussed below.)
If none of those pass, access is denied and the attempt is logged.
Suppose the policy on your site changes so root and only root should
be allowed to use the command
hwbrowser
.
To implement this new policy an administrator need only comment
out the second and third “auth” lines in the configuration file.
Control-flags and Module Return Values:
As mentioned above the “
The “
But, what does pass mean exactly? Each PAM module examines information provided by the program requesting authentication (usually the user's ID and a supplied password), plus other information found elsewhere (often there are per-module configuration files found in
In short, all modules of the correct type (context) are tried in the order
listed, except when a
sufficient
”
control-flag means that if the module passes, that is
enough and the remaining modules in the same context
(“auth
”are ignored.
On the other hand, if the module fails it doesn't mean an overall
result of fail;
if a subsequent sufficient
passes, or if all subsequent
required
modules pass, then the overall result is
pass.
The “
required
” control-flag means it isn't enough to
pass this one module to be allowed to run the command.
If no sufficient
lines return “pass
”,
then all required
modules listed are tried and all must
say “pass” before access is granted by PAM.
If any required
module fails, the remaining
required
modules are still tried
so that hackers won't know exactly which one failed, but it won't
matter if any of them pass.
A missing module acts like a “fail”, and the error is logged (via
the system logging daemon, usually
The order of the modules is significant.
If a prior syslog
).
If the line in the configuration file starts with a dash, the error isn't
logged.
This can be useful for modules that may not be present, for example, a
module for fingerprint authentication may not be present, but if it is,
it should be used.
To prevent authentication failure, such modules should be used with
sufficient
rather than required
, such as:
-auth sufficient pam_fingerprintd.so
required
module fails, and
a later sufficient
module passes, access
will be denied.
For example:
auth required pam_moduleA auth sufficient pam_moduleB auth required pam_moduleCWhat policy does this implement? It says access is allowed: if both modules A and B pass, or if both modules A and C pass. On the other hand, the policy implemented with:
auth sufficient pam_moduleB auth required pam_moduleA auth required pam_moduleCsays to allow access: if module B passes, or if modules A and C both pass.
But, what does pass mean exactly? Each PAM module examines information provided by the program requesting authentication (usually the user's ID and a supplied password), plus other information found elsewhere (often there are per-module configuration files found in
/etc/security
).
PAM then decides if the current user passes the authentication test
and meets the required account policies.
If so the module returns “pass”; otherwise it returns “fail”.
Actually PAM modules can return several different status values
and not simply pass or fail.
The control flag can say to do this if the
status is one thing, and to do that if the status is
something else.
In practice the older scheme of just pass and fail, with the
control-flag keywords of
You might occasionally see other control-flags listed in some configuration files. The “
sufficient
and
required
, is flexible enough for most policies,
and is commonly used.
You might occasionally see other control-flags listed in some configuration files. The “
pam
” man page and
PAM Administrator's Guide
describe everything that can go there in gory detail.
But for most policies, you only need to understand the
required
and sufficient
control-flags.
It is not specified what happens when the PAM config file for some
application is empty, or all of the (say) AUTH modules have been
commented out, or listed as
optional
.
By reading the
source for Linux PAM
(especially
pam_dispatch.c) and running some experiments,
I have determined that Linux PAM does the safe action: it fails in
these cases.
But system administrators should not rely on this undocumented
behavior.
Always have some required
(or
sufficient
) module for each type, even if only
pam_deny.so
or pam_permit.so
.
sufficient
module passes, or a
requisite
module fails.
In those two cases, the remaining modules are not run and PAM returns a
result immediately.
PAM Walk-through (II):
Back to our story!
Recall the PAM configuration file for
Note the
The
And what if you don't use the shadow suite, but something like LDAP instead? Then you just use a different module. This is the power of PAM: an easy way to change which authentication methods are used without re-writing all your applications, or changing the configuration of each application separately.
The explanation may be that (as mentioned above)
hwbrowser
above
also requires the common policy in system-auth
to pass.
The auth
and account
lines
(remember you can ignore the rest)
from the /etc/pam.d/system-auth
file look like this
(the default file on a Fedora 7 Linux system):
auth required pam_env.so
auth sufficient pam_unix.so nullok try_first_pass
auth requisite pam_succeed_if.so uid >= 500 quiet
auth required pam_deny.so
account required pam_unix.so
account sufficient pam_localuser.so
account sufficient pam_succeed_if.so uid < 500 quiet
account required pam_permit.so
Each of these modules should be looked up in the PAM reference
documentation.
That would tell you what each is for and what the
module arguments such as “nullok
”
mean.
Basically this (system default) policy authorizes a user to run
some command if the user provides a valid password.
(You've probably have seen this behavior when you try
any command with a similar access policy (hwbrowser
,
chfn
, and passwd
are some examples);
as root
you don't get asked a password to run
hwbrowser
, but as a regular user you must supply
a password to run it.)
Note the
requisite
control-flag.
This is the same as required
, except that if
the module fails no further modules are tried.
In other words requisite
is a “fail fast”
version of required
.
So this auth
section says access is permitted if
the user supplied a valid password, or is not a system user
(one with a UID less than 500 on Red Hat systems).
The
pam_unix.so
and pam_succeed_if.so
modules are interesting because they are used in two different
contexts, account
and auth
!
The explanation is that modules have different functions
depending from which context it is called.
Take the pam_unix.so
module for example:
In the auth
context this
module checks the user's name and password,
but in the account
context this same module checks
the account's aging and expiration information instead.
Many modules have multiple purposes, depending on the context.
When reading the documentation for some module, be sure to check
to refer to the part that describes the purpose of the module,
in the context that the module is used!
And what if you don't use the shadow suite, but something like LDAP instead? Then you just use a different module. This is the power of PAM: an easy way to change which authentication methods are used without re-writing all your applications, or changing the configuration of each application separately.
The
All these modules are nice, but the overlap in functionality means there are many, slightly different ways to use the same authentication service (single sign-on). To use LDAP for example, you could:
The pam_unix.so
module (and similar modules on other
systems such as the Solaris 8 pam_pwdb.so
module)
use standard system calls to check users and passwords.
On modern systems these system calls can use different account
databases depending on settings in the /etc/nsswitch.conf
file.
So, to use (say) NIS you either use the
pam_nis.so
module (if one is available on your
system), or use pam_unix.so
and configure the
nsswitch.conf
entries for passwd
,
shadow
, and group
to use
NIS.
A recently developed module uses SSSD, a common
service for all remote authentication, that can cache credentials
for when the network is unavailable.
All these modules are nice, but the overlap in functionality means there are many, slightly different ways to use the same authentication service (single sign-on). To use LDAP for example, you could:
- Use the pam_ldap module.
- Use the pam_unix module and configure the name service switch to use LDAP.
- Use the pam_sssd module and configure SSSD to use LDAP.
- Use the pam_unix module, and configure the name service switch to use SSSD, and configure that to use LDAP.
- Use some LDAP library directly, and bypass PAM.
- Use standard system calls (bypassing PAM), and configure the name service switch to use LDAP (or to use SSSD, which in turn uses LDAP).
account
section is interesting.
The first line says the user must have a valid (unexpired)
user account.
The second says it is sufficient if that user is listed in the
local /etc/passwd
and /etc/shadow
files,
while the third line says it is sufficient if you are a system
account (that is, an account with a UID of less than 500).
But the second through fourth account
lines don't
seem to do anything!
You can comment out those three lines and the result is apparently
the same policy.
(What policy do you think they were trying to implement
here?)
The explanation may be that (as mentioned above)
pam_unix
uses the standard
system calls to check for users and passwords, and those system
calls may not be checking any local files.
So the intended policy is probably to allow a user
if it is a standard system account, or
if it is a valid account in the local /etc/passwd
and /etc/shadow
files, or if it is a valid account
in the standard (usually networked) database.
(What changes would you make to correctly implement this
policy?)
Making Policy Changes:
While you could restrict the use of
Suppose you decide to change the
(Note that just commenting out the second and third
Other PAM changes are simpler. To modify “
When changing passwords the “
If you look up the
hwbrowser
to root
by changing the permissions on the program
(or change group membership or by adding ACLs),
this is not a good way to do control access.
Such changes get lost when updating commands, are hard to remember,
and do not log violations.
So you should use PAM to enforce your policies whenever possible.
Suppose you decide to change the
hwbrowser
configuration
so that only root
is allowed to run the command.
Take another look at the hwbrowser
configuration file's
auth
lines:
auth sufficient pam_rootok.so
auth sufficient pam_timestamp.so
auth required pam_stack.so service=system-auth
Now what would happen if you changed “sufficient
”
to “required
”?
Now root
access would be required.
However PAM would still try pam_timestamp
and run through the modules listed in
the “system-auth
” file.
If those lines were commented out as well as changing
“sufficient
” to “required
”
in the first line, then you get the behavior you want:
only root
can run the command.
To comment out a module means adding a “#
”
in the front of the line listing that module.
(Note that just commenting out the second and third
auth
lines will work since
if there are no required
modules, the failure of
all the sufficient
modules will cause PAM to
refuse authorization.
But this is undocumented PAM behavior, so I suggest you change
sufficient
to required
as well as
commenting out the second and third lines.)
Other PAM changes are simpler. To modify “
su
” to use the “wheel
”
group membership for sufficient or required permission to run
a command, examine the /etc/pam.d/su
file.
To change the password minimum length look at the
/etc/pam.d/passwd
file,
only in that case you will only see references to the
system-auth
file.
So go look at that file again.
If you want a different policy for some command then don't
use the pam-stack
module in that command's
PAM configuration file.
Many system administrators mistakenly think they can set minimum
password length in other configuration files such as
/etc/default/login
or /etc/login.defs
,
but changes to those files may or may not have any effect!
It depends on your version of Unix or Linux used, as well as the
version of the passwd
command on your system
and which database you are using (e.g., shadow suite,
NIS, etc.).
You should always set the password policy using PAM.
If you do set a minimum length in some other file(s) and
those settings are used on your system, then a
candidate password must meet the criteria from both the file(s)
and from PAM.
So you might as well only set your policy with PAM.
password
”
modules are used to determine password policies,
such as which database of passwords to use (e.g.,
/etc/shadow
, RADIUS, LDAP, etc.) and
password constraints (e.g., minimal length, types of characters
required such as a mix of letters and digits, etc.).
The “auth
” modules are still used to make sure the
current user has permission to change the password, but it is
the password
modules that determine acceptable passwords.
If you look up the
password
modules found in
the system-auth
file
in the on-line PAM reference, you will quickly discover
that only the “cracklib
” module controls password
constraints such as minimum password length.
This is done in a complex way so you really need to read
that module's description and the provided examples carefully.
(See some notes regarding pam_cracklib
below.)
Not all systems provide the exact same PAM modules, but usually
there are similar ones to the PAM_Linux distribution.
If your system doesn't seem to have
pam_cracklib
,
see if there is another module with similar functionality.
On Solaris 10 for example you can use pam_authtok_check
instead.
Some Security Issues of Policy Changes:
You need to be careful!
Modules with the same name may work differently on different
systems.
Always check the documentation and verify your PAM configuration
files implement the policies you think they do.
The default policies (the ones controlled by PAM anyway) aren't always the most secure, and you should carefully review them on any upgraded system as part of the post-install process. A larger organization can have standardized PAM configurations that can be applied as a patch or RPM (or similar) package.
The Linux
Solaris 10 no longer uses
Some versions of
The default policies (the ones controlled by PAM anyway) aren't always the most secure, and you should carefully review them on any upgraded system as part of the post-install process. A larger organization can have standardized PAM configurations that can be applied as a patch or RPM (or similar) package.
The Linux
pam_unix
module in a PAM configuration
file with the context (module type) of “account” checks
that an account exists and isn't expired.
It does not check if an account has
been locked or has an invalid shell!
(Apparently pam_unix
assumes the auth
component will fail if the account is locked.)
This means that users using SSH keys to log in
will be allowed to do so even if you lock the account with
the “passwd -l
” command (since
sshd
doesn't use the PAM auth modules in this
case)!
Setting an invalid shell is checked with the Linux
pam_shells
module, but that is usually included
only in the configuration files for FTP
servers.
(I've been locking users out this way for years and I've
never realized the danger.
Now I always add pam_shells
in the account
part of my PAM configuration (as required
),
and lock accounts by specifying an invalid shell such as
/bin/false
, for login
,
sshd
, and other remote access services.)
Solaris 10 no longer uses
pam_unix
and has
replaced it with other modules that each do part of what
pam_unix
used to do.
The new pam_unix_account
module does check
for locked accounts.
Some versions of
sshd
do check for locked accounts,
but only when configured to not use PAM.
When configured to use PAM, and sshd
uses keys
to authenticate the user, sshd
apparently only uses
the PAM account
and session
modules and
not the auth
modules.
While Linux PAM doesn’t contain any(!) account
modules
that can check for locked accounts, you may be able to find one you
can use from non-standard PAM modules found on the Internet, or
create one yourself.
(Note that not all *nix systems have this security bug.)
Under the Hood of PAM — A Programmers Perspective:
A program written to use the PAM library calls a series of
functions that in turn invoke the functioned defined in
various PAM modules.
A typical application makes the following function calls to the
PAM library:
If the service name isn't obvious and you can't find it in the program's documentation (or don't trust that) you can determine this name yourself, by checking the string passed as the first argument to the
Here's an example on Linux to determine the service name of the
So a PAM program starts.
The correct configuration file is found and read.
The program then calls
... pam_start(...); Initializes the PAM library ... if ( ! pam_authenticate(...) ) Autenticates using "auth" modules error_exit(); ... if ( ! pam-acct_mgmt(...) ) Checks for a valid, unexpired account and verifies access restrictions with "account" modules error_exit(); ... pam_setcred(...) Sets extra credentials, e.g. a Kerberos ticket ... pam_open_session(...); Sets up the session with "session" modules do_stuff(); pam_close_session(...); Tear-down session using the "session" modules pam_end(...);The only part of this a system administrator needs to understand is that a program that uses PAM will make function calls to the PAM library, and these in turn invoke functions in the related PAM modules.
PAM Service Names
Thepam_start
function is passed a service name
as the first argument.
This name is nearly always the same as the program's name.
The PAM configuration files in /etc/pam.d
are named
by this service name.
So if the application or server daemon has a different filename, an
administrator won't know which PAM configuration file it uses!
If the service name isn't obvious and you can't find it in the program's documentation (or don't trust that) you can determine this name yourself, by checking the string passed as the first argument to the
pam_start
function.
If you don't have access to the source code you can use tracing
and debugging tools to determine the service name.
Here's an example on Linux to determine the service name of the
vlock
application:
$ ltrace /usr/bin/vlock 2>&1 1>/dev/null </dev/null |grep 'pam_start' pam_start(0x8049ac0, 0x804a4c0, 0x804a210, 0xbf82adcc, 0x4554005a) = 0 ^^^^^^^--> this is the RAM address of the service name $ gdb /usr/bin/vlock (gdb) printf "%s\n",0x8049ac0 vlock (gdb) quit
pam_authenticate()
which in turn calls a specific function
(pam_sm_authenticate()
) in each of the
“auth” modules listed in the configuration file,
in order.
The results are combined according to the control-flags
for those modules.
Finally pam_authenticate()
returns a result
back to the program.
The other PAM functions used by the program work the same
way.
If some “auth” module wants to ask the user to re-enter
a password, the module invokes a function in the application
to prompt the user and to get the input.
This is called a “call-back” function.
Some Notes Regarding pam_cracklib
:
The
If the score is less than the value for
Suppose
You don't have to use such a complex test if you don't want to. If you set the credit for each type of character to zero then only the length of the password will matter.
Setting the credit for (say) digits to a number greater than
one or to a negative value allows more complex passwords to
be required.
Say you set
A negative credit number “-N” means the same as a positive number except that you must have at least that many or the candidate password will “fail” regardless of its overall score. For example, setting:
Another cracklib setting is “
To make the system remember old passwords, you need to add an argument of “
Cracklib has a number of options that can be used to support different policies, such as
cracklib
PAM module documentation
uses the term minimum length or “minlen
”,
but it's really a “score” of complexness and not just the
length of a password.
This score for a candidate password is computed as follows when
using the default settings:
- Add one for each character in the password regardless of the type of the character.
- Add one to that for each lowercase letter used, up to a maximum of
lcredit
. - Add one to that for each uppercase letter used, up to a maximum of
ucredit
. - Add one to that for each digit used, up to a maximum of
dcredit
. - Add one to that for each symbol (not a letter or digit) used, up to a maximum of
ocredit
.
lcredit
, ucredit
,
dcredit
, and ocredit
are 1
(one).
If the score is less than the value for
minlen
the password is not acceptable (it “fails” the module's
“simplicity” test.)
Here's an example:
Suppose
minlen=8
is used with
pam_cracklib
.
If the user tries to set a password of “foobar
”
then cracklib will not allow it.
The score for this password is 6 + 1 = 7,
but the minimum allowed score is 8.
The score for “Foobar
” would be
6 + 1 + 1 = 8, and that would
“pass” this test.
The score for “aB1$
” would be
4 + 1 + 1 + 1 + 1 = 8.
You don't have to use such a complex test if you don't want to. If you set the credit for each type of character to zero then only the length of the password will matter.
Besides this strength/complexity test for a minimum “length”,
pam_cracklib
has a hardcoded minimum number of bytes
(characters) in the password of 4.
(Perhaps because the U.S. government specifies that as a minimum
length, in
FIPS-112.)
In addition the system password changing code often defines a
minimum length (number of characters, not minimum strength), whether
or not you use pam_cracklib
.
For Solaris a length is defined in
/etc/default/passwd
.
For Linux (when using the “shadow” suite) it is defined
in /etc/login.defs
.
dcredit=3
.
Then you will add zero to the score if no digits
are in the candidate password, add one if there is one digit, two
if there is two digits, and three if there is three or more
digits.
Basically the value is a maximum amount of extra credit you can
have by using that type of character in your passwords.
Setting the four credit values to 0 (zero) means only the length
of the password matters.
A negative credit number “-N” means the same as a positive number except that you must have at least that many or the candidate password will “fail” regardless of its overall score. For example, setting:
password required pam_cracklib.so dcredit=-1 ucredit=-1 minlen=8(and leaving
lcredit
and ocredit
at the
default value of 1) will require all passwords to have at least one
digit and at least one uppercase letter.
So “Foobar” will fail even though its score is 8
(6 + 1 + 1).
But “Fo0bar” (note the zero) will pass this test (its
score is 6+1+1+1=9, and it has the required 1 digit).
Another cracklib setting is “
diffok
”.
It determines how many characters must be different from your old,
saved password(s).
Suppose you set that to 1.
Then for a candidate password of “Foobar”
cracklib with try every variation with one letter different
to see if that matches your old password.
That is it tries:
Aoobar Boobar Coobar ... Zoobar aoobar boobar ... FAobar FBobar FCobar ... FoAbar FoBbar FoCbar ... ...For each one it computes the encrypted (hashed) password and compares that with the old password hash(s) saved in
/etc/shadow
and /etc/security/opasswd
.
Setting diffok
too high can really slow down password
changing because of the many variations that must be tried.
To make the system remember old passwords, you need to add an argument of “
remember=N
” to the
pam_unix.so
module (the one for the
“password
” context, not the one for
“auth
”.)
Try adding “remember=3
” and then change your
password a few times.
Then examine the /etc/security/opasswd
file.
Cracklib has a number of options that can be used to support different policies, such as
reject_username
, maxrepeat
,
and minclass
.
See the Linux PAM documentation for cracklib for a list of all options
you can use.
PAM Advanced Syntax:
As mentioned previously PAM modules are not limited to returning
only pass or fail.
Linux PAM defines over 30 different return values that a module
might return (listed below).
Instead of one of the original control flags (required, sufficient,
requisite, and optional) you can use the new syntax with
square braces, like this:
type [value=action value=action ...] module optionsYou can list any one of seven different actions for each possible return type. That's a lot of flexibility! The
value
is one of the following
PAM module return values:
- ABORT
- Critical error, immediate abort,
- ACCT_EXPIRED
- User account has expired,
- AUTHINFO_UNAVAIL
- Authentication service cannot retrieve authentication info,
- AUTHTOK_DISABLE_AGING
- Authentication token aging disabled,
- AUTHTOK_ERR
- Authentication token manipulation error,
- AUTHTOK_EXPIRED
- Authentication token expired,
- AUTHTOK_LOCK_BUSY
- Authentication token lock busy,
- AUTHTOK_RECOVERY_ERR
- Authentication information cannot be recovered,
- AUTH_ERR
- Authentication failure,
- BUF_ERR
- Memory buffer error,
- CONV_ERR
- Conversation failure,
- CRED_ERR
- Failure setting user credentials,
- CRED_EXPIRED
- User credentials expired,
- CRED_INSUFFICIENT
- Insufficient credentials to access authentication data,
- CRED_UNAVAIL
- Authentication service cannot retrieve user credentials,
- IGNORE
- The return value should be ignored by PAM dispatch,
- INCOMPLETE
- Please call this function again to complete authentication stack; before calling again, verify that conversation is completed,
- MAXTRIES
- Have exhausted maximum number of retries for service,
- MODULE_UNKNOWN
- Module is unknown,
- NEW_AUTHTOK_REQD
- Authentication token is no longer valid; a new one required,
- NO_MODULE_DATA
- No module specific data is present,
- OPEN_ERR
- Failed to load module,
- PERM_DENIED
- Permission denied,
- SERVICE_ERR
- Error in service module,
- SESSION_ERR
- Cannot make/remove an entry for the specified session,
- SUCCESS
- Success,
- SYMBOL_ERR
- Symbol not found,
- SYSTEM_ERR
- System error,
- TRY_AGAIN
- Failed preliminary check by password service,
- USER_UNKNOWN
- User not known to the underlying authentication module,
- default
- All return values not explicitly listed.
action
says how to combine this return
value for the module in the overall pass or fail
value that is returned to the application for the whole
stack.
It is one of:
- ok
- This tells PAM that the administrator thinks this return code
should contribute directly to the return code of the full stack
of modules.
In other words, if the state of the stack so far would lead to
a return of SUCCESS, the module's return code will override
this value.
If the former state of the stack holds some value that is
indicative of a modules failure, this “
ok
” value will not be used to override that value. (This is essentially the same as the old “required” flag when the module returns SUCCESS, and is indeed often used as “[success=ok...]
”.) - done
- Equivalent to ok with the side effect of terminating the module stack and PAM immediately returning to the application. (Similar to “sufficient”.)
- bad
- This action indicates that the return code should be thought of
as indicative of the module failing.
If this module is the first in the stack to fail, its status
value will be used for that of the whole stack.
(This is similar to the “required” flag when the module did
not return SUCCSSS.
It is often used as “
[... default=bad]
”.) - die
- Equivalent to bad with the side effect of terminating the module stack and PAM immediately returning to the application. (Similar to “requisite”.)
- ignore
- The module's return status will not contribute to the return code the application obtains. (Similar to “optional”.)
- reset
- Clear all memory of the state of the stack and start again with the next stacked module.
- n
- (An unsigned integer) Skip the next n modules in the stack. (This provides a primitive form of if ... then control flow.)
[...]
syntax:
- required
-
[success=ok new_authtok_reqd=ok ignore=ignore default=bad]
- requisite
-
[success=ok new_authtok_reqd=ok ignore=ignore default=die]
- sufficient
-
[success=done new_authtok_reqd=done default=ignore]
- optional
-
[success=ok new_authtok_reqd=ok default=ignore]
Summary:
PAM is powerful but difficult, which is why it is so important to
understand how to use it correctly to enforce security policies.
By controlling which modules are used, their options, the order of
modules, and which control-flags are used, you have the flexibility
to enforce any security policy you can imagine.
You can use the more complex configuration file syntax for even more
precise control.
(You can read about that if you want to go beyond the simple
syntax discussed in this tutorial.)
You can even write your own modules (or you can hire someone to
do so).
Defining, implementing, and auditing security policies is a common and vital task of the Unix/Linux system administrator. You should become familiar with the standard PAM modules on your system so you will have an idea of the sort of policy you can use PAM to enforce.
Defining, implementing, and auditing security policies is a common and vital task of the Unix/Linux system administrator. You should become familiar with the standard PAM modules on your system so you will have an idea of the sort of policy you can use PAM to enforce.
No comments:
Post a Comment