fixed a problem in CryptoBox config reading
introduced "coding_guidelines.txt" for a consistent coding feeling :) added CryptoBoxRootActions for future privilege separation
This commit is contained in:
parent
b951efdd9c
commit
76ec1ee0ca
3 changed files with 149 additions and 1 deletions
|
@ -82,8 +82,10 @@ class CryptoBox:
|
|||
self.log.error("Could not find the specified configuration file (%s)" % config_file)
|
||||
sys.exit(1)
|
||||
try:
|
||||
self.cbxPrefs = configobj.ConfigObj(conf_file)
|
||||
self.cbxPrefs = configobj.ConfigObj(config_file)
|
||||
self.log.debug("found config: %s" % self.cbxPrefs.items())
|
||||
# TODO/RFC: more specific exception handling, please - or (if you want to have fun) just replace the line above with the following:
|
||||
# self.cbxPrefs = configobj.ConfigObj(obviouslyInvalidVariableName)
|
||||
except:
|
||||
self.log.error("Could not read configuration file. I give up.")
|
||||
sys.exit(1)
|
||||
|
|
132
pythonrewrite/bin2/CryptoBoxRootActions.py
Normal file
132
pythonrewrite/bin2/CryptoBoxRootActions.py
Normal file
|
@ -0,0 +1,132 @@
|
|||
#!/usr/bin/env python
|
||||
"""module for executing the programs, that need root privileges
|
||||
|
||||
Syntax:
|
||||
- program
|
||||
- device
|
||||
- [action]
|
||||
- [action args]
|
||||
"""
|
||||
|
||||
# current problem: how to identify the "cryptobox" user - to check its permissions?
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import pwd
|
||||
import grp
|
||||
|
||||
allowedProgs = {
|
||||
"sfdisk": "/sbin/sfdisk",
|
||||
"cryptsetup": "/sbin/cryptsetup",
|
||||
}
|
||||
|
||||
|
||||
# check if this user has write-access to the device
|
||||
allowedUser = "lars"
|
||||
# supply gids - otherwise the default groups of the above user are used
|
||||
#allowedGroups = [6, 1000]
|
||||
|
||||
|
||||
def isWriteableBlock(device):
|
||||
fstat = os.stat(device)
|
||||
(dev_type, perm_u, perm_g, perm_o) = (
|
||||
fstat.st_mode % 65536 / 4096,
|
||||
fstat.st_mode % 512 / 64,
|
||||
fstat.st_mode % 512 % 64 / 8,
|
||||
fstat.st_mode % 512 % 64 % 8)
|
||||
(owner_uid, owner_gid) = (fstat.st_uid, fstat.st_gid)
|
||||
(trustUserName, trustUID, groupsOfTrustUser) = getUserInfo(allowedUser)
|
||||
trustGIDs = []
|
||||
try:
|
||||
"if 'allowedGroups' are defined, then ignore the previously aquired groups"
|
||||
"TODO: for now only group ids (no names) are allowed"
|
||||
trustGIDs.extend(allowedGroups)
|
||||
except NameError:
|
||||
"'allowedGroups' was not defined - we use the default ones of the user"
|
||||
trustGIDs.extend(groupsOfTrustUser)
|
||||
except TypeError:
|
||||
"if it fails, then 'allowedGroups' was really not well defined"
|
||||
trustGIDs.append(allowedGID)
|
||||
DEF_TYPES = { "pipe":1, "char":2, "dir":4, "block":6, "file":8, "link":10, "socket":12}
|
||||
if dev_type != DEF_TYPES["block"]: return False
|
||||
# replace this access check by "os.access"
|
||||
"does the owner id match?"
|
||||
if owner_uid == trustUID:
|
||||
"is the write bit (2) set for the owner?"
|
||||
return perm_u & 2
|
||||
if owner_gid in trustGIDs:
|
||||
return perm_g & 2
|
||||
"we seem to be one of 'others' - so just check the bit"
|
||||
return perm_o & 2
|
||||
|
||||
|
||||
def run_cryptsetup(device, args):
|
||||
print "ok - you are free to call cryptsetup ..."
|
||||
print " not yet implemented ..."
|
||||
return True
|
||||
|
||||
|
||||
def run_sfdisk(device, args):
|
||||
print "ok - you are free to call sfdisk ..."
|
||||
print " not yet implemented ..."
|
||||
return True
|
||||
|
||||
|
||||
def getUserInfo(user):
|
||||
"""return information about the specified user
|
||||
|
||||
@user: (uid or name)
|
||||
@return: tuple of (name, uid, (groups))
|
||||
"""
|
||||
if user is None: raise "KeyError", "no user supplied"
|
||||
# first check, if 'user' contains an id - then check for a name
|
||||
try:
|
||||
userinfo = pwd.getpwuid(user)
|
||||
except TypeError:
|
||||
# if a KeyError is raised again, then the supplied user was invalid
|
||||
userinfo = pwd.getpwnam(user)
|
||||
u_groups =[one_group.gr_gid
|
||||
for one_group in grp.getgrall()
|
||||
if userinfo.pw_name in one_group.gr_mem]
|
||||
if not userinfo.pw_gid in u_groups: u_groups.append(userinfo.pw_gid)
|
||||
return (userinfo.pw_name, userinfo.pw_uid, u_groups)
|
||||
|
||||
|
||||
# **************** main **********************
|
||||
|
||||
# prevent import
|
||||
if __name__ == "__main__":
|
||||
|
||||
# remove program name
|
||||
sys.argv.remove(sys.argv[0])
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
sys.stderr.write("Not enough arguments supplied (%s)!\n" % " ".join(sys.argv))
|
||||
sys.exit(1)
|
||||
|
||||
progRequest = sys.argv[0]
|
||||
deviceRequest = sys.argv[1]
|
||||
sys.argv.remove(progRequest)
|
||||
sys.argv.remove(deviceRequest)
|
||||
|
||||
if not progRequest in allowedProgs.keys():
|
||||
sys.stderr.write("Invalid program requested: %s\n" % progRequest)
|
||||
sys.exit(2)
|
||||
|
||||
if not os.path.exists(deviceRequest):
|
||||
sys.stderr.write("The specified device (%s) does not exist!\n" % deviceRequest)
|
||||
sys.exit(3)
|
||||
|
||||
if not isWriteableBlock(deviceRequest):
|
||||
sys.stderr.write("This device (%s) must be a writeable block device!\n" % deviceRequest)
|
||||
sys.exit(4)
|
||||
|
||||
if progRequest == "cryptsetup": runner = run_cryptsetup
|
||||
elif progRequest == "sfdisk": runner = run_sfdisk
|
||||
else:
|
||||
sys.stderr.write("The interface for this program (%s) is not yet implemented!\n" % progRequest)
|
||||
sys.exit(1)
|
||||
|
||||
runner(deviceRequest, sys.argv)
|
||||
|
14
pythonrewrite/bin2/coding_guidelines.txt
Normal file
14
pythonrewrite/bin2/coding_guidelines.txt
Normal file
|
@ -0,0 +1,14 @@
|
|||
Maybe we can add some notes here to get a consistent coding experience :)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
comments:
|
||||
- should be usable for pydoc
|
||||
|
||||
error handling:
|
||||
- unspecific error handling is evil (try: "grep -r except: .")
|
||||
|
||||
unit testing:
|
||||
- commits with broken unit tests are evil (options: fix or disable)
|
||||
- all classes should contain exhaustive unit tests prior to the first release
|
||||
|
Loading…
Reference in a new issue