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:
lars 2006-08-21 08:09:05 +00:00
parent b951efdd9c
commit 76ec1ee0ca
3 changed files with 149 additions and 1 deletions

View file

@ -82,8 +82,10 @@ class CryptoBox:
self.log.error("Could not find the specified configuration file (%s)" % config_file) self.log.error("Could not find the specified configuration file (%s)" % config_file)
sys.exit(1) sys.exit(1)
try: try:
self.cbxPrefs = configobj.ConfigObj(conf_file) self.cbxPrefs = configobj.ConfigObj(config_file)
self.log.debug("found config: %s" % self.cbxPrefs.items()) 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: except:
self.log.error("Could not read configuration file. I give up.") self.log.error("Could not read configuration file. I give up.")
sys.exit(1) sys.exit(1)

View 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)

View 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