------------------------------------------------------------------------------- Linux Kernel Keyring The "systemd-ask-password" uses this specifically during the boot process, to mount multiple encrypted disk partitions using the same password. It creates or can create keyrings for sessions, users, groups, processes, and threads. These can hold passwords and strings info in kernel memory, such that the information has limited access, and totally ephemeral. That is it is deleted on power shutdown, logout, or on a timeout. Essentially it can be used to securely store information accessible by future processes run by the user, but which will automatically be cleared on timeout, logout, or poweroff. This makes it ideal for the temporary 'caching' of passwords, and other details, that will be needed in the near future. For example passwords needed for editing (and later re-encoding) encrypted files. See "passwd_caching.txt" for reasons why you would want to do this. Other things may also use the keyring, but it's hard to find any real info. In someways it is a simplified, user-limited database with key expiry. A bit like a kernel memory version of a "redis" network database. Keyring has both API and CLI access. Recommend you try to read and understand: man -s7 keyrings Though that isn't strictly necessary. Overview and Recent Developments of Keyrings Subsystem - David Howells, Red Hat https://www.youtube.com/watch?v=KUCwiQZuasA The guide you are now reading is a bare bones reference summery of how you can use it from command line "keyctl", or using specific utilities like "systemd-ask-password" for various purposes. --- FYI: Ecryptfs-users (dir-level encryption, used by ubuntu home encryption) makes use of the kernal keyring. A very brief summery is in https://lwn.net/Articles/210502/ --- Example uses... * Save a user input password for repeat use over a period of time. For example while mounting multiple file system using same password. * Saving password for encrypted files that are being edited. That way the same password can be used to re-encrypt the file! The stored password is then available both before and after file editing. * Passwords set for use by cron jobs (See Persistant Keyrings below) Any information you may provide is welcome! ------------------------------------------------------------------------------- Using "systemd-ask-password" to do password caching You can get "systemd-ask-password" to ask a password and immediately store it on the users keyring (known as "@u"), for future use. For Example... systemd-ask-password --keyname=keyname --accept-cached "password:" password: ******* testing Next time it will not ask the user for the password, but use the cached one. systemd-ask-password --keyname=keyname --accept-cached password: testing The "systemd-ask-password" key times out after... 2 min 30 sec (or 150 sec) NOTE: This is NOT the default timeout of the linux kernel keyring! See... https://github.com/systemd/systemd/commit/e287086b8aa2558356af225a12d9bfea8e7d61ca PROBLEMS... * If the typed password was wrong, it also will get cached, until you somehow manually clear that password from the keyring. Arrrrgghhh.... For example using: keyctl purge user keyname * Using "--accept-cached" option for the purposes of editing an encrypted file (or other data) is not a good idea. If the user needs to type a new password, the accepted practise it to ask for it TWICE, to ensure it is typed correctly. If you use this option, the password will be cached the first time, and the second time will retrieve that same password from the cache and not from the user. In other words it is useless for requesting new passwords twice. In such situations you want it to retrieve the password if cached, perhaps even reset any timeout for the password, but you do not want the password to be cached, until it has been typed a second time and verified. Of course editing encrypted files is not the intended purpose of this command, which was for mounting multiple encrypted file systems during boot. And "systemd-ask-password" does not provide such an option. Solutions... * Provide ways to clear password when no longer needed, or its a bad password in your encryption handling command. * Application should only cache password after is verified. That is the password works, or if the two typed password match. Deleting the password if the user aborts the editing session will also do the job. * For a password reader, have an option, to get password from cache, without storing the password, until it can be verified. See "askpass_stars" script "--retrieve" option... https://antofthy.gitlab.io/software/#askpass_stars Also see password handling in "keepout"... https://antofthy.gitlab.io/software/#keepout Vim editing of ".kpt" files... https://antofthy.gitlab.io/info/crypto/vim_encryption.txt And what I currently use in... https://antofthy.gitlab.io/software/#encrypt.vim --- WARNING: If you use "systemd-ask-password" to cache a password into the same key as an existing password (using "--keyname=" but not "--accept-cached"), it will APPEND the password to the one already cached with a NULL character separator! The previous password is not deleted or over-written, unless you manually 'purge' it before hand. Again this is in line with its original purpose of mounting encrypted filesystems during boot, where multiple passwords may be needed for mounting multiple the filesystems. When retrieving (using "--accept-cached"), "systemd-ask-password" will only return the first password. The second password that was stored will be ignored, which is typically not what the user wanted. For example of this multi-password caching... > systemd-ask-password --keyname=keyname Password: foobar foobar > systemd-ask-password --keyname=keyname Password: xyzzy xyzzy > systemd-ask-password --keyname=keyname --accept-cached foobar > systemd-ask-password --keyname=keyname --accept-cached --multiple foobar xyzzy NOTE: the option "--no-output" can be used to prevent "systemd-ask-password" outputing the password, just testing if password if retrievable from the cache. Checking cache directly using "keyctl" (See below)... > keyctl request user keyname 1046921573 > keyctl print 1046921573 :hex:666f6f6261720078797a7a79 > keyctl pipe 1046921573 | od -c 0000000 f o o b a r \0 x y z z y 0000014 Note that "keyctl print" (see below) can, and in this case does, output the cached password in hexadecimal format due to the presence of the binary NULL character. The "keyctl pipe" command does not do this. ASIDE: The "askpass_stars" password reader, and "keepout" file encryption will purge the cache before caching a new password to avoid this problem. It will also use the "keyctl" 'pipe' method to retrieve passwords in case the user manages to use something "keyctl" considers to be a binary character (emoji?). ------------------------------------------------------------------------------- Linux Kernel Key Management Facility - "keyctl" The "keyctl" is a CLI command that will let you directly manipulate the kernal keyring cache you have access to. The same cache that "systemd-ask-password", "askpass_stars", "keepout", and vim encrypted file editing, uses. Documentation See: manpage for "keyctl" and https://www.kernel.org/doc/Documentation/security/keys.txt Working with the kernel keyring (ownership, permissions, etc) https://mjg59.dreamwidth.org/37333.html In kernel docs... https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/security Add/update a key # What systemd-ask-password does internally... # Except, this will overwrite an existing password echo -n 'data' | keyctl padd user {keyname} @u # pipe in a password 123456789 # The number returned is the ID for that keyname. keyctl timeout 123456789 150 # set a timeout of 2-1/2 minutes # ALT: password given as a CLI argument (warning this is insecure) # NOTE: This will overwrite an existing password keyctl add user {keyname} 'data' @u 123456789 # retrieval of the cached data keyctl request user {keyname} # find the specific key id 123456789 keyctl print 123456789 # warning output may be in hex format! data keyctl pipe 123456789; echo '' # will output password as is (no hex) data Listing contents of your keyring keyctl show 546372819 ... keyring: _ses 987654321 ... \_ keyring: _uid.1000 123456789 ... \_ user: {keyname} # The ID numbers are randomly generated with the keys keyctl list @u 123456789: --alswrv 1000 1000 user: {keyname} keyctl rlist @u # space separated list of the keys 123456789 keyctl request user {keyname} # find a specific key 123456789 # note: request2 & prequest2 will also create the key, if not present keyctl search @s user {keyname} # search for a user key "keyname" in session 123456789 keyctl print 123456789 # print the key (outputs in hex if binary!) data keyctl pipe 123456789; echo '' # print without the newline, raw data **** data keyctl read 123456789 # key in hex groups of 4 chars (8 hex-digits) 4 bytes of data in key: # summery of length of key (new addition) 64617461 # the string data in hex Set Timeout NOTE: You can NOT get time that is left on a password! You can reset the timeout so it starts again, or times out more quickly keyctl timeout 123456789 1800 # set a 30 minute timeout keyctl timeout 123456789 0 # the key is never to timeout # what for end of session (logout) instead # systemd-ask-password defaults to 150 secs keyctl timeout 123456789 1 # timeout the key in 1 second! keyctl show # the key now has timed out 123456789: key inaccessible (Key has expired) keyctl print 123456789 # print the timeout error keyctl_read_alloc: Key has expired keyctl reap # removes invalid keys from keyring Remove keys keyctl purge user {keyname} # completely remove key by name <---- *** # no need for the key id keyctl print 123456789 # print shows it is 'not available' keyctl_read_alloc: Required key not available keyctl revoke 123456789 # revoke a key but does not remove it # (access generates "Key has been revoked") keyctl reap # removes invalid keys from keyring keyctl unlink 123456789 # Or remove key from this keyring # this is for moving key to different keyring Keyrings keyctl search @s keyring _uid.1000 # find a keyring 987654321 keyctl request keyring _uid.1000 # ditto 987654321 keyctl search 987654321 user {keyname} # find keyname on keyring 123456789 Persistent keyring This ring stays around longer (disconnected from session), even after the user has logged out. But does not continue beyond reboot or a keyring timeout (generally 3 days) though this timeout is reset every time it is accessed (such as via cron). A persistent keyring is not available until it is linked to a accessible keyring. This is meant to be used by cron jobs, which run at least once a day, or every weekday (thus the 3 day limit), after the user has set the credentials needed. For example kerberos credentials. keyctl get_persistent @u # link the persistent keyring to our uid But how exactly do you use it? Again VERY little information on the proceedure is available. You would this something like this was commonly done! Low level Access... cat /proc/keys # ALL the keys and keyrings (id's in hex) cat /proc/key-users # UID to usage instanced/total_keys quota/quota_size ------------------------------------------------------------------------------- Key requests with alturnative sources if not cached keyctl request2 user debug:hello wibble This will lookup a key, but if not defined create a partial key, and call some program to fill in the details of the key. But! HOW THIS WORKS is yet again not known, or very clear... Aaaaarrgghhh.... Configuration for lookup commands... /etc/request-key.conf and /etc/request-key.d/*.conf ------------------------------------------------------------------------------- Sharing keys with specific processes and users... https://mjg59.dreamwidth.org/37333.html While using sudo, create key in your session sudo keyctl add user testkey testdata @s # -> 678913344 Limit the keys access sudo keyctl setperm 678913344 0x3f3f0000 Now share it with the root user sudo keyctl link 678913344 @u Now remove it from our session so we as a user can NOT do things to it. sudo keyctl unlink 678913344 @s At this point root (uid 0) can read, modify and delete the key But users (not even the creating user) can not. ------------------------------------------------------------------------------- Trusted and Encrypted Keys For future research... https://www.kernel.org/doc/Documentation/security/keys-trusted-encrypted.txt ------------------------------------------------------------------------------- Miscellanious notes... List all keys, this process has current access... sudo cat /proc/keys ON RHEL, The DNS caches information in keyring uses this method! But I have not been able to get this to work! Clear DNS chached entries (as root) keyctl clear $((16#$(grep '.dns_resolver' /proc/keys | cut -f1 -d\ ) )) -------------------------------------------------------------------------------