source: trunk-3.0/source/python/py_winbind.c@ 102

Last change on this file since 102 was 1, checked in by Paul Smedley, 18 years ago

Initial code import

File size: 18.6 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3
4 Python wrapper for winbind client functions.
5
6 Copyright (C) Tim Potter 2002-2003
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21*/
22
23#include "py_winbind.h"
24
25/*
26 * Exceptions raised by this module
27 */
28
29PyObject *winbind_error; /* A winbind call returned WINBINDD_ERROR */
30
31/* Prototypes from common.h */
32
33NSS_STATUS winbindd_request_response(int req_type,
34 struct winbindd_request *request,
35 struct winbindd_response *response);
36
37/*
38 * Name <-> SID conversion
39 */
40
41/* Convert a name to a sid */
42
43static PyObject *py_name_to_sid(PyObject *self, PyObject *args)
44
45{
46 struct winbindd_request request;
47 struct winbindd_response response;
48 PyObject *result;
49 char *name, *p;
50 const char *sep;
51
52 if (!PyArg_ParseTuple(args, "s", &name))
53 return NULL;
54
55 ZERO_STRUCT(request);
56 ZERO_STRUCT(response);
57
58 sep = lp_winbind_separator();
59
60 if ((p = strchr(name, sep[0]))) {
61 *p = 0;
62 fstrcpy(request.data.name.dom_name, name);
63 fstrcpy(request.data.name.name, p + 1);
64 } else {
65 fstrcpy(request.data.name.dom_name, lp_workgroup());
66 fstrcpy(request.data.name.name, name);
67 }
68
69 if (winbindd_request_response(WINBINDD_LOOKUPNAME, &request, &response)
70 != NSS_STATUS_SUCCESS) {
71 PyErr_SetString(winbind_error, "lookup failed");
72 return NULL;
73 }
74
75 result = PyString_FromString(response.data.sid.sid);
76
77 return result;
78}
79
80/* Convert a sid to a name */
81
82static PyObject *py_sid_to_name(PyObject *self, PyObject *args)
83{
84 struct winbindd_request request;
85 struct winbindd_response response;
86 PyObject *result;
87 char *sid, *name;
88
89 if (!PyArg_ParseTuple(args, "s", &sid))
90 return NULL;
91
92 ZERO_STRUCT(request);
93 ZERO_STRUCT(response);
94
95 fstrcpy(request.data.sid, sid);
96
97 if (winbindd_request_response(WINBINDD_LOOKUPSID, &request, &response)
98 != NSS_STATUS_SUCCESS) {
99 PyErr_SetString(winbind_error, "lookup failed");
100 return NULL;
101 }
102
103 asprintf(&name, "%s%s%s", response.data.name.dom_name,
104 lp_winbind_separator(), response.data.name.name);
105
106 result = PyString_FromString(name);
107
108 free(name);
109
110 return result;
111}
112
113/*
114 * Enumerate users/groups
115 */
116
117/* Enumerate domain users */
118
119static PyObject *py_enum_domain_users(PyObject *self, PyObject *args)
120{
121 struct winbindd_response response;
122 PyObject *result;
123
124 if (!PyArg_ParseTuple(args, ""))
125 return NULL;
126
127 ZERO_STRUCT(response);
128
129 if (winbindd_request_response(WINBINDD_LIST_USERS, NULL, &response)
130 != NSS_STATUS_SUCCESS) {
131 PyErr_SetString(winbind_error, "lookup failed");
132 return NULL;
133 }
134
135 result = PyList_New(0);
136
137 if (response.extra_data.data) {
138 const char *extra_data = response.extra_data.data;
139 fstring name;
140
141 while (next_token(&extra_data, name, ",", sizeof(fstring)))
142 PyList_Append(result, PyString_FromString(name));
143 }
144
145 return result;
146}
147
148/* Enumerate domain groups */
149
150static PyObject *py_enum_domain_groups(PyObject *self, PyObject *args)
151{
152 struct winbindd_response response;
153 PyObject *result = NULL;
154
155 if (!PyArg_ParseTuple(args, ""))
156 return NULL;
157
158 ZERO_STRUCT(response);
159
160 if (winbindd_request_response(WINBINDD_LIST_GROUPS, NULL, &response)
161 != NSS_STATUS_SUCCESS) {
162 PyErr_SetString(winbind_error, "lookup failed");
163 return NULL;
164 }
165
166 result = PyList_New(0);
167
168 if (response.extra_data.data) {
169 const char *extra_data = response.extra_data.data;
170 fstring name;
171
172 while (next_token(&extra_data, name, ",", sizeof(fstring)))
173 PyList_Append(result, PyString_FromString(name));
174 }
175
176 return result;
177}
178
179/*
180 * Miscellaneous domain related
181 */
182
183/* Enumerate domain groups */
184
185static PyObject *py_enum_trust_dom(PyObject *self, PyObject *args)
186{
187 struct winbindd_response response;
188 PyObject *result = NULL;
189
190 if (!PyArg_ParseTuple(args, ""))
191 return NULL;
192
193 ZERO_STRUCT(response);
194
195 if (winbindd_request_response(WINBINDD_LIST_TRUSTDOM, NULL, &response)
196 != NSS_STATUS_SUCCESS) {
197 PyErr_SetString(winbind_error, "lookup failed");
198 return NULL;
199 }
200
201 result = PyList_New(0);
202
203 if (response.extra_data.data) {
204 const char *extra_data = response.extra_data.data;
205 fstring name;
206
207 while (next_token(&extra_data, name, ",", sizeof(fstring)))
208 PyList_Append(result, PyString_FromString(name));
209 }
210
211 return result;
212}
213
214/* Check machine account password */
215
216static PyObject *py_check_secret(PyObject *self, PyObject *args)
217{
218 struct winbindd_response response;
219
220 if (!PyArg_ParseTuple(args, ""))
221 return NULL;
222
223 ZERO_STRUCT(response);
224
225 if (winbindd_request_response(WINBINDD_CHECK_MACHACC, NULL, &response)
226 != NSS_STATUS_SUCCESS) {
227 PyErr_SetString(winbind_error, "lookup failed");
228 return NULL;
229 }
230
231 return PyInt_FromLong(response.data.num_entries);
232}
233
234/*
235 * Return a dictionary consisting of all the winbind related smb.conf
236 * parameters. This is stored in the module object.
237 */
238
239static PyObject *py_config_dict(void)
240{
241 PyObject *result;
242 uid_t ulow, uhi;
243 gid_t glow, ghi;
244
245 if (!(result = PyDict_New()))
246 return NULL;
247
248 /* Various string parameters */
249
250 PyDict_SetItemString(result, "workgroup",
251 PyString_FromString(lp_workgroup()));
252
253 PyDict_SetItemString(result, "separator",
254 PyString_FromString(lp_winbind_separator()));
255
256 PyDict_SetItemString(result, "template_homedir",
257 PyString_FromString(lp_template_homedir()));
258
259 PyDict_SetItemString(result, "template_shell",
260 PyString_FromString(lp_template_shell()));
261
262 /* idmap uid/gid range */
263
264 if (lp_idmap_uid(&ulow, &uhi)) {
265 PyDict_SetItemString(result, "uid_low", PyInt_FromLong(ulow));
266 PyDict_SetItemString(result, "uid_high", PyInt_FromLong(uhi));
267 }
268
269 if (lp_idmap_gid(&glow, &ghi)) {
270 PyDict_SetItemString(result, "gid_low", PyInt_FromLong(glow));
271 PyDict_SetItemString(result, "gid_high", PyInt_FromLong(ghi));
272 }
273
274 return result;
275}
276
277/*
278 * ID mapping
279 */
280
281/* Convert a uid to a SID */
282
283static PyObject *py_uid_to_sid(PyObject *self, PyObject *args)
284{
285 struct winbindd_request request;
286 struct winbindd_response response;
287 int id;
288
289 if (!PyArg_ParseTuple(args, "i", &id))
290 return NULL;
291
292 ZERO_STRUCT(request);
293 ZERO_STRUCT(response);
294
295 request.data.uid = id;
296
297 if (winbindd_request_response(WINBINDD_UID_TO_SID, &request, &response)
298 != NSS_STATUS_SUCCESS) {
299 PyErr_SetString(winbind_error, "lookup failed");
300 return NULL;
301 }
302
303 return PyString_FromString(response.data.sid.sid);
304}
305
306/* Convert a gid to a SID */
307
308static PyObject *py_gid_to_sid(PyObject *self, PyObject *args)
309{
310 struct winbindd_request request;
311 struct winbindd_response response;
312 int id;
313
314 if (!PyArg_ParseTuple(args, "i", &id))
315 return NULL;
316
317 ZERO_STRUCT(request);
318 ZERO_STRUCT(response);
319
320 request.data.gid = id;
321
322 if (winbindd_request_response(WINBINDD_GID_TO_SID, &request, &response)
323 != NSS_STATUS_SUCCESS) {
324 PyErr_SetString(winbind_error, "lookup failed");
325 return NULL;
326 }
327
328 return PyString_FromString(response.data.sid.sid);
329}
330
331/* Convert a sid to a uid */
332
333static PyObject *py_sid_to_uid(PyObject *self, PyObject *args)
334{
335 struct winbindd_request request;
336 struct winbindd_response response;
337 char *sid;
338
339 if (!PyArg_ParseTuple(args, "s", &sid))
340 return NULL;
341
342 ZERO_STRUCT(request);
343 ZERO_STRUCT(response);
344
345 fstrcpy(request.data.sid, sid);
346
347 if (winbindd_request_response(WINBINDD_SID_TO_UID, &request, &response)
348 != NSS_STATUS_SUCCESS) {
349 PyErr_SetString(winbind_error, "lookup failed");
350 return NULL;
351 }
352
353 return PyInt_FromLong(response.data.uid);
354}
355
356/* Convert a sid to a gid */
357
358static PyObject *py_sid_to_gid(PyObject *self, PyObject *args)
359{
360 struct winbindd_request request;
361 struct winbindd_response response;
362 char *sid;
363
364 if (!PyArg_ParseTuple(args, "s", &sid))
365 return NULL;
366
367 ZERO_STRUCT(request);
368 ZERO_STRUCT(response);
369
370 fstrcpy(request.data.sid, sid);
371
372 if (winbindd_request_response(WINBINDD_SID_TO_GID, &request, &response)
373 != NSS_STATUS_SUCCESS) {
374 PyErr_SetString(winbind_error, "lookup failed");
375 return NULL;
376 }
377
378 return PyInt_FromLong(response.data.gid);
379}
380
381/*
382 * PAM authentication functions
383 */
384
385/* Plaintext authentication */
386
387static PyObject *py_auth_plaintext(PyObject *self, PyObject *args)
388{
389 struct winbindd_request request;
390 struct winbindd_response response;
391 char *username, *password;
392
393 if (!PyArg_ParseTuple(args, "ss", &username, &password))
394 return NULL;
395
396 ZERO_STRUCT(request);
397 ZERO_STRUCT(response);
398
399 fstrcpy(request.data.auth.user, username);
400 fstrcpy(request.data.auth.pass, password);
401
402 if (winbindd_request_response(WINBINDD_PAM_AUTH, &request, &response)
403 != NSS_STATUS_SUCCESS) {
404 PyErr_SetString(winbind_error, "lookup failed");
405 return NULL;
406 }
407
408 return PyInt_FromLong(response.data.auth.nt_status);
409}
410
411/* Challenge/response authentication */
412
413static PyObject *py_auth_crap(PyObject *self, PyObject *args, PyObject *kw)
414{
415 static char *kwlist[] =
416 {"username", "password", "use_lm_hash", "use_nt_hash", NULL };
417 struct winbindd_request request;
418 struct winbindd_response response;
419 char *username, *password;
420 int use_lm_hash = 1, use_nt_hash = 1;
421
422 if (!PyArg_ParseTupleAndKeywords(
423 args, kw, "ss|ii", kwlist, &username, &password,
424 &use_lm_hash, &use_nt_hash))
425 return NULL;
426
427 ZERO_STRUCT(request);
428 ZERO_STRUCT(response);
429
430 if (push_utf8_fstring(request.data.auth_crap.user, username) == -1) {
431 PyErr_SetString(winbind_error, "unable to create utf8 string");
432 return NULL;
433 }
434
435 generate_random_buffer(request.data.auth_crap.chal, 8);
436
437 if (use_lm_hash) {
438 SMBencrypt((uchar *)password, request.data.auth_crap.chal,
439 (uchar *)request.data.auth_crap.lm_resp);
440 request.data.auth_crap.lm_resp_len = 24;
441 }
442
443 if (use_nt_hash) {
444 SMBNTencrypt((uchar *)password, request.data.auth_crap.chal,
445 (uchar *)request.data.auth_crap.nt_resp);
446 request.data.auth_crap.nt_resp_len = 24;
447 }
448
449 if (winbindd_request_response(WINBINDD_PAM_AUTH_CRAP, &request, &response)
450 != NSS_STATUS_SUCCESS) {
451 PyErr_SetString(winbind_error, "lookup failed");
452 return NULL;
453 }
454
455 return PyInt_FromLong(response.data.auth.nt_status);
456}
457
458#if 0 /* Include when auth_smbd merged to HEAD */
459
460/* Challenge/response authentication, with secret */
461
462static PyObject *py_auth_smbd(PyObject *self, PyObject *args, PyObject *kw)
463{
464 static char *kwlist[] =
465 {"username", "password", "use_lm_hash", "use_nt_hash", NULL };
466 struct winbindd_request request;
467 struct winbindd_response response;
468 char *username, *password;
469 int use_lm_hash = 1, use_nt_hash = 1;
470
471 if (!PyArg_ParseTupleAndKeywords(
472 args, kw, "ss|ii", kwlist, &username, &password,
473 &use_lm_hash, &use_nt_hash))
474 return NULL;
475
476 ZERO_STRUCT(request);
477 ZERO_STRUCT(response);
478
479 if (push_utf8_fstring(request.data.auth_crap.user, username) == -1) {
480 PyErr_SetString("unable to create utf8 string");
481 return NULL;
482 }
483
484 generate_random_buffer(request.data.smbd_auth_crap.chal, 8);
485
486 if (use_lm_hash) {
487 SMBencrypt((uchar *)password,
488 request.data.smbd_auth_crap.chal,
489 (uchar *)request.data.smbd_auth_crap.lm_resp);
490 request.data.smbd_auth_crap.lm_resp_len = 24;
491 }
492
493 if (use_nt_hash) {
494 SMBNTencrypt((uchar *)password,
495 request.data.smbd_auth_crap.chal,
496 (uchar *)request.data.smbd_auth_crap.nt_resp);
497 request.data.smbd_auth_crap.nt_resp_len = 24;
498 }
499
500 if (!secrets_fetch_trust_account_password(
501 lp_workgroup(), request.data.smbd_auth_crap.proof, NULL)) {
502 PyErr_SetString(
503 winbind_error, "unable to fetch domain secret");
504 return NULL;
505 }
506
507
508
509 if (winbindd_request_response(WINBINDD_SMBD_AUTH_CRAP, &request, &response)
510 != NSS_STATUS_SUCCESS) {
511 PyErr_SetString(winbind_error, "lookup failed");
512 return NULL;
513 }
514
515 return PyInt_FromLong(response.data.auth.nt_status);
516}
517
518#endif /* 0 */
519
520/* Get user info from name */
521
522static PyObject *py_getpwnam(PyObject *self, PyObject *args)
523{
524 struct winbindd_request request;
525 struct winbindd_response response;
526 char *username;
527 PyObject *result;
528
529 if (!PyArg_ParseTuple(args, "s", &username))
530 return NULL;
531
532 ZERO_STRUCT(request);
533 ZERO_STRUCT(response);
534
535 fstrcpy(request.data.username, username);
536
537 if (winbindd_request_response(WINBINDD_GETPWNAM, &request, &response)
538 != NSS_STATUS_SUCCESS) {
539 PyErr_SetString(winbind_error, "lookup failed");
540 return NULL;
541 }
542
543 if (!py_from_winbind_passwd(&result, &response)) {
544 result = Py_None;
545 Py_INCREF(result);
546 }
547
548 return result;
549}
550
551/* Get user info from uid */
552
553static PyObject *py_getpwuid(PyObject *self, PyObject *args)
554{
555 struct winbindd_request request;
556 struct winbindd_response response;
557 uid_t uid;
558 PyObject *result;
559
560 if (!PyArg_ParseTuple(args, "i", &uid))
561 return NULL;
562
563 ZERO_STRUCT(request);
564 ZERO_STRUCT(response);
565
566 request.data.uid = uid;
567
568 if (winbindd_request_response(WINBINDD_GETPWUID, &request, &response)
569 != NSS_STATUS_SUCCESS) {
570 PyErr_SetString(winbind_error, "lookup failed");
571 return NULL;
572 }
573
574 if (!py_from_winbind_passwd(&result, &response)) {
575 result = Py_None;
576 Py_INCREF(result);
577 }
578
579 return result;
580}
581
582/*
583 * Method dispatch table
584 */
585
586static PyMethodDef winbind_methods[] = {
587
588 { "getpwnam", (PyCFunction)py_getpwnam, METH_VARARGS, "getpwnam(3)" },
589 { "getpwuid", (PyCFunction)py_getpwuid, METH_VARARGS, "getpwuid(3)" },
590
591 /* Name <-> SID conversion */
592
593 { "name_to_sid", (PyCFunction)py_name_to_sid, METH_VARARGS,
594 "name_to_sid(s) -> string\n"
595"\n"
596"Return the SID for a name.\n"
597"\n"
598"Example:\n"
599"\n"
600">>> winbind.name_to_sid('FOO/Administrator')\n"
601"'S-1-5-21-406022937-1377575209-526660263-500' " },
602
603 { "sid_to_name", (PyCFunction)py_sid_to_name, METH_VARARGS,
604 "sid_to_name(s) -> string\n"
605"\n"
606"Return the name for a SID.\n"
607"\n"
608"Example:\n"
609"\n"
610">>> import winbind\n"
611">>> winbind.sid_to_name('S-1-5-21-406022937-1377575209-526660263-500')\n"
612"'FOO/Administrator' " },
613
614 /* Enumerate users/groups */
615
616 { "enum_domain_users", (PyCFunction)py_enum_domain_users, METH_VARARGS,
617 "enum_domain_users() -> list of strings\n"
618"\n"
619"Return a list of domain users.\n"
620"\n"
621"Example:\n"
622"\n"
623">>> winbind.enum_domain_users()\n"
624"['FOO/Administrator', 'FOO/anna', 'FOO/Anne Elk', 'FOO/build', \n"
625"'FOO/foo', 'FOO/foo2', 'FOO/foo3', 'FOO/Guest', 'FOO/user1', \n"
626"'FOO/whoops-ptang'] " },
627
628 { "enum_domain_groups", (PyCFunction)py_enum_domain_groups,
629 METH_VARARGS,
630 "enum_domain_groups() -> list of strings\n"
631"\n"
632"Return a list of domain groups.\n"
633"\n"
634"Example:\n"
635"\n"
636">>> winbind.enum_domain_groups()\n"
637"['FOO/cows', 'FOO/Domain Admins', 'FOO/Domain Guests', \n"
638"'FOO/Domain Users'] " },
639
640 /* ID mapping */
641
642 { "uid_to_sid", (PyCFunction)py_uid_to_sid, METH_VARARGS,
643 "uid_to_sid(int) -> string\n"
644"\n"
645"Return the SID for a UNIX uid.\n"
646"\n"
647"Example:\n"
648"\n"
649">>> winbind.uid_to_sid(10000) \n"
650"'S-1-5-21-406022937-1377575209-526660263-500' " },
651
652 { "gid_to_sid", (PyCFunction)py_gid_to_sid, METH_VARARGS,
653 "gid_to_sid(int) -> string\n"
654"\n"
655"Return the UNIX gid for a SID.\n"
656"\n"
657"Example:\n"
658"\n"
659">>> winbind.gid_to_sid(10001)\n"
660"'S-1-5-21-406022937-1377575209-526660263-512' " },
661
662 { "sid_to_uid", (PyCFunction)py_sid_to_uid, METH_VARARGS,
663 "sid_to_uid(string) -> int\n"
664"\n"
665"Return the UNIX uid for a SID.\n"
666"\n"
667"Example:\n"
668"\n"
669">>> winbind.sid_to_uid('S-1-5-21-406022937-1377575209-526660263-500')\n"
670"10000 " },
671
672 { "sid_to_gid", (PyCFunction)py_sid_to_gid, METH_VARARGS,
673 "sid_to_gid(string) -> int\n"
674"\n"
675"Return the UNIX gid corresponding to a SID.\n"
676"\n"
677"Example:\n"
678"\n"
679">>> winbind.sid_to_gid('S-1-5-21-406022937-1377575209-526660263-512')\n"
680"10001 " },
681
682 /* Miscellaneous */
683
684 { "check_secret", (PyCFunction)py_check_secret, METH_VARARGS,
685 "check_secret() -> int\n"
686"\n"
687"Check the machine trust account password. The NT status is returned\n"
688"with zero indicating success. " },
689
690 { "enum_trust_dom", (PyCFunction)py_enum_trust_dom, METH_VARARGS,
691 "enum_trust_dom() -> list of strings\n"
692"\n"
693"Return a list of trusted domains. The domain the server is a member \n"
694"of is not included.\n"
695"\n"
696"Example:\n"
697"\n"
698">>> winbind.enum_trust_dom()\n"
699"['NPSD-TEST2', 'SP2NDOM'] " },
700
701 /* PAM authorisation functions */
702
703 { "auth_plaintext", (PyCFunction)py_auth_plaintext, METH_VARARGS,
704 "auth_plaintext(s, s) -> int\n"
705"\n"
706"Authenticate a username and password using plaintext authentication.\n"
707"The NT status code is returned with zero indicating success." },
708
709 { "auth_crap", (PyCFunction)py_auth_crap, METH_VARARGS | METH_KEYWORDS,
710 "auth_crap(s, s) -> int\n"
711"\n"
712"Authenticate a username and password using the challenge/response\n"
713"protocol. The NT status code is returned with zero indicating\n"
714"success." },
715
716#if 0 /* Include when smbd_auth merged to HEAD */
717
718 { "auth_smbd", (PyCFunction)py_auth_crap, METH_VARARGS,
719 "auth_smbd(s, s) -> int\n"
720"\n"
721"Authenticate a username and password using the challenge/response\n"
722"protocol but using the domain secret to prove we are root. The NT \n"
723"status code is returned with zero indicating success." },
724
725#endif
726
727 { NULL }
728};
729
730static struct const_vals {
731 char *name;
732 uint32 value;
733 char *docstring;
734} module_const_vals[] = {
735
736 /* Well known RIDs */
737
738 { "DOMAIN_USER_RID_ADMIN", DOMAIN_USER_RID_ADMIN,
739 "Well-known RID for Administrator user" },
740
741 { "DOMAIN_USER_RID_GUEST", DOMAIN_USER_RID_GUEST,
742 "Well-known RID for Guest user" },
743
744 { "DOMAIN_GROUP_RID_ADMINS", DOMAIN_GROUP_RID_ADMINS,
745 "Well-known RID for Domain Admins group" },
746
747 { "DOMAIN_GROUP_RID_USERS", DOMAIN_GROUP_RID_USERS,
748 "Well-known RID for Domain Users group" },
749
750 { "DOMAIN_GROUP_RID_GUESTS", DOMAIN_GROUP_RID_GUESTS,
751 "Well-known RID for Domain Guests group" },
752
753 { NULL }
754};
755
756static void const_init(PyObject *dict)
757{
758 struct const_vals *tmp;
759 PyObject *obj;
760
761 for (tmp = module_const_vals; tmp->name; tmp++) {
762 obj = PyInt_FromLong(tmp->value);
763 PyDict_SetItemString(dict, tmp->name, obj);
764 Py_DECREF(obj);
765 }
766}
767
768/*
769 * Module initialisation
770 */
771
772static char winbind_module__doc__[] =
773"A python extension to winbind client functions.";
774
775void initwinbind(void)
776{
777 PyObject *module, *dict;
778
779 /* Initialise module */
780
781 module = Py_InitModule3("winbind", winbind_methods,
782 winbind_module__doc__);
783
784 dict = PyModule_GetDict(module);
785
786 winbind_error = PyErr_NewException("winbind.error", NULL, NULL);
787 PyDict_SetItemString(dict, "error", winbind_error);
788
789 /* Do samba initialisation */
790
791 py_samba_init();
792
793 /* Initialise constants */
794
795 const_init(dict);
796
797 /* Insert configuration dictionary */
798
799 PyDict_SetItemString(dict, "config", py_config_dict());
800}
Note: See TracBrowser for help on using the repository browser.