diff options
Diffstat (limited to 'actions/context.go')
| -rw-r--r-- | actions/context.go | 110 |
1 files changed, 57 insertions, 53 deletions
diff --git a/actions/context.go b/actions/context.go index 8ad1357..4253de2 100644 --- a/actions/context.go +++ b/actions/context.go @@ -22,33 +22,26 @@ // All of the actions include a significant amount of logging, so that good // output can be provided for cmd/fscrypt's verbose mode. // The top-level actions currently include: -// - Creating a new config file -// - Creating a context on which to perform actions -// - Creating, unlocking, and modifying Protectors -// - Creating, unlocking, and modifying Policies +// - Creating a new config file +// - Creating a context on which to perform actions +// - Creating, unlocking, and modifying Protectors +// - Creating, unlocking, and modifying Policies package actions import ( "log" "os/user" - "golang.org/x/sys/unix" - "github.com/pkg/errors" "github.com/google/fscrypt/filesystem" + "github.com/google/fscrypt/keyring" "github.com/google/fscrypt/metadata" "github.com/google/fscrypt/util" ) -// Errors relating to Config files or Config structures. -var ( - ErrNoConfigFile = errors.New("global config file does not exist") - ErrBadConfigFile = errors.New("global config file has invalid data") - ErrConfigFileExists = errors.New("global config file already exists") - ErrBadConfig = errors.New("invalid Config structure provided") - ErrLocked = errors.New("key needs to be unlocked first") -) +// ErrLocked indicates that the key hasn't been unwrapped yet. +var ErrLocked = errors.New("key needs to be unlocked first") // Context contains the necessary global state to perform most of fscrypt's // actions. @@ -56,20 +49,29 @@ type Context struct { // Config is the struct loaded from the global config file. It can be // modified after being loaded to customise parameters. Config *metadata.Config - // Mount is the filesystem relitive to which all Protectors and Policies - // are added, edited, removed, and applied. + // Mount is the filesystem relative to which all Protectors and Policies + // are added, edited, removed, and applied, and to which policies using + // the filesystem keyring are provisioned. Mount *filesystem.Mount - // TargetUser is the user for which protectors are created and to whose - // keyring policies are provisioned. + // TargetUser is the user for whom protectors are created, and to whose + // keyring policies using the user keyring are provisioned. It's also + // the user for whom the keys are claimed in the filesystem keyring when + // v2 policies are provisioned. TargetUser *user.User + // TrustedUser is the user for whom policies and protectors are allowed + // to be read. Specifically, if TrustedUser is set, then only + // policies and protectors owned by TrustedUser or by root will be + // allowed to be read. If it's nil, then all policies and protectors + // the process has filesystem-level read access to will be allowed. + TrustedUser *user.User } // NewContextFromPath makes a context for the filesystem containing the // specified path and whose Config is loaded from the global config file. On -// success, the Context contains a valid Config and Mount. The target defaults -// the the current effective user if none is specified. -func NewContextFromPath(path string, target *user.User) (*Context, error) { - ctx, err := newContextFromUser(target) +// success, the Context contains a valid Config and Mount. The target user +// defaults to the current effective user if none is specified. +func NewContextFromPath(path string, targetUser *user.User) (*Context, error) { + ctx, err := newContextFromUser(targetUser) if err != nil { return nil, err } @@ -78,16 +80,16 @@ func NewContextFromPath(path string, target *user.User) (*Context, error) { } log.Printf("%s is on %s filesystem %q (%s)", path, - ctx.Mount.Filesystem, ctx.Mount.Path, ctx.Mount.Device) + ctx.Mount.FilesystemType, ctx.Mount.Path, ctx.Mount.Device) return ctx, nil } // NewContextFromMountpoint makes a context for the filesystem at the specified // mountpoint and whose Config is loaded from the global config file. On -// success, the Context contains a valid Config and Mount. The target defaults -// the the current effective user if none is specified. -func NewContextFromMountpoint(mountpoint string, target *user.User) (*Context, error) { - ctx, err := newContextFromUser(target) +// success, the Context contains a valid Config and Mount. The target user +// defaults to the current effective user if none is specified. +func NewContextFromMountpoint(mountpoint string, targetUser *user.User) (*Context, error) { + ctx, err := newContextFromUser(targetUser) if err != nil { return nil, err } @@ -95,60 +97,62 @@ func NewContextFromMountpoint(mountpoint string, target *user.User) (*Context, e return nil, err } - log.Printf("found %s filesystem %q (%s)", ctx.Mount.Filesystem, + log.Printf("found %s filesystem %q (%s)", ctx.Mount.FilesystemType, ctx.Mount.Path, ctx.Mount.Device) return ctx, nil } // newContextFromUser makes a context with the corresponding target user, and -// whose Config is loaded from the global config file. If the target is nil, the -// effecitive user is used. -func newContextFromUser(target *user.User) (*Context, error) { +// whose Config is loaded from the global config file. If the target user is +// nil, the effective user is used. +func newContextFromUser(targetUser *user.User) (*Context, error) { var err error - if target == nil { - if target, err = util.EffectiveUser(); err != nil { + if targetUser == nil { + if targetUser, err = util.EffectiveUser(); err != nil { return nil, err } } - ctx := &Context{TargetUser: target} + ctx := &Context{TargetUser: targetUser} if ctx.Config, err = getConfig(); err != nil { return nil, err } - log.Printf("creating context for %q", target.Username) + // By default, when running as a non-root user we only read policies and + // protectors owned by the user or root. When running as root, we allow + // reading all policies and protectors. + if !ctx.Config.GetAllowCrossUserMetadata() && !util.IsUserRoot() { + ctx.TrustedUser, err = util.EffectiveUser() + if err != nil { + return nil, err + } + } + + log.Printf("creating context for user %q", targetUser.Username) return ctx, nil } -// checkContext verifies that the context contains an valid config and a mount +// checkContext verifies that the context contains a valid config and a mount // which is being used with fscrypt. func (ctx *Context) checkContext() error { if err := ctx.Config.CheckValidity(); err != nil { - return errors.Wrap(ErrBadConfig, err.Error()) + return &ErrBadConfig{ctx.Config, err} } - return ctx.Mount.CheckSetup() + return ctx.Mount.CheckSetup(ctx.TrustedUser) } -// getService returns the keyring service for this context. We use the presence -// of the LegacyConfig flag to determine if we should use the legacy services. -// For ext4 systems before v4.8 and f2fs systems before v4.6, filesystem -// specific services must be used (these legacy services will still work with -// later kernels). -func (ctx *Context) getService() string { - // For legacy configurations, we may need non-standard services - if ctx.Config.HasCompatibilityOption(LegacyConfig) { - switch ctx.Mount.Filesystem { - case "ext4", "f2fs": - return ctx.Mount.Filesystem + ":" - } +func (ctx *Context) getKeyringOptions() *keyring.Options { + return &keyring.Options{ + Mount: ctx.Mount, + User: ctx.TargetUser, + UseFsKeyringForV1Policies: ctx.Config.GetUseFsKeyringForV1Policies(), } - return unix.FS_KEY_DESC_PREFIX } // getProtectorOption returns the ProtectorOption for the protector on the // context's mountpoint with the specified descriptor. func (ctx *Context) getProtectorOption(protectorDescriptor string) *ProtectorOption { - mnt, data, err := ctx.Mount.GetProtector(protectorDescriptor) + mnt, data, err := ctx.Mount.GetProtector(protectorDescriptor, ctx.TrustedUser) if err != nil { return &ProtectorOption{ProtectorInfo{}, nil, err} } @@ -167,7 +171,7 @@ func (ctx *Context) ProtectorOptions() ([]*ProtectorOption, error) { if err := ctx.checkContext(); err != nil { return nil, err } - descriptors, err := ctx.Mount.ListProtectors() + descriptors, err := ctx.Mount.ListProtectors(ctx.TrustedUser) if err != nil { return nil, err } |