aboutsummaryrefslogtreecommitdiff
path: root/strcaps.c
blob: 3426196ff192c4ac6fa655b8e6a41b0fdd423bc2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include <Python.h>

#include <sys/capability.h>
#include <errno.h>


static PyObject *
strcaps_get_file(PyObject *self, PyObject *args) { // (int) fd / (str) path / (file) file
	PyObject *file;
	if (!PyArg_ParseTuple(args, "O", &file)) return NULL;
	cap_t caps;
	if (PyFile_Check(file)) caps = cap_get_fd(PyObject_AsFileDescriptor(file));
	else if (PyInt_Check(file)) caps = cap_get_fd(PyInt_AsLong(file));
	else if (PyString_Check(file)) caps = cap_get_file(PyString_AsString(file));
	else if (PyUnicode_Check(file)) {
		PyObject *file_dec = PyUnicode_AsEncodedString(
			file, Py_FileSystemDefaultEncoding, "strict" );
		if (file_dec == NULL) return NULL;
		caps = cap_get_file(PyString_AsString(file_dec));
		Py_DECREF(file_dec); }
	else {
		PyErr_SetString( PyExc_TypeError,
			"Expecting file object, descriptor int or path string" );
		return NULL; }
	size_t strcaps_len; char *strcaps;
	if (caps == NULL) {
		if (errno == ENODATA) { strcaps = "\0"; strcaps_len = 0; }
		else {
			PyErr_SetFromErrno(PyExc_OSError);
			return NULL; } }
	else strcaps = cap_to_text(caps, &strcaps_len);
	cap_free(caps);
	return Py_BuildValue("s#", strcaps, strcaps_len); }; // (str) caps

static PyObject *
strcaps_get_process(PyObject *self, PyObject *args) { // (int) pid or None
	int pid = 0;
	if (!PyArg_ParseTuple(args, "|i", &pid)) return NULL;
	cap_t caps;
	if (!pid) caps = cap_get_proc();
	else caps = cap_get_pid(pid);
	size_t strcaps_len; char *strcaps;
	if (caps == NULL) {
		if (errno == ENODATA) { strcaps = "\0"; strcaps_len = 0; }
		else {
			PyErr_SetFromErrno(PyExc_OSError);
			return NULL; } }
	else strcaps = cap_to_text(caps, &strcaps_len);
	cap_free(caps);
	return Py_BuildValue("s#", strcaps, strcaps_len); }; // (str) caps


static PyObject *
strcaps_set_file(PyObject *self, PyObject *args) { // (str) caps, (int) fd / (str) path / (file) file
	char *strcaps; PyObject *file;
	if (!PyArg_ParseTuple(args, "etO",
		Py_FileSystemDefaultEncoding, &strcaps, &file)) return NULL;
	cap_t caps;
	if ((caps = cap_from_text(strcaps)) == NULL) {
		PyErr_SetString(PyExc_ValueError, "Invalid capability specification");
		PyMem_Free(strcaps);
		return NULL; }
	PyMem_Free(strcaps);
	int err;
	if (PyFile_Check(file)) err = cap_set_fd(PyObject_AsFileDescriptor(file), caps);
	else if (PyInt_Check(file)) err = cap_set_fd(PyInt_AsLong(file), caps);
	else if (PyString_Check(file)) err = cap_set_file(PyString_AsString(file), caps);
	else if (PyUnicode_Check(file)) {
		PyObject *file_dec = PyUnicode_AsEncodedString(
			file, Py_FileSystemDefaultEncoding, "strict" );
		if (file_dec == NULL) return NULL;
		err = cap_set_file(PyString_AsString(file_dec), caps);
		Py_DECREF(file_dec); }
	else {
		PyErr_SetString( PyExc_TypeError,
			"Expecting file object, descriptor int or path string" );
		cap_free(caps);
		return NULL; }
	cap_free(caps);
	if (err) {
		PyErr_SetFromErrno(PyExc_OSError);
		return NULL; }
	Py_RETURN_NONE; };

static PyObject *
strcaps_set_process(PyObject *self, PyObject *args) { // (str) caps, (int) pid or None
	char *strcaps; int pid = 0;
	if (!PyArg_ParseTuple(args, "et|i",
		Py_FileSystemDefaultEncoding, &strcaps, &pid)) return NULL;
	cap_t caps;
	if ((caps = cap_from_text(strcaps)) == NULL) {
		PyErr_SetString(PyExc_ValueError, "Invalid capability specification");
		PyMem_Free(strcaps);
		return NULL; }
	PyMem_Free(strcaps);
	int err;
	if (!pid) err = cap_set_proc(caps);
	else err = capsetp(pid, caps);
	if (err) {
		PyErr_SetFromErrno(PyExc_OSError);
		cap_free(caps);
		return NULL; }
	cap_free(caps);
	Py_RETURN_NONE; };



static PyMethodDef strcaps_methods[] = {
	{"get_file", strcaps_get_file, METH_VARARGS,
		"Get capabilities string from path, file or descriptor.\n"},
	{"get_process", strcaps_get_process, METH_VARARGS,
		"Get capabilities string from pid or current thread, if pid is omitted.\n"},
	{"set_file", strcaps_set_file, METH_VARARGS,
		"Set capabilities from string to a path, file or descriptor.\n"},
	{"set_process", strcaps_set_process, METH_VARARGS,
		"Set capabilities from string for a pid or current thread, if pid is omitted,"
		" setting caps for an arbitrary pid is deprecated and might be unsupported.\n"},
	{NULL, NULL, 0, NULL} };

PyDoc_STRVAR( strcaps__doc__,
	"String-based POSIX capabilities manipulation interface." );


PyMODINIT_FUNC
initstrcaps(void) {
	PyObject *module;
	module = Py_InitModule3("strcaps", strcaps_methods, strcaps__doc__); };