diff options
| author | Joe Richey joerichey@google.com <joerichey@google.com> | 2017-06-21 10:21:21 -0700 |
|---|---|---|
| committer | Joe Richey joerichey@google.com <joerichey@google.com> | 2017-06-28 15:15:21 -0700 |
| commit | 37c866e1e16a6d2dded11ba93c2e04af3764a139 (patch) | |
| tree | 745d548ed30e9e70b4702622510690af62a48b58 /cmd/fscrypt/protector.go | |
| parent | 93415b198a3ef427c02893b8fdf036aa75ffe50f (diff) | |
cmd/fscrypt: setup, encrypt, unlock commands
This commit adds in the framework for adding commands and subcommands to
the fscrypt tool. This commit adds in the "setup", "encrypt", and
"unlock" commands. Additional information can be found by running:
fscrypt <command> --help.
This commit defines how flags are parsed and errors are handled. It also
creates an extensible framework for prompting the user for information.
Change-Id: I159d7f44ee2b2bbc5e072f0802850e082d9a13ce
Diffstat (limited to 'cmd/fscrypt/protector.go')
| -rw-r--r-- | cmd/fscrypt/protector.go | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/cmd/fscrypt/protector.go b/cmd/fscrypt/protector.go new file mode 100644 index 0000000..e77a2e3 --- /dev/null +++ b/cmd/fscrypt/protector.go @@ -0,0 +1,123 @@ +/* + * protector.go - Functions for creating and getting action.Protectors which + * ensure that login passphrases are on the correct filesystem. + * + * Copyright 2017 Google Inc. + * Author: Joe Richey (joerichey@google.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package main + +import ( + "log" + + "fscrypt/actions" + "fscrypt/filesystem" + "fscrypt/metadata" +) + +// createProtector makes a new protector on either ctx.Mount or if the requested +// source is a pam_passphrase, creates it on the root filesystem. Prompts for +// user input are used to get the source, name and keys. +func createProtectorFromContext(ctx *actions.Context) (*actions.Protector, error) { + if err := promptForSource(ctx); err != nil { + return nil, err + } + log.Printf("using source: %s", ctx.Config.Source.String()) + + name, err := promptForName(ctx) + if err != nil { + return nil, err + } + log.Printf("using name: %s", name) + + // We only want to create new login protectors on the root filesystem. + // So we make a new context if necessary. + if ctx.Config.Source == metadata.SourceType_pam_passphrase && ctx.Mount.Path != "/" { + log.Printf("creating login protector on %q instead of %q", "/", ctx.Mount.Path) + if ctx, err = modifiedContext(ctx); err != nil { + return nil, err + } + } + + return actions.CreateProtector(ctx, name, createKeyFn) +} + +// selectExistingProtector returns a locked Protector which corresponds to an +// options in the non-empty slice of options. Prompts for user input are used to +// get the keys and select the option. +func selectExistingProtector(ctx *actions.Context, options []*actions.ProtectorOption) (*actions.Protector, error) { + idx, err := promptForProtector(options) + if err != nil { + return nil, err + } + option := options[idx] + + log.Printf("using %s", formatInfo(option.ProtectorInfo)) + return actions.GetProtectorFromOption(ctx, option) +} + +// expandedProtectorOptions gets all the actions.ProtectorOptions for ctx.Mount +// as well as any pam_passphrase protectors for the root filesystem. +func expandedProtectorOptions(ctx *actions.Context) ([]*actions.ProtectorOption, error) { + options, err := ctx.ProtectorOptions() + if err != nil { + return nil, err + } + + // Do nothing different if we are at the root, or cannot load the root. + if ctx.Mount.Path == "/" { + return options, nil + } + if ctx, err = modifiedContext(ctx); err != nil { + log.Print(err) + return options, nil + } + rootOptions, err := ctx.ProtectorOptions() + if err != nil { + log.Print(err) + return options, nil + } + log.Print("adding additional ProtectorOptions") + + // Keep track of what we have seen, so we don't have duplicates + seenOptions := make(map[string]bool) + for _, option := range options { + seenOptions[option.Descriptor()] = true + } + + for _, option := range rootOptions { + // Add in unseen passphrase protectors on the root filesystem + // to the options list as potential linked protectors. + if option.Source() == metadata.SourceType_pam_passphrase && + !seenOptions[option.Descriptor()] { + option.LinkedMount = ctx.Mount + options = append(options, option) + } + } + + return options, nil +} + +// modifiedContext returns a copy of ctx with the mountpoint replaced by that of +// the root filesystem. +func modifiedContext(ctx *actions.Context) (*actions.Context, error) { + mnt, err := filesystem.GetMount("/") + if err != nil { + return nil, err + } + + return &actions.Context{Config: ctx.Config, Mount: mnt}, nil +} |