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.
- 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 |
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.