· 3 years ago · May 22, 2022, 05:30 PM
1-- Vault Shell v1.0
2-- by Majd123mc
3-- Licensed under CCPL which may be found here: https://github.com/dan200/ComputerCraft/blob/master/LICENSE
4
5os.loadAPI("sha256.lua")
6
7local _os_pullEvent = os.pullEvent
8os.pullEvent = os.pullEventRaw
9
10function printColor(text,color)
11 local _color = term.getTextColor()
12 term.setTextColor(color)
13 print(text)
14 term.setTextColor(_color)
15end
16
17function flushSettings()
18 settings.save("/.settings")
19end
20
21function clearScreen()
22 term.setCursorPos(1,1)
23 term.clear()
24end
25
26-- Taken from shell.lua
27local function createShellEnv( sDir )
28 local tEnv = {}
29 tEnv[ "shell" ] = shell
30 tEnv[ "multishell" ] = multishell
31
32 local package = {}
33 package.loaded = {
34 _G = _G,
35 bit32 = bit32,
36 coroutine = coroutine,
37 math = math,
38 package = package,
39 string = string,
40 table = table,
41 }
42 package.path = "?;?.lua;?/init.lua;/rom/modules/main/?;/rom/modules/main/?.lua;/rom/modules/main/?/init.lua"
43 if turtle then
44 package.path = package.path..";/rom/modules/turtle/?;/rom/modules/turtle/?.lua;/rom/modules/turtle/?/init.lua"
45 elseif command then
46 package.path = package.path..";/rom/modules/command/?;/rom/modules/command/?.lua;/rom/modules/command/?/init.lua"
47 end
48 package.config = "/\n;\n?\n!\n-"
49 package.preload = {}
50 package.loaders = {
51 function( name )
52 if package.preload[name] then
53 return package.preload[name]
54 else
55 return nil, "no field package.preload['" .. name .. "']"
56 end
57 end,
58 function( name )
59 local fname = string.gsub(name, "%.", "/")
60 local sError = ""
61 for pattern in string.gmatch(package.path, "[^;]+") do
62 local sPath = string.gsub(pattern, "%?", fname)
63 if sPath:sub(1,1) ~= "/" then
64 sPath = fs.combine(sDir, sPath)
65 end
66 if fs.exists(sPath) and not fs.isDir(sPath) then
67 local fnFile, sError = loadfile( sPath, tEnv )
68 if fnFile then
69 return fnFile, sPath
70 else
71 return nil, sError
72 end
73 else
74 if #sError > 0 then
75 sError = sError .. "\n"
76 end
77 sError = sError .. "no file '" .. sPath .. "'"
78 end
79 end
80 return nil, sError
81 end
82 }
83
84 local sentinel = {}
85 local function require( name )
86 if type( name ) ~= "string" then
87 error( "bad argument #1 (expected string, got " .. type( name ) .. ")", 2 )
88 end
89 if package.loaded[name] == sentinel then
90 error("Loop detected requiring '" .. name .. "'", 0)
91 end
92 if package.loaded[name] then
93 return package.loaded[name]
94 end
95
96 local sError = "Error loading module '" .. name .. "':"
97 for n,searcher in ipairs(package.loaders) do
98 local loader, err = searcher(name)
99 if loader then
100 package.loaded[name] = sentinel
101 local result = loader( err )
102 if result ~= nil then
103 package.loaded[name] = result
104 return result
105 else
106 package.loaded[name] = true
107 return true
108 end
109 else
110 sError = sError .. "\n" .. err
111 end
112 end
113 error(sError, 2)
114 end
115
116 tEnv["package"] = package
117 tEnv["require"] = require
118
119 return tEnv
120end
121
122-- Prompting
123
124function promptUsername()
125 term.write("Username> ")
126 local usr = read()
127
128 if not usr then
129 return nil
130 end
131
132 if not usr:match("[a-zA-Z0-9_]+") then
133 print("Invalid username. Usernames may only contain letters, numbers, and underscores")
134 return promptUsername()
135 end
136
137 return usr
138end
139
140function promptPassword()
141 term.write("Password> ")
142 return read("*")
143end
144
145function promptLogin()
146 print("Please enter your credentials:")
147 local usr = promptUsername()
148 if not usr then return false end
149 local pwd = promptPassword()
150
151 return true,usr,pwd
152end
153
154function promptConfirmPwd(new)
155 term.write((new and "New " or "") .. "Password> ")
156 local pwd = read("*")
157 term.write("Confirm> ")
158 local con = read("*")
159
160 if pwd == con then
161 return pwd
162 else
163 print("Passowrds do not match. Please try again")
164 return promptConfirmPwd()
165 end
166end
167
168function promptChangePassword()
169 print("Please enter username and new credentials")
170 local usr = promptUsername()
171
172 if not usr then
173 return false
174 elseif not userExists(usr) then
175 print("No such user exists")
176 return false
177 end
178
179 local pwd = promptConfirmPwd(true)
180
181 return true,usr,pwd
182end
183
184function promptDeleteUser()
185 print("Enter the username for the account to be deleted")
186 local usr = promptUsername()
187
188 if not usr then
189 return false
190 elseif not userExists(usr) then
191 print("No such user exists")
192 return false
193 end
194
195 return true, usr
196end
197
198function promptCreateUser()
199 --print("It looks like this is the first time you have run Vault Shell")
200 print("Please enter credentials for new account")
201 local usr = promptUsername()
202
203 if not usr then
204 return false
205 elseif userExists(usr) then
206 print("A user with that name already exists. Please try again")
207 return promptCreateUser()
208 end
209
210 local pwd = promptConfirmPwd()
211
212 return true,usr,pwd
213end
214
215function promptSetup()
216 print("It looks like this is the first time you have run Vault Shell")
217 return promptCreateUser()
218end
219
220-- User accounts
221
222function getUserHash(usr)
223 return settings.get("vsh.login." .. usr)
224end
225
226function userExists(usr)
227 return getUserHash(usr) ~= nil
228end
229
230function verifyLogin(usr,pwd)
231 local test_hash = getUserHash(usr)
232 local input_hash = sha256.digestStr(pwd)
233
234 return test_hash == input_hash
235end
236
237function createUser(usr,pwd)
238 local hash = sha256.digestStr(pwd)
239 settings.set("vsh.login." .. usr,hash)
240
241 local users = settings.get("vsh.users") or {}
242 table.insert(users, usr)
243 settings.set("vsh.users", users)
244
245 flushSettings()
246 return true
247end
248
249function setPassword(usr, pwd)
250 local hash = sha256.digestStr(pwd)
251 settings.set("vsh.login." .. usr,hash)
252 flushSettings()
253 return true
254end
255
256function deleteUser(usr)
257 settings.unset("vsh.login." .. usr)
258
259 local users = settings.get("vsh.users") or {}
260 for i, usr2 in ipairs(users) do
261 if usr2 == usr then
262 table.remove(users, i)
263 end
264 end
265 settings.set("vsh.users", users)
266
267 flushSettings()
268 return true
269end
270
271-- Main
272
273function loginShell(usr)
274 os.pullEvent = _os_pullEvent
275
276 shell.run("rom/programs/shell.lua")
277
278 os.pullEvent = os.pullEventRaw
279end
280
281function mainLogin()
282 local success,usr,pwd = promptLogin()
283 if not success then
284 print("Please enter a username to log in")
285 mainLogin()
286 end
287
288 local validLogin = verifyLogin(usr,pwd)
289 if validLogin then
290 print("Login successful!\n")
291
292 _G.vsh.usr = usr
293 loginShell(usr,pwd)
294 _G.vsh.usr = nil
295
296 clearScreen()
297 mainLogin()
298 else
299 print("Invalid credentials. Please try again")
300 mainLogin()
301 end
302end
303
304function init()
305 clearScreen()
306 printColor("Vault Shell v1.0 - Majd123mc 2022\n",colors.yellow)
307
308 multishell.setTitle(multishell.getCurrent(), "vsh")
309
310 local setupComplete = settings.get("vsh.setup")
311
312 if not setupComplete then
313 local success,usr,pwd = promptSetup()
314 if not success then
315 print("You must create a user to use Vault Shell. Exiting to CraftOS")
316 shell.run("sh")
317 return
318 end
319
320 createUser(usr,pwd)
321 settings.set("vsh.setup",true)
322 flushSettings()
323
324 print("Account created successfully. You must reenter your credentials to log in.\n")
325 end
326
327 mainLogin()
328end
329
330_G.vsh = _G.vsh or {}
331
332local arg = ...
333
334if not arg then
335 if not _G.vsh.usr then
336 init()
337 else
338 print("Already logged in. Type exit to log out")
339 end
340elseif arg == "help" then
341 print("vsh help - View help")
342 print("vsh chpwd - Change password")
343 print("vsh add - Add user")
344 print("vsh del - Remove user")
345 print("vsh users - List users")
346elseif arg == "chpwd" then
347 local success, usr, pwd = promptChangePassword()
348
349 if not success then
350 return
351 end
352
353 createUser(usr, pwd)
354elseif arg == "add" then
355 local success, usr, pwd = promptCreateUser()
356 if not success then
357 print("Error")
358 return
359 end
360
361 createUser(usr, pwd)
362 print("Account created successfully.")
363elseif arg == "del" then
364 if #settings.get("vsh.users") <= 1 then
365 print("At least one user must exist on the system")
366 return
367 end
368
369 local success, usr = promptDeleteUser()
370
371 if not success then
372 return
373 end
374
375 deleteUser(usr)
376elseif arg == "users" then
377 for _, user in ipairs(settings.get("vsh.users")) do
378 print(user)
379 end
380else
381 print("Unknown argument " .. arg .. ". Type vsh help for more info")
382end