podman

Форк
0
/
lookup.go 
171 строка · 4.9 Кб
1
package lookup
2

3
import (
4
	"os"
5
	"strconv"
6

7
	securejoin "github.com/cyphar/filepath-securejoin"
8
	"github.com/moby/sys/user"
9
	"github.com/sirupsen/logrus"
10
)
11

12
const (
13
	etcpasswd = "/etc/passwd"
14
	etcgroup  = "/etc/group"
15
)
16

17
// Overrides allows you to override defaults in GetUserGroupInfo.
18
type Overrides struct {
19
	DefaultUser            *user.ExecUser
20
	ContainerEtcPasswdPath string
21
	ContainerEtcGroupPath  string
22
}
23

24
// GetUserGroupInfo takes string forms of the container's mount path and the container user and
25
// returns an ExecUser with uid, gid, sgids, and home.  And override can be provided for defaults.
26
func GetUserGroupInfo(containerMount, containerUser string, override *Overrides) (*user.ExecUser, error) {
27
	var (
28
		passwdDest, groupDest string
29
		defaultExecUser       *user.ExecUser
30
		err                   error
31
	)
32

33
	if override != nil {
34
		// Check for an override /etc/passwd path
35
		if override.ContainerEtcPasswdPath != "" {
36
			passwdDest = override.ContainerEtcPasswdPath
37
		}
38
		// Check for an override for /etc/group path
39
		if override.ContainerEtcGroupPath != "" {
40
			groupDest = override.ContainerEtcGroupPath
41
		}
42
	}
43

44
	if passwdDest == "" {
45
		// Make sure the /etc/passwd destination is not a symlink to something naughty
46
		if passwdDest, err = securejoin.SecureJoin(containerMount, etcpasswd); err != nil {
47
			logrus.Debug(err)
48
			return nil, err
49
		}
50
	}
51
	if groupDest == "" {
52
		// Make sure the /etc/group destination is not a symlink to something naughty
53
		if groupDest, err = securejoin.SecureJoin(containerMount, etcgroup); err != nil {
54
			logrus.Debug(err)
55
			return nil, err
56
		}
57
	}
58

59
	// Check for an override default user
60
	if override != nil && override.DefaultUser != nil {
61
		defaultExecUser = override.DefaultUser
62
	} else {
63
		// Define a default container user
64
		// defaultExecUser = &user.ExecUser{
65
		//	Uid:  0,
66
		//	Gid:  0,
67
		//	Home: "/",
68
		defaultExecUser = nil
69
	}
70

71
	return user.GetExecUserPath(containerUser, defaultExecUser, passwdDest, groupDest)
72
}
73

74
// GetContainerGroups uses securejoin to get a list of numerical groupids from a container. Per the runc
75
// function it calls: If a group name cannot be found, an error will be returned. If a group id cannot be found,
76
// or the given group data is nil, the id will be returned as-is  provided it is in the legal range.
77
func GetContainerGroups(groups []string, containerMount string, override *Overrides) ([]uint32, error) {
78
	var (
79
		groupDest string
80
		err       error
81
	)
82

83
	groupPath := etcgroup
84
	if override != nil && override.ContainerEtcGroupPath != "" {
85
		groupPath = override.ContainerEtcGroupPath
86
	}
87

88
	if groupDest, err = securejoin.SecureJoin(containerMount, groupPath); err != nil {
89
		logrus.Debug(err)
90
		return nil, err
91
	}
92

93
	gids, err := user.GetAdditionalGroupsPath(groups, groupDest)
94
	if err != nil {
95
		return nil, err
96
	}
97
	uintgids := make([]uint32, 0, len(gids))
98
	// For libpod, we want []uint32s
99
	for _, gid := range gids {
100
		uintgids = append(uintgids, uint32(gid))
101
	}
102
	return uintgids, nil
103
}
104

105
// GetUser takes a containermount path and user name or ID and returns
106
// a matching User structure from /etc/passwd.  If it cannot locate a user
107
// with the provided information, an ErrNoPasswdEntries is returned.
108
// When the provided user name was an ID, a User structure with Uid
109
// set is returned along with ErrNoPasswdEntries.
110
func GetUser(containerMount, userIDorName string) (*user.User, error) {
111
	var inputIsName bool
112
	uid, err := strconv.Atoi(userIDorName)
113
	if err != nil {
114
		inputIsName = true
115
	}
116
	passwdDest, err := securejoin.SecureJoin(containerMount, etcpasswd)
117
	if err != nil {
118
		return nil, err
119
	}
120
	users, err := user.ParsePasswdFileFilter(passwdDest, func(u user.User) bool {
121
		if inputIsName {
122
			return u.Name == userIDorName
123
		}
124
		return u.Uid == uid
125
	})
126
	if err != nil && !os.IsNotExist(err) {
127
		return nil, err
128
	}
129
	if len(users) > 0 {
130
		return &users[0], nil
131
	}
132
	if !inputIsName {
133
		return &user.User{Uid: uid}, user.ErrNoPasswdEntries
134
	}
135
	return nil, user.ErrNoPasswdEntries
136
}
137

138
// GetGroup takes a containermount path and a group name or ID and returns
139
// a match Group struct from /etc/group.  If it cannot locate a group,
140
// an ErrNoGroupEntries error is returned.  When the provided group name
141
// was an ID, a Group structure with Gid set is returned along with
142
// ErrNoGroupEntries.
143
func GetGroup(containerMount, groupIDorName string) (*user.Group, error) {
144
	var inputIsName bool
145
	gid, err := strconv.Atoi(groupIDorName)
146
	if err != nil {
147
		inputIsName = true
148
	}
149

150
	groupDest, err := securejoin.SecureJoin(containerMount, etcgroup)
151
	if err != nil {
152
		return nil, err
153
	}
154

155
	groups, err := user.ParseGroupFileFilter(groupDest, func(g user.Group) bool {
156
		if inputIsName {
157
			return g.Name == groupIDorName
158
		}
159
		return g.Gid == gid
160
	})
161
	if err != nil && !os.IsNotExist(err) {
162
		return nil, err
163
	}
164
	if len(groups) > 0 {
165
		return &groups[0], nil
166
	}
167
	if !inputIsName {
168
		return &user.Group{Gid: gid}, user.ErrNoGroupEntries
169
	}
170
	return nil, user.ErrNoGroupEntries
171
}
172

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.