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