PAM Integration
Motivation
For Yocto 1.1 we are working to ensure that PAM (Pluggable Authentication Module) support is consistent and enabled in recipes where it is applicable.
Common configure files
For convenience, list common configure files here:
common-auth
auth [success=1 default=ignore] pam_unix.so nullok_secure auth requisite pam_deny.so auth required pam_permit.so
common-account
account [success=1 new_authtok_reqd=done default=ignore] pam_unix.so account requisite pam_deny.so account required pam_permit.so
common-password
password [success=1 default=ignore] pam_unix.so obscure sha512 password requisite pam_deny.so password required pam_permit.so
common-session
session [default=1] pam_permit.so session requisite pam_deny.so session required pam_permit.so session required pam_unix.so
common-session-noninteractive
session [default=1] pam_permit.so session requisite pam_deny.so session required pam_permit.so session required pam_unix.so
Recipes with PAM support
The following recipes were identified to have PAM support (some already implemented) on 2011-06-27:
at
- Open issue:
- It can't be ran by a non-root user, error message is:
Can't signal atd (permission denied)
- Simple ways to verify 'at':
$ at now $ echo "$msg_to_print" >> /tmp/at_test $ < ctrl+D > $ cat /tmp/at_test # Verify if the message has been there
- /etc/pam.d/atd - not installed by default, copy it from source code and replace '@include' with appropriate 'module-type include':
auth required pam_env.so auth include common-auth account include common-account session include common-session-noninteractive session required pam_limits.so
- test pam plugins
- pam_env.so
modify /etc/pam.d/atd
auth required pam_env.so debug
modify /etc/security/pam_env.conf, add a test entry such as:
MYNAME DEFAULT="test-at"
log in /var/log/auth.log:
Jul 11 08:41:22 qemux86 atd[678]: pam_env(atd:setcred): pam_putenv("MYNAME=test-at")
- pam_limits.so
add line to /etc/security/limits.conf
root - nofile 3
'at' job failed, log in /var/log/auth.log:
Jul 11 08:49:42 qemux86 atd[699]: pam_env(atd:setcred): Unable to open config file: /etc/security/pam_env.conf: Too many open files
modify the line:
root - nofile 4
'at' job successed, log in /var/log/auth.log:
Jul 11 08:59:59 qemux86 atd[738]: pam_unix(atd:session): session opened for user root by (uid=0) Jul 11 08:59:59 qemux86 atd[738]: pam_unix(atd:session): session closed for user root
consolekit
Consolekit provides a pam module pam_ck_connector.so and not the package that use pam. Drop it.
cronie
- Open issue:
- Can't run 'crontab' command with non-root user, error message is:
You (test-pam) are not allowed to access to (crontab) because of pam configuration. Jul 12 02:36:14 qemux86 unix_chkpwd[768]: could not obtain user info (test-pam)
- /etc/pam.d/crond:
account required pam_access.so account include password-auth session required pam_loginuid.so session include password-auth auth include password-auth
- /etc/pam.d/password-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 type= password sufficient pam_unix.so sha512 shadow nullok try_first_pass use_authtok password required pam_deny.so session optional pam_keyinit.so revoke session required pam_limits.so -session optional pam_systemd.so session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid session required pam_unix.so
- test commands:
crontab -e # establish a crontab jobs and check if it works crontab -l # list crontab jobs for current user
- test pam plugins
Verified, test ways and the logs/results please refer to other packages:
- pam_env.so
- pam_access.so
- pam_unix.so
- pam_permit.so
- pam_keyinit.so
- pam_localuser.so
copy '/etc/passwd' to '/tmp/passwd' and delete the entry for 'root'; modify /etc/pam.d/password-auth:
account requisite pam_localuser.so file=/tmp/passwd debug
log in /var/log/auth.log:
Jul 12 02:58:51 qemux86 crontab: pam_localuser(crond:account): set filename to "/tmp/passwd" Jul 12 02:58:51 qemux86 crontab: pam_localuser(crond:account): checking "daemon:x:1:1:daemon:/usr/sbin:/bin/sh " Jul 12 02:58:51 qemux86 crontab: pam_localuser(crond:account): checking "bin:x:2:2:bin:/bin:/bin/sh " ...
- pam_succeed_if.so
account requisite pam_succeed_if.so uid > 500 debug
log in /var/log/auth.log:
Jul 12 03:14:14 qemux86 crontab: pam_succeed_if(crond:account): 'uid' resolves to '0' Jul 12 03:14:14 qemux86 crontab: pam_succeed_if(crond:account): requirement "uid > 500" not met by user "root"
- pam_loginuid.so
TBD
- pam_systemd.so
no this module
cups
dropbear
- For supporting pam in dropbear, we need two steps:
- Add configuration "--enable-pam"
- Add patches to open macro definition for supporting in option.h
--- a/ptions.h 2011-07-12 11:32:34.165333202 +0800 +++ b/options.h.new 2011-07-12 11:33:25.757332986 +0800 @@ -149,9 +149,9 @@ * but there's an interface via a PAM module - don't bother using it otherwise. * You can't enable both PASSWORD and PAM. */ -#define ENABLE_SVR_PASSWORD_AUTH +//#define ENABLE_SVR_PASSWORD_AUTH /* PAM requires ./configure --enable-pam */ -/*#define ENABLE_SVR_PAM_AUTH*/ +#define ENABLE_SVR_PAM_AUTH #define ENABLE_SVR_PUBKEY_AUTH /* Wether to ake public key options in authorized_keys file into account */
- Test result(dropbeat only support simple authentication, account and auth)
- Server(account)
- Test result(dropbeat only support simple authentication, account and auth)
(server ip:192.168.7.2) $touch /etc/pam.d/sshd account required pam_access.so $vi /etc/security/access.conf - : root : ALL
- Client
$ssh root@192.168.7.2 root@192.168.7.2's password: Permission denied, please try again. root@192.168.7.2's password: Permission denied, please try again. root@192.168.7.2's password: Permission denied (publickey,password).
- Server(auth)
$vi /etc/pam.d/sshd auth include common-auth $vi /etc/pam.d/common-auth #auth [success=1 default=ignore] pam_unix.so nullok_secure auth [success=0 default=ignore] pam_unix.so debug
- Client
$ssh root@192.168.7.2 root@192.168.7.2's password: Permission denied, please try again. root@192.168.7.2's password: Permission denied, please try again. root@192.168.7.2's password: Permission denied (publickey,password).
gnome-keyring
- gnome-keyring can't call configuration file like "/etc/pam.d/gnome-keyring" because it is called by other program like "gnome-screensave" and "gdm". If we want test "pam_gnome_keyring.so", we need write .bb files to cross-compile gnome-screensave or gdm.
openssh
- Absent configuration /etc/pam.d/sshd, we need to add patches. After adding this file, it can support pam function through simple test.
- Test Result
- Configuration of sshd
auth include common-auth account required pam_nologin.so account include common-account password include common-password session optional pam_keyinit.so force revoke session include common-session session required pam_loginuid.so
- auth include common-auth
$echo 'UsePAM no' >>/etc/ssh/sshd_config $vi /etc/ssh/sshd_config PermitEmptyPasswords yes
Other is as same as sudo
- log information
Jul 12 11:16:21 qemux86 sshd[650]: pam_unix(sshd:session): session opened for user test by (uid=0)
- account required pam_nologin.so --Server
$touch /etc/nologin
- Client
$ssh username@server-ip (can't log in)
- log information --Server
Jul 13 01:43:48 qemux86 sshd[672]: Accepted keyboard-interactive/pam for yxf from 192.168.7.1 port 59877 ssh2 Jul 13 01:43:48 qemux86 sshd[672]: fatal: PAM: pam_setcred(): Failure setting user credentia
- account include common-account --Server
$vi /etc/ssh/sshd_config PermitEmptyPasswords no Other is same as dropbear's account
- log information
Jul 13 02:11:24 qemux86 sshd[752]: Failed password for root from 192.168.7.1 port 53784 ssh2
polkit
screen
screen use pam to authenticate users during unlock terminal. Its configure file screen comes from Fedora and replace system-auth with common-auth
#%PAM-1.0 auth include common-auth
First start screen:
root@qemux86:/etc/pam.d# screen
it will show some information about screen, just press Space or Enter and it will give a screen terminal:
root@qemux86:/etc/pam.d#
then press "Ctrl+a x" will lock the screen terminal and show:
Screen used by root <root>. Password:
In another root terminal, clear the root's password:
password -d root
modify one line in common-auth
auth [success=1 default=ignore] pam_unix.so nullok_secure
with
auth [success=1 default=ignore] pam_unix.so debug
option nullok_secure will allow users who has blank password login, after remove it these users are not allowed to login.
Back to the screen terminal, press <Enter>(because root's password is blank now) will fail:
Screen used by root <root>. Password: Screen used by root <root>. Password:
then modify the line in common-auth with
auth [success=1 default=ignore] pam_unix.so nullok_secure debug
On the screen terminal press <Enter> again it unlock the terminal.
the log in /var/log/auth.log:
Jul 11 14:14:14 qemux86 screen: pam_unix(screen:auth): authentication failure; logname=root uid=0 euid=0 tty= ruser= rhost= user=root
shadow
- chage
/etc/pam.d/chage: need patch to replace system-auth to common-auth
#%PAM-1.0 auth sufficient pam_rootok.so account required pam_permit.so password include common-auth
- test pam_rootok.so
add the only option for pam_rootok.so
auth sufficient pam_rootok.so debug
run command chage as root:
root@qemux86:/etc/pam.d# chage -m 10 test
log info in /var/log/message shows pam_rootok.so return success:
Jul 12 06:55:18 qemux86 authpriv.debug chage[575]: pam_rootok(chage:auth): root check succeeded Jul 12 06:55:18 qemux86 authpriv.info chage[575]: changed password expiry for test
- test pam_unix.so
the content of common-auth are shown at section "Common configure files"
comment the pam_rootok.so line, because it will make pam return success:
#auth sufficient pam_rootok.so
and modify the pam_unix.so line in common-auth:
auth [success=1 default=ignore] pam_unix.so debug
run commands:
root@qemux86:/etc/pam.d# passwd -d root root@qemux86:/etc/pam.d# chfn -f testself test # test is a unprivileged user Password: chfn: PAM authentication failed
log in /var/log/message:
Jul 12 07:53:16 qemux86 authpriv.notice chfn[673]: pam_unix(chfn:auth): authentication failure; logname=root uid=0 euid=0 tty= ruser= rhost= user=root
- chfn
/etc/pam.d/chfn
auth sufficient pam_rootok.so auth include common-auth account include common-account session include common-session
add option debug to pam_rootok.so
auth sufficient pam_rootok.so debug
- pam_rootok.so
run command chfn as root:
root@qemux86:/etc/pam.d# chfn -f testyayay test
log info in /var/log/message shows pam_rootok.so return success:
Jul 12 07:22:59 qemux86 authpriv.debug chfn[638]: pam_rootok(chfn:auth): root check succeeded Jul 12 07:22:59 qemux86 authpriv.info chfn[638]: changed user 'test' information
- pam_unix.so
please refer to chage test steps.
- chgpasswd
/etc/pam.d/chgpasswd
#%PAM-1.0 auth sufficient pam_rootok.so account required pam_permit.so password include system-auth
test pam_rootok.so and pam_unix refer to test steps in chage
- chpasswd
/etc/pam.d/chpasswd
password include common-password
/etc/pam.d/chsh /etc/pam.d/groupadd /etc/pam.d/groupdel /etc/pam.d/groupmems /etc/pam.d/groupmod /etc/pam.d/login /etc/pam.d/newusers /etc/pam.d/passwd /etc/pam.d/su /etc/pam.d/useradd /etc/pam.d/userdel /etc/pam.d/usermod
sudo
- /etc/pam.d/sudo comes from Fedora, and replace system-auth with common-auth
#%PAM-1.0 auth include common-auth account include common-auth password include common-auth session required pam_keyinit.so revoke session required pam_limits.so
and content of common-auth has been show above.
- test pam plugins
- pam_unix.so
modify common-auth:
auth [success=1 default=ignore] pam_unix.so debug
then unpriviledge user can NOT run sudo with blank password
qemux86:~$ sudo rm /test Password: Sorry, try again. Password: Sorry, try again. Password: Sorry, try again. sudo: 3 incorrect password attempts qemux86:~$ sudo rm /test qemux86:~$
log in /var/log/auth.log:
Jul 8 16:39:04 qemux86 sudo: pam_unix(sudo:auth): authentication failure; logname=test-pam uid=0 euid=0 tty=/dev/pts/1 ruser=test-pam rhost= user=test-pam Jul 8 16:39:14 qemux86 sudo: test-pam : 3 incorrect password attempts ; TTY=pts/1 ; PWD=/home/test-pam ; USER=root ; COMMAND=/bin/rm /test Jul 8 16:39:31 qemux86 sudo: pam_warn(sudo:account): function=[pam_sm_acct_mgmt] service=[sudo] terminal=[/dev/pts/1] user=[test-pam] ruser=[test-pam] rhost=[<unknown>] Jul 8 16:39:31 qemux86 sudo: test-pam : TTY=pts/1 ; PWD=/home/test-pam ; USER=root ; COMMAND=/bin/rm /test
- pam_deny.so
mv line
auth requisite pam_deny.so
to the head of file, unprivilege user can NOT sudo any more:
qemux86:~$ sudo rm /test Sorry, try again. Sorry, try again. Sorry, try again. sudo: 3 incorrect password attempts qemux86:~$
log in /var/log/auth.log:
Jul 7 14:03:29 qemux86 sudo: test-pam : 3 incorrect password attempts ; TTY=pts/1 ; PWD=/home/test-pam ; USER=root ; COMMAND=/bin/rm /test
- pam_permit.so
comment this line
auth required pam_permit.so
sudo will fail without ask user to enter password:
qemux86:~$ sudo rm /test Sorry, try again. Sorry, try again. Sorry, try again. sudo: 3 incorrect password attempts qemux86:~$
log in /var/log/auth.log:
Jul 7 12:43:22 qemux86 sudo: test-pam : 3 incorrect password attempts ; TTY=pts/1 ; PWD=/home/test-pam ; USER=root ; COMMAND=/bin/rm -f /test
- pam_limits.so
add line to /etc/security/limits.conf
* - nofile 3
then sudo will fail:
qemux86:~$ sudo rm /test Inconsistency detected by ld.so: dl-deps.c: 622: _dl_map_object_deps: Assertion `nlist > 1' failed!
modify the line:
* - nofile 4 qemux86:~$ sudo rm /test qemux86:~$
log in /var/log/auth.log:
Jul 8 14:24:41 qemux86 sudo: pam_warn(sudo:account): function=[pam_sm_acct_mgmt] service=[sudo] terminal=[/dev/pts/1] user=[test-pam] ruser=[test-pam] rhost=[<unknown>] Jul 8 14:24:41 qemux86 sudo: test-pam : TTY=pts/1 ; PWD=/home/test-pam ; USER=root ; COMMAND=/bin/rm /test Jul 8 14:24:41 qemux86 sudo: pam_limits(sudo:session): reading settings from '/etc/security/limits.conf' Jul 8 14:24:41 qemux86 sudo: pam_limits(sudo:session): process_limit: processing - nofile 3 for DEFAULT Jul 8 14:24:50 qemux86 sudo: test-pam : TTY=pts/1 ; PWD=/home/test-pam ; USER=root ; COMMAND=/bin/rm /test Jul 8 14:24:50 qemux86 sudo: pam_limits(sudo:session): reading settings from '/etc/security/limits.conf' Jul 8 14:24:50 qemux86 sudo: pam_limits(sudo:session): process_limit: processing - nofile 4 for DEFAULT
- pam_keyinit
add option debug
session optional pam_keyinit.so revoke debug
log shows pam_keyinit was called:
Jul 7 14:13:39 qemux86 sudo: pam_warn(sudo:account): function=[pam_sm_acct_mgmt] service=[sudo] terminal=[/dev/pts/1] user=[test-pam] ruser=[test-pam] rhost=[<unknown>] Jul 7 14:13:39 qemux86 sudo: test-pam : TTY=pts/1 ; PWD=/home/test-pam ; USER=root ; COMMAND=/bin/rm /test Jul 7 14:13:39 qemux86 sudo: pam_keyinit(sudo:session): OPEN 1 Jul 7 14:13:39 qemux86 sudo: pam_keyinit(sudo:session): UID:0 [0] GID:0 [1000] Jul 7 14:13:39 qemux86 sudo: pam_keyinit(sudo:session): GET SESSION = 143761918 Jul 7 14:13:39 qemux86 sudo: pam_keyinit(sudo:session): GET SESSION = 669161571
according the source code pam_keyinit.c line 102 in function init_keyrings, the module return PAM_SUCCESS
util-linux
Three programs chfn chsh and login in util-linux will use libpam. Right now these programs are provided by package shadow. In util-linux.inc, EXTRA_OECONF has option "--disable-login-utils " which will disable to build them.
Drop it.
xserver-xf86-lite
Notes:
- mc: mc has remove package mcserv and dropped dependency on PAM already, but didn't remove checking security/pam_misc.h. Drop it. Official change log
- libcap: if pam exists, libcap will create a pam plugin pam_cap.so to add a new front end for the authentication function. Because it is not a application, remove it from list.
- libuser: pam is libuser's build dependency, so remove it too.
- The busybox login has a option to use pam, but we use tinylogin's login right now (tinylogin also provides the su command)
- gettext only has a example "hello-c++-kde" use pam under source code directory, and it doen't be compiled and only copied to destination. So omit gettext.
- sysvinit has a patch contrib/notify-pam-dead.patch for /sbin/init to use pam, but the whole contrib directory didn't take part in compilation. Drop it.
Identify upstream PAM patches to use
After checking the Fedora develop repository, the following packages may need patches(only libpam need to upgrade, other patches are pam related configure file but they are absent in poky):
- libpam: need update from current 1.1.3 to 1.1.4 Release Notes
- sudo: package sudo in Fedora provides /etc/pam.d/sudo and /etc/pam.d/sudo-i
- /etc/pam.d/sudo (Yocto use common-auth instead of system-auth)
#%PAM-1.0 auth include system-auth account include system-auth password include system-auth session optional pam_keyinit.so revoke session required pam_limits.so
- screen: check Fedora screen.pam
- util-linux: check Fedora source file util-linux-remote.pamd
- at: check Fedora util-linux-remote.pamd
- cups: check Fedora cups-1.1.16-system-auth.patch
- openssh: check Fedora sshd.pam
PAM Unit Tests
We use unit test cases provided by libpam itself, a subdirectory with name "xtests" under libpam source code.
On build machine run
bitbake libpam -c patch
to get the libpam source code Linux-PAM-1.1.4, and scp it to host(target) machine.
On the target machine under Linux-PAM-1.1.4, run
./configure make xtests
will get the test result of 28 unit test case. If you want to run sigle test case, go to subdirectory xtests and run (take tst-pam_time1 for example)
./run-xtests.sh . tst-pam_time1
Some unit test can NOT pass(15/28), they need some pam plugin libraies:
- tst-pam_access1
- tst-pam_access2
- tst-pam_access3
- tst-pam_access4
- the tst-pam_access test cases need pam_access.so, install package pam-plugin-access will make them pass the test
- tst-pam_authsucceed
- need pam_debug.so, install pam-plugin-debug to make it pass
- tst-pam_cracklib1
- tst-pam_cracklib2
- need /lib/security/pam_cracklib.so, need build cracklib, and then libpam will check it and create pam-plugin-cracklib
- need /usr/share/cracklib/pw_dict.pwd file, please run command on host machine:
create-cracklib-dict /usr/share/cracklib/cracklib-small
- tst-pam_dispatch1
- tst-pam_dispatch2
- tst-pam_dispatch3
- tst-pam_dispatch4
- need pam_debug.so, install pam-plugin-debug to make tst-pam_dispatch pass
- tst-pam_pwhistory1
- need /lib/security/pam_pwhistory.so, install pam-plugin-pwhistory to make it pass
- tst-pam_substack2
- need pam_debug.so, install pam-plugin-debug to make tst-pam_dispatch pass
- tst-pam_succeed_if1
- install pam-plugin-succeed-if to make it pass
- tst-pam_time1
- install pam-plugin-time to make it pass