ctdb-tests: Avoid a race
[samba.git] / python / pyglue.c
blob0e1bf82fa7a39d55b2164ab142f1f2d3ca9b2acd
1 /*
2 Unix SMB/CIFS implementation.
3 Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
4 Copyright (C) Matthias Dieter Wallnöfer 2009
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.
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.
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/>.
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"
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;
35 static PyObject *py_generate_random_str(PyObject *self, PyObject *args)
37 int len;
38 PyObject *ret;
39 char *retstr;
40 if (!PyArg_ParseTuple(args, "i", &len))
41 return NULL;
43 retstr = generate_random_str(NULL, len);
44 ret = PyUnicode_FromString(retstr);
45 talloc_free(retstr);
46 return ret;
49 static PyObject *py_generate_random_password(PyObject *self, PyObject *args)
51 int min, max;
52 PyObject *ret;
53 char *retstr;
54 if (!PyArg_ParseTuple(args, "ii", &min, &max))
55 return NULL;
57 retstr = generate_random_password(NULL, min, max);
58 if (retstr == NULL) {
59 return NULL;
61 ret = PyUnicode_FromString(retstr);
62 talloc_free(retstr);
63 return ret;
66 static PyObject *py_generate_random_machine_password(PyObject *self, PyObject *args)
68 int min, max;
69 PyObject *ret;
70 char *retstr;
71 if (!PyArg_ParseTuple(args, "ii", &min, &max))
72 return NULL;
74 retstr = generate_random_machine_password(NULL, min, max);
75 if (retstr == NULL) {
76 return NULL;
78 ret = PyUnicode_FromString(retstr);
79 talloc_free(retstr);
80 return ret;
83 static PyObject *py_check_password_quality(PyObject *self, PyObject *args)
85 char *pass;
87 if (!PyArg_ParseTuple(args, "s", &pass)) {
88 return NULL;
91 return PyBool_FromLong(check_password_quality(pass));
94 static PyObject *py_generate_random_bytes(PyObject *self, PyObject *args)
96 int len;
97 PyObject *ret;
98 uint8_t *bytes = NULL;
100 if (!PyArg_ParseTuple(args, "i", &len))
101 return NULL;
103 bytes = talloc_zero_size(NULL, len);
104 generate_random_buffer(bytes, len);
105 ret = PyBytes_FromStringAndSize((const char *)bytes, len);
106 talloc_free(bytes);
107 return ret;
110 static PyObject *py_unix2nttime(PyObject *self, PyObject *args)
112 time_t t;
113 unsigned int _t;
114 NTTIME nt;
116 if (!PyArg_ParseTuple(args, "I", &_t)) {
117 return NULL;
119 t = _t;
121 unix_to_nt_time(&nt, t);
123 return PyLong_FromLongLong((uint64_t)nt);
126 static PyObject *py_nttime2unix(PyObject *self, PyObject *args)
128 time_t t;
129 NTTIME nt;
130 if (!PyArg_ParseTuple(args, "K", &nt))
131 return NULL;
133 t = nt_time_to_unix(nt);
135 return PyLong_FromLong((uint64_t)t);
138 static PyObject *py_float2nttime(PyObject *self, PyObject *args)
140 double ft = 0;
141 double ft_sec = 0;
142 double ft_nsec = 0;
143 struct timespec ts;
144 NTTIME nt = 0;
146 if (!PyArg_ParseTuple(args, "d", &ft)) {
147 return NULL;
150 ft_sec = (double)(int)ft;
151 ft_nsec = (ft - ft_sec) * 1.0e+9;
153 ts.tv_sec = (int)ft_sec;
154 ts.tv_nsec = (int)ft_nsec;
156 nt = full_timespec_to_nt_time(&ts);
158 return PyLong_FromLongLong((uint64_t)nt);
161 static PyObject *py_nttime2float(PyObject *self, PyObject *args)
163 double ft = 0;
164 struct timespec ts;
165 const struct timespec ts_zero = { .tv_sec = 0, };
166 NTTIME nt = 0;
168 if (!PyArg_ParseTuple(args, "K", &nt)) {
169 return NULL;
172 ts = nt_time_to_full_timespec(nt);
173 if (is_omit_timespec(&ts)) {
174 return PyFloat_FromDouble(1.0);
176 ft = timespec_elapsed2(&ts_zero, &ts);
178 return PyFloat_FromDouble(ft);
181 static PyObject *py_nttime2string(PyObject *self, PyObject *args)
183 PyObject *ret;
184 NTTIME nt;
185 TALLOC_CTX *tmp_ctx;
186 const char *string;
187 if (!PyArg_ParseTuple(args, "K", &nt))
188 return NULL;
190 tmp_ctx = talloc_new(NULL);
191 if (tmp_ctx == NULL) {
192 PyErr_NoMemory();
193 return NULL;
196 string = nt_time_string(tmp_ctx, nt);
197 ret = PyUnicode_FromString(string);
199 talloc_free(tmp_ctx);
201 return ret;
204 static PyObject *py_set_debug_level(PyObject *self, PyObject *args)
206 unsigned level;
207 if (!PyArg_ParseTuple(args, "I", &level))
208 return NULL;
209 debuglevel_set(level);
210 Py_RETURN_NONE;
213 static PyObject *py_get_debug_level(PyObject *self,
214 PyObject *Py_UNUSED(ignored))
216 return PyLong_FromLong(debuglevel_get());
219 static PyObject *py_fault_setup(PyObject *self,
220 PyObject *Py_UNUSED(ignored))
222 static bool done;
223 if (!done) {
224 fault_setup();
225 done = true;
227 Py_RETURN_NONE;
230 static PyObject *py_is_ntvfs_fileserver_built(PyObject *self,
231 PyObject *Py_UNUSED(ignored))
233 #ifdef WITH_NTVFS_FILESERVER
234 Py_RETURN_TRUE;
235 #else
236 Py_RETURN_FALSE;
237 #endif
240 static PyObject *py_is_heimdal_built(PyObject *self,
241 PyObject *Py_UNUSED(ignored))
243 #ifdef SAMBA4_USES_HEIMDAL
244 Py_RETURN_TRUE;
245 #else
246 Py_RETURN_FALSE;
247 #endif
250 static PyObject *py_is_ad_dc_built(PyObject *self,
251 PyObject *Py_UNUSED(ignored))
253 #ifdef AD_DC_BUILD_IS_ENABLED
254 Py_RETURN_TRUE;
255 #else
256 Py_RETURN_FALSE;
257 #endif
260 static PyObject *py_is_selftest_enabled(PyObject *self,
261 PyObject *Py_UNUSED(ignored))
263 #ifdef ENABLE_SELFTEST
264 Py_RETURN_TRUE;
265 #else
266 Py_RETURN_FALSE;
267 #endif
270 static PyObject *py_ndr_token_max_list_size(PyObject *self,
271 PyObject *Py_UNUSED(ignored))
273 return PyLong_FromLong(ndr_token_max_list_size());
277 return the list of interface IPs we have configured
278 takes an loadparm context, returns a list of IPs in string form
280 Does not return addresses on 127.0.0.0/8
282 static PyObject *py_interface_ips(PyObject *self, PyObject *args)
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 int all_interfaces = 1;
293 if (!PyArg_ParseTuple(args, "O|i", &py_lp_ctx, &all_interfaces))
294 return NULL;
296 tmp_ctx = talloc_new(NULL);
297 if (tmp_ctx == NULL) {
298 PyErr_NoMemory();
299 return NULL;
302 lp_ctx = lpcfg_from_py_object(tmp_ctx, py_lp_ctx);
303 if (lp_ctx == NULL) {
304 talloc_free(tmp_ctx);
305 return NULL;
308 load_interface_list(tmp_ctx, lp_ctx, &ifaces);
310 count = iface_list_count(ifaces);
312 /* first count how many are not loopback addresses */
313 for (ifcount = i = 0; i<count; i++) {
314 const char *ip = iface_list_n_ip(ifaces, i);
316 if (all_interfaces) {
317 ifcount++;
318 continue;
321 if (iface_list_same_net(ip, "127.0.0.1", "255.0.0.0")) {
322 continue;
325 if (iface_list_same_net(ip, "169.254.0.0", "255.255.0.0")) {
326 continue;
329 if (iface_list_same_net(ip, "::1", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")) {
330 continue;
333 if (iface_list_same_net(ip, "fe80::", "ffff:ffff:ffff:ffff::")) {
334 continue;
337 ifcount++;
340 pylist = PyList_New(ifcount);
341 for (ifcount = i = 0; i<count; i++) {
342 const char *ip = iface_list_n_ip(ifaces, i);
344 if (all_interfaces) {
345 PyList_SetItem(pylist, ifcount, PyUnicode_FromString(ip));
346 ifcount++;
347 continue;
350 if (iface_list_same_net(ip, "127.0.0.1", "255.0.0.0")) {
351 continue;
354 if (iface_list_same_net(ip, "169.254.0.0", "255.255.0.0")) {
355 continue;
358 if (iface_list_same_net(ip, "::1", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")) {
359 continue;
362 if (iface_list_same_net(ip, "fe80::", "ffff:ffff:ffff:ffff::")) {
363 continue;
366 PyList_SetItem(pylist, ifcount, PyUnicode_FromString(ip));
367 ifcount++;
369 talloc_free(tmp_ctx);
370 return pylist;
373 static PyObject *py_strcasecmp_m(PyObject *self, PyObject *args)
375 const char *s1 = NULL;
376 const char *s2 = NULL;
377 long cmp_result = 0;
378 if (!PyArg_ParseTuple(args, PYARG_STR_UNI
379 PYARG_STR_UNI,
380 "utf8", &s1, "utf8", &s2)) {
381 return NULL;
384 cmp_result = strcasecmp_m(s1, s2);
385 PyMem_Free(discard_const_p(char, s1));
386 PyMem_Free(discard_const_p(char, s2));
387 return PyLong_FromLong(cmp_result);
390 static PyObject *py_strstr_m(PyObject *self, PyObject *args)
392 const char *s1 = NULL;
393 const char *s2 = NULL;
394 char *strstr_ret = NULL;
395 PyObject *result = NULL;
396 if (!PyArg_ParseTuple(args, PYARG_STR_UNI
397 PYARG_STR_UNI,
398 "utf8", &s1, "utf8", &s2))
399 return NULL;
401 strstr_ret = strstr_m(s1, s2);
402 if (!strstr_ret) {
403 PyMem_Free(discard_const_p(char, s1));
404 PyMem_Free(discard_const_p(char, s2));
405 Py_RETURN_NONE;
407 result = PyUnicode_FromString(strstr_ret);
408 PyMem_Free(discard_const_p(char, s1));
409 PyMem_Free(discard_const_p(char, s2));
410 return result;
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"
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?" },
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,
483 MODULE_INIT_FUNC(_glue)
485 PyObject *m;
487 debug_setup_talloc_log();
489 m = PyModule_Create(&moduledef);
490 if (m == NULL)
491 return NULL;
493 PyModule_AddObject(m, "version",
494 PyUnicode_FromString(SAMBA_VERSION_STRING));
495 PyExc_NTSTATUSError = PyErr_NewException(discard_const_p(char, "samba.NTSTATUSError"), PyExc_RuntimeError, NULL);
496 if (PyExc_NTSTATUSError != NULL) {
497 Py_INCREF(PyExc_NTSTATUSError);
498 PyModule_AddObject(m, "NTSTATUSError", PyExc_NTSTATUSError);
501 PyExc_WERRORError = PyErr_NewException(discard_const_p(char, "samba.WERRORError"), PyExc_RuntimeError, NULL);
502 if (PyExc_WERRORError != NULL) {
503 Py_INCREF(PyExc_WERRORError);
504 PyModule_AddObject(m, "WERRORError", PyExc_WERRORError);
507 PyExc_HRESULTError = PyErr_NewException(discard_const_p(char, "samba.HRESULTError"), PyExc_RuntimeError, NULL);
508 if (PyExc_HRESULTError != NULL) {
509 Py_INCREF(PyExc_HRESULTError);
510 PyModule_AddObject(m, "HRESULTError", PyExc_HRESULTError);
513 PyExc_DsExtendedError = PyErr_NewException(discard_const_p(char, "samba.DsExtendedError"), PyExc_RuntimeError, NULL);
514 if (PyExc_DsExtendedError != NULL) {
515 Py_INCREF(PyExc_DsExtendedError);
516 PyModule_AddObject(m, "DsExtendedError", PyExc_DsExtendedError);
519 return m;