aboutsummaryrefslogtreecommitdiff
path: root/actions/context.go
diff options
context:
space:
mode:
Diffstat (limited to 'actions/context.go')
-rw-r--r--actions/context.go110
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
}