diff options
| author | Joe Richey <joerichey@google.com> | 2017-08-30 18:16:16 -0700 |
|---|---|---|
| committer | Joe Richey <joerichey@google.com> | 2017-08-30 18:16:16 -0700 |
| commit | 11b31826334bc3faa4d4c7ee05a3b2996a88c969 (patch) | |
| tree | 8fe4a0d0a9e683b84ff70eed7986eebb857a2fdf /cmd/fscrypt/flags.go | |
| parent | 5814155d0c0247d501f7479f760a676185cd4b6d (diff) | |
cmd/fscrypt: Add --user flag for running as root
The --user flag can now be used to have the targe user (the one whose
keyring and password will be used in fscrypt) be different than the
calling user. Very usefull for things like
sudo fscrypt purge /media/joerichey/usb --user=joerichey
which will now have privileges to drop caches, but will properly clear
the keys from the user's keyring.
Diffstat (limited to 'cmd/fscrypt/flags.go')
| -rw-r--r-- | cmd/fscrypt/flags.go | 57 |
1 files changed, 43 insertions, 14 deletions
diff --git a/cmd/fscrypt/flags.go b/cmd/fscrypt/flags.go index a06b952..e883a6d 100644 --- a/cmd/fscrypt/flags.go +++ b/cmd/fscrypt/flags.go @@ -25,6 +25,7 @@ import ( "flag" "fmt" "log" + "os/user" "regexp" "strconv" "time" @@ -32,6 +33,7 @@ import ( "github.com/urfave/cli" "github.com/google/fscrypt/actions" + "github.com/google/fscrypt/util" ) // We define the types boolFlag, durationFlag, and stringFlag here instead of @@ -204,6 +206,12 @@ var ( formatted as raw binary and should be exactly 32 bytes long.`, } + userFlag = &stringFlag{ + Name: "user", + ArgName: "USERNAME", + Usage: `Specifiy which user should be used for login passphrases + or to which user's keyring keys should be provisioned.`, + } protectorFlag = &stringFlag{ Name: "protector", ArgName: "MOUNTPOINT:ID", @@ -233,27 +241,31 @@ var ( // group is required and corresponds to the descriptor. var idFlagRegex = regexp.MustCompile("^([[:print:]]+):([[:alnum:]]+)$") +func matchMetadataFlag(flagValue string) (mountpoint, descriptor string, err error) { + matches := idFlagRegex.FindStringSubmatch(flagValue) + if matches == nil { + return "", "", fmt.Errorf("flag value %q does not have format %s", + flagValue, mountpointIDArg) + } + log.Printf("parsed flag: mountpoint=%q descriptor=%s", matches[1], matches[2]) + return matches[1], matches[2], nil +} + // parseMetadataFlag takes the value of either protectorFlag or policyFlag // formatted as MOUNTPOINT:DESCRIPTOR, and returns a context for the mountpoint // and a string for the descriptor. -func parseMetadataFlag(flagValue string) (*actions.Context, string, error) { - matches := idFlagRegex.FindStringSubmatch(flagValue) - if matches == nil { - err := fmt.Errorf("flag value %q does not have format %s", flagValue, mountpointIDArg) +func parseMetadataFlag(flagValue string, target *user.User) (*actions.Context, string, error) { + mountpoint, descriptor, err := matchMetadataFlag(flagValue) + if err != nil { return nil, "", err } - - mountpoint := matches[1] - descriptor := matches[2] - log.Printf("parsed flag: mountpoint=%q descriptor=%s", mountpoint, descriptor) - - ctx, err := actions.NewContextFromMountpoint(mountpoint) + ctx, err := actions.NewContextFromMountpoint(mountpoint, target) return ctx, descriptor, err } // getProtectorFromFlag gets an existing locked protector from protectorFlag. -func getProtectorFromFlag(flagValue string) (*actions.Protector, error) { - ctx, descriptor, err := parseMetadataFlag(flagValue) +func getProtectorFromFlag(flagValue string, target *user.User) (*actions.Protector, error) { + ctx, descriptor, err := parseMetadataFlag(flagValue, target) if err != nil { return nil, err } @@ -261,10 +273,27 @@ func getProtectorFromFlag(flagValue string) (*actions.Protector, error) { } // getPolicyFromFlag gets an existing locked policy from policyFlag. -func getPolicyFromFlag(flagValue string) (*actions.Policy, error) { - ctx, descriptor, err := parseMetadataFlag(flagValue) +func getPolicyFromFlag(flagValue string, target *user.User) (*actions.Policy, error) { + ctx, descriptor, err := parseMetadataFlag(flagValue, target) if err != nil { return nil, err } return actions.GetPolicy(ctx, descriptor) } + +// parseUserFlag returns the user specified by userFlag or the current effective +// user if the flag value is missing. If the effective user is root, however, a +// user must specified in the flag. +func parseUserFlag() (*user.User, error) { + if userFlag.Value != "" { + return user.Lookup(userFlag.Value) + } + effectiveUser, err := util.EffectiveUser() + if err != nil { + return nil, err + } + if util.IsUserRoot() { + return nil, ErrSpecifyUser + } + return effectiveUser, nil +} |