aboutsummaryrefslogtreecommitdiff
path: root/pam_fscrypt/pam_fscrypt.go
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2021-12-20 11:14:08 -0600
committerEric Biggers <ebiggers@google.com>2021-12-21 13:00:58 -0600
commitdce50d2a55525ec1309fd60a3c240d243d5f7145 (patch)
tree2fbe4381eae0b234f82671a7d62998e063fa3c8b /pam_fscrypt/pam_fscrypt.go
parent9a8ce15408edae0c92128fd36f50dafa81013266 (diff)
[BROKEN] pam_fscrypt: save unlocked protector keys in root user keyring
Diffstat (limited to 'pam_fscrypt/pam_fscrypt.go')
-rw-r--r--pam_fscrypt/pam_fscrypt.go61
1 files changed, 29 insertions, 32 deletions
diff --git a/pam_fscrypt/pam_fscrypt.go b/pam_fscrypt/pam_fscrypt.go
index 2e31af9..7a3f25c 100644
--- a/pam_fscrypt/pam_fscrypt.go
+++ b/pam_fscrypt/pam_fscrypt.go
@@ -43,8 +43,6 @@ import (
const (
moduleName = "pam_fscrypt"
- // authtokLabel tags the AUTHTOK in the PAM data.
- authtokLabel = "fscrypt_authtok"
// These flags are used to toggle behavior of the PAM module.
debugFlag = "debug"
@@ -76,18 +74,31 @@ func Authenticate(handle *pam.Handle, _ map[string]bool) error {
defer handle.StopAsPamUser()
// If this user doesn't have a login protector, no unlocking is needed.
- if _, err := loginProtector(handle); err != nil {
+ protector, err := loginProtector(handle)
+ if err != nil {
log.Printf("no protector, no need for AUTHTOK: %s", err)
return nil
}
- log.Print("copying AUTHTOK for use in the session open")
- authtok, err := handle.GetItem(pam.Authtok)
- if err != nil {
- return errors.Wrap(err, "could not get AUTHTOK")
+ log.Print("unlocking user's login protector")
+ keyFn := func(_ actions.ProtectorInfo, retry bool) (*crypto.Key, error) {
+ if retry {
+ return nil, pam.ErrPassphrase
+ }
+ authtok, err := handle.GetItem(pam.Authtok)
+ if err != nil {
+ return nil, errors.Wrap(err, "could not get AUTHTOK")
+ }
+ return crypto.NewKeyFromCString(authtok)
+ }
+ if err := protector.Unlock(keyFn); err != nil {
+ return errors.Wrap(err, "could not unlock login protector")
}
- err = handle.SetSecret(authtokLabel, authtok)
- return errors.Wrap(err, "could not set AUTHTOK data")
+ handle.StopAsPamUser()
+ if err := keyring.SaveProtectorKey(protector.InternalKey(), handle.PamUser); err != nil {
+ return errors.Wrap(err, "could not save protector key")
+ }
+ return nil
}
func beginProvisioningOp(handle *pam.Handle, policy *actions.Policy) error {
@@ -129,13 +140,16 @@ func setupUserKeyringIfNeeded(handle *pam.Handle, policies []*actions.Policy) er
// 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
- defer handle.ClearData(authtokLabel)
+ // We will always delete the saved protector key
+ defer keyring.DeleteSavedProtectorKey(handle.PamUser)
// Increment the count as we add a session
if _, err := AdjustCount(handle, +1); err != nil {
return err
}
+ protectorKey, protectorKeyErr := keyring.RestoreProtectorKey(handle.PamUser)
+ defer protectorKey.Wipe()
+
if err := handle.StartAsPamUser(); err != nil {
return err
}
@@ -157,29 +171,12 @@ func OpenSession(handle *pam.Handle, _ map[string]bool) error {
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 {
- // Login passphrase and login protector have diverged.
- // We could prompt the user for the old passphrase and
- // rewrap, but we currently don't.
- return nil, pam.ErrPassphrase
- }
+ log.Printf("unlocking %d policies protected by login protector", len(policies))
- authtok, err := handle.GetSecret(authtokLabel)
- if err != nil {
- // pam_sm_authenticate was not run before the session is
- // opened. This can happen when a user does something
- // like "sudo su <user>". We could prompt for the
- // login passphrase here, but we currently don't.
- return nil, errors.Wrap(err, "AUTHTOK data missing")
- }
-
- return crypto.NewKeyFromCString(authtok)
- }
- if err := protector.Unlock(keyFn); err != nil {
- return errors.Wrapf(err, "unlocking protector %s", protector.Descriptor())
+ if protectorKeyErr != nil {
+ return protectorKeyErr
}
+ protector.UnlockFromInternalKey(protectorKey)
defer protector.Lock()
// We don't stop provisioning polices on error, we try all of them.