"github.com/google/fscrypt/actions"
"github.com/google/fscrypt/filesystem"
+ "github.com/google/fscrypt/keyring"
"github.com/google/fscrypt/metadata"
"github.com/google/fscrypt/security"
"github.com/google/fscrypt/util"
return nil
}
+// validateKeyringPrereqs ensures we're ready to add, remove, or get the status
+// of the key for the given encryption policy (if policy != nil) or for the
+// current default encryption policy (if policy == nil).
+func validateKeyringPrereqs(ctx *actions.Context, policy *actions.Policy) error {
+ if ctx.Config.GetUseFsKeyringForV1Policies() {
+ // We'll be using the filesystem keyring, but it's a v1
+ // encryption policy so root is required.
+ if !util.IsUserRoot() {
+ return ErrFsKeyringPerm
+ }
+ return nil
+ }
+ // We'll be using the target user's user keyring, so make sure a user
+ // was explicitly specified if the command is being run as root, and
+ // make sure that user's keyring is accessible.
+ if userFlag.Value == "" && util.IsUserRoot() {
+ return ErrSpecifyUser
+ }
+ if _, err := keyring.UserKeyringID(ctx.TargetUser, true); err != nil {
+ return err
+ }
+ return nil
+}
+
// encryptPath sets up encryption on path and provisions the policy to the
// keyring unless --skip-unlock is used. On failure, an error is returned, any
// metadata creation is reverted, and the directory is unmodified.
func encryptPath(path string) (err error) {
- targetUser, err := parseUserFlag(!skipUnlockFlag.Value)
+ targetUser, err := parseUserFlag()
if err != nil {
return
}
if policyFlag.Value != "" {
log.Printf("getting policy for %q", path)
- policy, err = getPolicyFromFlag(policyFlag.Value, ctx.TargetUser)
+ if policy, err = getPolicyFromFlag(policyFlag.Value, ctx.TargetUser); err != nil {
+ return
+ }
+
+ if !skipUnlockFlag.Value {
+ if err = validateKeyringPrereqs(ctx, policy); err != nil {
+ return
+ }
+ }
} else {
log.Printf("creating policy for %q", path)
+ if !skipUnlockFlag.Value {
+ if err = validateKeyringPrereqs(ctx, nil); err != nil {
+ return
+ }
+ }
+
protector, created, protErr := selectOrCreateProtector(ctx)
// Successfully created protector should be reverted on failure.
if protErr != nil {
if err = protector.Unlock(existingKeyFn); err != nil {
return
}
- policy, err = actions.CreatePolicy(ctx, protector)
+ if policy, err = actions.CreatePolicy(ctx, protector); err != nil {
+ return
+ }
}
// Successfully created policy should be reverted on failure.
- if err != nil {
- return
- }
defer func() {
policy.Lock()
if err != nil {
return expectedArgsErr(c, 1, false)
}
- targetUser, err := parseUserFlag(true)
+ targetUser, err := parseUserFlag()
if err != nil {
return newExitError(c, err)
}
if err != nil {
return newExitError(c, err)
}
+ // Ensure the keyring is ready.
+ if err = validateKeyringPrereqs(ctx, policy); err != nil {
+ return newExitError(c, err)
+ }
// Check if directory is already unlocked
if policy.IsProvisioned() {
log.Printf("policy %s is already provisioned", policy.Descriptor())
return expectedArgsErr(c, 1, false)
}
- targetUser, err := parseUserFlag(true)
+ targetUser, err := parseUserFlag()
if err != nil {
return newExitError(c, err)
}
if err != nil {
return newExitError(c, err)
}
+ // Ensure the keyring is ready.
+ if err = validateKeyringPrereqs(ctx, policy); err != nil {
+ return newExitError(c, err)
+ }
// Check if directory is already locked
if policy.IsFullyDeprovisioned() {
log.Printf("policy %s is already fully deprovisioned", policy.Descriptor())
}
}
- targetUser, err := parseUserFlag(true)
+ targetUser, err := parseUserFlag()
if err != nil {
return newExitError(c, err)
}
if err != nil {
return newExitError(c, err)
}
+ if err = validateKeyringPrereqs(ctx, nil); err != nil {
+ return newExitError(c, err)
+ }
question := fmt.Sprintf("Purge all policy keys from %q", ctx.Mount.Path)
if dropCachesFlag.Value {
return expectedArgsErr(c, 1, false)
}
- targetUser, err := parseUserFlag(false)
+ targetUser, err := parseUserFlag()
if err != nil {
return newExitError(c, err)
}
"github.com/urfave/cli"
"github.com/google/fscrypt/actions"
- "github.com/google/fscrypt/keyring"
"github.com/google/fscrypt/util"
)
}
// 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. If checkKeyring is true, we also make sure
-// there are no problems accessing the user keyring.
-func parseUserFlag(checkKeyring bool) (targetUser *user.User, err error) {
+// user if the flag value is missing.
+func parseUserFlag() (targetUser *user.User, err error) {
if userFlag.Value != "" {
- targetUser, err = user.Lookup(userFlag.Value)
- } else {
- if util.IsUserRoot() {
- return nil, ErrSpecifyUser
- }
- targetUser, err = util.EffectiveUser()
+ return user.Lookup(userFlag.Value)
}
- if err != nil {
- return nil, err
- }
-
- if checkKeyring {
- _, err = keyring.UserKeyringID(targetUser, true)
- }
- return targetUser, err
+ return util.EffectiveUser()
}