From 462d166d5355d33a05271d24de4d52f30dd62f67 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 15 Dec 2019 19:31:39 -0800 Subject: Add keyring package In preparation for introducing support for the new filesystem-level keyrings, move the existing user keyring management code from security/keyring.go and crypto/crypto.go into a new package, 'keyring'. This package provides functions AddEncryptionKey, RemoveEncryptionKey, and GetEncryptionKeyStatus which delegate to either the filesystem keyring (added by a later patch) or to the user keyring. This provides a common interface to both types of keyrings, to the extent possible. --- cmd/fscrypt/errors.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'cmd/fscrypt/errors.go') diff --git a/cmd/fscrypt/errors.go b/cmd/fscrypt/errors.go index 288e697..ed57dbe 100644 --- a/cmd/fscrypt/errors.go +++ b/cmd/fscrypt/errors.go @@ -34,8 +34,8 @@ import ( "github.com/google/fscrypt/actions" "github.com/google/fscrypt/crypto" "github.com/google/fscrypt/filesystem" + "github.com/google/fscrypt/keyring" "github.com/google/fscrypt/metadata" - "github.com/google/fscrypt/security" "github.com/google/fscrypt/util" ) @@ -94,11 +94,11 @@ func getErrorSuggestions(err error) string { needs to be enabled for this filesystem. See the documentation on how to enable encryption on ext4 systems (and the risks of doing so).` - case security.ErrSessionUserKeying: + case keyring.ErrSessionUserKeying: return `This is usually the result of a bad PAM configuration. Either correct the problem in your PAM stack, enable pam_keyinit.so, or run "keyctl link @u @s".` - case security.ErrAccessUserKeyring: + case keyring.ErrAccessUserKeyring: return fmt.Sprintf(`You can only use %s to access the user keyring of another user if you are running as root.`, shortDisplay(userFlag)) -- cgit v1.2.3 From 9003a0331a112e8901fae8279f4897a825ee8069 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 15 Dec 2019 19:31:39 -0800 Subject: cmd/fscrypt: add 'fscrypt lock' command Add support for 'fscrypt lock'. This command "locks" a directory, undoing 'fscrypt unlock'. When the filesystem keyring is used, 'fscrypt lock' also detects when a directory wasn't fully locked due to some files still being in-use. It can then be run again later to try to finish locking the files. --- cmd/fscrypt/errors.go | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'cmd/fscrypt/errors.go') diff --git a/cmd/fscrypt/errors.go b/cmd/fscrypt/errors.go index ed57dbe..68135fe 100644 --- a/cmd/fscrypt/errors.go +++ b/cmd/fscrypt/errors.go @@ -56,6 +56,7 @@ var ( ErrAllLoadsFailed = errors.New("could not load any protectors") ErrMustBeRoot = errors.New("this command must be run as root") ErrPolicyUnlocked = errors.New("this file or directory is already unlocked") + ErrPolicyLocked = errors.New("this file or directory is already locked") ErrBadOwners = errors.New("you do not own this directory") ErrNotEmptyDir = errors.New("not an empty directory") ErrNotPassphrase = errors.New("protector does not use a passphrase") @@ -94,6 +95,11 @@ func getErrorSuggestions(err error) string { needs to be enabled for this filesystem. See the documentation on how to enable encryption on ext4 systems (and the risks of doing so).` + case keyring.ErrKeyFilesOpen: + return `Directory was incompletely locked because some files are + still open. These files remain accessible. Try killing + any processes using files in the directory, then + re-running 'fscrypt lock'.` case keyring.ErrSessionUserKeying: return `This is usually the result of a bad PAM configuration. Either correct the problem in your PAM stack, enable -- cgit v1.2.3 From 0829eb74863bd279ae012779e52040ecc7f7178e Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 15 Dec 2019 19:31:39 -0800 Subject: cmd/fscrypt: adjust user and keyring validation and preparation Don't force the user to provide a --user argument when running fscrypt as root if they're doing something where the TargetUser isn't actually needed, such as provisioning/deprovisioning a v1 encryption policy to/from the filesystem keyring, or creating a non-login protector. Also don't set up the user keyring (or check for it being set up) if it won't actually be used. Finally, if we'll be provisioning/deprovisioning a v1 encryption policy to/from the filesystem keyring, make sure the command is running as root, since the kernel requires this. --- cmd/fscrypt/errors.go | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'cmd/fscrypt/errors.go') diff --git a/cmd/fscrypt/errors.go b/cmd/fscrypt/errors.go index 68135fe..ac969f6 100644 --- a/cmd/fscrypt/errors.go +++ b/cmd/fscrypt/errors.go @@ -63,6 +63,7 @@ var ( ErrUnknownUser = errors.New("unknown user") ErrDropCachesPerm = errors.New("inode cache can only be dropped as root") ErrSpecifyUser = errors.New("user must be specified when run as root") + ErrFsKeyringPerm = errors.New("root is required to add/remove v1 encryption policy keys to/from filesystem") ) var loadHelpText = fmt.Sprintf("You may need to mount a linked filesystem. Run with %s for more information.", shortDisplay(verboseFlag)) @@ -141,6 +142,10 @@ func getErrorSuggestions(err error) string { properly clear the inode cache, or it should be run with %s=false (this may leave encrypted files and directories in an accessible state).`, shortDisplay(dropCachesFlag)) + case ErrFsKeyringPerm: + return `Either this command should be run as root, or you should + set '"use_fs_keyring_for_v1_policies": false' in + /etc/fscrypt.conf.` case ErrSpecifyUser: return fmt.Sprintf(`When running this command as root, you usually still want to provision/remove keys for a normal -- cgit v1.2.3 From 42e0dfe85ec7a75a2fa30c417d57eae60b5a881d Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 15 Dec 2019 19:31:39 -0800 Subject: Keyring support for v2 encryption policies Implement adding/removing v2 encryption policy keys to/from the kernel. The kernel requires that the new ioctls FS_IOC_ADD_ENCRYPTION_KEY and FS_IOC_REMOVE_ENCRYPTION_KEY be used for this. Root is not required. However, non-root support brings an extra complication: the kernel keeps track of which users have called FS_IOC_ADD_ENCRYPTION_KEY for the same key. FS_IOC_REMOVE_ENCRYPTION_KEY only works as one of these users, and it only removes the calling user's claim to the key; the key is only truly removed when the last claim is removed. Implement the following behavior: - 'fscrypt unlock' and pam_fscrypt add the key for the user, even if other user(s) have it added already. This behavior is needed so that another user can't remove the key out from under the user. - 'fscrypt lock' and pam_fscrypt remove the key for the user. However, if the key wasn't truly removed because other users still have it added, 'fscrypt lock' prints a warning. - 'fscrypt status' shows whether the directory is unlocked for anyone. --- cmd/fscrypt/errors.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'cmd/fscrypt/errors.go') diff --git a/cmd/fscrypt/errors.go b/cmd/fscrypt/errors.go index ac969f6..ba9ec7a 100644 --- a/cmd/fscrypt/errors.go +++ b/cmd/fscrypt/errors.go @@ -101,6 +101,9 @@ func getErrorSuggestions(err error) string { still open. These files remain accessible. Try killing any processes using files in the directory, then re-running 'fscrypt lock'.` + case keyring.ErrKeyAddedByOtherUsers: + return `Directory couldn't be fully locked because other user(s) + have unlocked it.` case keyring.ErrSessionUserKeying: return `This is usually the result of a bad PAM configuration. Either correct the problem in your PAM stack, enable @@ -145,7 +148,10 @@ func getErrorSuggestions(err error) string { case ErrFsKeyringPerm: return `Either this command should be run as root, or you should set '"use_fs_keyring_for_v1_policies": false' in - /etc/fscrypt.conf.` + /etc/fscrypt.conf, or you should re-create your + encrypted directories using v2 encryption policies + rather than v1 (this requires setting '"policy_version": + "2"' in the "options" section of /etc/fscrypt.conf).` case ErrSpecifyUser: return fmt.Sprintf(`When running this command as root, you usually still want to provision/remove keys for a normal -- cgit v1.2.3 From 068879664efd8a0f983cbc3e8115571047fe9edd Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 15 Dec 2019 19:31:39 -0800 Subject: cmd/fscrypt, keyring: add --all-users option to 'fscrypt lock' Allow root to provide the --all-users option to 'fscrypt lock' to force an encryption key to be removed from the filesystem (i.e., force an encrypted directory to be locked), even if other users have added it. To implement this option, we just need to use the FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS ioctl rather than FS_IOC_REMOVE_ENCRYPTION_KEY. In theory this option could be implemented for the user keyrings case too, but it would be difficult and the user keyrings are being deprecated for fscrypt, so don't bother. --- cmd/fscrypt/errors.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'cmd/fscrypt/errors.go') diff --git a/cmd/fscrypt/errors.go b/cmd/fscrypt/errors.go index ba9ec7a..5239155 100644 --- a/cmd/fscrypt/errors.go +++ b/cmd/fscrypt/errors.go @@ -103,7 +103,8 @@ func getErrorSuggestions(err error) string { re-running 'fscrypt lock'.` case keyring.ErrKeyAddedByOtherUsers: return `Directory couldn't be fully locked because other user(s) - have unlocked it.` + have unlocked it. If you want to force the directory to + be locked, use 'sudo fscrypt lock --all-users DIR'.` case keyring.ErrSessionUserKeying: return `This is usually the result of a bad PAM configuration. Either correct the problem in your PAM stack, enable -- cgit v1.2.3