aboutsummaryrefslogtreecommitdiff
path: root/pam_fscrypt/pam_fscrypt.go
diff options
context:
space:
mode:
Diffstat (limited to 'pam_fscrypt/pam_fscrypt.go')
-rw-r--r--pam_fscrypt/pam_fscrypt.go71
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())