From 37c866e1e16a6d2dded11ba93c2e04af3764a139 Mon Sep 17 00:00:00 2001 From: "Joe Richey joerichey@google.com" Date: Wed, 21 Jun 2017 10:21:21 -0700 Subject: 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 --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 --- cmd/fscrypt/protector.go | 123 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 cmd/fscrypt/protector.go (limited to 'cmd/fscrypt/protector.go') 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 +} -- cgit v1.2.3