diff options
Diffstat (limited to 'actions/protector.go')
| -rw-r--r-- | actions/protector.go | 90 |
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) } |