Advertisement
Majd07

VaultShell - ComputerCraft Secure Shell

May 22nd, 2022
1,209
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 9.63 KB | None | 0 0
  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.  
  5. os.loadAPI("sha256.lua")
  6.  
  7. local _os_pullEvent = os.pullEvent
  8. os.pullEvent = os.pullEventRaw
  9.  
  10. function printColor(text,color)
  11.     local _color = term.getTextColor()
  12.     term.setTextColor(color)
  13.     print(text)
  14.     term.setTextColor(_color)
  15. end
  16.  
  17. function flushSettings()
  18.     settings.save("/.settings")
  19. end
  20.  
  21. function clearScreen()
  22.     term.setCursorPos(1,1)
  23.     term.clear()
  24. end
  25.  
  26. -- Taken from shell.lua
  27. local 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
  120. end
  121.  
  122. -- Prompting
  123.  
  124. function 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
  138. end
  139.  
  140. function promptPassword()
  141.     term.write("Password> ")
  142.     return read("*")
  143. end
  144.  
  145. function 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
  152. end
  153.  
  154. function 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
  166. end
  167.  
  168. function 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
  182. end
  183.  
  184. function 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
  196. end
  197.  
  198. function 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
  213. end
  214.  
  215. function promptSetup()
  216.     print("It looks like this is the first time you have run Vault Shell")
  217.     return promptCreateUser()
  218. end
  219.  
  220. -- User accounts
  221.  
  222. function getUserHash(usr)
  223.     return settings.get("vsh.login." .. usr)
  224. end
  225.  
  226. function userExists(usr)
  227.     return getUserHash(usr) ~= nil
  228. end
  229.  
  230. function verifyLogin(usr,pwd)
  231.     local test_hash = getUserHash(usr)
  232.     local input_hash = sha256.digestStr(pwd)
  233.  
  234.     return test_hash == input_hash
  235. end
  236.  
  237. function 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
  247. end
  248.  
  249. function setPassword(usr, pwd)
  250.     local hash = sha256.digestStr(pwd)
  251.     settings.set("vsh.login." .. usr,hash)
  252.     flushSettings()
  253.     return true
  254. end
  255.  
  256. function 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
  269. end
  270.  
  271. -- Main
  272.  
  273. function loginShell(usr)
  274.     os.pullEvent = _os_pullEvent
  275.  
  276.     shell.run("rom/programs/shell.lua")
  277.  
  278.     os.pullEvent = os.pullEventRaw
  279. end
  280.  
  281. function 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
  302. end
  303.  
  304. function 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()
  328. end
  329.  
  330. _G.vsh = _G.vsh or {}
  331.  
  332. local arg = ...
  333.  
  334. if 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
  340. elseif 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")
  346. elseif arg == "chpwd" then
  347.     local success, usr, pwd = promptChangePassword()
  348.    
  349.     if not success then
  350.         return
  351.     end
  352.  
  353.     createUser(usr, pwd)
  354. elseif 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.")
  363. elseif 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)
  376. elseif arg == "users" then
  377.     for _, user in ipairs(settings.get("vsh.users")) do
  378.         print(user)
  379.     end
  380. else
  381.     print("Unknown argument " .. arg .. ". Type vsh help for more info")
  382. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement