github.com/cs3org/reva/v2@v2.27.7/pkg/storage/utils/decomposedfs/usermapper/usermapper_linux.go (about) 1 // Copyright 2018-2021 CERN 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // In applying this license, CERN does not waive the privileges and immunities 16 // granted to it by virtue of its status as an Intergovernmental Organization 17 // or submit itself to any jurisdiction. 18 19 package usermapper 20 21 import ( 22 "context" 23 "fmt" 24 "os/user" 25 "runtime" 26 "strconv" 27 28 "golang.org/x/sys/unix" 29 30 revactx "github.com/cs3org/reva/v2/pkg/ctx" 31 ) 32 33 // UnixMapper is a user mapper that maps users to unix uids and gids 34 type UnixMapper struct { 35 baseUid int 36 baseGid int 37 } 38 39 // New returns a new user mapper 40 func NewUnixMapper() *UnixMapper { 41 baseUid, _ := unix.SetfsuidRetUid(-1) 42 baseGid, _ := unix.SetfsgidRetGid(-1) 43 44 return &UnixMapper{ 45 baseUid: baseUid, 46 baseGid: baseGid, 47 } 48 } 49 50 // RunInUserScope runs the given function in the scope of the base user 51 func (um *UnixMapper) RunInBaseScope(f func() error) error { 52 unscope, err := um.ScopeBase() 53 if err != nil { 54 return err 55 } 56 defer func() { _ = unscope() }() 57 58 return f() 59 } 60 61 // ScopeBase returns to the base uid and gid returning a function that can be used to restore the previous scope 62 func (um *UnixMapper) ScopeBase() (func() error, error) { 63 return um.ScopeUserByIds(-1, um.baseGid) 64 } 65 66 // ScopeUser returns to the base uid and gid returning a function that can be used to restore the previous scope 67 func (um *UnixMapper) ScopeUser(ctx context.Context) (func() error, error) { 68 u := revactx.ContextMustGetUser(ctx) 69 70 uid, gid, err := um.mapUser(u.Username) 71 if err != nil { 72 return nil, err 73 } 74 return um.ScopeUserByIds(uid, gid) 75 } 76 77 // ScopeUserByIds scopes the current user to the given uid and gid returning a function that can be used to restore the previous scope 78 func (um *UnixMapper) ScopeUserByIds(uid, gid int) (func() error, error) { 79 runtime.LockOSThread() // Lock this Goroutine to the current OS thread 80 81 var err error 82 var prevUid int 83 var prevGid int 84 if uid >= 0 { 85 prevUid, err = unix.SetfsuidRetUid(uid) 86 if err != nil { 87 return nil, err 88 } 89 if testUid, _ := unix.SetfsuidRetUid(-1); testUid != uid { 90 return nil, fmt.Errorf("failed to setfsuid to %d", uid) 91 } 92 } 93 if gid >= 0 { 94 prevGid, err = unix.SetfsgidRetGid(gid) 95 if err != nil { 96 return nil, err 97 } 98 if testGid, _ := unix.SetfsgidRetGid(-1); testGid != gid { 99 return nil, fmt.Errorf("failed to setfsgid to %d", gid) 100 } 101 } 102 103 return func() error { 104 if uid >= 0 { 105 _ = unix.Setfsuid(prevUid) 106 } 107 if gid >= 0 { 108 _ = unix.Setfsgid(prevGid) 109 } 110 runtime.UnlockOSThread() 111 return nil 112 }, nil 113 } 114 115 func (u *UnixMapper) mapUser(username string) (int, int, error) { 116 userDetails, err := user.Lookup(username) 117 if err != nil { 118 return 0, 0, err 119 } 120 121 uid, err := strconv.Atoi(userDetails.Uid) 122 if err != nil { 123 return 0, 0, err 124 } 125 gid, err := strconv.Atoi(userDetails.Gid) 126 if err != nil { 127 return 0, 0, err 128 } 129 130 return uid, gid, nil 131 }