Security/Tizen 3.X Key Manager PAM integration
The key used for database encryption is protected with token provided by the user. Key-Manager must receive following events:
- user login - event should provide UID and token to generate the database key ("unlock the DB");
- user logout - event should provide UID to remove the database key ("lock the DB");
- user token change - event should provide UID and both old & new tokens to re-encrypt the database key;
- user account removal - to remove the user database;
High Level Design
Comparison with Tizen 2.X
Tizen 3.0 does not provide security-server like service for password management, which has been used previously to notify the Key-Manager. New mechanism to notify the Key-Manager must be provided. Candidates are: TLM (tiny login manager) and PAM. Both provide comfortable mechanism for adding new functionalities using .so plugins. Key-Manager will receive events from PAM, because TLM does not provide information on user token change. PAM provides all required events, but also requires additional configuration steps.
- linux encrypts the passwords: user token will not be accessible to the Key-Manager in the original form, only encrypted "shadow" form;
- pam_key_manager_plugin.so - plugin library that implements PAM interfaces (session, password) (proof of concept: );
- configuration changes to /etc/pam.d/:
- - session interface added to all login/logout events (i.e. from tlm, ssh etc.);
- - password interface changes (/etc/pam.d/system-auth):
- prevent pam_unix.so from terminating the procedure after successful password change;
- pam_key_manager_plugin called (with an arg "change_step=before") before pam_unix.so to save the previous password in the session (PAM_OLDAUTHTOK);
- pam_key_manager_plugin called (with an arg "change_step=after") after successful pam_unix.so password change - it has old token in PAM_OLDAUTHTOK and new token -> can call Key Manager change password with both tokens.;
- pam_key_manager_plugin called with flag PAM_PRELIM_CHECK returns success immediately with PAM_SUCCESS;
- pam_key_manager_plugin configured in /etc/pam.d/ as optional - if no pam_key_manager_plugin present, PAM will not fail;
- possible problem if pam_key_manager_plugin configured as optional: if pam_key_manager_plugin fails internally, PAM will not honor the error code and continue changing password;
- PAM does not provide information on user removal. GUMD selected as user removal notification source - to provide key-manager hooks to GUMD.
- system & key-manager password desynchronization: in case of this very rare event, key-manager will remove it's database. Any way of providing recovery mechanism would require deep changes to PAM's pam_unix.so module.;
- The password change considerations above concern only local password change. If password is managed by LDAP or a new service to manage passwords is introduced, appropriate PAM config changes must be applied.
- gumd: when user is removed, PAM does not provide logout event, so if the database files were removed, key-manager would be left with open handles to the non-existing database files. Gumd hook should lock the database and then remove it via an API call.;
Automatic testing of the PAM & GUMD integration is difficult. It is possible to create testing applications that will interface with PAM and GUMD, but such apps would be bigger task to do than the actual solution - TODO. Testing can be done manually:
- do appropriate changes to the /etc/pam.d/system-auth (look into commit message: ) (changes mentioned above to be integrated with PAM default config).
- create new user, set up password, login via GUI or ssh, check if database is created:
- - gum-utils -a --username=testme --usertype=normal
- - passwd testme, setup the password
- - login as user testme
- - check the UID of user testme in /etc/passwd
- - check if database file exists in /opt/data/ckm for specified UID.
- - log in/log out a few times, check if no errors are generated from PAM and the plugin ("journalctl -f")
- change user password - success scenario
- - passwd testme, set up new password
- - log in/log out a few times, check if no errors come in the journal log
- change user password - fail scenario
- - log out the testme user (to ensure DB will be locked)
- - copy files /opt/data/ckm/*-<UID> into your location
- - passwd testme, change the password
- - bring the copied files back to /opt/data/ckm - this is to imitate the system & key-manager password desynchronization situation.
- - log in the testme user - logs should contain "key-manager and system password desynchronized,removing key-manager database for user" string.
- - to ensure database has been removed, logout and login again. The message mentioned above should not appear.
- remove user
- - gum-utils -d --uid=<UID> (do use gum only!)
- - check if user files have been removed from /opt/data/ckm directory.