@@ -16,7 +16,7 @@ import (
16
16
17
17
type User struct {
18
18
User string
19
- Uid uint32 //nolint:revive
19
+ Uid uint32
20
20
Group string
21
21
Gid uint32
22
22
Home string
@@ -30,6 +30,14 @@ type Group struct {
30
30
var users map [string ]User
31
31
var groups map [string ]Group
32
32
33
+ // regexUsername matches user and group names to be valid for `useradd`.
34
+ // `useradd` allows names with a trailing '$', but it feels prudent to map those
35
+ // names to the fallback user as well, so the regex does not allow them.
36
+ var regexUsername = regexp .MustCompile ("^[a-z_][a-z0-9_-]*$" )
37
+
38
+ // regexPath detects valid Linux path.
39
+ var regexPath = regexp .MustCompile ("^[/a-zA-Z0-9_-]+$" )
40
+
33
41
func LookupUser (name string ) (User , error ) {
34
42
if users == nil {
35
43
users = make (map [string ]User )
@@ -43,15 +51,15 @@ func LookupUser(name string) (User, error) {
43
51
if err != nil {
44
52
return User {}, err
45
53
}
46
- uid , err := strconv . ParseUint (u .Uid , 10 , 32 )
54
+ uid , err := parseUidGid (u .Uid )
47
55
if err != nil {
48
56
return User {}, err
49
57
}
50
- gid , err := strconv . ParseUint (u .Gid , 10 , 32 )
58
+ gid , err := parseUidGid (u .Gid )
51
59
if err != nil {
52
60
return User {}, err
53
61
}
54
- users [name ] = User {User : u .Username , Uid : uint32 ( uid ) , Group : g .Name , Gid : uint32 ( gid ) , Home : u .HomeDir }
62
+ users [name ] = User {User : u .Username , Uid : uid , Group : g .Name , Gid : gid , Home : u .HomeDir }
55
63
}
56
64
return users [name ], nil
57
65
}
@@ -65,18 +73,18 @@ func LookupGroup(name string) (Group, error) {
65
73
if err != nil {
66
74
return Group {}, err
67
75
}
68
- gid , err := strconv . ParseUint (g .Gid , 10 , 32 )
76
+ gid , err := parseUidGid (g .Gid )
69
77
if err != nil {
70
78
return Group {}, err
71
79
}
72
- groups [name ] = Group {Name : g .Name , Gid : uint32 ( gid ) }
80
+ groups [name ] = Group {Name : g .Name , Gid : gid }
73
81
}
74
82
return groups [name ], nil
75
83
}
76
84
77
85
const (
78
86
fallbackUser = "lima"
79
- fallbackUid = 1000 //nolint:revive
87
+ fallbackUid = 1000
80
88
fallbackGid = 1000
81
89
)
82
90
@@ -101,12 +109,9 @@ func LimaUser(warn bool) (*user.User, error) {
101
109
cache .Do (func () {
102
110
cache .u , cache .err = user .Current ()
103
111
if cache .err == nil {
104
- // `useradd` only allows user and group names matching the following pattern:
105
- // (it allows a trailing '$', but it feels prudent to map those to the fallback user as well)
106
- validName := "^[a-z_][a-z0-9_-]*$"
107
- if ! regexp .MustCompile (validName ).Match ([]byte (cache .u .Username )) {
112
+ if ! regexUsername .MatchString (cache .u .Username ) {
108
113
warning := fmt .Sprintf ("local user %q is not a valid Linux username (must match %q); using %q username instead" ,
109
- cache .u .Username , validName , fallbackUser )
114
+ cache .u .Username , regexUsername . String () , fallbackUser )
110
115
cache .warnings = append (cache .warnings , warning )
111
116
cache .u .Username = fallbackUser
112
117
}
@@ -115,29 +120,29 @@ func LimaUser(warn bool) (*user.User, error) {
115
120
if err != nil {
116
121
logrus .Debug (err )
117
122
}
118
- uid , err := strconv . ParseUint (idu , 10 , 32 )
123
+ uid , err := parseUidGid (idu )
119
124
if err != nil {
120
125
uid = fallbackUid
121
126
}
122
- if ! regexp . MustCompile ( "^[0-9]+$" ). Match ([] byte ( cache .u .Uid )) {
127
+ if _ , err := parseUidGid ( cache .u .Uid ); err != nil {
123
128
warning := fmt .Sprintf ("local uid %q is not a valid Linux uid (must be integer); using %d uid instead" ,
124
129
cache .u .Uid , uid )
125
130
cache .warnings = append (cache .warnings , warning )
126
- cache .u .Uid = fmt . Sprintf ( "%d" , uid )
131
+ cache .u .Uid = formatUidGid ( uid )
127
132
}
128
133
idg , err := call ([]string {"id" , "-g" })
129
134
if err != nil {
130
135
logrus .Debug (err )
131
136
}
132
- gid , err := strconv . ParseUint (idg , 10 , 32 )
137
+ gid , err := parseUidGid (idg )
133
138
if err != nil {
134
139
gid = fallbackGid
135
140
}
136
- if ! regexp . MustCompile ( "^[0-9]+$" ). Match ([] byte ( cache .u .Gid )) {
141
+ if _ , err := parseUidGid ( cache .u .Gid ); err != nil {
137
142
warning := fmt .Sprintf ("local gid %q is not a valid Linux gid (must be integer); using %d gid instead" ,
138
143
cache .u .Gid , gid )
139
144
cache .warnings = append (cache .warnings , warning )
140
- cache .u .Gid = fmt . Sprintf ( "%d" , gid )
145
+ cache .u .Gid = formatUidGid ( gid )
141
146
}
142
147
home , err := call ([]string {"cygpath" , cache .u .HomeDir })
143
148
if err != nil {
@@ -150,10 +155,9 @@ func LimaUser(warn bool) (*user.User, error) {
150
155
prefix := strings .ToLower (fmt .Sprintf ("/%c" , drive [0 ]))
151
156
home = strings .Replace (home , drive , prefix , 1 )
152
157
}
153
- validPath := "^[/a-zA-Z0-9_-]+$"
154
- if ! regexp .MustCompile (validPath ).Match ([]byte (cache .u .HomeDir )) {
158
+ if ! regexPath .MatchString (cache .u .HomeDir ) {
155
159
warning := fmt .Sprintf ("local home %q is not a valid Linux path (must match %q); using %q home instead" ,
156
- cache .u .HomeDir , validPath , home )
160
+ cache .u .HomeDir , regexPath . String () , home )
157
161
cache .warnings = append (cache .warnings , warning )
158
162
cache .u .HomeDir = home
159
163
}
@@ -167,3 +171,17 @@ func LimaUser(warn bool) (*user.User, error) {
167
171
}
168
172
return cache .u , cache .err
169
173
}
174
+
175
+ // parseUidGid converts string value to Linux uid or gid.
176
+ func parseUidGid (uidOrGid string ) (uint32 , error ) {
177
+ res , err := strconv .ParseUint (uidOrGid , 10 , 32 )
178
+ if err != nil {
179
+ return 0 , err
180
+ }
181
+ return uint32 (res ), nil
182
+ }
183
+
184
+ // formatUidGid converts uid or gid to string value.
185
+ func formatUidGid (uidOrGid uint32 ) string {
186
+ return strconv .FormatUint (uint64 (uidOrGid ), 10 )
187
+ }
0 commit comments