aboutsummaryrefslogtreecommitdiff
path: root/cmd/fscrypt/fscrypt.go
diff options
context:
space:
mode:
authorJoe Richey joerichey@google.com <joerichey@google.com>2017-10-17 02:39:07 -0700
committerJoseph Richey <joerichey94@gmail.com>2017-10-19 02:22:26 -0700
commitbab7dfdf68075b345e4de3ae79ea685ca884668f (patch)
treeeced4ecdfd37aae1a92f28ba0864837db1205eb0 /cmd/fscrypt/fscrypt.go
parentb5cc60b2b974645f0d09721c292cd243d049cbcf (diff)
Move around and fscrypt refactor
Diffstat (limited to 'cmd/fscrypt/fscrypt.go')
-rw-r--r--cmd/fscrypt/fscrypt.go188
1 files changed, 180 insertions, 8 deletions
diff --git a/cmd/fscrypt/fscrypt.go b/cmd/fscrypt/fscrypt.go
index f1649fc..65da7cb 100644
--- a/cmd/fscrypt/fscrypt.go
+++ b/cmd/fscrypt/fscrypt.go
@@ -27,9 +27,35 @@ package main
import (
"fmt"
+ "github.com/google/fscrypt/filesystem"
+ "github.com/google/fscrypt/security"
+ "github.com/pkg/errors"
+
+ "github.com/google/fscrypt/actions"
+
"github.com/google/fscrypt/cmd"
)
+// Arguments used in fscrypt commands.
+var (
+ unusedMountpointArg = &cmd.Argument{
+ Name: "mountpoint",
+ Usage: "path to a mountpoint on which to setup fscrypt",
+ }
+ usedMountpointArg = &cmd.Argument{
+ Name: "mountpoint",
+ Usage: "path to a mountpoint being used with fscrypt",
+ }
+ directoryToEncryptArg = &cmd.Argument{
+ Name: "directory",
+ Usage: "path to an empty directory to encrypt with fscrypt",
+ }
+ encryptedPathArg = &cmd.Argument{
+ Name: "path",
+ Usage: "file or directory encrypted with fscrypt",
+ }
+)
+
func main() { fscryptCommand.Run() }
var fscryptCommand = cmd.Command{
@@ -40,10 +66,10 @@ var fscryptCommand = cmd.Command{
cmd.VersionUsage,
},
SubCommands: []*Command{
- &setupCommand,
- &encryptCommand,
- // unlockCommand,
- // purgeCommand,
+ setupCommand,
+ encryptCommand,
+ unlockCommand,
+ purgeCommand,
// statusCommand,
// metadataCommand,
cmd.VersionCommand,
@@ -58,9 +84,9 @@ var setupCommand = &cmd.Command{
Title: "setup a system/filesystem to use fscrypt",
UsageLines: []string{
fmt.Sprintf("[options]"),
- fmt.Sprintf("%s [%s]", mountpointArg, cmd.ForceFlag),
+ fmt.Sprintf("%s [%s]", unusedMountpointArg, cmd.ForceFlag),
},
- Arguments: []*cmd.Argument{mountpointArg},
+ Arguments: []*cmd.Argument{unusedMountpointArg},
InheritFlags: true,
Flags: []cmd.Flag{configFileFlag, targetFlag, legacyFlag, cmd.ForceFlag},
ManPage: &cmd.ManPage{Name: "fscrypt-setup", Section: 8},
@@ -80,5 +106,151 @@ func setupAction(c *cmd.Context) error {
}
}
-// encrypt performs the functions of setupDirectory and Unlock in one command.
-var encryptCommand = &cmd.Command{}
+// encrypt takes an empty directory, enables encryption, and unlocks it.
+var encryptCommand = &cmd.Command{
+ Name: "encrypt",
+ Title: "start encrypting an empty directory",
+ UsageLines: nil, // TODO(joerichey)
+ Arguments: []*cmd.Argument{directoryToEncryptArg},
+ InheritFlags: true,
+ Flags: []cmd.Flag{sourceFlag, nameFlag, protectorFlag, policyFlag,
+ keyFileFlag, userFlag, skipUnlockFlag},
+ ManPage: &cmd.ManPage{Name: "fscrypt-encrypt", Section: 8},
+ Action: encryptAction,
+}
+
+func encryptAction(c *cmd.Context) error {
+ if err := cmd.CheckExpectedArgs(c, 1, false); err != nil {
+ return err
+ }
+
+ path := c.Args[0]
+ if err := encryptPath(path); err != nil {
+ return err
+ }
+
+ if !skipUnlockFlag.Value {
+ fmt.Fprintf(cmd.Output, "%q is now encrypted, unlocked, and ready for use.\n", path)
+ return nil
+ }
+
+ fmt.Fprintf(cmd.Output, "%q is now encrypted, but it is still locked.\n", path)
+ fmt.Fprintf(cmd.Output, "It can be unlocked with: fscrypt unlock %q\n", path)
+ return nil
+}
+
+// unlock takes an encrypted path and makes it available for reading/writing.
+var unlockCommand = &cmd.Command{
+ Name: "unlock",
+ Title: "unlock an encrypted file or directory",
+ UsageLines: nil, // TODO(joerichey)
+ Arguments: []*cmd.Argument{encryptedPathArg},
+ InheritFlags: true,
+ Flags: []cmd.Flag{protectorFlag, policyFlag, keyFileFlag, userFlag},
+ ManPage: &cmd.ManPage{Name: "fscrypt-unlock", Section: 8},
+ Action: unlockAction,
+}
+
+func unlockAction(c *cmd.Context) error {
+ if err := cmd.CheckExpectedArgs(c, 1, false); err != nil {
+ return err
+ }
+
+ path := c.Args[0]
+ if err := unlockPath(path); err != nil {
+ return err
+ }
+
+ fmt.Fprintf(cmd.Output, "%q is now unlocked and ready for use.\n", path)
+ return nil
+}
+
+// purge removes all the policy keys from the keyring (my require unmount).
+var purgeCommand = &cmd.Command{
+ Name: "purge",
+ Title: "remove a directory's encryption keys",
+ UsageLines: []string{fmt.Sprintf("%s, [%s=false] [%s] [%s]",
+ usedMountpointArg, dropCachesFlag, userFlag, cmd.ForceFlag)},
+ Arguments: []*cmd.Argument{usedMountpointArg},
+ InheritFlags: true,
+ Flags: []cmd.Flag{dropCachesFlag, userFlag, cmd.ForceFlag},
+ ManPage: &cmd.ManPage{Name: "fscrypt-purge", Section: 8},
+ Action: purgeAction,
+}
+
+func purgeAction(c *cmd.Context) error {
+ if err := cmd.CheckExpectedArgs(c, 1, false); err != nil {
+ return err
+ }
+ if dropCachesFlag.Value {
+ if cmd.CheckIfRoot() != nil {
+ return ErrDropCachesPerm
+ }
+ }
+
+ targetUser, err := parseUserFlag(true)
+ if err != nil {
+ return err
+ }
+ ctx, err := actions.NewContextFromMountpoint(c.Args[0], target)
+ if err != nil {
+ return err
+ }
+
+ question := fmt.Sprintf("Purge all policy keys from %q", ctx.Mount.Path)
+ if dropCachesFlag.Value {
+ question += " and drop global inode cache"
+ }
+ warning := "Encrypted data on this filesystem will be inaccessible until unlocked again!!"
+ if err = cmd.AskConfirmation(question+"?", warning, false); err != nil {
+ return err
+ }
+ if err = actions.PurgeAllPolicies(ctx); err != nil {
+ return err
+ }
+ fmt.Fprintf(cmd.Output, "Policies purged from filesystem %q.\n", ctx.Mount.Path)
+
+ if !dropCachesFlag.Value {
+ fmt.Fprintf(cmd.Output, "Filesystem %q should now be unmounted.\n", cmd.Mount.Path)
+ return nil
+ }
+ if err = security.DropFilesystemCache(); err != nil {
+ return err
+ }
+ fmt.Fprintln(cmd.Output, "Encrypted data removed from filesystem cache.")
+ return nil
+}
+
+// status is a command that gets info about the system, a mountpoint, or a path.
+var statusCommand = &cmd.Command{
+ Name: "status",
+ Title: "get the status of the system or a path",
+ UsageLines: []string{"", usedMountpointArg.String(), encryptedPathArg.String()},
+ Flags: []cmd.Flag{cmd.VerboseFlag, cmd.HelpFlag},
+ ManPage: &cmd.ManPage{Name: "fscrypt-status", Section: 8},
+ Action: statusAction,
+}
+
+func statusAction(c *cmd.Context) error {
+ switch len(c.Args) {
+ case 0:
+ // Case (1) - global status
+ return writeGlobalStatus()
+ case 1:
+ path := c.Args[0]
+ ctx, mntErr := actions.NewContextFromMountpoint(path, nil)
+
+ switch errors.Cause(mntErr) {
+ case nil:
+ // Case (2) - mountpoint status
+ return writeFilesystemStatus(ctx)
+ case filesystem.ErrNotAMountpoint:
+ // Case (3) - file or directory status
+ return writePathStatus(path)
+ default:
+ return mntErr
+ }
+ default:
+ return expectedArgsErr(c, 1, true)
+ }
+}