Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Secure File System (sfs) implements file system
- -- permissions. Each file and directory has an
- -- owner and four access flags: owner read, owner
- -- write, other read , and other write. The owner
- -- read and owner write flags control the file
- -- owners access to the file. The other read and
- -- other write flags control all other users access
- -- to the file. Each directory has a .sfs file
- -- which stores permission data for that
- -- directory's files and sub-directories. If
- -- a .sfs file is not found then access to that
- -- directory is not restricted. If the .sfs file
- -- is missing an entry for a file, that file will
- -- also not have access restricted.
- --
- -- Author: GhastTearz
- -- Writen in CC Version: 1.5
- -- LICENCE: Public Domain
- -------------------------------
- -- local copy of original fs api
- local _fs = fs
- -- Returns the parent directory of path. The root
- -- directory's parent is itself ( / maps to / ). If
- -- path is relative or the path is invalid returns
- -- an empty string.
- --
- -- path is a path to a directory or file
- local function getParentDirectory(path)
- if path == "/" or path == "\\" then
- return "/"
- end
- -- remove any tailing slashes
- local lastChar = string.sub(path,#path,#path)
- if lastChar == "/" or lastChar == "\\" then
- path = string.sub(path,1,#path - 1)
- end
- for i = #path, 1, -1 do
- local char = string.sub(path,i,i)
- if char == "/" or char == "\\" then
- return string.sub(path,1,i)
- end
- end
- return ""
- end
- -- returns the components of a path as a table.
- -- example: a path of "/a/b/c" returns a table of
- -- {"/","/a/","/a/b/","/a/b/c"}
- --
- -- path is an absolute path
- local function getPathComponents(path)
- local components = {}
- for i = 1, #path do
- local char = string.sub(path,i,i)
- if char == "/" or
- char == "\\" or
- i == #path then
- table.insert(components,string.sub(path,1,i))
- end
- end
- return components
- end
- -- Same as fs.getName(), execpt an input of "/"
- -- returns "/" instead of "root"
- local function getName(path)
- if path == "/" or path == "\\" then
- return "/"
- end
- return _fs.getName(path)
- end
- -- get the sfs file table. returns nil if
- -- not successful.
- --
- -- path is an absolute path to directory
- local function getFileTable(path)
- -- get contents of sfs file
- local sfsPath = getParentDirectory(path)..".sfs"
- if not _fs.exists(sfsPath) then
- return nil
- end
- local sfsFile = _fs.open(sfsPath,"r")
- local contents = sfsFile.readAll()
- sfsFile.close()
- -- try to parse contents into a table
- local fileTable = textutils.unserialize(
- contents )
- if fileTable == nil then
- return nil
- end
- return fileTable
- end
- -- attempts to get the permission table for then
- -- file at path. Returns nil if it cannot get
- -- the file's permission table
- --
- -- path is an absolute path to a direcory
- local function getPermTable(path)
- local sfsTable = getFileTable(path)
- if sfsTable == nil then
- return nil
- end
- -- try to get the table for file at path
- local permTable = sfsTable[getName(path)]
- -- no entry for the file at path
- if permTable == nil then
- return nil
- end
- -- Check that permTable has all required fields.
- -- If any fields are missing return nil.
- if permTable["owner"] == nil or
- permTable["ownerRead"] == nil or
- permTable["ownerWrite"] == nil or
- permTable["otherRead"] == nil or
- permTable["otherWrite"] == nil then
- return nil
- end
- return permTable
- end
- -- removes an entry from an sfs file
- --
- -- path is an absolute path of file
- local function removePermTable(path)
- local sfsTable = getFileTable(path)
- if sfsTable == nil then
- return nil
- end
- sfsTable[getName(path)] = nil
- -- save to file
- local file = _fs.open(getParentDirectory(path)..".sfs","w")
- file.write(textutils.serialize(sfsTable))
- file.close()
- end
- -- adds an enrty to a sfs file
- --
- -- user is a table with a "userName" field
- -- path is an absolute path of file
- -- permTable is a permission table for the file
- local function addPermTable(user, path, permTable)
- local sfsTable = getFileTable(path)
- if sfsTable == nil then
- sfsTable = {
- [".sfs"] =
- {
- ["owner"] = "root",
- ["ownerRead"] = true,
- ["ownerWrite"] = true,
- ["otherRead"] = false,
- ["otherWrite"] = false,
- },
- }
- end
- if permTable == nil then
- permTable =
- {
- ["owner"] = user.userName,
- ["ownerRead"] = true,
- ["ownerWrite"] = true,
- ["otherRead"] = true,
- ["otherWrite"] = true,
- }
- end
- sfsTable[getName(path)] = permTable
- -- save to file
- local file = _fs.open(getParentDirectory(path)..".sfs","w")
- file.write(textutils.serialize(sfsTable))
- file.close()
- end
- -- Checks if user has read permission to the file
- -- at path. Returns false if the file does not exist.
- -- "root" user always can read.
- --
- -- user is a table with a "userName" field
- -- path is an absolute path to file
- local function hasRead(user, path)
- if not _fs.exists(path) then
- return false
- end
- if user.userName == "root" then
- return true
- end
- permTable = getPermTable(path)
- if permTable == nil then
- return true
- end
- if user.userName == permTable.owner then
- return permTable.ownerRead
- else
- return permTable.otherRead
- end
- end
- -- Checks each directory from root all the way
- -- down path if user has read access to file.
- -- If user does not have read permission an
- -- error is thrown. Returns nothing.
- --
- -- user is a table with a "userName" field
- -- path is an absolute path to a file
- local function assertHasRead(user, path)
- local pathComponents = getPathComponents(path)
- for i = 1, #pathComponents do
- local permTable = getPermTable(pathComponents[i])
- if permTable ~= nil and
- not hasRead(user,pathComponents[i]) then
- error("Cannot Access "..pathComponents[i])
- end
- end
- end
- -- Checks if user has write permission to the file
- -- at path. If the file does not exist, checks
- -- the write permission value of parent directory.
- -- The user must have read permission to parent
- -- directory in order to change an existing file.
- -- This function returns nothing. "root" user
- -- always has write access.
- --
- -- user is a table with a "userName" field
- -- path is an absolute path to a file
- local function assertHasWrite(user, path)
- if user.userName == "root" then
- return
- end
- if _fs.exists(path) then
- assertHasRead(user,getParentDirectory(path))
- local permTable = getPermTable(path)
- if permTable ~= nil then
- if permTable.owner == user.userName then
- if not permTable.ownerWrite then
- error("Cannot write to "..path)
- end
- else
- if not permTable.otherWrite then
- error("Cannot write to "..path)
- end
- end
- end
- else
- assertHasWrite(user,getParentDirectory(path))
- end
- end
- -- creates a wrapper of the fs api using sfs
- --
- -- user is a table containing a "userName" field
- local function newFs(user)
- local FS = {}
- FS.list =
- function(path)
- assertHasRead(user,path)
- return _fs.list(path)
- end
- FS.exists =
- function(path)
- assertHasRead(user,getParentDirectory(path))
- return _fs.exists(path)
- end
- FS.isDir =
- function(path)
- assertHasRead(user,getParentDirectory(path))
- return _fs.isDir(path)
- end
- FS.isReadOnly =
- function (path)
- assertHasRead(user,getParentDirectory(path))
- return _fs.isReadOnly(path) or
- (not pcall(assertHasWrite,user,path))
- end
- FS.getName = _fs.getName
- FS.getDrive =
- function(path)
- assertHasRead(user,getParentDirectory(path))
- return _fs.getDrive(path)
- end
- FS.getSize =
- function(path)
- assertHasRead(user,path)
- return _fs.getSize(path)
- end
- FS.getFreeSpace =
- function(path)
- assertHasRead(user,path) print("getting parent of "..path)
- return _fs.getFreeSpace(path)
- end
- FS.makeDir =
- function(path)
- assertHasWrite(user,getParentDirectory(path))
- addPermTable(user,path,{
- ["owner"] = user.userName,
- ["ownerRead"] = true,
- ["ownerWrite"] = true,
- ["otherRead"] = true,
- ["otherWrite"] = true,
- })
- return _fs.makeDir(path)
- end
- -- user needs access to read source and to write
- -- destination
- FS.move =
- function(fromPath, toPath)
- assertHasRead(user,fromPath)
- assertHasWrite(user,toPath)
- addPermTable(user,toPath,getPermTable(fromPath))
- removePermTable(fromPath)
- return _fs.move(fromPath, toPath)
- end
- -- user needs access to read source and to write
- -- destination
- FS.copy =
- function(fromPath, toPath)
- assertHasRead(user,fromPath)
- assertHasWrite(user,toPath)
- addPermTable(user,toPath,getPermTable(fromPath))
- return _fs.copy(fromPath,toPath)
- end
- FS.delete =
- function(path)
- assertHasWrite(user,path)
- removePermTable(path)
- return _fs.delete(path)
- end
- -- like normal combine, execpt with leading slash
- FS.combine =
- function(pathA, pathB)
- local result = _fs.combine(pathA,pathB)
- local char = string.sub(result,1,1)
- if char == "/" or char == "\\" then
- return result
- else
- return "/"..result
- end
- end
- FS.open =
- function(path, mode)
- local char = string.sub(mode,1,1)
- if char == "r" then
- assertHasRead(user,path)
- return _fs.open(path,mode)
- elseif char == "w" or char == "a" then
- assertHasWrite(user,path)
- -- if path does not exist add perm table
- if not _fs.exists(path) then
- addPermTable(user,path,{
- ["owner"] = user.userName,
- ["ownerRead"] = true,
- ["ownerWrite"] = true,
- ["otherRead"] = true,
- ["otherWrite"] = true,
- })
- end
- return _fs.open(path,mode)
- end
- end
- return FS
- end
- -- for the setter functions below
- local mainUser
- -- changes the fs api to use sfs. To prevent users
- -- from bypassing sfs, the computer will need to
- -- be rebooted to restore original fs api. start
- -- can only be called once, it removes itself.
- --
- -- user is a table with a "userName" field
- function start ( user )
- -- Check if user has userName field
- if user.userName == nil then
- error("user does not contain userName field")
- end
- mainUser = user
- _G.fs = newFs(user)
- fs = newFs(user)
- --remove this function
- _G.sfs.start = nil
- sfs.start = nil
- end
- -- sets the field of a sfs entry
- --
- -- path is an absolute path to directory
- -- field is field to be set
- -- value is the value field is set to
- local function setField(path,field,value)
- local permTable = getPermTable(path)
- if permTable == nil then
- permTable = {
- ["owner"] = mainUser.userName,
- ["ownerRead"] = true,
- ["ownerWrite"] = true,
- ["otherRead"] = true,
- ["otherWrite"] = true,
- }
- end
- permTable[field] = value
- addPermTable(mainUser,path,permTable)
- end
- -- changes owner of a file.
- -- Only "root" user can change the owner of a file
- --
- -- path is an absolute path to file
- -- newOwner is a string username of new owner
- function setOwner(path, newOwner)
- if mainUser.userName ~= "root" then
- error("Only root user may change owner")
- end
- setField(path,"owner", newOwner)
- end
- -- Sets the ownerRead flag. only the
- -- owner and root may change this value
- --
- -- path is absolute path to file
- -- flag is new boolean value for ownerRead flag
- function setOwnerRead(path, flag)
- local permTable = getPermTable(path)
- local owner = permTable.owner
- if mainUser.userName == owner or
- mainUser.userName == "root" then
- setField(path,"ownerRead", flag)
- else
- error("Only owner may set ownerRead flag")
- end
- end
- -- Sets the ownerWrite flag. only the
- -- owner and root may change this value
- --
- -- path is absolute path to file
- -- flag is new boolean value for ownerWrite flag
- function setOwnerWrite(path, flag)
- local permTable = getPermTable(path)
- local owner = permTable.owner
- if mainUser.userName == owner or
- mainUser.userName == "root" then
- setField(path,"ownerWrite", flag)
- else
- error("Only owner may set ownerWrite flag")
- end
- end
- -- Sets the otherRead flag. only the
- -- owner and root may change this value
- --
- -- path is absolute path to file
- -- flag is new boolean value for otherRead flag
- function setOtherRead(path, flag)
- local permTable = getPermTable(path)
- local owner = permTable.owner
- if mainUser.userName == owner or
- mainUser.userName == "root" then
- setField(path,"otherRead", flag)
- else
- error("Only owner may set otherRead flag")
- end
- end
- -- Sets the otherWrite flag. only the
- -- owner and root may change this value
- --
- -- path is absolute path to file
- -- flag is new boolean value for otherRead flag
- function setOtherWrite(path, flag)
- local permTable = getPermTable(path)
- local owner = permTable.owner
- if mainUser.userName == owner or
- mainUser.userName == "root" then
- setField(path,"otherWrite",flag)
- else
- error("Only owner may set ownerRead flag")
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement