// Authenticate copies the AUTHTOK (if necessary) into the PAM data so it can be
// used in pam_sm_open_session.
func Authenticate(handle *pam.Handle, _ map[string]bool) error {
- if err := handle.DropThreadPrivileges(); err != nil {
+ log.Print("Authenticate()")
+ if err := handle.StartAsPamUser(); err != nil {
return err
}
- defer handle.RaiseThreadPrivileges()
+ defer handle.StopAsPamUser()
// If this user doesn't have a login protector, no unlocking is needed.
if _, err := loginProtector(handle); err != nil {
- log.Printf("no need to copy AUTHTOK: %s", err)
+ log.Printf("no protector, no need for AUTHTOK: %s", err)
return nil
}
- log.Print("Authenticate: copying AUTHTOK for use in the session")
+ 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")
// OpenSession provisions any policies protected with the login protector.
func OpenSession(handle *pam.Handle, _ map[string]bool) error {
+ log.Print("OpenSession()")
// We will always clear the the AUTHTOK data
defer handle.ClearData(authtokLabel)
// Increment the count as we add a session
return err
}
- if err := handle.DropThreadPrivileges(); err != nil {
+ if err := handle.StartAsPamUser(); err != nil {
return err
}
- defer handle.RaiseThreadPrivileges()
+ defer handle.StopAsPamUser()
// If there are no polices for the login protector, no unlocking needed.
protector, err := loginProtector(handle)
if err != nil {
- log.Printf("nothing to unlock: %s", err)
+ log.Printf("no protector to unlock: %s", err)
return nil
}
policies := policiesUsingProtector(protector)
return nil
}
- log.Print("OpenSession: unlocking policies protected with AUTHTOK")
+ 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.
// CloseSession can deprovision all keys provisioned at the start of the
// session. It can also clear the cache so these changes take effect.
func CloseSession(handle *pam.Handle, args map[string]bool) error {
+ log.Printf("CloseSession(%v)", args)
// Only do stuff on session close when we are the last session
if count, err := AdjustCount(handle, -1); err != nil || count != 0 {
log.Printf("count is %d and we are not locking", count)
var errLock, errCache error
// Don't automatically drop privileges, we may need them to drop caches.
if args[lockFlag] {
- log.Print("CloseSession: locking polices protected with login")
+ log.Print("locking polices protected with login protector")
errLock = lockLoginPolicies(handle)
}
if args[cacheFlag] {
- log.Print("CloseSession: dropping inode caches")
+ log.Print("dropping inode caches at session close")
errCache = security.DropInodeCache()
}
// lockLoginPolicies deprovisions all policy keys that are protected by
// the user's login protector.
func lockLoginPolicies(handle *pam.Handle) error {
- if err := handle.DropThreadPrivileges(); err != nil {
+ if err := handle.StartAsPamUser(); err != nil {
return err
}
- defer handle.RaiseThreadPrivileges()
+ defer handle.StopAsPamUser()
// If there are no polices for the login protector, no locking needed.
protector, err := loginProtector(handle)
// Chauthtok rewraps the login protector when the passphrase changes.
func Chauthtok(handle *pam.Handle, _ map[string]bool) error {
- if err := handle.DropThreadPrivileges(); err != nil {
+ log.Print("Chauthtok()")
+ if err := handle.StartAsPamUser(); err != nil {
return err
}
- defer handle.RaiseThreadPrivileges()
+ defer handle.StopAsPamUser()
protector, err := loginProtector(handle)
if err != nil {
- log.Printf("nothing to rewrap: %s", err)
+ log.Printf("no login protector to rewrap: %s", err)
return nil
}
return crypto.NewKeyFromCString(authtok)
}
- log.Print("Chauthtok: rewrapping login protector")
+ log.Print("rewrapping login protector")
if err = protector.Unlock(oldKeyFn); err != nil {
return err
}
// one exists. This protector descriptor (if found) will be cached in the pam
// data, under descriptorLabel.
func loginProtector(handle *pam.Handle) (*actions.Protector, error) {
- ctx, err := actions.NewContextFromMountpoint("/")
+ ctx, err := actions.NewContextFromMountpoint("/", handle.PamUser)
if err != nil {
return nil, err
}
if err != nil {
return nil, err
}
+ uid := int64(util.AtoiOrPanic(handle.PamUser.Uid))
for _, option := range options {
- if option.Source() == metadata.SourceType_pam_passphrase &&
- option.UID() == int64(handle.UID) {
+ if option.Source() == metadata.SourceType_pam_passphrase && option.UID() == uid {
return actions.GetProtectorFromOption(ctx, option)
}
}
- return nil, errors.Errorf("no PAM protector for UID=%d on %q", handle.UID, ctx.Mount.Path)
+ return nil, errors.Errorf("no PAM protector for UID=%d on %q", uid, ctx.Mount.Path)
}
// policiesUsingProtector searches all the mountpoints for any policies
continue
}
- ctx := &actions.Context{Config: protector.Context.Config, Mount: mount}
+ // Clone context but modify the mountpoint
+ ctx := *protector.Context
+ ctx.Mount = mount
for _, policyDescriptor := range policyDescriptors {
- policy, err := actions.GetPolicy(ctx, policyDescriptor)
+ policy, err := actions.GetPolicy(&ctx, policyDescriptor)
if err != nil {
log.Printf("reading policy: %s", err)
continue
return 0, err
}
- path := filepath.Join(countDirectory, fmt.Sprintf("%d.count", handle.UID))
+ path := filepath.Join(countDirectory, handle.PamUser.Uid+".count")
file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, countFilePermissions)
if err != nil {
return 0, err
return 0, err
}
- log.Printf("Session count for UID=%d updated to %d", handle.UID, newCount)
+ log.Printf("Session count for UID=%s updated to %d", handle.PamUser.Uid, newCount)
return newCount, nil
}