summaryrefslogtreecommitdiffstats
path: root/meta/classes/useradd-staticids.bbclass
diff options
context:
space:
mode:
authorPeter Kjellerstedt <peter.kjellerstedt@axis.com>2015-12-19 00:53:51 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2016-01-18 11:47:06 +0000
commit4f2c3525807f79d4e264d39bb70e0b8e4096355b (patch)
tree42d5d5d39a1211728bf411db722c446ba8ab1e84 /meta/classes/useradd-staticids.bbclass
parent4cbdb1577e34079550ace3d7dd8695a1934afbe1 (diff)
downloadpoky-4f2c3525807f79d4e264d39bb70e0b8e4096355b.tar.gz
useradd-staticids.bbclass: Read passwd/group files before parsing
Read and merge the passwd/group files before parsing the user and group definitions. This means they will only be read once per recipe. This solves a problem where if a user was definied in multiple files, it could generate group definitions for groups that should not be created. E.g., if the first passwd file read defines a user as: foobar::1234:::: and the second passwd file defines it as: foobar:::nogroup:The foobar user:/:/bin/sh then a foobar group would be created even if the user will use the nogroup as its primary group. (From OE-Core rev: 3149319ad997379a01d87f2b1b5d14f66541997f) Signed-off-by: Peter Kjellerstedt <peter.kjellerstedt@axis.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/classes/useradd-staticids.bbclass')
-rw-r--r--meta/classes/useradd-staticids.bbclass164
1 files changed, 91 insertions, 73 deletions
diff --git a/meta/classes/useradd-staticids.bbclass b/meta/classes/useradd-staticids.bbclass
index df4902ee9a..4e0ab1bf84 100644
--- a/meta/classes/useradd-staticids.bbclass
+++ b/meta/classes/useradd-staticids.bbclass
@@ -22,6 +22,30 @@ def update_useradd_static_config(d):
22 and return it as a list""" 22 and return it as a list"""
23 return list(itertools.islice(itertools.chain(iterable, itertools.repeat(obj)), length)) 23 return list(itertools.islice(itertools.chain(iterable, itertools.repeat(obj)), length))
24 24
25 def merge_files(file_list, exp_fields):
26 """Read each passwd/group file in file_list, split each line and create
27 a dictionary with the user/group names as keys and the split lines as
28 values. If the user/group name already exists in the dictionary, then
29 update any fields in the list with the values from the new list (if they
30 are set)."""
31 id_table = dict()
32 for conf in file_list.split():
33 if os.path.exists(conf):
34 f = open(conf, "r")
35 for line in f:
36 if line.startswith('#'):
37 continue
38 # Make sure there always are at least exp_fields elements in
39 # the field list. This allows for leaving out trailing
40 # colons in the files.
41 fields = list_extend(line.rstrip().split(":"), exp_fields)
42 if fields[0] not in id_table:
43 id_table[fields[0]] = fields
44 else:
45 id_table[fields[0]] = list(itertools.imap(lambda x, y: x or y, fields, id_table[fields[0]]))
46
47 return id_table
48
25 # We parse and rewrite the useradd components 49 # We parse and rewrite the useradd components
26 def rewrite_useradd(params): 50 def rewrite_useradd(params):
27 # The following comes from --help on useradd from shadow 51 # The following comes from --help on useradd from shadow
@@ -63,6 +87,7 @@ def update_useradd_static_config(d):
63 return str 87 return str
64 88
65 newparams = [] 89 newparams = []
90 users = None
66 for param in re.split('''[ \t]*;[ \t]*(?=(?:[^'"]|'[^']*'|"[^"]*")*$)''', params): 91 for param in re.split('''[ \t]*;[ \t]*(?=(?:[^'"]|'[^']*'|"[^"]*")*$)''', params):
67 param = param.strip() 92 param = param.strip()
68 if not param: 93 if not param:
@@ -72,10 +97,9 @@ def update_useradd_static_config(d):
72 except: 97 except:
73 raise bb.build.FuncFailed("%s: Unable to parse arguments for USERADD_PARAM_%s: '%s'" % (d.getVar('PN', True), pkg, param)) 98 raise bb.build.FuncFailed("%s: Unable to parse arguments for USERADD_PARAM_%s: '%s'" % (d.getVar('PN', True), pkg, param))
74 99
75 # files/passwd or the contents of USERADD_UID_TABLES 100 # Read all passwd files specified in USERADD_UID_TABLES or files/passwd
76 # Use the standard passwd layout: 101 # Use the standard passwd layout:
77 # username:password:user_id:group_id:comment:home_directory:login_shell 102 # username:password:user_id:group_id:comment:home_directory:login_shell
78 # (we want to process in reverse order, as 'last found' in the list wins)
79 # 103 #
80 # If a field is left blank, the original value will be used. The 'username' 104 # If a field is left blank, the original value will be used. The 'username'
81 # field is required. 105 # field is required.
@@ -84,61 +108,57 @@ def update_useradd_static_config(d):
84 # in the useradd command may introduce a security hole. It's assumed that 108 # in the useradd command may introduce a security hole. It's assumed that
85 # all new users get the default ('*' which prevents login) until the user is 109 # all new users get the default ('*' which prevents login) until the user is
86 # specifically configured by the system admin. 110 # specifically configured by the system admin.
87 for conf in get_passwd_list(d).split()[::-1]: 111 if not users:
88 if os.path.exists(conf): 112 users = merge_files(get_passwd_list(d), 7)
89 f = open(conf, "r") 113
90 for line in f: 114 if uaargs.LOGIN not in users:
91 if line.startswith('#'): 115 continue
92 continue 116
93 # Make sure there always are at least seven elements in 117 field = users[uaargs.LOGIN]
94 # the field list. This allows for leaving out trailing 118
95 # colons in the passwd file. 119 if uaargs.uid and field[2] and (uaargs.uid != field[2]):
96 field = list_extend(line.rstrip().split(":"), 7) 120 bb.warn("%s: Changing username %s's uid from (%s) to (%s), verify configuration files!" % (d.getVar('PN', True), uaargs.LOGIN, uaargs.uid, field[2]))
97 if field[0] == uaargs.LOGIN: 121 uaargs.uid = field[2] or uaargs.uid
98 if uaargs.uid and field[2] and (uaargs.uid != field[2]): 122
99 bb.warn("%s: Changing username %s's uid from (%s) to (%s), verify configuration files!" % (d.getVar('PN', True), uaargs.LOGIN, uaargs.uid, field[2])) 123 # Determine the possible groupname
100 uaargs.uid = field[2] or uaargs.uid 124 # Unless the group name (or gid) is specified, we assume that the LOGIN is the groupname
101 125 #
102 # Determine the possible groupname 126 # By default the system has creation of the matching groups enabled
103 # Unless the group name (or gid) is specified, we assume that the LOGIN is the groupname 127 # So if the implicit username-group creation is on, then the implicit groupname (LOGIN)
104 # 128 # is used, and we disable the user_group option.
105 # By default the system has creation of the matching groups enabled 129 #
106 # So if the implicit username-group creation is on, then the implicit groupname (LOGIN) 130 user_group = uaargs.user_group is None or uaargs.user_group is True
107 # is used, and we disable the user_group option. 131 uaargs.groupname = uaargs.LOGIN if user_group else uaargs.gid
108 # 132 uaargs.groupid = field[3] or uaargs.gid or uaargs.groupname
109 user_group = uaargs.user_group is None or uaargs.user_group is True 133
110 uaargs.groupname = uaargs.LOGIN if user_group else uaargs.gid 134 if uaargs.groupid and uaargs.gid != uaargs.groupid:
111 uaargs.groupid = field[3] or uaargs.gid or uaargs.groupname 135 newgroup = None
112 136 if not uaargs.groupid.isdigit():
113 if uaargs.groupid and uaargs.gid != uaargs.groupid: 137 # We don't have a group number, so we have to add a name
114 newgroup = None 138 bb.debug(1, "Adding group %s!" % uaargs.groupid)
115 if not uaargs.groupid.isdigit(): 139 newgroup = "%s %s" % (' --system' if uaargs.system else '', uaargs.groupid)
116 # We don't have a group number, so we have to add a name 140 elif uaargs.groupname and not uaargs.groupname.isdigit():
117 bb.debug(1, "Adding group %s!" % uaargs.groupid) 141 # We have a group name and a group number to assign it to
118 newgroup = "%s %s" % (' --system' if uaargs.system else '', uaargs.groupid) 142 bb.debug(1, "Adding group %s (gid %s)!" % (uaargs.groupname, uaargs.groupid))
119 elif uaargs.groupname and not uaargs.groupname.isdigit(): 143 newgroup = "-g %s %s" % (uaargs.groupid, uaargs.groupname)
120 # We have a group name and a group number to assign it to 144 else:
121 bb.debug(1, "Adding group %s (gid %s)!" % (uaargs.groupname, uaargs.groupid)) 145 # We want to add a group, but we don't know it's name... so we can't add the group...
122 newgroup = "-g %s %s" % (uaargs.groupid, uaargs.groupname) 146 # We have to assume the group has previously been added or we'll fail on the adduser...
123 else: 147 # Note: specifying the actual gid is very rare in OE, usually the group name is specified.
124 # We want to add a group, but we don't know it's name... so we can't add the group... 148 bb.warn("%s: Changing gid for login %s to %s, verify configuration files!" % (d.getVar('PN', True), uaargs.LOGIN, uaargs.groupid))
125 # We have to assume the group has previously been added or we'll fail on the adduser... 149
126 # Note: specifying the actual gid is very rare in OE, usually the group name is specified. 150 uaargs.gid = uaargs.groupid
127 bb.warn("%s: Changing gid for login %s to %s, verify configuration files!" % (d.getVar('PN', True), uaargs.LOGIN, uaargs.groupid)) 151 uaargs.user_group = None
128 152 if newgroup:
129 uaargs.gid = uaargs.groupid 153 groupadd = d.getVar("GROUPADD_PARAM_%s" % pkg, True)
130 uaargs.user_group = None 154 if groupadd:
131 if newgroup: 155 d.setVar("GROUPADD_PARAM_%s" % pkg, "%s ; %s" % (groupadd, newgroup))
132 groupadd = d.getVar("GROUPADD_PARAM_%s" % pkg, True) 156 else:
133 if groupadd: 157 d.setVar("GROUPADD_PARAM_%s" % pkg, newgroup)
134 d.setVar("GROUPADD_PARAM_%s" % pkg, "%s ; %s" % (groupadd, newgroup)) 158
135 else: 159 uaargs.comment = "'%s'" % field[4] if field[4] else uaargs.comment
136 d.setVar("GROUPADD_PARAM_%s" % pkg, newgroup) 160 uaargs.home_dir = field[5] or uaargs.home_dir
137 161 uaargs.shell = field[6] or uaargs.shell
138 uaargs.comment = "'%s'" % field[4] if field[4] else uaargs.comment
139 uaargs.home_dir = field[5] or uaargs.home_dir
140 uaargs.shell = field[6] or uaargs.shell
141 break
142 162
143 # Should be an error if a specific option is set... 163 # Should be an error if a specific option is set...
144 if d.getVar('USERADD_ERROR_DYNAMIC', True) == '1' and not ((uaargs.uid and uaargs.uid.isdigit()) and uaargs.gid): 164 if d.getVar('USERADD_ERROR_DYNAMIC', True) == '1' and not ((uaargs.uid and uaargs.uid.isdigit()) and uaargs.gid):
@@ -200,6 +220,7 @@ def update_useradd_static_config(d):
200 return str 220 return str
201 221
202 newparams = [] 222 newparams = []
223 groups = None
203 for param in re.split('''[ \t]*;[ \t]*(?=(?:[^'"]|'[^']*'|"[^"]*")*$)''', params): 224 for param in re.split('''[ \t]*;[ \t]*(?=(?:[^'"]|'[^']*'|"[^"]*")*$)''', params):
204 param = param.strip() 225 param = param.strip()
205 if not param: 226 if not param:
@@ -210,7 +231,7 @@ def update_useradd_static_config(d):
210 except: 231 except:
211 raise bb.build.FuncFailed("%s: Unable to parse arguments for GROUPADD_PARAM_%s: '%s'" % (d.getVar('PN', True), pkg, param)) 232 raise bb.build.FuncFailed("%s: Unable to parse arguments for GROUPADD_PARAM_%s: '%s'" % (d.getVar('PN', True), pkg, param))
212 233
213 # Need to iterate over layers and open the right file(s) 234 # Read all group files specified in USERADD_GID_TABLES or files/group
214 # Use the standard group layout: 235 # Use the standard group layout:
215 # groupname:password:group_id:group_members 236 # groupname:password:group_id:group_members
216 # 237 #
@@ -219,21 +240,18 @@ def update_useradd_static_config(d):
219 # 240 #
220 # Note: similar to the passwd file, the 'password' filed is ignored 241 # Note: similar to the passwd file, the 'password' filed is ignored
221 # Note: group_members is ignored, group members must be configured with the GROUPMEMS_PARAM 242 # Note: group_members is ignored, group members must be configured with the GROUPMEMS_PARAM
222 for conf in get_group_list(d).split()[::-1]: 243 if not groups:
223 if os.path.exists(conf): 244 groups = merge_files(get_group_list(d), 4)
224 f = open(conf, "r") 245
225 for line in f: 246 if gaargs.GROUP not in groups:
226 if line.startswith('#'): 247 continue
227 continue 248
228 # Make sure there always are at least four elements in 249 field = groups[gaargs.GROUP]
229 # the field list. This allows for leaving out trailing 250
230 # colons in the group file. 251 if field[2]:
231 field = list_extend(line.rstrip().split(":"), 4) 252 if gaargs.gid and (gaargs.gid != field[2]):
232 if field[0] == gaargs.GROUP and field[2]: 253 bb.warn("%s: Changing groupname %s's gid from (%s) to (%s), verify configuration files!" % (d.getVar('PN', True), gaargs.GROUP, gaargs.gid, field[2]))
233 if gaargs.gid and (gaargs.gid != field[2]): 254 gaargs.gid = field[2]
234 bb.warn("%s: Changing groupname %s's gid from (%s) to (%s), verify configuration files!" % (d.getVar('PN', True), gaargs.GROUP, gaargs.gid, field[2]))
235 gaargs.gid = field[2]
236 break
237 255
238 if d.getVar('USERADD_ERROR_DYNAMIC', True) == '1' and not (gaargs.gid and gaargs.gid.isdigit()): 256 if d.getVar('USERADD_ERROR_DYNAMIC', True) == '1' and not (gaargs.gid and gaargs.gid.isdigit()):
239 #bb.error("Skipping recipe %s, package %s which adds groupname %s does not have a static gid defined." % (d.getVar('PN', True), pkg, gaargs.GROUP)) 257 #bb.error("Skipping recipe %s, package %s which adds groupname %s does not have a static gid defined." % (d.getVar('PN', True), pkg, gaargs.GROUP))