diff options
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 +} |