aboutsummaryrefslogtreecommitdiff
path: root/actions/protector.go
diff options
context:
space:
mode:
Diffstat (limited to 'actions/protector.go')
-rw-r--r--actions/protector.go90
1 files changed, 65 insertions, 25 deletions
diff --git a/actions/protector.go b/actions/protector.go
index ffc3c43..b986eb0 100644
--- a/actions/protector.go
+++ b/actions/protector.go
@@ -22,21 +22,55 @@ package actions
import (
"fmt"
"log"
-
- "github.com/pkg/errors"
+ "os/user"
"github.com/google/fscrypt/crypto"
"github.com/google/fscrypt/metadata"
"github.com/google/fscrypt/util"
)
-// Errors relating to Protectors
-var (
- ErrProtectorName = errors.New("login protectors do not need a name")
- ErrMissingProtectorName = errors.New("custom protectors must have a name")
- ErrDuplicateName = errors.New("protector with this name already exists")
- ErrDuplicateUID = errors.New("login protector for this user already exists")
-)
+// LoginProtectorMountpoint is the mountpoint where login protectors are stored.
+// This can be overridden by the user of this package.
+var LoginProtectorMountpoint = "/"
+
+// ErrLoginProtectorExists indicates that a user already has a login protector.
+type ErrLoginProtectorExists struct {
+ User *user.User
+}
+
+func (err *ErrLoginProtectorExists) Error() string {
+ return fmt.Sprintf("user %q already has a login protector", err.User.Username)
+}
+
+// ErrLoginProtectorName indicates that a name was given for a login protector.
+type ErrLoginProtectorName struct {
+ Name string
+ User *user.User
+}
+
+func (err *ErrLoginProtectorName) Error() string {
+ return fmt.Sprintf(`cannot assign name %q to new login protector for
+ user %q because login protectors are identified by user, not by name.`,
+ err.Name, err.User.Username)
+}
+
+// ErrMissingProtectorName indicates that a protector name is needed.
+type ErrMissingProtectorName struct {
+ Source metadata.SourceType
+}
+
+func (err *ErrMissingProtectorName) Error() string {
+ return fmt.Sprintf("%s protectors must be named", err.Source)
+}
+
+// ErrProtectorNameExists indicates that a protector name already exists.
+type ErrProtectorNameExists struct {
+ Name string
+}
+
+func (err *ErrProtectorNameExists) Error() string {
+ return fmt.Sprintf("there is already a protector named %q", err.Name)
+}
// checkForProtectorWithName returns an error if there is already a protector
// on the filesystem with a specific name (or if we cannot read the necessary
@@ -48,7 +82,7 @@ func checkForProtectorWithName(ctx *Context, name string) error {
}
for _, option := range options {
if option.Name() == name {
- return errors.Wrapf(ErrDuplicateName, "name %q", name)
+ return &ErrProtectorNameExists{name}
}
}
return nil
@@ -64,7 +98,7 @@ func checkIfUserHasLoginProtector(ctx *Context, uid int64) error {
}
for _, option := range options {
if option.Source() == metadata.SourceType_pam_passphrase && option.UID() == uid {
- return errors.Wrapf(ErrDuplicateUID, "user %q", ctx.TargetUser.Username)
+ return &ErrLoginProtectorExists{ctx.TargetUser}
}
}
return nil
@@ -75,17 +109,18 @@ func checkIfUserHasLoginProtector(ctx *Context, uid int64) error {
// to unlock policies and create new polices. As with the key struct, a
// Protector should be wiped after use.
type Protector struct {
- Context *Context
- data *metadata.ProtectorData
- key *crypto.Key
- created bool
+ Context *Context
+ data *metadata.ProtectorData
+ key *crypto.Key
+ created bool
+ ownerIfCreating *user.User
}
// CreateProtector creates an unlocked protector with a given name (name only
// needed for custom and raw protector types). The keyFn provided to create the
// Protector key will only be called once. If an error is returned, no data has
// been changed on the filesystem.
-func CreateProtector(ctx *Context, name string, keyFn KeyFunc) (*Protector, error) {
+func CreateProtector(ctx *Context, name string, keyFn KeyFunc, owner *user.User) (*Protector, error) {
if err := ctx.checkContext(); err != nil {
return nil, err
}
@@ -93,12 +128,12 @@ func CreateProtector(ctx *Context, name string, keyFn KeyFunc) (*Protector, erro
if ctx.Config.Source == metadata.SourceType_pam_passphrase {
// login protectors don't need a name (we use the username instead)
if name != "" {
- return nil, ErrProtectorName
+ return nil, &ErrLoginProtectorName{name, ctx.TargetUser}
}
} else {
// non-login protectors need a name (so we can distinguish between them)
if name == "" {
- return nil, ErrMissingProtectorName
+ return nil, &ErrMissingProtectorName{ctx.Config.Source}
}
// we don't want to duplicate naming
if err := checkForProtectorWithName(ctx, name); err != nil {
@@ -113,7 +148,8 @@ func CreateProtector(ctx *Context, name string, keyFn KeyFunc) (*Protector, erro
Name: name,
Source: ctx.Config.Source,
},
- created: true,
+ created: true,
+ ownerIfCreating: owner,
}
// Extra data is needed for some SourceTypes
@@ -123,7 +159,7 @@ func CreateProtector(ctx *Context, name string, keyFn KeyFunc) (*Protector, erro
// UID for this kind of source.
protector.data.Uid = int64(util.AtoiOrPanic(ctx.TargetUser.Uid))
// Make sure we aren't duplicating protectors
- if err := checkIfUserHasLoginProtector(ctx, protector.data.Uid); err != nil {
+ if err = checkIfUserHasLoginProtector(ctx, protector.data.Uid); err != nil {
return nil, err
}
fallthrough
@@ -140,9 +176,13 @@ func CreateProtector(ctx *Context, name string, keyFn KeyFunc) (*Protector, erro
if protector.key, err = crypto.NewRandomKey(metadata.InternalKeyLen); err != nil {
return nil, err
}
- protector.data.ProtectorDescriptor = crypto.ComputeDescriptor(protector.key)
+ protector.data.ProtectorDescriptor, err = crypto.ComputeKeyDescriptor(protector.key, 1)
+ if err != nil {
+ protector.Lock()
+ return nil, err
+ }
- if err := protector.Rewrap(keyFn); err != nil {
+ if err = protector.Rewrap(keyFn); err != nil {
protector.Lock()
return nil, err
}
@@ -161,7 +201,7 @@ func GetProtector(ctx *Context, descriptor string) (*Protector, error) {
}
protector := &Protector{Context: ctx}
- protector.data, err = ctx.Mount.GetRegularProtector(descriptor)
+ protector.data, err = ctx.Mount.GetRegularProtector(descriptor, ctx.TrustedUser)
return protector, err
}
@@ -180,7 +220,7 @@ func GetProtectorFromOption(ctx *Context, option *ProtectorOption) (*Protector,
// Replace the context if this is a linked protector
if option.LinkedMount != nil {
- ctx = &Context{ctx.Config, option.LinkedMount, ctx.TargetUser}
+ ctx = &Context{ctx.Config, option.LinkedMount, ctx.TargetUser, ctx.TrustedUser}
}
return &Protector{Context: ctx, data: option.data}, nil
}
@@ -256,5 +296,5 @@ func (protector *Protector) Rewrap(keyFn KeyFunc) error {
return err
}
- return protector.Context.Mount.AddProtector(protector.data)
+ return protector.Context.Mount.AddProtector(protector.data, protector.ownerIfCreating)
}