aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Richey <joerichey94@gmail.com>2017-10-19 03:15:28 -0700
committerJoseph Richey <joerichey94@gmail.com>2017-10-19 03:34:51 -0700
commitb7de8535f899f2b88d61f4f1264fe6a272196536 (patch)
tree4caf8a0e426caf45440b5115664baba12749a11f
parent7885d63f644bb49d8da1d8313d5f4870d586a9c1 (diff)
util: Add better user lookup functions
When looking up users in fscrypt, we often want to proceed even if the requested uid doesn't appear to be a valid user on the system. This mainly occurs when a user is deleted, but they still have a login protector on disk. Thus, GetUser() with a bad uid creates a fake user with a pretty placeholder name. The corresponding call sites of util.EffectiveUser are changed (often simplifying logic). Various documentation is updated and typos are fixed.
-rw-r--r--actions/context.go10
-rw-r--r--cmd/fscrypt/flags.go26
-rw-r--r--crypto/crypto_test.go6
-rw-r--r--pam/pam.go8
-rw-r--r--util/users.go50
-rw-r--r--util/util.go13
6 files changed, 78 insertions, 35 deletions
diff --git a/actions/context.go b/actions/context.go
index 8ad1357..ed7729d 100644
--- a/actions/context.go
+++ b/actions/context.go
@@ -67,7 +67,7 @@ type Context struct {
// NewContextFromPath makes a context for the filesystem containing the
// specified path and whose Config is loaded from the global config file. On
// success, the Context contains a valid Config and Mount. The target defaults
-// the the current effective user if none is specified.
+// the the current user if none is specified.
func NewContextFromPath(path string, target *user.User) (*Context, error) {
ctx, err := newContextFromUser(target)
if err != nil {
@@ -85,7 +85,7 @@ func NewContextFromPath(path string, target *user.User) (*Context, error) {
// NewContextFromMountpoint makes a context for the filesystem at the specified
// mountpoint and whose Config is loaded from the global config file. On
// success, the Context contains a valid Config and Mount. The target defaults
-// the the current effective user if none is specified.
+// the the current user if none is specified.
func NewContextFromMountpoint(mountpoint string, target *user.User) (*Context, error) {
ctx, err := newContextFromUser(target)
if err != nil {
@@ -102,13 +102,11 @@ func NewContextFromMountpoint(mountpoint string, target *user.User) (*Context, e
// newContextFromUser makes a context with the corresponding target user, and
// whose Config is loaded from the global config file. If the target is nil, the
-// effecitive user is used.
+// current user is used.
func newContextFromUser(target *user.User) (*Context, error) {
var err error
if target == nil {
- if target, err = util.EffectiveUser(); err != nil {
- return nil, err
- }
+ target = util.CurrentUser()
}
ctx := &Context{TargetUser: target}
diff --git a/cmd/fscrypt/flags.go b/cmd/fscrypt/flags.go
index 5137eff..b6eb446 100644
--- a/cmd/fscrypt/flags.go
+++ b/cmd/fscrypt/flags.go
@@ -282,25 +282,27 @@ func getPolicyFromFlag(flagValue string, target *user.User) (*actions.Policy, er
return actions.GetPolicy(ctx, descriptor)
}
-// parseUserFlag returns the user specified by userFlag or the current effective
-// user if the flag value is missing. If the effective user is root, however, a
-// user must specified in the flag. If checkKeyring is true, we also make sure
-// there are no problems accessing the user keyring.
+// parseUserFlag returns the user specified by userFlag or the current user if
+// the flag is not given. If the effective user is root, however, a user must be
+// specified in the flag. If checkKeyring is true, we also make sure there are
+// no problems accessing the user keyring.
func parseUserFlag(checkKeyring bool) (targetUser *user.User, err error) {
if userFlag.Value != "" {
- targetUser, err = user.Lookup(userFlag.Value)
+ if targetUser, err = user.Lookup(userFlag.Value); err != nil {
+ return nil, err
+ }
} else {
- if util.IsUserRoot() {
+ targetID := util.CurrentUserID()
+ if targetID == 0 {
return nil, ErrSpecifyUser
}
- targetUser, err = util.EffectiveUser()
- }
- if err != nil {
- return nil, err
+ targetUser = util.GetUser(targetID)
}
if checkKeyring {
- _, err = security.UserKeyringID(targetUser, true)
+ if _, err = security.UserKeyringID(targetUser, true); err != nil {
+ return nil, err
+ }
}
- return targetUser, err
+ return targetUser, nil
}
diff --git a/crypto/crypto_test.go b/crypto/crypto_test.go
index 444f847..a353052 100644
--- a/crypto/crypto_test.go
+++ b/crypto/crypto_test.go
@@ -62,10 +62,10 @@ var (
fakeInvalidPolicyKey, _ = makeKey(42, metadata.PolicyKeyLen-1)
fakeWrappingKey, _ = makeKey(17, metadata.InternalKeyLen)
- testUser, _ = util.EffectiveUser()
+ testUser = util.CurrentUser()
)
-// As the passpharase hashing function clears the passphrase, we need to make
+// As the passphrase hashing function clears the passphrase, we need to make
// a new passphrase key for each test
func fakePassphraseKey() (*Key, error) {
return NewFixedLengthKeyFromReader(bytes.NewReader(fakePassword), len(fakePassword))
@@ -613,7 +613,7 @@ func BenchmarkUnwrap(b *testing.B) {
}
}
-func BenchmarkUnwrapNolock(b *testing.B) {
+func BenchmarkUnwrapNoLock(b *testing.B) {
b.StopTimer()
UseMlock = false
diff --git a/pam/pam.go b/pam/pam.go
index 0f20f30..adcb0c2 100644
--- a/pam/pam.go
+++ b/pam/pam.go
@@ -52,8 +52,9 @@ type Handle struct {
func NewHandle(pamh unsafe.Pointer) (*Handle, error) {
var err error
h := &Handle{
- handle: (*C.pam_handle_t)(pamh),
- status: C.PAM_SUCCESS,
+ handle: (*C.pam_handle_t)(pamh),
+ status: C.PAM_SUCCESS,
+ OrigUser: util.CurrentUser(),
}
var pamUsername *C.char
@@ -65,9 +66,6 @@ func NewHandle(pamh unsafe.Pointer) (*Handle, error) {
if h.PamUser, err = user.Lookup(C.GoString(pamUsername)); err != nil {
return nil, err
}
- if h.OrigUser, err = util.EffectiveUser(); err != nil {
- return nil, err
- }
return h, nil
}
diff --git a/util/users.go b/util/users.go
new file mode 100644
index 0000000..92affa8
--- /dev/null
+++ b/util/users.go
@@ -0,0 +1,50 @@
+/*
+ * util.go - Functions for dealing with users
+ *
+ * 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 util
+
+import (
+ "fmt"
+ "os"
+ "os/user"
+ "strconv"
+)
+
+// CurrentUserID returns the uid of the effective user.
+func CurrentUserID() int {
+ return os.Geteuid()
+}
+
+// GetUser returns the user entry corresponding to the provided uid.
+func GetUser(uid int) *user.User {
+ uidString := strconv.Itoa(uid)
+ foundUser, err := user.LookupId(uidString)
+ if err != nil {
+ return &user.User{
+ Uid: uidString,
+ Username: fmt.Sprintf("[uid=%d]", uid),
+ }
+ }
+ return foundUser
+}
+
+// CurrentUser returns the user entry for the effective user.
+func CurrentUser() *user.User {
+ return GetUser(CurrentUserID())
+}
diff --git a/util/util.go b/util/util.go
index 3de4a1a..ed78519 100644
--- a/util/util.go
+++ b/util/util.go
@@ -19,15 +19,15 @@
// Package util contains useful components for simplifying Go code.
//
-// The package contains common error types (errors.go) and functions for
-// converting arrays to pointers.
+// The package contains functions missing from the standard library, error
+// utility functions, functions for converting arrays to pointers, and functions
+// for dealing with users and uids.
package util
import (
"bufio"
"math"
"os"
- "os/user"
"strconv"
"unsafe"
)
@@ -118,12 +118,7 @@ func AtoiOrPanic(input string) int {
return i
}
-// EffectiveUser returns the user entry corresponding to the effective user.
-func EffectiveUser() (*user.User, error) {
- return user.LookupId(strconv.Itoa(os.Geteuid()))
-}
-
// IsUserRoot checks if the effective user is root.
func IsUserRoot() bool {
- return os.Geteuid() == 0
+ return CurrentUserID() == 0
}