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