(original) (raw)
from ctypes import Structure, POINTER, c_int, CDLL, pointer, cast from ctypes.util import find_library """Opaque c capabilities structure.""" class __c_cap_s(Structure): pass """Capabilities.""" c_cap_t = POINTER(__c_cap_s) """Capabilities values.""" c_cap_value_t = c_int CAP_CHOWN = 0 CAP_DAOVERRIDE = 1 CAP_DAREAD_SEARCH = 2 CAP_FOWNER = 3 CAP_FSETID = 4 CAP_KILL = 5 CAP_SETGID = 6 CAP_SETUID = 7 CAP_SETPCAP = 8 CAP_LINUX_IMMUTABLE = 9 CAP_NET_BIND_SERVICE = 10 CAP_NET_BROADCAST = 11 CAP_NET_ADMIN = 12 CAP_NET_RAW = 13 CAP_IPLOCK = 14 CAP_IPOWNER = 15 CAP_SYS_MODULE = 16 CAP_SYS_RAWIO = 17 CAP_SYS_CHROOT = 18 CAP_SYS_PTRACE = 19 CAP_SYS_PACCT = 20 CAP_SYS_ADMIN = 21 CAP_SYS_BOOT = 22 CAP_SYS_NICE = 23 CAP_SYS_RESOURCE = 24 CAP_SYS_TIME = 25 CAP_SYS_TTY_CONFIG = 26 CAP_MKNOD = 27 CAP_LEASE = 28 CAP_FS_MASK = 31 """Capability value data.""" c_cap_value_data = {CAP_CHOWN : ("CAP_CHOWN", CAP_CHOWN), CAP_DAOVERRIDE : ("CAP_DAOVERRIDE", CAP_DAOVERRIDE), CAP_DAREAD_SEARCH : ("CAP_DAREAD_SEARCH", CAP_DAREAD_SEARCH), CAP_FOWNER : ("CAP_FOWNER", CAP_FOWNER), CAP_FSETID : ("CAP_FSETID", CAP_FSETID), CAP_KILL : ("CAP_KILL", CAP_KILL), CAP_SETGID : ("CAP_SETGID", CAP_SETGID), CAP_SETUID : ("CAP_SETUID", CAP_SETUID), CAP_SETPCAP : ("CAP_SETPCAP", CAP_SETPCAP), CAP_LINUX_IMMUTABLE : ("CAP_LINUX_IMMUTABLE", CAP_LINUX_IMMUTABLE), CAP_NET_BIND_SERVICE : ("CAP_NET_BIND_SERVICE", CAP_NET_BIND_SERVICE), CAP_NET_BROADCAST : ("CAP_NET_BROADCAST", CAP_NET_BROADCAST), CAP_NET_ADMIN : ("CAP_NET_ADMIN", CAP_NET_ADMIN), CAP_NET_RAW : ("CAP_NET_RAW", CAP_NET_RAW), CAP_IPLOCK : ("CAP_IPLOCK", CAP_IPLOCK), CAP_IPOWNER : ("CAP_IPOWNER", CAP_IPOWNER), CAP_SYS_MODULE : ("CAP_SYS_MODULE", CAP_SYS_MODULE), CAP_SYS_RAWIO : ("CAP_SYS_RAWIO", CAP_SYS_RAWIO), CAP_SYS_CHROOT : ("CAP_SYS_CHROOT", CAP_SYS_CHROOT), CAP_SYS_PTRACE : ("CAP_SYS_PTRACE", CAP_SYS_PTRACE), CAP_SYS_PACCT : ("CAP_SYS_PACCT", CAP_SYS_PACCT), CAP_SYS_ADMIN : ("CAP_SYS_ADMIN", CAP_SYS_ADMIN), CAP_SYS_BOOT : ("CAP_SYS_BOOT", CAP_SYS_BOOT), CAP_SYS_NICE : ("CAP_SYS_NICE", CAP_SYS_NICE), CAP_SYS_RESOURCE : ("CAP_SYS_RESOURCE", CAP_SYS_RESOURCE), CAP_SYS_TIME : ("CAP_SYS_TIME", CAP_SYS_TIME), CAP_SYS_TTY_CONFIG : ("CAP_SYS_TTY_CONFIG", CAP_SYS_TTY_CONFIG), CAP_MKNOD : ("CAP_MKNOD", CAP_MKNOD), CAP_LEASE : ("CAP_LEASE", CAP_LEASE), CAP_FS_MASK : ("CAP_FS_MASK", CAP_FS_MASK)} """Capability flags.""" c_cap_flag_t = c_int CAP_EFFECTIVE = 0 CAP_PERMITTED = 1 CAP_INHERITABLE = 2 """Capability flag data.""" c_cap_flag_data = {CAP_EFFECTIVE : ("CAP_EFFECTIVE", CAP_EFFECTIVE), CAP_PERMITTED : ("CAP_PERMITTED", CAP_PERMITTED), CAP_INHERITABLE : ("CAP_INHERITABLE", CAP_INHERITABLE)} """Capability flag values.""" c_cap_flag_value_t = c_int CAP_CLEAR = 0 CAP_SET = 1 """Posix capabilities.""" class PosixCapabilities: def __init__(self, lib, caps): """Initialise PosixCapabilities instance.""" self.__lib = lib self.__caps = caps def __del__(self): """Destroy Capability instance.""" self.__lib.cap_free(self.__caps) def hasPosixCapability(self, cap, flag): """Test whether the given capability/flag is set.""" v = c_cap_value_t(0) r = self.__lib.cap_get_flag(self.__caps, cap, flag, pointer(v)) if r == 0: return (v.value == CAP_SET) else: import errno raise OSError(errno.EINVAL, "Failed to test posix capability flag") def setPosixCapability(self, cap, flag, flagValue=True): """Sets (or clears) the given capability/flag.""" if flagValue: flagValue = c_cap_flag_value_t(1) else: flagValue = c_cap_flag_value_t(0) v = c_cap_value_t(cap) r = self.__lib.cap_set_flag(self.__caps, flag, 1, pointer(v), flagValue) if r != 0: import errno raise OSError(errno.EINVAL, "Failed to set/clear posix capability flag") def clearPosixCapability(self, cap, flag): """Clears the given capability/flag.""" self.setPosixCapability(cap, flag, False) def clearAllPosixCapabilities(self): """Clears all the capabilities/flags.""" for flag in c_cap_flag_data.values(): for cap in c_cap_value_data.values(): try: self.clearPosixCapability(cap[1], flag[1]) except OSError, e: pass def getCapabilitiesInternal(self): """Helper function for setProcessCapabilities.""" return self.__caps def __str__(self): result = '' firstFlag = True for flag in c_cap_flag_data.values(): if not firstFlag: result += '; ' firstFlag = False result += flag[0] + ':' firstCap = True for cap in c_cap_value_data.values(): try: if not self.hasPosixCapability(cap[1], flag[1]): continue if not firstCap: result += ',' firstCap = False result += ' ' + cap[0] except OSError, e: pass return result """Posix capability library. Singleton.""" class PosixCapabilityLibrary: """PosixCapabilityLibrary instance.""" __instance = None def __init__(self): """Initialise PosixCapabilityLibrary instance.""" self.__lib = CDLL(find_library('cap')) #self.__lib.cap_get_proc.restype = c_cap_t def getProcessCapabilities(self): """Return process capabilities.""" caps = self.__lib.cap_get_proc() if caps == 0: import errno raise OSError(errno.EINVAL, "Failed to get process capabilities") caps = cast(caps, c_cap_t) return PosixCapabilities(self.__lib, caps) def setProcessCapabilities(self, caps): """Set process capabilities.""" r = self.__lib.cap_set_proc(caps.getCapabilitiesInternal()) if r != 0: import errno raise OSError(errno.EINVAL, "Failed to set process capabilities") def getInstance(): """Create new or return existing PosixCapabilityLibrary instance.""" if not PosixCapabilityLibrary.__instance: PosixCapabilityLibrary.__instance = PosixCapabilityLibrary() return PosixCapabilityLibrary.__instance getInstance = staticmethod(getInstance) def getProcessCapabilities(): """Get process capabilities.""" return PosixCapabilityLibrary.getInstance().getProcessCapabilities() def setProcessCapabilities(caps): """Set process capabilities.""" return PosixCapabilityLibrary.getInstance().setProcessCapabilities(caps)