from ctypes import *
import os
global libpdp
global libc
global get_errno_loc
class PDPException(Exception):
def __init__(self, msg):
self.msg = msg
self.errno = errno()
def __str__(self):
if self.errno != 0:
return '%s; %s' % (self.msg, os.strerror(self.errno))
else:
return '%s' % self.msg
class PDPL:
def __init__(self, val):
if type(val) is str:
ctext = create_string_buffer(val.encode('utf-8'))
self.ptr = libpdp.pdpl_get_from_text(ctext)
elif type(val) is int:
if not val:
raise PDPException('Invalid constructor argument (null ptr)')
self.ptr = val
else:
raise PDPException('Invalid constructor argument')
def __repr__(self):
return pdpl_ptr_to_text(self.ptr)
def __del__(self):
libpdp.pdpl_put(self.ptr)
def set_path(self, path):
cpath = create_string_buffer(path.encode('utf-8'))
return libpdp.pdp_set_path(cpath, self.ptr)
def set_lpath(self, path):
cpath = create_string_buffer(path.encode('utf-8'))
return libpdp.pdp_set_lpath(cpath, self.ptr)
def set_fd(self, fd):
return libpdp.pdp_set_fd(c_int(fd), self.ptr)
def set_pid(self, pid):
return libpdp.pdp_set_pid(c_int(pid), self.ptr)
def set_current(self):
return self.set_pid(0)
def set_pid_n(self, pid):
return libpdp.pdp_set_pid_n(c_int(pid), self.ptr)
def set_current_n(self):
return self.set_pid_n(0)
def supports_type(self, type, mode):
return libpdp.pdpl_supports_type(self.ptr, type, mode)
def pdpl_ptr_to_text(pdpl_ptr):
ctext = libpdp.pdpl_get_text(pdpl_ptr, 0)
pdpl_text_b = c_char_p(ctext).value
libc.free(ctext)
return pdpl_text_b.decode('utf-8')
def pdpl_get_from_text(text):
ctext = create_string_buffer(text.encode('utf-8'))
ptr = libpdp.pdpl_get_from_text(ctext)
if not ptr:
raise PDPException('pdpl_get_from_text failed')
return PDPL(ptr)
def pdp_get_path(path):
cpath = create_string_buffer(path.encode('utf-8'))
ptr = libpdp.pdp_get_path(cpath)
if not ptr:
raise PDPException('pdp_get_path failed')
return PDPL(ptr)
def pdp_get_fd(fd):
ptr = libpdp.pdp_get_fd(c_int(fd))
if not ptr:
raise PDPException('pdp_get_fd failed')
return PDPL(ptr)
def pdp_get_peer_label(fd):
ptr = libpdp.pdp_get_peer_label(c_int(fd))
if not ptr:
raise PDPException('pdp_get_peer_label failed')
return PDPL(ptr)
def pdp_set_ehole(path):
cpath = create_string_buffer(path.encode('utf-8'))
return libpdp.pdp_set_ehole(cpath)
def pdp_set_ehole_fd(fd):
return libpdp.pdp_set_ehole_fd(c_int(fd))
def pdp_get_sys_max():
return pdp_get_path('/')
def pdp_get_pid(fd):
ptr = libpdp.pdp_get_pid(c_int(fd))
if not ptr:
raise PDPException('pdp_get_pid failed')
return PDPL(ptr)
def pdp_get_current():
return pdp_get_pid(0)
def pdp_get_max_ilev():
return libpdp.pdp_get_max_ilev()
def pdp_get_current_ilev():
return libpdp.pdp_get_current_ilev()
def pdp_get_ilevs():
ccount = c_int()
c_ilevs = libpdp.pdp_get_ilevs(byref(ccount))
count = ccount.value
ret = []
for i in range(count):
ret += [c_ilevs[i]]
return ret
def pdp_is_super_root():
return libpdp.pdp_is_super_root() != 0
class PARSEC_CAPS(Structure):
_fields_ = [
("cap_effective", c_uint),
("cap_permitted", c_uint),
("cap_inheritable", c_uint)]
def __repr__(self):
return 'effective: 0x%x, inheritable: 0x%x, permited: 0x%x' % (
self.cap_effective,
self.cap_inheritable,
self.cap_permitted)
def parsec_caps_apply(pid, caps_mask, or_caps):
c = PARSEC_CAPS()
if libparsec_cap.parsec_capget(pid, byref(c)) != 0:
return -errno()
if or_caps:
c.cap_effective |= caps_mask
c.cap_inheritable |= caps_mask
c.cap_permitted |= caps_mask
else:
c.cap_effective = caps_mask
c.cap_inheritable = caps_mask
c.cap_permitted = caps_mask
if libparsec_cap.parsec_capset(pid, byref(c)) != 0:
return -errno()
return 0
def parsec_caps_get(pid):
c = PARSEC_CAPS()
if libparsec_cap.parsec_capget(pid, byref(c)) != 0:
raise OSError(errno())
return c
libc = CDLL('libc.so.6')
get_errno_loc = libc.__errno_location
get_errno_loc.restype = POINTER(c_int)
def errno():
return get_errno_loc()[0]
libpdp = CDLL('libpdp.so.3')
libparsec_cap = CDLL('libparsec-cap.so.3')
libpdp.pdpl_get_text.argtypes = [c_void_p, c_int]
libpdp.pdpl_get_text.restype = c_void_p
libpdp.pdp_set_path.argtypes = [c_char_p, c_void_p]
libpdp.pdp_set_path.restype = c_int
libpdp.pdp_set_lpath.argtypes = [c_char_p, c_void_p]
libpdp.pdp_set_lpath.restype = c_int
libpdp.pdp_set_fd.argtypes = [c_int, c_void_p]
libpdp.pdp_set_fd.restype = c_int
libpdp.pdp_get_path.argtypes = [c_char_p]
libpdp.pdp_get_path.restype = c_void_p
libpdp.pdp_get_lpath.argtypes = [c_char_p]
libpdp.pdp_get_lpath.restype = c_void_p
libpdp.pdp_get_fd.argtypes = [c_int]
libpdp.pdp_get_fd.restype = c_void_p
libpdp.pdp_get_peer_label.argtypes = [c_int]
libpdp.pdp_get_peer_label.restype = c_void_p
libpdp.pdp_set_ehole_fd.argtypes = [c_int]
libpdp.pdp_set_ehole_fd.restype = c_int
libpdp.pdp_set_ehole.argtypes = [c_char_p]
libpdp.pdp_set_ehole.restype = c_int
libpdp.pdp_set_pid.argtypes = [c_int, c_void_p]
libpdp.pdp_set_pid.restype = c_int
libpdp.pdp_set_pid_n.argtypes = [c_int, c_void_p]
libpdp.pdp_set_pid_n.restype = c_int
libpdp.pdp_get_pid.argtypes = [c_int]
libpdp.pdp_get_pid.restype = c_void_p
libpdp.pdp_get_max_ilev.argtypes = []
libpdp.pdp_get_max_ilev.restype = c_int
libpdp.pdp_get_current_ilev.argtypes = []
libpdp.pdp_get_current_ilev.restype = c_int
libpdp.pdp_get_ilevs.argtypes = [POINTER(c_int)]
libpdp.pdp_get_ilevs.restype = POINTER(c_int)
libpdp.pdpl_supports_type.argtypes = [c_void_p, c_int, c_int]
libpdp.pdpl_supports_type.restype = c_int
libpdp.pdp_is_super_root.argtypes = []
libpdp.pdp_is_super_root.restype = c_int
libparsec_cap.parsec_capget.argtypes = [c_int, POINTER(PARSEC_CAPS)]
libparsec_cap.parsec_capget.restype = c_int
PARSEC_CAP_FILE_CAP = 0 # 1
PARSEC_CAP_AUDIT = 1 # 2
PARSEC_CAP_SETMAC = 2 # 4
PARSEC_CAP_CHMAC = 3 # 8
PARSEC_CAP_IGNMACLVL = 4 # 10
PARSEC_CAP_IGNMACCAT = 5 # 20
PARSEC_CAP_SIG = 6 # 40
PARSEC_CAP_UPDATE_ATIME = 7 # 80
PARSEC_CAP_PRIV_SOCK = 8 # 100
PARSEC_CAP_READSEARCH = 9 # 200
PARSEC_CAP_CAP = 10 # 400
PARSEC_CAP_MAC_SOCK = 11 # 800
PARSEC_CAP_UNSAFE_SETXATTR = 12 # 1000
PARSEC_CAP_IGNMACINT = 13 # 2000
PARSEC_CAP_SUMAC = 14 # 4000
PARSEC_CAP_BYPASS_KIOSK = 15 # 8000
PARSEC_CAP_IPC_OWNER = 16 # 10000
PARSEC_CAP_INHERIT_INTEGRITY = 17 # 20000
PARSEC_CAP_BYPASS_XATTR = 18 # 40000
PARSEC_CAP_PROCFS = 19 # 80000
PARSEC_CAP_NUM = 20
def parsec_caps_to_mask(cap_list):
mask = 0
for cap in cap_list:
mask |= (1 << cap)
return mask
def parsec_is_cap_set(mask, cap):
return (mask & (1 << cap)) != 0