diff options
Diffstat (limited to 'pam_fscrypt/pam_fscrypt.go')
| -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()) |