Pluggable Authentication Module (PAM)

Please note these notes are based on CentOS/RHEL 5

– What is PAM ?

The glue between authentication methods [eg one-time pwds, kerberos, smart cards] and applications requiring authentication services [eg. ftpd, sshd, imapd] etc
It is another layer on 1st-Level defense in Linux.

– The 4 directories we are concerned with:

/lib/libpam*      [3 files & 3 symlinks]     PAM System Libs
/lib/security/.so [60 files]    PAM Loadable Modules [PLM]
/etc/pam.d/       [94 files]
/etc/security/    [ 16 .conf files and some other files/dirs]

 ———————————————— ———————————————— ———————————————–

 /etc/pam.d/  – The PAM Config Files

– All configuration files of PAM are located in /etc/pam.d.
– All are ASCI text files. That means you can open it in VIM, EMACs etc.
– Format of files:

Inside all files, you will see below kind of format.

     module-type    control-flag      module-path            Arguments
    auth                  required            pam_securetty.so           debug

Default module-path is /lib/security so no path is mentioned above.           

  1. A.    module-type

i.    auth : Serves 2 functions – first authenticating users to be who they claim to be, and second allowing other privileges to be granted to the users
ii.    account: Provides account-management options not related to authentication. Typically used to restrict based on factors such as origin
      [eg only non-root users allow remote login, or time of day]
iii.    password: Called only when updating the auth token associated with the User
iv.   session: Tasks to be performed before/after the user is allowed access.

      B.    control-flag

 flag                        Description
required      Compulsory to succeed. If it does not, executing of other modules of the same module-type still continues
requisite      Similar to required. Compulsory to succeed. However, in the case of failure, control is passed straight back to the app,
                   rather than other modules being executed
sufficient     If a module with the control flag sufficient succeeds, no further modules of the same module-type are called and
                   the entire module-type succeeds PROVIDED all other modules before it have succeeded – in the same module type, of course
optional       Success of this module is optional, success or failure is irrelevant

          

        C.    module-path
            Default module-path is /lib/security so no path is mentioned above.

        D.    Arguments

debug                     :           Log debug info using syslog
no_warn                  :           Suppress warning messages
use_first_pass          :           If a password has been previously entered, use it and do not prompt user another time
try_first_pass           :           Auth should be tried with the previously entered password. If a password was not entered or is invalid,
                                        the user is prompted for a password
expose_account       :           By default, PAM attempt to hide a/c info like user’s full name or default shell [a cracker could use this] This argument allows
                                        such info to be displayed, making for a more friendly login experience [eg “Pl enter your password, <UserName>), but
                                        should be used in a secure environment
nullok                     :           If you remove the ‘x’ in /etc/passwd, a user can login w/o a password. That is because of this. Remove nullok and it will not allow
retry=N                  :          The default number of times this module will request a new password (for strength-checking) from the user is 1. Using this argument this can be
                                        increased to N This happens when you are changing the passwd from the CLI and not when you are logging in, obviously!
type=                     :         The default action is for the module to use the following prompts when requesting passwords:
                                       “New UNIX password: ” and “Retype UNIX password: ”. Using this option you can replace the word UNIX with XXX

1.   Authentication by PAM:

When we log in, what does /bin/login binary do?

1. Accepts Username & Password
2. Loads the 2 PAM libs into the RAM

Please check

 $ ldd /bin/login
        linux-gate.so.1 =>  (0x00d12000)
        libcrypt.so.1 => /lib/libcrypt.so.1 (0x04b3f000)
         libpam.so.0 => /lib/libpam.so.0 (0x04147000)
          libpam_misc.so.0 => /lib/libpam_misc.so.0 (0x009d3000)
        libaudit.so.0 => /lib/libaudit.so.0 (0x00cf6000)
        ...

3. Hands over this Username & Password to these libs
4. Then instructs the libs to loads login’s PAM config file –/etc/pam.d/login
[The PAM config file of the login* service which is by the same name i.e. /etc/pam.d/login]
5. Hands over control to the PAM libs
6. PAM System Libs start processing the file /etc/pam.d/login
7. libpam loads and unloads the Modules as given in the config (/etc/pam.d/login) file

Inside of /etc/pam.d/login 

auth [user_unknown=ignore success=ok ignore=ignore default=bad] pam_securetty.so
auth          include           system-auth
account       required         pam_nologin.so
account       include           system-auth
password      include           system-auth
# pam_selinux.so close should be the first session rule
session       required          pam_selinux.so close
session        include          system-auth
session       required          pam_loginuid.so
session       optional          pam_console.so

# pam_selinux.so open should only be followed by sessions to be executed in the user context
session       required          pam_selinux.so open
session       optional          pam_keyinit.so force revoke
session       sufficient       /lib/security/pam_lsass.so

8. It checks first line of /etc/pam.d/login

auth [user_unknown=ignore success=ok ignore=ignore default=bad] pam_securetty.so

I will simplify it to understand

auth      required            pam_securetty.so

Here, module-type is “auth”, control flag is “required” that means if this case fails then, user won’t be able to login. Here module-argument is pam_security.so. pam_security.so reads “/etc/securetty”.

“/etc/securetty” is ASCII Text file. List of Terminals is mentioned here.

vc/1
vc/2
vc/3
vc/4
tty1
tty2
tty3
tty4
…

So if user is attempting login from any of the terminal listed in “/etc/securetty”, User is allowed to login.
For eg. If I want to disable login for tty4 then, simply I will delete “tty4” from /etc/securetty.

9. After Success on first line, it will go to second line

auth       include           system-auth

Here control-flag is “include” and argument is “system-auth” that means, it includes /etc/pam.d/system-auth file and credentials will be passed to it.

Inside of /etc/pam.d/system-auth

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

password    requisite     pam_cracklib.so try_first_pass retry=3
password    sufficient    pam_unix.so md5 shadow nullok try_first_pass use_authtok
password    required      pam_deny.so

session     required      pam_limits.so
session     required      pam_unix.so

a. First line will get challenge.

auth        required      pam_env.so

“pam_env.so” read “/etc/security/pam_env.conf” file. Default variables can be set in this file.

For eg. If I want Variable “MYNAME” to be set to “NEELESH” after login then I can enter below line in /etc/security/pam_env.conf

MYNAME          DEFAULT=local       OVERRIDE=NEELESH

Or MYNAME      DEFAULT=NEELESH

Now log in to the system and try “echo $MYNAME”

b. Credentials are passed on to second line

auth                  sufficient           pam_unix.so      nullok try_first_pass

Module “pam_unix.so” does actual work of Authentication.

Just try login to the server, you will get below entry in /var/log/secure or /var/log/auth
login: pam_unix(login:session): session opened for user root by LOGIN(uid=0)
Or if login failure happens then you will find below entry in same log files:
pam_unix(login:auth): authentication failure;
In both the entries, you will find “pam_unix” common. It is there because it does the actual authentication work.

It checks Username & Password from /etc/passwd & /etc/shadow and if both are ok then goes to next line.

In above line
“nullok”:  username with No password can also login. If you remove “nullok”, then it won’t allow blank passwords.
“try_first_pass“ : If the Authentication fails or no password has been entered, the user is prompted for another password. If you use “use_first_pass” instead of “try_first_pass” then user is not prompted for another password.
Control Flag for this line is “sufficient”, that means if pam_unix.so challenge gets success result then, it will allow to login and it will not go to next lines from “auth” module type.

Here Authentication will be successful but still Authorization is yet to be processed.

c. If credentials provided are incorrect then, pam_unix.so challenge will fail and then credentials will pass to next line.

auth        requisite     pam_succeed_if.so uid >= 500 quiet

This line is added by authconfig on Fedora and RHEL systems. It is not much useful (but harmless) unless there are additional network-based authentication modules after them. There can be pam_ldap, pam_sss, pam_krb5 etc. These provide authentication against network servers and it is common requirement that the system accounts (uid<500) should not be authenticated against the network servers.

To understand this you will need to comment next line of pam_deny.so.

After commenting it just try to login with any user other than root, and uid must be greater than or equal to 500 with any words or character as password. It will allow that user. But same time it won’t allow “root” to login. If you want “root” also should be login with any password, then just change “uid >= 0”.

 d.  auth        required      pam_deny.so

pam_deny is used to deny access.
Here Authentication process gets ended.

 

2.   User Account Validation by PAM

10. After “system-auth” next line of /etc/pam.d/login will get processed.

account    required     pam_nologin.so

Module-type is “account” & control flag is “required”. That means this challenge should be Pass.
“pam_nologin.so” checks /etc/nologin, if it exists and user is not root then user is not permitted to login.
If /etc/nologin is not there then it process to next line.

11. account    include      system-auth

Here again “system-auth” file is included but the module-type is different. Module-type is “account”.
So it will go to first line of “account” section in “system-auth” file. i.e.
account     required      pam_unix.so

It again calls pam_unix.so module.  Here it checks weather the account is Active or not.

Try this ->

– Create a “test” user.
– In /etc/shadow change add 2 in 8th field.
test:$1$BHebdtAA$ipp6LuWWQvYqloQGsDHIf/:15026:0:99999:7::2:

This means Account is expired

– Now try login with test account. It will show “Your account is expired.”
– Comment “account     required      pam_unix.so” in /etc/pam.d/system-auth
– Now try login with same account. You will be able to login.

12. If account is active, then above challenge will get pass and next line will get process.

account     sufficient    pam_localuser.so

 It will check if account is local or remote. If it is local, then it will not run next challenges from “account” module-type. This module reads /etc/passwd file to check local account.

13. pam_permit

account     required      pam_permit.so

This line will only allow access. Pam_permit.so should be use very carefully.

3. Validating Session:

In /etc/pam.d/login, minimum below line is required for validating session.

session    include      system-auth

It include system-auth here. And in system-auth file below lines are required:

session     required      pam_limits.so
session     required      pam_unix.so

pam_limits.so applies limits from /etc/security/limits.conf.
pam_unix.so logs the username and the service type to /var/log/messages at the beginning and end of each session

4.   Updating “password”:

When user or root changes his or users password, Module-type “password” comes into picture.
When a user change password, it ask for current password first. After validating current password, it ask for New Password.

a. When user enter New Password it goes to

password    requisite     pam_cracklib.so try_first_pass retry=3

pam_cracklib.so checks strength of password. And “retry=3” will give only 3 chance to type New Password.
After 3 chance it will get automatically exit, throwing error on screen.

b. After giving proper new password, it will process following line

 password  sufficient pam_unix.so  md5  shadow  nullok  try_first_pass  use_authtok

———————————————— ———————————————— ———————————————— ————————————————

Why “root” never ask password when he does “su – <username>” ?

 Login as root
 $ su foo

root is never asked for a password when she su’s to another user, Why?

Ans: Because you are root?    Wrong!

$ ldd `which su`
libpam.so.0 => /lib/libpam.so.0 (0x40034000)  <------- su* is PAM-aware
libpam_misc.so.0 => /lib/libpam_misc.so.0 (0x4003c000)
.....

The su* binary is PAM-aware!
Hence su* has to have a PAM config file in /etc/pam.d/ to consult for authentication.
Now, the config file name is the same as the service name [su*] hence su* consults this file /etc/pam.d/su

 #%PAM-1.0
auth       sufficient          pam_rootok.so
# Uncomment the following line to implicitly trust users in the "wheel" group.
#auth       sufficient        pam_wheel.so trust use_uid
.......
.......

Now try this:

   * Change “sufficient” in Line 1 to “required” or comment that line. 

Login as root
# su - foo

And u will be asked for the password even if you are root.

Neelesh Gurjar has written 122 articles

Leave a Reply