Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
4 : Copyright (C) Matthias Dieter Wallnöfer 2009
5 :
6 : This program is free software; you can redistribute it and/or modify
7 : it under the terms of the GNU General Public License as published by
8 : the Free Software Foundation; either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : This program is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : GNU General Public License for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with this program. If not, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : #include <Python.h>
21 : #include "python/py3compat.h"
22 : #include "includes.h"
23 : #include "version.h"
24 : #include "param/pyparam.h"
25 : #include "lib/socket/netif.h"
26 : #include "lib/util/debug.h"
27 : #include "librpc/ndr/ndr_private.h"
28 :
29 : void init_glue(void);
30 : static PyObject *PyExc_NTSTATUSError;
31 : static PyObject *PyExc_WERRORError;
32 : static PyObject *PyExc_HRESULTError;
33 : static PyObject *PyExc_DsExtendedError;
34 :
35 0 : static PyObject *py_generate_random_str(PyObject *self, PyObject *args)
36 : {
37 : int len;
38 : PyObject *ret;
39 : char *retstr;
40 0 : if (!PyArg_ParseTuple(args, "i", &len))
41 0 : return NULL;
42 :
43 0 : retstr = generate_random_str(NULL, len);
44 0 : ret = PyUnicode_FromString(retstr);
45 0 : talloc_free(retstr);
46 0 : return ret;
47 : }
48 :
49 1053 : static PyObject *py_generate_random_password(PyObject *self, PyObject *args)
50 : {
51 : int min, max;
52 : PyObject *ret;
53 : char *retstr;
54 1053 : if (!PyArg_ParseTuple(args, "ii", &min, &max))
55 0 : return NULL;
56 :
57 1053 : retstr = generate_random_password(NULL, min, max);
58 1053 : if (retstr == NULL) {
59 0 : return NULL;
60 : }
61 1053 : ret = PyUnicode_FromString(retstr);
62 1053 : talloc_free(retstr);
63 1053 : return ret;
64 : }
65 :
66 347 : static PyObject *py_generate_random_machine_password(PyObject *self, PyObject *args)
67 : {
68 : int min, max;
69 : PyObject *ret;
70 : char *retstr;
71 347 : if (!PyArg_ParseTuple(args, "ii", &min, &max))
72 0 : return NULL;
73 :
74 347 : retstr = generate_random_machine_password(NULL, min, max);
75 347 : if (retstr == NULL) {
76 0 : return NULL;
77 : }
78 347 : ret = PyUnicode_FromString(retstr);
79 347 : talloc_free(retstr);
80 347 : return ret;
81 : }
82 :
83 44 : static PyObject *py_check_password_quality(PyObject *self, PyObject *args)
84 : {
85 : char *pass;
86 :
87 44 : if (!PyArg_ParseTuple(args, "s", &pass)) {
88 0 : return NULL;
89 : }
90 :
91 44 : return PyBool_FromLong(check_password_quality(pass));
92 : }
93 :
94 4805 : static PyObject *py_generate_random_bytes(PyObject *self, PyObject *args)
95 : {
96 : int len;
97 : PyObject *ret;
98 4805 : uint8_t *bytes = NULL;
99 :
100 4805 : if (!PyArg_ParseTuple(args, "i", &len))
101 0 : return NULL;
102 :
103 4805 : bytes = talloc_zero_size(NULL, len);
104 4805 : generate_random_buffer(bytes, len);
105 4805 : ret = PyBytes_FromStringAndSize((const char *)bytes, len);
106 4805 : talloc_free(bytes);
107 4805 : return ret;
108 : }
109 :
110 498 : static PyObject *py_unix2nttime(PyObject *self, PyObject *args)
111 : {
112 : time_t t;
113 : unsigned int _t;
114 : NTTIME nt;
115 :
116 498 : if (!PyArg_ParseTuple(args, "I", &_t)) {
117 0 : return NULL;
118 : }
119 498 : t = _t;
120 :
121 498 : unix_to_nt_time(&nt, t);
122 :
123 498 : return PyLong_FromLongLong((uint64_t)nt);
124 : }
125 :
126 66873 : static PyObject *py_nttime2unix(PyObject *self, PyObject *args)
127 : {
128 : time_t t;
129 : NTTIME nt;
130 66873 : if (!PyArg_ParseTuple(args, "K", &nt))
131 0 : return NULL;
132 :
133 66873 : t = nt_time_to_unix(nt);
134 :
135 66873 : return PyLong_FromLong((uint64_t)t);
136 : }
137 :
138 0 : static PyObject *py_float2nttime(PyObject *self, PyObject *args)
139 : {
140 0 : double ft = 0;
141 0 : double ft_sec = 0;
142 0 : double ft_nsec = 0;
143 : struct timespec ts;
144 0 : NTTIME nt = 0;
145 :
146 0 : if (!PyArg_ParseTuple(args, "d", &ft)) {
147 0 : return NULL;
148 : }
149 :
150 0 : ft_sec = (double)(int)ft;
151 0 : ft_nsec = (ft - ft_sec) * 1.0e+9;
152 :
153 0 : ts.tv_sec = (int)ft_sec;
154 0 : ts.tv_nsec = (int)ft_nsec;
155 :
156 0 : nt = full_timespec_to_nt_time(&ts);
157 :
158 0 : return PyLong_FromLongLong((uint64_t)nt);
159 : }
160 :
161 72 : static PyObject *py_nttime2float(PyObject *self, PyObject *args)
162 : {
163 72 : double ft = 0;
164 : struct timespec ts;
165 72 : const struct timespec ts_zero = { .tv_sec = 0, };
166 72 : NTTIME nt = 0;
167 :
168 72 : if (!PyArg_ParseTuple(args, "K", &nt)) {
169 0 : return NULL;
170 : }
171 :
172 72 : ts = nt_time_to_full_timespec(nt);
173 72 : if (is_omit_timespec(&ts)) {
174 0 : return PyFloat_FromDouble(1.0);
175 : }
176 72 : ft = timespec_elapsed2(&ts_zero, &ts);
177 :
178 72 : return PyFloat_FromDouble(ft);
179 : }
180 :
181 154 : static PyObject *py_nttime2string(PyObject *self, PyObject *args)
182 : {
183 : PyObject *ret;
184 : NTTIME nt;
185 : TALLOC_CTX *tmp_ctx;
186 : const char *string;
187 154 : if (!PyArg_ParseTuple(args, "K", &nt))
188 0 : return NULL;
189 :
190 154 : tmp_ctx = talloc_new(NULL);
191 154 : if (tmp_ctx == NULL) {
192 0 : PyErr_NoMemory();
193 0 : return NULL;
194 : }
195 :
196 154 : string = nt_time_string(tmp_ctx, nt);
197 154 : ret = PyUnicode_FromString(string);
198 :
199 154 : talloc_free(tmp_ctx);
200 :
201 154 : return ret;
202 : }
203 :
204 1989 : static PyObject *py_set_debug_level(PyObject *self, PyObject *args)
205 : {
206 : unsigned level;
207 1989 : if (!PyArg_ParseTuple(args, "I", &level))
208 0 : return NULL;
209 1989 : debuglevel_set(level);
210 1989 : Py_RETURN_NONE;
211 : }
212 :
213 2188 : static PyObject *py_get_debug_level(PyObject *self,
214 : PyObject *Py_UNUSED(ignored))
215 : {
216 2188 : return PyLong_FromLong(debuglevel_get());
217 : }
218 :
219 11256 : static PyObject *py_fault_setup(PyObject *self,
220 : PyObject *Py_UNUSED(ignored))
221 : {
222 : static bool done;
223 11256 : if (!done) {
224 5297 : fault_setup();
225 5297 : done = true;
226 : }
227 11256 : Py_RETURN_NONE;
228 : }
229 :
230 2240 : static PyObject *py_is_ntvfs_fileserver_built(PyObject *self,
231 : PyObject *Py_UNUSED(ignored))
232 : {
233 : #ifdef WITH_NTVFS_FILESERVER
234 2240 : Py_RETURN_TRUE;
235 : #else
236 : Py_RETURN_FALSE;
237 : #endif
238 : }
239 :
240 164 : static PyObject *py_is_heimdal_built(PyObject *self,
241 : PyObject *Py_UNUSED(ignored))
242 : {
243 : #ifdef SAMBA4_USES_HEIMDAL
244 130 : Py_RETURN_TRUE;
245 : #else
246 34 : Py_RETURN_FALSE;
247 : #endif
248 : }
249 :
250 592 : static PyObject *py_is_ad_dc_built(PyObject *self,
251 : PyObject *Py_UNUSED(ignored))
252 : {
253 : #ifdef AD_DC_BUILD_IS_ENABLED
254 592 : Py_RETURN_TRUE;
255 : #else
256 : Py_RETURN_FALSE;
257 : #endif
258 : }
259 :
260 560 : static PyObject *py_is_selftest_enabled(PyObject *self,
261 : PyObject *Py_UNUSED(ignored))
262 : {
263 : #ifdef ENABLE_SELFTEST
264 560 : Py_RETURN_TRUE;
265 : #else
266 : Py_RETURN_FALSE;
267 : #endif
268 : }
269 :
270 0 : static PyObject *py_ndr_token_max_list_size(PyObject *self,
271 : PyObject *Py_UNUSED(ignored))
272 : {
273 0 : return PyLong_FromLong(ndr_token_max_list_size());
274 : }
275 :
276 : /*
277 : return the list of interface IPs we have configured
278 : takes an loadparm context, returns a list of IPs in string form
279 :
280 : Does not return addresses on 127.0.0.0/8
281 : */
282 397 : static PyObject *py_interface_ips(PyObject *self, PyObject *args)
283 : {
284 : PyObject *pylist;
285 : int count;
286 : TALLOC_CTX *tmp_ctx;
287 : PyObject *py_lp_ctx;
288 : struct loadparm_context *lp_ctx;
289 : struct interface *ifaces;
290 : int i, ifcount;
291 397 : int all_interfaces = 1;
292 :
293 397 : if (!PyArg_ParseTuple(args, "O|i", &py_lp_ctx, &all_interfaces))
294 0 : return NULL;
295 :
296 397 : tmp_ctx = talloc_new(NULL);
297 397 : if (tmp_ctx == NULL) {
298 0 : PyErr_NoMemory();
299 0 : return NULL;
300 : }
301 :
302 397 : lp_ctx = lpcfg_from_py_object(tmp_ctx, py_lp_ctx);
303 397 : if (lp_ctx == NULL) {
304 0 : talloc_free(tmp_ctx);
305 0 : return NULL;
306 : }
307 :
308 397 : load_interface_list(tmp_ctx, lp_ctx, &ifaces);
309 :
310 397 : count = iface_list_count(ifaces);
311 :
312 : /* first count how many are not loopback addresses */
313 1856 : for (ifcount = i = 0; i<count; i++) {
314 1459 : const char *ip = iface_list_n_ip(ifaces, i);
315 :
316 1459 : if (all_interfaces) {
317 222 : ifcount++;
318 222 : continue;
319 : }
320 :
321 1237 : if (iface_list_same_net(ip, "127.0.0.1", "255.0.0.0")) {
322 0 : continue;
323 : }
324 :
325 1237 : if (iface_list_same_net(ip, "169.254.0.0", "255.255.0.0")) {
326 0 : continue;
327 : }
328 :
329 1237 : if (iface_list_same_net(ip, "::1", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")) {
330 0 : continue;
331 : }
332 :
333 1237 : if (iface_list_same_net(ip, "fe80::", "ffff:ffff:ffff:ffff::")) {
334 0 : continue;
335 : }
336 :
337 1237 : ifcount++;
338 : }
339 :
340 397 : pylist = PyList_New(ifcount);
341 1856 : for (ifcount = i = 0; i<count; i++) {
342 1459 : const char *ip = iface_list_n_ip(ifaces, i);
343 :
344 1459 : if (all_interfaces) {
345 222 : PyList_SetItem(pylist, ifcount, PyUnicode_FromString(ip));
346 222 : ifcount++;
347 222 : continue;
348 : }
349 :
350 1237 : if (iface_list_same_net(ip, "127.0.0.1", "255.0.0.0")) {
351 0 : continue;
352 : }
353 :
354 1237 : if (iface_list_same_net(ip, "169.254.0.0", "255.255.0.0")) {
355 0 : continue;
356 : }
357 :
358 1237 : if (iface_list_same_net(ip, "::1", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")) {
359 0 : continue;
360 : }
361 :
362 1237 : if (iface_list_same_net(ip, "fe80::", "ffff:ffff:ffff:ffff::")) {
363 0 : continue;
364 : }
365 :
366 1237 : PyList_SetItem(pylist, ifcount, PyUnicode_FromString(ip));
367 1237 : ifcount++;
368 : }
369 397 : talloc_free(tmp_ctx);
370 397 : return pylist;
371 : }
372 :
373 0 : static PyObject *py_strcasecmp_m(PyObject *self, PyObject *args)
374 : {
375 0 : const char *s1 = NULL;
376 0 : const char *s2 = NULL;
377 0 : long cmp_result = 0;
378 0 : if (!PyArg_ParseTuple(args, PYARG_STR_UNI
379 : PYARG_STR_UNI,
380 : "utf8", &s1, "utf8", &s2)) {
381 0 : return NULL;
382 : }
383 :
384 0 : cmp_result = strcasecmp_m(s1, s2);
385 0 : PyMem_Free(discard_const_p(char, s1));
386 0 : PyMem_Free(discard_const_p(char, s2));
387 0 : return PyLong_FromLong(cmp_result);
388 : }
389 :
390 0 : static PyObject *py_strstr_m(PyObject *self, PyObject *args)
391 : {
392 0 : const char *s1 = NULL;
393 0 : const char *s2 = NULL;
394 0 : char *strstr_ret = NULL;
395 0 : PyObject *result = NULL;
396 0 : if (!PyArg_ParseTuple(args, PYARG_STR_UNI
397 : PYARG_STR_UNI,
398 : "utf8", &s1, "utf8", &s2))
399 0 : return NULL;
400 :
401 0 : strstr_ret = strstr_m(s1, s2);
402 0 : if (!strstr_ret) {
403 0 : PyMem_Free(discard_const_p(char, s1));
404 0 : PyMem_Free(discard_const_p(char, s2));
405 0 : Py_RETURN_NONE;
406 : }
407 0 : result = PyUnicode_FromString(strstr_ret);
408 0 : PyMem_Free(discard_const_p(char, s1));
409 0 : PyMem_Free(discard_const_p(char, s2));
410 0 : return result;
411 : }
412 :
413 : static PyMethodDef py_misc_methods[] = {
414 : { "generate_random_str", (PyCFunction)py_generate_random_str, METH_VARARGS,
415 : "generate_random_str(len) -> string\n"
416 : "Generate random string with specified length." },
417 : { "generate_random_password", (PyCFunction)py_generate_random_password,
418 : METH_VARARGS, "generate_random_password(min, max) -> string\n"
419 : "Generate random password (based on printable ascii characters) "
420 : "with a length >= min and <= max." },
421 : { "generate_random_machine_password", (PyCFunction)py_generate_random_machine_password,
422 : METH_VARARGS, "generate_random_machine_password(min, max) -> string\n"
423 : "Generate random password "
424 : "(based on random utf16 characters converted to utf8 or "
425 : "random ascii characters if 'unix charset' is not 'utf8')"
426 : "with a length >= min (at least 14) and <= max (at most 255)." },
427 : { "check_password_quality", (PyCFunction)py_check_password_quality,
428 : METH_VARARGS, "check_password_quality(pass) -> bool\n"
429 : "Check password quality against Samba's check_password_quality,"
430 : "the implementation of Microsoft's rules:"
431 : "http://msdn.microsoft.com/en-us/subscriptions/cc786468%28v=ws.10%29.aspx"
432 : },
433 : { "unix2nttime", (PyCFunction)py_unix2nttime, METH_VARARGS,
434 : "unix2nttime(timestamp) -> nttime" },
435 : { "nttime2unix", (PyCFunction)py_nttime2unix, METH_VARARGS,
436 : "nttime2unix(nttime) -> timestamp" },
437 : { "float2nttime", (PyCFunction)py_float2nttime, METH_VARARGS,
438 : "pytime2nttime(floattimestamp) -> nttime" },
439 : { "nttime2float", (PyCFunction)py_nttime2float, METH_VARARGS,
440 : "nttime2pytime(nttime) -> floattimestamp" },
441 : { "nttime2string", (PyCFunction)py_nttime2string, METH_VARARGS,
442 : "nttime2string(nttime) -> string" },
443 : { "set_debug_level", (PyCFunction)py_set_debug_level, METH_VARARGS,
444 : "set debug level" },
445 : { "get_debug_level", (PyCFunction)py_get_debug_level, METH_NOARGS,
446 : "get debug level" },
447 : { "fault_setup", (PyCFunction)py_fault_setup, METH_NOARGS,
448 : "setup the default samba panic handler" },
449 : { "interface_ips", (PyCFunction)py_interface_ips, METH_VARARGS,
450 : "interface_ips(lp_ctx[, all_interfaces) -> list_of_ifaces\n"
451 : "\n"
452 : "get interface IP address list"},
453 : { "strcasecmp_m", (PyCFunction)py_strcasecmp_m, METH_VARARGS,
454 : "(for testing) compare two strings using Samba's strcasecmp_m()"},
455 : { "strstr_m", (PyCFunction)py_strstr_m, METH_VARARGS,
456 : "(for testing) find one string in another with Samba's strstr_m()"},
457 : { "is_ntvfs_fileserver_built", (PyCFunction)py_is_ntvfs_fileserver_built, METH_NOARGS,
458 : "is the NTVFS file server built in this installation?" },
459 : { "is_heimdal_built", (PyCFunction)py_is_heimdal_built, METH_NOARGS,
460 : "is Samba built with Heimdal Kerberbos?" },
461 : { "generate_random_bytes",
462 : (PyCFunction)py_generate_random_bytes,
463 : METH_VARARGS,
464 : "generate_random_bytes(len) -> bytes\n"
465 : "Generate random bytes with specified length." },
466 : { "is_ad_dc_built", (PyCFunction)py_is_ad_dc_built, METH_NOARGS,
467 : "is Samba built with AD DC?" },
468 : { "is_selftest_enabled", (PyCFunction)py_is_selftest_enabled,
469 : METH_NOARGS, "is Samba built with selftest enabled?" },
470 : { "ndr_token_max_list_size", (PyCFunction)py_ndr_token_max_list_size,
471 : METH_NOARGS, "How many NDR internal tokens is too many for this build?" },
472 : {0}
473 : };
474 :
475 : static struct PyModuleDef moduledef = {
476 : PyModuleDef_HEAD_INIT,
477 : .m_name = "_glue",
478 : .m_doc = "Python bindings for miscellaneous Samba functions.",
479 : .m_size = -1,
480 : .m_methods = py_misc_methods,
481 : };
482 :
483 7561 : MODULE_INIT_FUNC(_glue)
484 : {
485 : PyObject *m;
486 :
487 7561 : debug_setup_talloc_log();
488 :
489 7561 : m = PyModule_Create(&moduledef);
490 7561 : if (m == NULL)
491 0 : return NULL;
492 :
493 7561 : PyModule_AddObject(m, "version",
494 : PyUnicode_FromString(SAMBA_VERSION_STRING));
495 7561 : PyExc_NTSTATUSError = PyErr_NewException(discard_const_p(char, "samba.NTSTATUSError"), PyExc_RuntimeError, NULL);
496 7561 : if (PyExc_NTSTATUSError != NULL) {
497 7561 : Py_INCREF(PyExc_NTSTATUSError);
498 7561 : PyModule_AddObject(m, "NTSTATUSError", PyExc_NTSTATUSError);
499 : }
500 :
501 7561 : PyExc_WERRORError = PyErr_NewException(discard_const_p(char, "samba.WERRORError"), PyExc_RuntimeError, NULL);
502 7561 : if (PyExc_WERRORError != NULL) {
503 7561 : Py_INCREF(PyExc_WERRORError);
504 7561 : PyModule_AddObject(m, "WERRORError", PyExc_WERRORError);
505 : }
506 :
507 7561 : PyExc_HRESULTError = PyErr_NewException(discard_const_p(char, "samba.HRESULTError"), PyExc_RuntimeError, NULL);
508 7561 : if (PyExc_HRESULTError != NULL) {
509 7561 : Py_INCREF(PyExc_HRESULTError);
510 7561 : PyModule_AddObject(m, "HRESULTError", PyExc_HRESULTError);
511 : }
512 :
513 7561 : PyExc_DsExtendedError = PyErr_NewException(discard_const_p(char, "samba.DsExtendedError"), PyExc_RuntimeError, NULL);
514 7561 : if (PyExc_DsExtendedError != NULL) {
515 7561 : Py_INCREF(PyExc_DsExtendedError);
516 7561 : PyModule_AddObject(m, "DsExtendedError", PyExc_DsExtendedError);
517 : }
518 :
519 7561 : return m;
520 : }
521 :
|