diff options
| author | Joseph Richey <joerichey94@gmail.com> | 2017-10-24 13:19:08 -0700 |
|---|---|---|
| committer | Joseph Richey <joerichey94@gmail.com> | 2017-10-24 13:21:36 -0700 |
| commit | f7b99a39152694f72104b95e6a30e245248c75d7 (patch) | |
| tree | d020baa01807d8e0e73ac7cbb2bc5edbc0c7b55e /crypto/privileges.go | |
| parent | 6de6b14a09b3695fe797e5fd59a04b3c3834641a (diff) | |
crypto: Merge with security packagerefactor
Diffstat (limited to 'crypto/privileges.go')
| -rw-r--r-- | crypto/privileges.go | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/crypto/privileges.go b/crypto/privileges.go new file mode 100644 index 0000000..c57fd30 --- /dev/null +++ b/crypto/privileges.go @@ -0,0 +1,94 @@ +/* + * privileges.go - Functions for managing users and privileges. + * + * 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 crypto + +import ( + "log" + "os" + "os/user" + + "github.com/pkg/errors" + "golang.org/x/sys/unix" + + "github.com/google/fscrypt/util" +) + +// SetThreadPrivileges temporarily drops the privileges of the current thread to +// have the effective uid/gid of the target user. The privileges can be changed +// again with another call to SetThreadPrivileges. +func SetThreadPrivileges(target *user.User) error { + euid := util.AtoiOrPanic(target.Uid) + egid := util.AtoiOrPanic(target.Gid) + if os.Geteuid() == euid { + log.Printf("Privileges already set to %q", target.Username) + return nil + } + log.Printf("Setting privileges to %q", target.Username) + + // If setting privs to root, we want to set the uid first, so we will + // then have the necessary permissions to perform the other actions. + if euid == 0 { + if err := setUids(-1, euid); err != nil { + return err + } + } + if err := setGids(-1, egid); err != nil { + return err + } + if err := setGroups(target); err != nil { + return err + } + // If not setting privs to root, we want to avoid dropping the uid + // util the very end. + if euid != 0 { + if err := setUids(-1, euid); err != nil { + return err + } + } + return nil +} + +func setUids(ruid, euid int) error { + err := unix.Setreuid(ruid, euid) + log.Printf("Setreuid(%d, %d) = %v", ruid, euid, err) + return errors.Wrapf(err, "setting uids") +} + +func setGids(rgid, egid int) error { + err := unix.Setregid(rgid, egid) + log.Printf("Setregid(%d, %d) = %v", rgid, egid, err) + return errors.Wrapf(err, "setting gids") +} + +func setGroups(target *user.User) error { + groupStrings, err := target.GroupIds() + if err != nil { + return util.SystemError(err.Error()) + } + + gids := make([]int, len(groupStrings)) + for i, groupString := range groupStrings { + gids[i] = util.AtoiOrPanic(groupString) + } + + err = unix.Setgroups(gids) + log.Printf("Setgroups(%v) = %v", gids, err) + return errors.Wrapf(err, "setting groups") +} |