diff options
| author | Joe Richey joerichey@google.com <joerichey@google.com> | 2017-08-22 15:41:18 -0700 |
|---|---|---|
| committer | Joe Richey joerichey@google.com <joerichey@google.com> | 2017-08-22 15:41:18 -0700 |
| commit | ef5cc07774674c66b5dbeb7c655a26ac6371e378 (patch) | |
| tree | ea9996782b0528bebd44f36dd13e13eb9a3e791f | |
| parent | ca70b81fddb340ed5212741a773c3a4a0c4ea3e2 (diff) | |
pam_fscrypt: lock all PAM policies w/ flag
| -rw-r--r-- | pam/pam.go | 35 | ||||
| -rw-r--r-- | pam_fscrypt/config | 2 | ||||
| -rw-r--r-- | pam_fscrypt/pam_fscrypt.go | 84 |
3 files changed, 38 insertions, 83 deletions
@@ -32,8 +32,6 @@ import ( "errors" "fmt" "unsafe" - - "github.com/google/fscrypt/util" ) // Handle wraps the C pam_handle_t type. This is used from within modules. @@ -99,39 +97,6 @@ func (h *Handle) GetString(name string) (string, error) { return C.GoString((*C.char)(data)), nil } -// SetSlice sets a []string value for the PAM data with the specified name. -func (h *Handle) SetSlice(name string, slice []string) error { - sliceLength := uintptr(len(slice)) - memorySize := (sliceLength + 1) * unsafe.Sizeof(uintptr(0)) - data := C.malloc(C.size_t(memorySize)) - - cSlice := util.PointerSlice(data) - for i, str := range slice { - cSlice[i] = unsafe.Pointer(C.CString(str)) - } - cSlice[sliceLength] = nil - - return h.setData(name, data, C.CleanupFunc(C.freeArray)) -} - -// GetSlice gets a []string value for the PAM data with the specified name. It -// should have been previously set with SetSlice(). -func (h *Handle) GetSlice(name string) ([]string, error) { - data, err := h.getData(name) - if err != nil { - return nil, err - } - - var slice []string - for _, cString := range util.PointerSlice(data) { - if cString == nil { - return slice, nil - } - slice = append(slice, C.GoString((*C.char)(cString))) - } - panic("We will never get here") -} - // GetItem retrieves a PAM information item. This a pointer directory to the // data, so it shouldn't be modified. func (h *Handle) GetItem(i Item) (unsafe.Pointer, error) { diff --git a/pam_fscrypt/config b/pam_fscrypt/config index 26b7767..795a4f8 100644 --- a/pam_fscrypt/config +++ b/pam_fscrypt/config @@ -7,7 +7,7 @@ Auth-Final: Session-Type: Additional Session-Interactive-Only: yes Session-Final: - optional pam_fscrypt.so drop_caches + optional pam_fscrypt.so drop_caches lock_policies Password-Type: Additional Password-Final: optional pam_fscrypt.so diff --git a/pam_fscrypt/pam_fscrypt.go b/pam_fscrypt/pam_fscrypt.go index ad7cfdc..84b848e 100644 --- a/pam_fscrypt/pam_fscrypt.go +++ b/pam_fscrypt/pam_fscrypt.go @@ -50,11 +50,14 @@ import ( ) const ( + moduleName = "pam_fscrypt" // These labels are used to tag items in the PAM data. - authtokLabel = "fscrypt_authtok" - descriptorLabel = "fscrypt_descriptor" - provisionedKeysLabel = "fscrypt_provisioned_keys" - moduleName = "pam_fscrypt" + authtokLabel = "fscrypt_authtok" + descriptorLabel = "fscrypt_descriptor" + // These flags are used to toggle behavior of the PAM module. + debugFlag = "debug" + lockFlag = "lock_policies" + cacheFlag = "drop_caches" ) // parseArgs takes a list of C arguments into a PAM function and returns a map @@ -73,7 +76,7 @@ func parseArgs(argc C.int, argv **C.char) map[string]bool { func setupLogging(args map[string]bool) io.Writer { log.SetFlags(0) // Syslog already includes time data itself log.SetOutput(ioutil.Discard) - if args["debug"] { + if args[debugFlag] { debugWriter, err := syslog.New(syslog.LOG_DEBUG, moduleName) if err == nil { log.SetOutput(debugWriter) @@ -96,12 +99,6 @@ func loginProtector(handle *pam.Handle) (*actions.Protector, error) { return nil, err } - // Retrieve the cached value if one exists. - if descriptor, err := handle.GetString(descriptorLabel); err == nil { - log.Printf("using cached descriptor %q", descriptor) - return actions.GetProtector(ctx, descriptor) - } - // Find the user's PAM protector. uid := int64(unix.Geteuid()) if err != nil { @@ -112,17 +109,9 @@ func loginProtector(handle *pam.Handle) (*actions.Protector, error) { return nil, err } for _, option := range options { - if option.Source() != metadata.SourceType_pam_passphrase || option.UID() != uid { - continue + if option.Source() == metadata.SourceType_pam_passphrase && option.UID() == uid { + return actions.GetProtectorFromOption(ctx, option) } - - log.Printf("caching descriptor %q", option.Descriptor()) - if err = handle.SetString(descriptorLabel, option.Descriptor()); err != nil { - log.Printf("could not set descriptor data: %s", err) - // We can still get the protector, so no error. - } - - return actions.GetProtectorFromOption(ctx, option) } return nil, fmt.Errorf("no PAM protector on %q", ctx.Mount.Path) } @@ -159,10 +148,10 @@ func pam_sm_setcred(pamh unsafe.Pointer, flags, argc C.int, argv **C.char) C.int return C.PAM_SUCCESS } -// policiesToProvision searches all the mountpoints for any unprovisioned -// policies protected with the specified protector. An error during this search -// does not halt the search, instead the errors are written to errWriter. -func policiesToProvision(protector *actions.Protector, errWriter io.Writer) []*actions.Policy { +// policiesUsingProtector searches all the mountpoints for any policies +// protected with the specified protector. An error during this search does not +// halt the search, instead the errors are written to errWriter. +func policiesUsingProtector(protector *actions.Protector, errWriter io.Writer) []*actions.Policy { mounts, err := filesystem.AllFilesystems() if err != nil { fmt.Fprint(errWriter, err) @@ -189,7 +178,7 @@ func policiesToProvision(protector *actions.Protector, errWriter io.Writer) []*a continue } - if policy.UsesProtector(protector) && !policy.IsProvisioned() { + if policy.UsesProtector(protector) { policies = append(policies, policy) } } @@ -205,7 +194,7 @@ func pam_sm_open_session(pamh unsafe.Pointer, flags, argc C.int, argv **C.char) protector, err := loginProtector(handle) if err != nil { - log.Printf("no directories to unlock: %s", err) + log.Printf("no pam protector for this user: %s", err) return C.PAM_SUCCESS } @@ -229,11 +218,10 @@ func pam_sm_open_session(pamh unsafe.Pointer, flags, argc C.int, argv **C.char) return crypto.NewKeyFromCString(authtok) } - log.Print("searching for policies to provision in pam_sm_open_session()") - policies := policiesToProvision(protector, errWriter) - + log.Print("searching for policies to unlock in pam_sm_open_session()") + policies := policiesUsingProtector(protector, errWriter) if len(policies) == 0 { - log.Print("no policies to provision") + log.Print("no policies to unlock") return C.PAM_SUCCESS } @@ -243,8 +231,11 @@ func pam_sm_open_session(pamh unsafe.Pointer, flags, argc C.int, argv **C.char) } defer protector.Lock() - var provisionedKeys []string for _, policy := range policies { + if policy.IsProvisioned() { + log.Printf("policy %s already provisioned", policy.Descriptor()) + continue + } if err := policy.UnlockWithProtector(protector); err != nil { fmt.Fprintf(errWriter, "unlocking policy %s: %s", policy.Descriptor(), err) continue @@ -257,18 +248,8 @@ func pam_sm_open_session(pamh unsafe.Pointer, flags, argc C.int, argv **C.char) } log.Printf("policy %s provisioned", policy.Descriptor()) - provisionedKeys = append(provisionedKeys, policy.Description()) } - if len(provisionedKeys) == 0 { - fmt.Fprint(errWriter, "could not provision any policies") - return C.PAM_SERVICE_ERR - } - - if err := handle.SetSlice(provisionedKeysLabel, provisionedKeys); err != nil { - fmt.Fprintf(errWriter, "setting key list data: %s", err) - return C.PAM_SERVICE_ERR - } return C.PAM_SUCCESS } @@ -280,10 +261,19 @@ func pam_sm_close_session(pamh unsafe.Pointer, flags, argc C.int, argv **C.char) args := parseArgs(argc, argv) errWriter := setupLogging(args) - provisionedKeys, err := handle.GetSlice(provisionedKeysLabel) - if err != nil { - log.Printf("no directories to lock: %s", err) - return C.PAM_SUCCESS + if args[lockFlag] { + protector, err := loginProtector(handle) + if err != nil { + log.Printf("no pam protector for this user: %s", err) + return C.PAM_SUCCESS + } + + policies := policiesUsingProtector(protector, errWriter) + + if len(policies) == 0 { + log.Print("no policies to lock") + return C.PAM_SUCCESS + } } log.Print("locking directories in pam_sm_close_session()") @@ -293,7 +283,7 @@ func pam_sm_close_session(pamh unsafe.Pointer, flags, argc C.int, argv **C.char) } } - if args["drop_caches"] { + if args[cacheFlag] { if err = security.DropInodeCache(); err != nil { fmt.Fprint(errWriter, err) return C.PAM_SERVICE_ERR |