python: samba.credentials: Port pycredentials.c to Python3-compatible form.
[martins/samba.git] / auth / credentials / pycredentials.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
4    
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9    
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14    
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <Python.h>
20 #include "python/py3compat.h"
21 #include "includes.h"
22 #include "pycredentials.h"
23 #include "param/param.h"
24 #include "lib/cmdline/credentials.h"
25 #include "librpc/gen_ndr/samr.h" /* for struct samr_Password */
26 #include "libcli/util/pyerrors.h"
27 #include "param/pyparam.h"
28 #include <tevent.h>
29
30 void initcredentials(void);
31
32 static PyObject *PyString_FromStringOrNULL(const char *str)
33 {
34         if (str == NULL)
35                 Py_RETURN_NONE;
36         return PyStr_FromString(str);
37 }
38
39 static PyObject *py_creds_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
40 {
41         return pytalloc_steal(type, cli_credentials_init(NULL));
42 }
43
44 static PyObject *py_creds_get_username(PyObject *self, PyObject *unused)
45 {
46         return PyString_FromStringOrNULL(cli_credentials_get_username(PyCredentials_AsCliCredentials(self)));
47 }
48
49 static PyObject *py_creds_set_username(PyObject *self, PyObject *args)
50 {
51         char *newval;
52         enum credentials_obtained obt = CRED_SPECIFIED;
53         int _obt = obt;
54
55         if (!PyArg_ParseTuple(args, "s|i", &newval, &_obt)) {
56                 return NULL;
57         }
58         obt = _obt;
59
60         return PyBool_FromLong(cli_credentials_set_username(PyCredentials_AsCliCredentials(self), newval, obt));
61 }
62
63 static PyObject *py_creds_get_ntlm_username_domain(PyObject *self, PyObject *unused)
64 {
65         TALLOC_CTX *frame = talloc_stackframe();
66         const char *user = NULL;
67         const char *domain = NULL;
68         PyObject *ret = NULL;
69         cli_credentials_get_ntlm_username_domain(PyCredentials_AsCliCredentials(self),
70                                                  frame, &user, &domain);
71         ret = Py_BuildValue("(OO)",
72                             PyString_FromStringOrNULL(user),
73                             PyString_FromStringOrNULL(domain));
74         TALLOC_FREE(frame);
75         return ret;
76 }
77
78 static PyObject *py_creds_get_principal(PyObject *self, PyObject *unused)
79 {
80         TALLOC_CTX *frame = talloc_stackframe();
81         PyObject *ret = PyString_FromStringOrNULL(cli_credentials_get_principal(PyCredentials_AsCliCredentials(self), frame));
82         TALLOC_FREE(frame);
83         return ret;
84 }
85
86 static PyObject *py_creds_set_principal(PyObject *self, PyObject *args)
87 {
88         char *newval;
89         enum credentials_obtained obt = CRED_SPECIFIED;
90         int _obt = obt;
91
92         if (!PyArg_ParseTuple(args, "s|i", &newval, &_obt)) {
93                 return NULL;
94         }
95         obt = _obt;
96
97         return PyBool_FromLong(cli_credentials_set_principal(PyCredentials_AsCliCredentials(self), newval, obt));
98 }
99
100 static PyObject *py_creds_get_password(PyObject *self, PyObject *unused)
101 {
102         return PyString_FromStringOrNULL(cli_credentials_get_password(PyCredentials_AsCliCredentials(self)));
103 }
104
105 static PyObject *py_creds_set_password(PyObject *self, PyObject *args)
106 {
107         char *newval;
108         enum credentials_obtained obt = CRED_SPECIFIED;
109         int _obt = obt;
110
111         if (!PyArg_ParseTuple(args, "s|i", &newval, &_obt)) {
112                 return NULL;
113         }
114         obt = _obt;
115
116         return PyBool_FromLong(cli_credentials_set_password(PyCredentials_AsCliCredentials(self), newval, obt));
117 }
118
119 static PyObject *py_creds_set_utf16_password(PyObject *self, PyObject *args)
120 {
121         enum credentials_obtained obt = CRED_SPECIFIED;
122         int _obt = obt;
123         PyObject *newval = NULL;
124         DATA_BLOB blob = data_blob_null;
125         Py_ssize_t size =  0;
126         int result;
127         bool ok;
128
129         if (!PyArg_ParseTuple(args, "O|i", &newval, &_obt)) {
130                 return NULL;
131         }
132         obt = _obt;
133
134         result = PyBytes_AsStringAndSize(newval, (char **)&blob.data, &size);
135         if (result != 0) {
136                 PyErr_SetString(PyExc_RuntimeError, "Failed to convert passed value to Bytes");
137                 return NULL;
138         }
139         blob.length = size;
140
141         ok = cli_credentials_set_utf16_password(PyCredentials_AsCliCredentials(self),
142                                                 &blob, obt);
143
144         return PyBool_FromLong(ok);
145 }
146
147 static PyObject *py_creds_get_old_password(PyObject *self, PyObject *unused)
148 {
149         return PyString_FromStringOrNULL(cli_credentials_get_old_password(PyCredentials_AsCliCredentials(self)));
150 }
151
152 static PyObject *py_creds_set_old_password(PyObject *self, PyObject *args)
153 {
154         char *oldval;
155         enum credentials_obtained obt = CRED_SPECIFIED;
156         int _obt = obt;
157
158         if (!PyArg_ParseTuple(args, "s|i", &oldval, &_obt)) {
159                 return NULL;
160         }
161         obt = _obt;
162
163         return PyBool_FromLong(cli_credentials_set_old_password(PyCredentials_AsCliCredentials(self), oldval, obt));
164 }
165
166 static PyObject *py_creds_set_old_utf16_password(PyObject *self, PyObject *args)
167 {
168         PyObject *oldval = NULL;
169         DATA_BLOB blob = data_blob_null;
170         Py_ssize_t size =  0;
171         int result;
172         bool ok;
173
174         if (!PyArg_ParseTuple(args, "O", &oldval)) {
175                 return NULL;
176         }
177
178         result = PyBytes_AsStringAndSize(oldval, (char **)&blob.data, &size);
179         if (result != 0) {
180                 PyErr_SetString(PyExc_RuntimeError, "Failed to convert passed value to Bytes");
181                 return NULL;
182         }
183         blob.length = size;
184
185         ok = cli_credentials_set_old_utf16_password(PyCredentials_AsCliCredentials(self),
186                                                     &blob);
187
188         return PyBool_FromLong(ok);
189 }
190
191 static PyObject *py_creds_get_domain(PyObject *self, PyObject *unused)
192 {
193         return PyString_FromStringOrNULL(cli_credentials_get_domain(PyCredentials_AsCliCredentials(self)));
194 }
195
196 static PyObject *py_creds_set_domain(PyObject *self, PyObject *args)
197 {
198         char *newval;
199         enum credentials_obtained obt = CRED_SPECIFIED;
200         int _obt = obt;
201
202         if (!PyArg_ParseTuple(args, "s|i", &newval, &_obt)) {
203                 return NULL;
204         }
205         obt = _obt;
206
207         return PyBool_FromLong(cli_credentials_set_domain(PyCredentials_AsCliCredentials(self), newval, obt));
208 }
209
210 static PyObject *py_creds_get_realm(PyObject *self, PyObject *unused)
211 {
212         return PyString_FromStringOrNULL(cli_credentials_get_realm(PyCredentials_AsCliCredentials(self)));
213 }
214
215 static PyObject *py_creds_set_realm(PyObject *self, PyObject *args)
216 {
217         char *newval;
218         enum credentials_obtained obt = CRED_SPECIFIED;
219         int _obt = obt;
220
221         if (!PyArg_ParseTuple(args, "s|i", &newval, &_obt)) {
222                 return NULL;
223         }
224         obt = _obt;
225
226         return PyBool_FromLong(cli_credentials_set_realm(PyCredentials_AsCliCredentials(self), newval, obt));
227 }
228
229 static PyObject *py_creds_get_bind_dn(PyObject *self, PyObject *unused)
230 {
231         return PyString_FromStringOrNULL(cli_credentials_get_bind_dn(PyCredentials_AsCliCredentials(self)));
232 }
233
234 static PyObject *py_creds_set_bind_dn(PyObject *self, PyObject *args)
235 {
236         char *newval;
237         if (!PyArg_ParseTuple(args, "s", &newval))
238                 return NULL;
239
240         return PyBool_FromLong(cli_credentials_set_bind_dn(PyCredentials_AsCliCredentials(self), newval));
241 }
242
243 static PyObject *py_creds_get_workstation(PyObject *self, PyObject *unused)
244 {
245         return PyString_FromStringOrNULL(cli_credentials_get_workstation(PyCredentials_AsCliCredentials(self)));
246 }
247
248 static PyObject *py_creds_set_workstation(PyObject *self, PyObject *args)
249 {
250         char *newval;
251         enum credentials_obtained obt = CRED_SPECIFIED;
252         int _obt = obt;
253
254         if (!PyArg_ParseTuple(args, "s|i", &newval, &_obt)) {
255                 return NULL;
256         }
257         obt = _obt;
258
259         return PyBool_FromLong(cli_credentials_set_workstation(PyCredentials_AsCliCredentials(self), newval, obt));
260 }
261
262 static PyObject *py_creds_is_anonymous(PyObject *self, PyObject *unused)
263 {
264         return PyBool_FromLong(cli_credentials_is_anonymous(PyCredentials_AsCliCredentials(self)));
265 }
266
267 static PyObject *py_creds_set_anonymous(PyObject *self, PyObject *unused)
268 {
269         cli_credentials_set_anonymous(PyCredentials_AsCliCredentials(self));
270         Py_RETURN_NONE;
271 }
272
273 static PyObject *py_creds_authentication_requested(PyObject *self, PyObject *unused)
274 {
275         return PyBool_FromLong(cli_credentials_authentication_requested(PyCredentials_AsCliCredentials(self)));
276 }
277
278 static PyObject *py_creds_wrong_password(PyObject *self, PyObject *unused)
279 {
280         return PyBool_FromLong(cli_credentials_wrong_password(PyCredentials_AsCliCredentials(self)));
281 }
282
283 static PyObject *py_creds_set_cmdline_callbacks(PyObject *self, PyObject *unused)
284 {
285         return PyBool_FromLong(cli_credentials_set_cmdline_callbacks(PyCredentials_AsCliCredentials(self)));
286 }
287
288 static PyObject *py_creds_parse_string(PyObject *self, PyObject *args)
289 {
290         char *newval;
291         enum credentials_obtained obt = CRED_SPECIFIED;
292         int _obt = obt;
293
294         if (!PyArg_ParseTuple(args, "s|i", &newval, &_obt)) {
295                 return NULL;
296         }
297         obt = _obt;
298
299         cli_credentials_parse_string(PyCredentials_AsCliCredentials(self), newval, obt);
300         Py_RETURN_NONE;
301 }
302
303 static PyObject *py_creds_parse_file(PyObject *self, PyObject *args)
304 {
305         char *newval;
306         enum credentials_obtained obt = CRED_SPECIFIED;
307         int _obt = obt;
308
309         if (!PyArg_ParseTuple(args, "s|i", &newval, &_obt)) {
310                 return NULL;
311         }
312         obt = _obt;
313
314         cli_credentials_parse_file(PyCredentials_AsCliCredentials(self), newval, obt);
315         Py_RETURN_NONE;
316 }
317
318 static PyObject *py_cli_credentials_set_password_will_be_nt_hash(PyObject *self, PyObject *args)
319 {
320         struct cli_credentials *creds = PyCredentials_AsCliCredentials(self);
321         PyObject *py_val = NULL;
322         bool val = false;
323
324         if (!PyArg_ParseTuple(args, "O!", &PyBool_Type, &py_val)) {
325                 return NULL;
326         }
327         val = PyObject_IsTrue(py_val);
328
329         cli_credentials_set_password_will_be_nt_hash(creds, val);
330         Py_RETURN_NONE;
331 }
332
333 static PyObject *py_creds_get_nt_hash(PyObject *self, PyObject *unused)
334 {
335         PyObject *ret;
336         struct cli_credentials *creds = PyCredentials_AsCliCredentials(self);
337         struct samr_Password *ntpw = cli_credentials_get_nt_hash(creds, creds);
338
339         ret = PyBytes_FromStringAndSize(discard_const_p(char, ntpw->hash), 16);
340         TALLOC_FREE(ntpw);
341         return ret;
342 }
343
344 static PyObject *py_creds_get_kerberos_state(PyObject *self, PyObject *unused)
345 {
346         int state = cli_credentials_get_kerberos_state(PyCredentials_AsCliCredentials(self));
347         return PyInt_FromLong(state);
348 }
349
350 static PyObject *py_creds_set_kerberos_state(PyObject *self, PyObject *args)
351 {
352         int state;
353         if (!PyArg_ParseTuple(args, "i", &state))
354                 return NULL;
355
356         cli_credentials_set_kerberos_state(PyCredentials_AsCliCredentials(self), state);
357         Py_RETURN_NONE;
358 }
359
360 static PyObject *py_creds_set_krb_forwardable(PyObject *self, PyObject *args)
361 {
362         int state;
363         if (!PyArg_ParseTuple(args, "i", &state))
364                 return NULL;
365
366         cli_credentials_set_krb_forwardable(PyCredentials_AsCliCredentials(self), state);
367         Py_RETURN_NONE;
368 }
369
370
371 static PyObject *py_creds_get_forced_sasl_mech(PyObject *self, PyObject *unused)
372 {
373         return PyString_FromStringOrNULL(cli_credentials_get_forced_sasl_mech(PyCredentials_AsCliCredentials(self)));
374 }
375
376 static PyObject *py_creds_set_forced_sasl_mech(PyObject *self, PyObject *args)
377 {
378         char *newval;
379         enum credentials_obtained obt = CRED_SPECIFIED;
380         int _obt = obt;
381
382         if (!PyArg_ParseTuple(args, "s", &newval)) {
383                 return NULL;
384         }
385         obt = _obt;
386
387         cli_credentials_set_forced_sasl_mech(PyCredentials_AsCliCredentials(self), newval);
388         Py_RETURN_NONE;
389 }
390
391 static PyObject *py_creds_guess(PyObject *self, PyObject *args)
392 {
393         PyObject *py_lp_ctx = Py_None;
394         struct loadparm_context *lp_ctx;
395         TALLOC_CTX *mem_ctx;
396         struct cli_credentials *creds;
397
398         creds = PyCredentials_AsCliCredentials(self);
399
400         if (!PyArg_ParseTuple(args, "|O", &py_lp_ctx))
401                 return NULL;
402
403         mem_ctx = talloc_new(NULL);
404         if (mem_ctx == NULL) {
405                 PyErr_NoMemory();
406                 return NULL;
407         }
408
409         lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
410         if (lp_ctx == NULL) {
411                 talloc_free(mem_ctx);
412                 return NULL;
413         }
414
415         cli_credentials_guess(creds, lp_ctx);
416
417         talloc_free(mem_ctx);
418
419         Py_RETURN_NONE;
420 }
421
422 static PyObject *py_creds_set_machine_account(PyObject *self, PyObject *args)
423 {
424         PyObject *py_lp_ctx = Py_None;
425         struct loadparm_context *lp_ctx;
426         NTSTATUS status;
427         struct cli_credentials *creds;
428         TALLOC_CTX *mem_ctx;
429
430         creds = PyCredentials_AsCliCredentials(self);
431
432         if (!PyArg_ParseTuple(args, "|O", &py_lp_ctx))
433                 return NULL;
434
435         mem_ctx = talloc_new(NULL);
436         if (mem_ctx == NULL) {
437                 PyErr_NoMemory();
438                 return NULL;
439         }
440
441         lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
442         if (lp_ctx == NULL) {
443                 talloc_free(mem_ctx);
444                 return NULL;
445         }
446
447         status = cli_credentials_set_machine_account(creds, lp_ctx);
448         talloc_free(mem_ctx);
449
450         PyErr_NTSTATUS_IS_ERR_RAISE(status);
451
452         Py_RETURN_NONE;
453 }
454
455 static PyObject *PyCredentialCacheContainer_from_ccache_container(struct ccache_container *ccc)
456 {
457         return pytalloc_reference(&PyCredentialCacheContainer, ccc);
458 }
459
460
461 static PyObject *py_creds_get_named_ccache(PyObject *self, PyObject *args)
462 {
463         PyObject *py_lp_ctx = Py_None;
464         char *ccache_name;
465         struct loadparm_context *lp_ctx;
466         struct ccache_container *ccc;
467         struct tevent_context *event_ctx;
468         int ret;
469         const char *error_string;
470         struct cli_credentials *creds;
471         TALLOC_CTX *mem_ctx;
472
473         creds = PyCredentials_AsCliCredentials(self);
474
475         if (!PyArg_ParseTuple(args, "|Os", &py_lp_ctx, &ccache_name))
476                 return NULL;
477
478         mem_ctx = talloc_new(NULL);
479         if (mem_ctx == NULL) {
480                 PyErr_NoMemory();
481                 return NULL;
482         }
483
484         lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
485         if (lp_ctx == NULL) {
486                 talloc_free(mem_ctx);
487                 return NULL;
488         }
489
490         event_ctx = samba_tevent_context_init(mem_ctx);
491
492         ret = cli_credentials_get_named_ccache(creds, event_ctx, lp_ctx,
493                                                ccache_name, &ccc, &error_string);
494         talloc_unlink(mem_ctx, lp_ctx);
495         if (ret == 0) {
496                 talloc_steal(ccc, event_ctx);
497                 talloc_free(mem_ctx);
498                 return PyCredentialCacheContainer_from_ccache_container(ccc);
499         }
500
501         PyErr_SetString(PyExc_RuntimeError, error_string?error_string:"NULL");
502
503         talloc_free(mem_ctx);
504         return NULL;
505 }
506
507 static PyObject *py_creds_set_gensec_features(PyObject *self, PyObject *args)
508 {
509         unsigned int gensec_features;
510
511         if (!PyArg_ParseTuple(args, "I", &gensec_features))
512                 return NULL;
513
514         cli_credentials_set_gensec_features(PyCredentials_AsCliCredentials(self), gensec_features);
515
516         Py_RETURN_NONE;
517 }
518
519 static PyObject *py_creds_get_gensec_features(PyObject *self, PyObject *args)
520 {
521         unsigned int gensec_features;
522
523         gensec_features = cli_credentials_get_gensec_features(PyCredentials_AsCliCredentials(self));
524         return PyInt_FromLong(gensec_features);
525 }
526
527
528 static PyMethodDef py_creds_methods[] = {
529         { "get_username", py_creds_get_username, METH_NOARGS,
530                 "S.get_username() -> username\nObtain username." },
531         { "set_username", py_creds_set_username, METH_VARARGS,
532                 "S.set_username(name[, credentials.SPECIFIED]) -> None\n"
533                 "Change username." },
534         { "get_principal", py_creds_get_principal, METH_NOARGS,
535                 "S.get_principal() -> user@realm\nObtain user principal." },
536         { "set_principal", py_creds_set_principal, METH_VARARGS,
537                 "S.set_principal(name[, credentials.SPECIFIED]) -> None\n"
538                 "Change principal." },
539         { "get_password", py_creds_get_password, METH_NOARGS,
540                 "S.get_password() -> password\n"
541                 "Obtain password." },
542         { "get_ntlm_username_domain", py_creds_get_ntlm_username_domain, METH_NOARGS,
543                 "S.get_ntlm_username_domain() -> (domain, username)\n"
544                 "Obtain NTLM username and domain, split up either as (DOMAIN, user) or (\"\", \"user@realm\")." },
545         { "set_password", py_creds_set_password, METH_VARARGS,
546                 "S.set_password(password[, credentials.SPECIFIED]) -> None\n"
547                 "Change password." },
548         { "set_utf16_password", py_creds_set_utf16_password, METH_VARARGS,
549                 "S.set_utf16_password(password[, credentials.SPECIFIED]) -> None\n"
550                 "Change password." },
551         { "get_old_password", py_creds_get_old_password, METH_NOARGS,
552                 "S.get_old_password() -> password\n"
553                 "Obtain old password." },
554         { "set_old_password", py_creds_set_old_password, METH_VARARGS,
555                 "S.set_old_password(password[, credentials.SPECIFIED]) -> None\n"
556                 "Change old password." },
557         { "set_old_utf16_password", py_creds_set_old_utf16_password, METH_VARARGS,
558                 "S.set_old_utf16_password(password[, credentials.SPECIFIED]) -> None\n"
559                 "Change old password." },
560         { "get_domain", py_creds_get_domain, METH_NOARGS,
561                 "S.get_domain() -> domain\n"
562                 "Obtain domain name." },
563         { "set_domain", py_creds_set_domain, METH_VARARGS,
564                 "S.set_domain(domain[, credentials.SPECIFIED]) -> None\n"
565                 "Change domain name." },
566         { "get_realm", py_creds_get_realm, METH_NOARGS,
567                 "S.get_realm() -> realm\n"
568                 "Obtain realm name." },
569         { "set_realm", py_creds_set_realm, METH_VARARGS,
570                 "S.set_realm(realm[, credentials.SPECIFIED]) -> None\n"
571                 "Change realm name." },
572         { "get_bind_dn", py_creds_get_bind_dn, METH_NOARGS,
573                 "S.get_bind_dn() -> bind dn\n"
574                 "Obtain bind DN." },
575         { "set_bind_dn", py_creds_set_bind_dn, METH_VARARGS,
576                 "S.set_bind_dn(bind_dn) -> None\n"
577                 "Change bind DN." },
578         { "is_anonymous", py_creds_is_anonymous, METH_NOARGS,
579                 NULL },
580         { "set_anonymous", py_creds_set_anonymous, METH_NOARGS,
581                 "S.set_anonymous() -> None\n"
582                 "Use anonymous credentials." },
583         { "get_workstation", py_creds_get_workstation, METH_NOARGS,
584                 NULL },
585         { "set_workstation", py_creds_set_workstation, METH_VARARGS,
586                 NULL },
587         { "authentication_requested", py_creds_authentication_requested, METH_NOARGS,
588                 NULL },
589         { "wrong_password", py_creds_wrong_password, METH_NOARGS,
590                 "S.wrong_password() -> bool\n"
591                 "Indicate the returned password was incorrect." },
592         { "set_cmdline_callbacks", py_creds_set_cmdline_callbacks, METH_NOARGS,
593                 "S.set_cmdline_callbacks() -> bool\n"
594                 "Use command-line to obtain credentials not explicitly set." },
595         { "parse_string", py_creds_parse_string, METH_VARARGS,
596                 "S.parse_string(text[, credentials.SPECIFIED]) -> None\n"
597                 "Parse credentials string." },
598         { "parse_file", py_creds_parse_file, METH_VARARGS,
599                 "S.parse_file(filename[, credentials.SPECIFIED]) -> None\n"
600                 "Parse credentials file." },
601         { "set_password_will_be_nt_hash",
602                 py_cli_credentials_set_password_will_be_nt_hash, METH_VARARGS,
603                 "S.set_password_will_be_nt_hash(bool) -> None\n"
604                 "Alters the behaviour of S.set_password() "
605                 "to expect the NTHASH as hexstring." },
606         { "get_nt_hash", py_creds_get_nt_hash, METH_NOARGS,
607                 NULL },
608         { "get_kerberos_state", py_creds_get_kerberos_state, METH_NOARGS,
609                 NULL },
610         { "set_kerberos_state", py_creds_set_kerberos_state, METH_VARARGS,
611                 NULL },
612         { "set_krb_forwardable", py_creds_set_krb_forwardable, METH_VARARGS,
613                 NULL },
614         { "guess", py_creds_guess, METH_VARARGS, NULL },
615         { "set_machine_account", py_creds_set_machine_account, METH_VARARGS, NULL },
616         { "get_named_ccache", py_creds_get_named_ccache, METH_VARARGS, NULL },
617         { "set_gensec_features", py_creds_set_gensec_features, METH_VARARGS, NULL },
618         { "get_gensec_features", py_creds_get_gensec_features, METH_NOARGS, NULL },
619         { "get_forced_sasl_mech", py_creds_get_forced_sasl_mech, METH_NOARGS,
620                 "S.get_forced_sasl_mech() -> SASL mechanism\nObtain forced SASL mechanism." },
621         { "set_forced_sasl_mech", py_creds_set_forced_sasl_mech, METH_VARARGS,
622                 "S.set_forced_sasl_mech(name) -> None\n"
623                 "Set forced SASL mechanism." },
624         { NULL }
625 };
626
627 static struct PyModuleDef moduledef = {
628     PyModuleDef_HEAD_INIT,
629     .m_name = "credentials",
630     .m_doc = "Credentials management.",
631     .m_size = -1,
632     .m_methods = py_creds_methods,
633 };
634
635 PyTypeObject PyCredentials = {
636         .tp_name = "credentials.Credentials",
637         .tp_new = py_creds_new,
638         .tp_flags = Py_TPFLAGS_DEFAULT,
639         .tp_methods = py_creds_methods,
640 };
641
642
643 PyTypeObject PyCredentialCacheContainer = {
644         .tp_name = "credentials.CredentialCacheContainer",
645         .tp_flags = Py_TPFLAGS_DEFAULT,
646 };
647
648 MODULE_INIT_FUNC(credentials)
649 {
650         PyObject *m;
651         if (pytalloc_BaseObject_PyType_Ready(&PyCredentials) < 0)
652                 return NULL;
653
654         if (pytalloc_BaseObject_PyType_Ready(&PyCredentialCacheContainer) < 0)
655                 return NULL;
656
657         m = PyModule_Create(&moduledef);
658         if (m == NULL)
659                 return NULL;
660
661         PyModule_AddObject(m, "UNINITIALISED", PyInt_FromLong(CRED_UNINITIALISED));
662         PyModule_AddObject(m, "CALLBACK", PyInt_FromLong(CRED_CALLBACK));
663         PyModule_AddObject(m, "GUESS_ENV", PyInt_FromLong(CRED_GUESS_ENV));
664         PyModule_AddObject(m, "GUESS_FILE", PyInt_FromLong(CRED_GUESS_FILE));
665         PyModule_AddObject(m, "CALLBACK_RESULT", PyInt_FromLong(CRED_CALLBACK_RESULT));
666         PyModule_AddObject(m, "SPECIFIED", PyInt_FromLong(CRED_SPECIFIED));
667
668         PyModule_AddObject(m, "AUTO_USE_KERBEROS", PyInt_FromLong(CRED_AUTO_USE_KERBEROS));
669         PyModule_AddObject(m, "DONT_USE_KERBEROS", PyInt_FromLong(CRED_DONT_USE_KERBEROS));
670         PyModule_AddObject(m, "MUST_USE_KERBEROS", PyInt_FromLong(CRED_MUST_USE_KERBEROS));
671
672         PyModule_AddObject(m, "AUTO_KRB_FORWARDABLE",  PyInt_FromLong(CRED_AUTO_KRB_FORWARDABLE));
673         PyModule_AddObject(m, "NO_KRB_FORWARDABLE",    PyInt_FromLong(CRED_NO_KRB_FORWARDABLE));
674         PyModule_AddObject(m, "FORCE_KRB_FORWARDABLE", PyInt_FromLong(CRED_FORCE_KRB_FORWARDABLE));
675
676         Py_INCREF(&PyCredentials);
677         PyModule_AddObject(m, "Credentials", (PyObject *)&PyCredentials);
678         Py_INCREF(&PyCredentialCacheContainer);
679         PyModule_AddObject(m, "CredentialCacheContainer", (PyObject *)&PyCredentialCacheContainer);
680         return m;
681 }