diff options
Diffstat (limited to 'cmd/fscrypt/status.go')
| -rw-r--r-- | cmd/fscrypt/status.go | 72 |
1 files changed, 57 insertions, 15 deletions
diff --git a/cmd/fscrypt/status.go b/cmd/fscrypt/status.go index 1465a4e..bc8f1ee 100644 --- a/cmd/fscrypt/status.go +++ b/cmd/fscrypt/status.go @@ -27,11 +27,9 @@ import ( "strings" "text/tabwriter" - "github.com/pkg/errors" - "github.com/google/fscrypt/actions" "github.com/google/fscrypt/filesystem" - "github.com/google/fscrypt/metadata" + "github.com/google/fscrypt/keyring" ) // Creates a writer which correctly aligns tabs with the specified header. @@ -45,12 +43,13 @@ func makeTableWriter(w io.Writer, header string) *tabwriter.Writer { // encryptionStatus will be printed in the ENCRYPTION column. An empty string // indicates the filesystem should not be printed. func encryptionStatus(err error) string { - switch errors.Cause(err) { - case nil: + if err == nil { return "supported" - case metadata.ErrEncryptionNotEnabled: + } + switch err.(type) { + case *filesystem.ErrEncryptionNotEnabled: return "not enabled" - case metadata.ErrEncryptionNotSupported: + case *filesystem.ErrEncryptionNotSupported: return "not supported" default: // Unknown error regarding support @@ -65,7 +64,31 @@ func yesNoString(b bool) string { return "No" } -// writeGlobalStatus prints all the filesystem that use (or could use) fscrypt. +func policyUnlockedStatus(policy *actions.Policy, path string) string { + status := policy.GetProvisioningStatus() + + // Due to a limitation in the old kernel API for fscrypt, for v1 + // policies using the user keyring that are incompletely locked or are + // unlocked by another user, we'll get KeyAbsent. If we have a + // directory path, use a heuristic to try to detect these cases. + if status == keyring.KeyAbsent && policy.NeedsUserKeyring() && + path != "" && isDirUnlockedHeuristic(path) { + return "Partially (incompletely locked, or unlocked by another user)" + } + + switch status { + case keyring.KeyPresent, keyring.KeyPresentButOnlyOtherUsers: + return "Yes" + case keyring.KeyAbsent: + return "No" + case keyring.KeyAbsentButFilesBusy: + return "Partially (incompletely locked)" + default: + return "Unknown" + } +} + +// writeGlobalStatus prints all the filesystems that use (or could use) fscrypt. func writeGlobalStatus(w io.Writer) error { mounts, err := filesystem.AllFilesystems() if err != nil { @@ -78,7 +101,7 @@ func writeGlobalStatus(w io.Writer) error { t := makeTableWriter(w, "MOUNTPOINT\tDEVICE\tFILESYSTEM\tENCRYPTION\tFSCRYPT") for _, mount := range mounts { // Only print mountpoints backed by devices or using fscrypt. - usingFscrypt := mount.CheckSetup() == nil + usingFscrypt := mount.CheckSetup(nil) == nil if !usingFscrypt && mount.Device == "" { continue } @@ -91,7 +114,10 @@ func writeGlobalStatus(w io.Writer) error { continue } - fmt.Fprintf(t, "%s\t%s\t%s\t%s\t%s\n", mount.Path, mount.Device, mount.Filesystem, + fmt.Fprintf(t, "%s\t%s\t%s\t%s\t%s\n", + filesystem.EscapeString(mount.Path), + filesystem.EscapeString(mount.Device), + filesystem.EscapeString(mount.FilesystemType), supportString, yesNoString(usingFscrypt)) if supportErr == nil { @@ -134,13 +160,27 @@ func writeFilesystemStatus(w io.Writer, ctx *actions.Context) error { return err } - policyDescriptors, err := ctx.Mount.ListPolicies() + policyDescriptors, err := ctx.Mount.ListPolicies(ctx.TrustedUser) if err != nil { return err } - fmt.Fprintf(w, "%s filesystem %q has %s and %s\n\n", ctx.Mount.Filesystem, ctx.Mount.Path, - pluralize(len(options), "protector"), pluralize(len(policyDescriptors), "policy")) + filterDescription := "" + if ctx.TrustedUser != nil { + filterDescription = fmt.Sprintf(" (only including ones owned by %s or root)", ctx.TrustedUser.Username) + } + fmt.Fprintf(w, "%s filesystem %q has %s and %s%s.\n", ctx.Mount.FilesystemType, + ctx.Mount.Path, pluralize(len(options), "protector"), + pluralize(len(policyDescriptors), "policy"), filterDescription) + if setupMode, user, err := ctx.Mount.GetSetupMode(); err == nil { + switch setupMode { + case filesystem.WorldWritable: + fmt.Fprintf(w, "All users can create fscrypt metadata on this filesystem.\n") + case filesystem.SingleUserWritable: + fmt.Fprintf(w, "Only %s can create fscrypt metadata on this filesystem.\n", user.Username) + } + } + fmt.Fprintf(w, "\n") if len(options) > 0 { writeOptions(w, options) @@ -159,7 +199,8 @@ func writeFilesystemStatus(w io.Writer, ctx *actions.Context) error { continue } - fmt.Fprintf(t, "%s\t%s\t%s\n", descriptor, yesNoString(policy.IsProvisioned()), + fmt.Fprintf(t, "%s\t%s\t%s\n", descriptor, + policyUnlockedStatus(policy, ""), strings.Join(policy.ProtectorDescriptors(), ", ")) } return t.Flush() @@ -178,7 +219,8 @@ func writePathStatus(w io.Writer, path string) error { fmt.Fprintf(w, "%q is encrypted with fscrypt.\n", path) fmt.Fprintln(w) fmt.Fprintf(w, "Policy: %s\n", policy.Descriptor()) - fmt.Fprintf(w, "Unlocked: %s\n", yesNoString(policy.IsProvisioned())) + fmt.Fprintf(w, "Options: %s\n", policy.Options()) + fmt.Fprintf(w, "Unlocked: %s\n", policyUnlockedStatus(policy, path)) fmt.Fprintln(w) options := policy.ProtectorOptions() |