diff options
| author | Eric Biggers <ebiggers@google.com> | 2019-12-15 19:31:39 -0800 |
|---|---|---|
| committer | Eric Biggers <ebiggers@google.com> | 2020-01-05 10:02:13 -0800 |
| commit | d0ac36dcea341ff000aca983dd80e7bef9fc30ec (patch) | |
| tree | 673eef073fd0646bbc16bc088a315d0dfe68dfb7 /pam_fscrypt | |
| parent | 0829eb74863bd279ae012779e52040ecc7f7178e (diff) | |
pam_fscrypt: update to handle filesystem keyring
FS_IOC_ADD_ENCRYPTION_KEY and FS_IOC_REMOVE_ENCRYPTION_KEY require root
for v1 policy keys, so update the PAM module to re-acquire root
privileges while provisioning/deprovisioning policies that need this.
Also, only set up the user keyring if it will actually be used.
Diffstat (limited to 'pam_fscrypt')
| -rw-r--r-- | pam_fscrypt/pam_fscrypt.go | 71 |
1 files changed, 66 insertions, 5 deletions
diff --git a/pam_fscrypt/pam_fscrypt.go b/pam_fscrypt/pam_fscrypt.go index c7f9931..b3c7a0e 100644 --- a/pam_fscrypt/pam_fscrypt.go +++ b/pam_fscrypt/pam_fscrypt.go @@ -36,6 +36,7 @@ import ( "github.com/google/fscrypt/actions" "github.com/google/fscrypt/crypto" + "github.com/google/fscrypt/keyring" "github.com/google/fscrypt/pam" "github.com/google/fscrypt/security" ) @@ -81,6 +82,43 @@ func Authenticate(handle *pam.Handle, _ map[string]bool) error { return errors.Wrap(err, "could not set AUTHTOK data") } +func beginProvisioningOp(handle *pam.Handle, policy *actions.Policy) error { + if policy.NeedsRootToProvision() { + return handle.StopAsPamUser() + } + return nil +} + +func endProvisioningOp(handle *pam.Handle, policy *actions.Policy) error { + if policy.NeedsRootToProvision() { + return handle.StartAsPamUser() + } + return nil +} + +// Set up the PAM user's keyring if needed by any encryption policies. +func setupUserKeyringIfNeeded(handle *pam.Handle, policies []*actions.Policy) error { + needed := false + for _, policy := range policies { + if policy.NeedsUserKeyring() { + needed = true + break + } + } + if !needed { + return nil + } + err := handle.StopAsPamUser() + if err != nil { + return err + } + _, err = keyring.UserKeyringID(handle.PamUser, true) + if err != nil { + log.Printf("Setting up keyrings in PAM: %v", err) + } + return handle.StartAsPamUser() +} + // OpenSession provisions any policies protected with the login protector. func OpenSession(handle *pam.Handle, _ map[string]bool) error { // We will always clear the AUTHTOK data @@ -107,6 +145,10 @@ func OpenSession(handle *pam.Handle, _ map[string]bool) error { return nil } + if err = setupUserKeyringIfNeeded(handle, policies); err != nil { + return errors.Wrapf(err, "setting up user keyring") + } + log.Printf("unlocking %d policies protected with AUTHTOK", len(policies)) keyFn := func(_ actions.ProtectorInfo, retry bool) (*crypto.Key, error) { if retry { @@ -144,8 +186,15 @@ func OpenSession(handle *pam.Handle, _ map[string]bool) error { } defer policy.Lock() - if err := policy.Provision(); err != nil { - log.Printf("provisioning policy %s: %s", policy.Descriptor(), err) + if err := beginProvisioningOp(handle, policy); err != nil { + return err + } + provisionErr := policy.Provision() + if err := endProvisioningOp(handle, policy); err != nil { + return err + } + if provisionErr != nil { + log.Printf("provisioning policy %s: %s", policy.Descriptor(), provisionErr) continue } log.Printf("policy %s provisioned", policy.Descriptor()) @@ -163,7 +212,8 @@ func CloseSession(handle *pam.Handle, args map[string]bool) error { } var errLock, errCache error - // Don't automatically drop privileges, we may need them to drop caches. + // Don't automatically drop privileges, since we may need them to + // deprovision policies or to drop caches. if args[lockFlag] { log.Print("locking polices protected with login protector") errLock = lockLoginPolicies(handle) @@ -200,14 +250,25 @@ func lockLoginPolicies(handle *pam.Handle) error { return nil } + if err = setupUserKeyringIfNeeded(handle, policies); err != nil { + return errors.Wrapf(err, "setting up user keyring") + } + // We will try to deprovision all of the policies. for _, policy := range policies { if !policy.IsProvisioned() { log.Printf("policy %s not provisioned", policy.Descriptor()) continue } - if err := policy.Deprovision(); err != nil { - log.Printf("deprovisioning policy %s: %s", policy.Descriptor(), err) + if err := beginProvisioningOp(handle, policy); err != nil { + return err + } + deprovisionErr := policy.Deprovision() + if err := endProvisioningOp(handle, policy); err != nil { + return err + } + if deprovisionErr != nil { + log.Printf("deprovisioning policy %s: %s", policy.Descriptor(), deprovisionErr) continue } log.Printf("policy %s deprovisioned", policy.Descriptor()) |