Обертка Python для API Parsec#

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