1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
|
-- SPDX-License-Identifier: BSD-2-Clause
--
-- Copyright(c) 2022 Baptiste Daroussin <bapt@FreeBSD.org>
local pu = require("posix.unistd")
local function warnmsg(str)
io.stderr:write(str.."\n")
end
local function errmsg(str)
io.stderr:write(str.."\n")
os.exit(1)
end
local function dirname(oldpath)
if not oldpath then
return nil
end
local path = oldpath:gsub("[^/]+/*$", "")
if path == "" then
return nil
end
return path
end
local function mkdir_p(path)
if lfs.attributes(path, "mode") ~= nil then
return true
end
local r,err = mkdir_p(dirname(path))
if not r then
return nil,err.." (creating "..path..")"
end
return lfs.mkdir(path)
end
local function sethostname(hostname)
if hostname == nil then return end
local root = os.getenv("NUAGE_FAKE_ROOTDIR")
if not root then
root = ""
end
local hostnamepath = root .. "/etc/rc.conf.d/hostname"
mkdir_p(dirname(hostnamepath))
local f,err = io.open(hostnamepath, "w")
if not f then
warnmsg("Impossible to open "..hostnamepath .. ":" ..err)
return
end
f:write("hostname=\""..hostname.."\"\n")
f:close()
end
local function splitlist(list)
local ret = {}
if type(list) == "string" then
for str in list:gmatch("([^, ]+)") do
ret[#ret + 1] = str
end
elseif type(list) == "table" then
ret = list
else
warnmsg("Invalid type ".. type(list) ..", expecting table or string")
end
return ret
end
local function adduser(pwd)
if (type(pwd) ~= "table") then
warnmsg("Argument should be a table")
return nil
end
local f = io.popen("getent passwd "..pwd.name)
local pwdstr = f:read("*a")
f:close()
if pwdstr:len() ~= 0 then
return pwdstr:match("%a+:.+:%d+:%d+:.*:(.*):.*")
end
if not pwd.gecos then
pwd.gecos = pwd.name .. " User"
end
if not pwd.home then
pwd.home = "/home/" .. pwd.name
end
local extraargs=""
if pwd.groups then
local list = splitlist(pwd.groups)
extraargs = " -G ".. table.concat(list, ',')
end
-- pw will automatically create a group named after the username
-- do not add a -g option in this case
if pwd.primary_group and pwd.primary_group ~= pwd.name then
extraargs = extraargs .. " -g " .. pwd.primary_group
end
if not pwd.no_create_home then
extraargs = extraargs .. " -m "
end
if not pwd.shell then
pwd.shell = "/bin/sh"
end
local precmd = ""
local postcmd = ""
if pwd.passwd then
precmd = "echo "..pwd.passwd .. "| "
postcmd = " -H 0 "
elseif pwd.plain_text_passwd then
precmd = "echo "..pwd.plain_text_passwd .. "| "
postcmd = " -H 0 "
end
local root = os.getenv("NUAGE_FAKE_ROOTDIR")
local cmd = precmd .. "pw "
if root then
cmd = cmd .. "-R " .. root .. " "
end
cmd = cmd .. "useradd -n ".. pwd.name .. " -M 0755 -w none "
cmd = cmd .. extraargs .. " -c '".. pwd.gecos
cmd = cmd .. "' -d '" .. pwd.home .. "' -s "..pwd.shell .. postcmd
local r = os.execute(cmd)
if not r then
warnmsg("nuageinit: fail to add user "..pwd.name);
warnmsg(cmd)
return nil
end
if pwd.locked then
cmd = "pw "
if root then
cmd = cmd .. "-R " .. root .. " "
end
cmd = cmd .. "lock " .. pwd.name
os.execute(cmd)
end
return pwd.home
end
local function addgroup(grp)
if (type(grp) ~= "table") then
warnmsg("Argument should be a table")
return false
end
local f = io.popen("getent group "..grp.name)
local grpstr = f:read("*a")
f:close()
if grpstr:len() ~= 0 then
return true
end
local extraargs = ""
if grp.members then
local list = splitlist(grp.members)
extraargs = " -M " .. table.concat(list, ',')
end
local root = os.getenv("NUAGE_FAKE_ROOTDIR")
local cmd = "pw "
if root then
cmd = cmd .. "-R " .. root .. " "
end
cmd = cmd .. "groupadd -n ".. grp.name .. extraargs
local r = os.execute(cmd)
if not r then
warnmsg("nuageinit: fail to add group ".. grp.name);
warnmsg(cmd)
return false
end
return true
end
local function addsshkey(homedir, key)
local chownak = false
local chowndotssh = false
local ak_path = homedir .. "/.ssh/authorized_keys"
local dotssh_path = homedir .. "/.ssh"
local dirattrs = lfs.attributes(ak_path)
if dirattrs == nil then
chownak = true
dirattrs = lfs.attributes(dotssh_path)
if dirattrs == nil then
if not lfs.mkdir(dotssh_path) then
warnmsg("nuageinit: impossible to create ".. dotssh_path)
return
end
chowndotssh = true
dirattrs = lfs.attributes(homedir)
end
end
local f = io.open(ak_path, "a")
if not f then
warnmsg("nuageinit: impossible to open "..ak_path)
return
end
f:write(key .. "\n")
f:close()
if chownak then
pu.chown(ak_path, dirattrs.uid, dirattrs.gid)
end
if chowndotssh then
pu.chown(dotssh_path, dirattrs.uid, dirattrs.gid)
end
end
local n = {
warn = warnmsg,
err = errmsg,
sethostname = sethostname,
adduser = adduser,
addgroup = addgroup,
addsshkey = addsshkey,
dirname = dirname,
mkdir_p = mkdir_p,
}
return n
|