diff --git a/pythonrewrite/bin2/CryptoBox.py b/pythonrewrite/bin2/CryptoBox.py index add05ee..e7b2d4c 100644 --- a/pythonrewrite/bin2/CryptoBox.py +++ b/pythonrewrite/bin2/CryptoBox.py @@ -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) diff --git a/pythonrewrite/bin2/CryptoBoxRootActions.py b/pythonrewrite/bin2/CryptoBoxRootActions.py new file mode 100644 index 0000000..9cc9f65 --- /dev/null +++ b/pythonrewrite/bin2/CryptoBoxRootActions.py @@ -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) + diff --git a/pythonrewrite/bin2/coding_guidelines.txt b/pythonrewrite/bin2/coding_guidelines.txt new file mode 100644 index 0000000..e5716ee --- /dev/null +++ b/pythonrewrite/bin2/coding_guidelines.txt @@ -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 +