smbd: Use leases_db in lease_match()
[gd/samba-autobuild/.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 "auth/credentials/credentials_internal.h"
26 #include "librpc/gen_ndr/samr.h" /* for struct samr_Password */
27 #include "librpc/gen_ndr/netlogon.h"
28 #include "libcli/util/pyerrors.h"
29 #include "libcli/auth/libcli_auth.h"
30 #include "param/pyparam.h"
31 #include <tevent.h>
32 #include "libcli/auth/libcli_auth.h"
33 #include "auth/credentials/credentials_internal.h"
34 #include "system/kerberos.h"
35 #include "auth/kerberos/kerberos.h"
36
37 void initcredentials(void);
38
39 static PyObject *PyString_FromStringOrNULL(const char *str)
40 {
41         if (str == NULL)
42                 Py_RETURN_NONE;
43         return PyStr_FromString(str);
44 }
45
46 static PyObject *py_creds_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
47 {
48         return pytalloc_steal(type, cli_credentials_init(NULL));
49 }
50
51 static PyObject *py_creds_get_username(PyObject *self, PyObject *unused)
52 {
53         return PyString_FromStringOrNULL(cli_credentials_get_username(PyCredentials_AsCliCredentials(self)));
54 }
55
56 static PyObject *py_creds_set_username(PyObject *self, PyObject *args)
57 {
58         char *newval;
59         enum credentials_obtained obt = CRED_SPECIFIED;
60         int _obt = obt;
61
62         if (!PyArg_ParseTuple(args, "s|i", &newval, &_obt)) {
63                 return NULL;
64         }
65         obt = _obt;
66
67         return PyBool_FromLong(cli_credentials_set_username(PyCredentials_AsCliCredentials(self), newval, obt));
68 }
69
70 static PyObject *py_creds_get_ntlm_username_domain(PyObject *self, PyObject *unused)
71 {
72         TALLOC_CTX *frame = talloc_stackframe();
73         const char *user = NULL;
74         const char *domain = NULL;
75         PyObject *ret = NULL;
76         cli_credentials_get_ntlm_username_domain(PyCredentials_AsCliCredentials(self),
77                                                  frame, &user, &domain);
78         ret = Py_BuildValue("(ss)",
79                             user,
80                             domain);
81
82         TALLOC_FREE(frame);
83         return ret;
84 }
85
86 static PyObject *py_creds_get_ntlm_response(PyObject *self, PyObject *args, PyObject *kwargs)
87 {
88         TALLOC_CTX *frame = talloc_stackframe();
89         PyObject *ret = NULL;
90         int flags;
91         struct timeval tv_now;
92         NTTIME server_timestamp;
93         DATA_BLOB challenge = data_blob_null;
94         DATA_BLOB target_info = data_blob_null;
95         NTSTATUS status;
96         DATA_BLOB lm_response = data_blob_null;
97         DATA_BLOB nt_response = data_blob_null;
98         DATA_BLOB lm_session_key = data_blob_null;
99         DATA_BLOB nt_session_key = data_blob_null;
100         const char *kwnames[] = { "flags", "challenge",
101                                   "target_info",
102                                   NULL };
103
104         tv_now = timeval_current();
105         server_timestamp = timeval_to_nttime(&tv_now);
106
107         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "is#|s#",
108                                          discard_const_p(char *, kwnames),
109                                          &flags,
110                                          &challenge.data,
111                                          &challenge.length,
112                                          &target_info.data,
113                                          &target_info.length)) {
114                 return NULL;
115         }
116
117         status = cli_credentials_get_ntlm_response(PyCredentials_AsCliCredentials(self),
118                                                    frame, &flags,
119                                                    challenge,
120                                                    &server_timestamp,
121                                                    target_info,
122                                                    &lm_response, &nt_response,
123                                                    &lm_session_key, &nt_session_key);
124
125         if (!NT_STATUS_IS_OK(status)) {
126                 PyErr_SetNTSTATUS(status);
127                 TALLOC_FREE(frame);
128                 return NULL;
129         }
130
131         ret = Py_BuildValue("{sis" PYARG_BYTES_LEN "s" PYARG_BYTES_LEN
132                                     "s" PYARG_BYTES_LEN "s" PYARG_BYTES_LEN "}",
133                             "flags", flags,
134                             "lm_response",
135                             (const char *)lm_response.data, lm_response.length,
136                             "nt_response",
137                             (const char *)nt_response.data, nt_response.length,
138                             "lm_session_key",
139                             (const char *)lm_session_key.data, lm_session_key.length,
140                             "nt_session_key",
141                             (const char *)nt_session_key.data, nt_session_key.length);
142         TALLOC_FREE(frame);
143         return ret;
144 }
145
146 static PyObject *py_creds_get_principal(PyObject *self, PyObject *unused)
147 {
148         TALLOC_CTX *frame = talloc_stackframe();
149         PyObject *ret = PyString_FromStringOrNULL(cli_credentials_get_principal(PyCredentials_AsCliCredentials(self), frame));
150         TALLOC_FREE(frame);
151         return ret;
152 }
153
154 static PyObject *py_creds_set_principal(PyObject *self, PyObject *args)
155 {
156         char *newval;
157         enum credentials_obtained obt = CRED_SPECIFIED;
158         int _obt = obt;
159
160         if (!PyArg_ParseTuple(args, "s|i", &newval, &_obt)) {
161                 return NULL;
162         }
163         obt = _obt;
164
165         return PyBool_FromLong(cli_credentials_set_principal(PyCredentials_AsCliCredentials(self), newval, obt));
166 }
167
168 static PyObject *py_creds_get_password(PyObject *self, PyObject *unused)
169 {
170         return PyString_FromStringOrNULL(cli_credentials_get_password(PyCredentials_AsCliCredentials(self)));
171 }
172
173 static PyObject *py_creds_set_password(PyObject *self, PyObject *args)
174 {
175         const char *newval = NULL;
176         enum credentials_obtained obt = CRED_SPECIFIED;
177         int _obt = obt;
178         PyObject *result = NULL;
179         if (!PyArg_ParseTuple(args, PYARG_STR_UNI"|i", "utf8", &newval, &_obt)) {
180                 return NULL;
181         }
182         obt = _obt;
183
184         result = PyBool_FromLong(cli_credentials_set_password(PyCredentials_AsCliCredentials(self), newval, obt));
185         PyMem_Free(discard_const_p(void*, newval));
186         return result;
187 }
188
189 static PyObject *py_creds_set_utf16_password(PyObject *self, PyObject *args)
190 {
191         enum credentials_obtained obt = CRED_SPECIFIED;
192         int _obt = obt;
193         PyObject *newval = NULL;
194         DATA_BLOB blob = data_blob_null;
195         Py_ssize_t size =  0;
196         int result;
197         bool ok;
198
199         if (!PyArg_ParseTuple(args, "O|i", &newval, &_obt)) {
200                 return NULL;
201         }
202         obt = _obt;
203
204         result = PyBytes_AsStringAndSize(newval, (char **)&blob.data, &size);
205         if (result != 0) {
206                 PyErr_SetString(PyExc_RuntimeError, "Failed to convert passed value to Bytes");
207                 return NULL;
208         }
209         blob.length = size;
210
211         ok = cli_credentials_set_utf16_password(PyCredentials_AsCliCredentials(self),
212                                                 &blob, obt);
213
214         return PyBool_FromLong(ok);
215 }
216
217 static PyObject *py_creds_get_old_password(PyObject *self, PyObject *unused)
218 {
219         return PyString_FromStringOrNULL(cli_credentials_get_old_password(PyCredentials_AsCliCredentials(self)));
220 }
221
222 static PyObject *py_creds_set_old_password(PyObject *self, PyObject *args)
223 {
224         char *oldval;
225         enum credentials_obtained obt = CRED_SPECIFIED;
226         int _obt = obt;
227
228         if (!PyArg_ParseTuple(args, "s|i", &oldval, &_obt)) {
229                 return NULL;
230         }
231         obt = _obt;
232
233         return PyBool_FromLong(cli_credentials_set_old_password(PyCredentials_AsCliCredentials(self), oldval, obt));
234 }
235
236 static PyObject *py_creds_set_old_utf16_password(PyObject *self, PyObject *args)
237 {
238         PyObject *oldval = NULL;
239         DATA_BLOB blob = data_blob_null;
240         Py_ssize_t size =  0;
241         int result;
242         bool ok;
243
244         if (!PyArg_ParseTuple(args, "O", &oldval)) {
245                 return NULL;
246         }
247
248         result = PyBytes_AsStringAndSize(oldval, (char **)&blob.data, &size);
249         if (result != 0) {
250                 PyErr_SetString(PyExc_RuntimeError, "Failed to convert passed value to Bytes");
251                 return NULL;
252         }
253         blob.length = size;
254
255         ok = cli_credentials_set_old_utf16_password(PyCredentials_AsCliCredentials(self),
256                                                     &blob);
257
258         return PyBool_FromLong(ok);
259 }
260
261 static PyObject *py_creds_get_domain(PyObject *self, PyObject *unused)
262 {
263         return PyString_FromStringOrNULL(cli_credentials_get_domain(PyCredentials_AsCliCredentials(self)));
264 }
265
266 static PyObject *py_creds_set_domain(PyObject *self, PyObject *args)
267 {
268         char *newval;
269         enum credentials_obtained obt = CRED_SPECIFIED;
270         int _obt = obt;
271
272         if (!PyArg_ParseTuple(args, "s|i", &newval, &_obt)) {
273                 return NULL;
274         }
275         obt = _obt;
276
277         return PyBool_FromLong(cli_credentials_set_domain(PyCredentials_AsCliCredentials(self), newval, obt));
278 }
279
280 static PyObject *py_creds_get_realm(PyObject *self, PyObject *unused)
281 {
282         return PyString_FromStringOrNULL(cli_credentials_get_realm(PyCredentials_AsCliCredentials(self)));
283 }
284
285 static PyObject *py_creds_set_realm(PyObject *self, PyObject *args)
286 {
287         char *newval;
288         enum credentials_obtained obt = CRED_SPECIFIED;
289         int _obt = obt;
290
291         if (!PyArg_ParseTuple(args, "s|i", &newval, &_obt)) {
292                 return NULL;
293         }
294         obt = _obt;
295
296         return PyBool_FromLong(cli_credentials_set_realm(PyCredentials_AsCliCredentials(self), newval, obt));
297 }
298
299 static PyObject *py_creds_get_bind_dn(PyObject *self, PyObject *unused)
300 {
301         return PyString_FromStringOrNULL(cli_credentials_get_bind_dn(PyCredentials_AsCliCredentials(self)));
302 }
303
304 static PyObject *py_creds_set_bind_dn(PyObject *self, PyObject *args)
305 {
306         char *newval;
307         if (!PyArg_ParseTuple(args, "s", &newval))
308                 return NULL;
309
310         return PyBool_FromLong(cli_credentials_set_bind_dn(PyCredentials_AsCliCredentials(self), newval));
311 }
312
313 static PyObject *py_creds_get_workstation(PyObject *self, PyObject *unused)
314 {
315         return PyString_FromStringOrNULL(cli_credentials_get_workstation(PyCredentials_AsCliCredentials(self)));
316 }
317
318 static PyObject *py_creds_set_workstation(PyObject *self, PyObject *args)
319 {
320         char *newval;
321         enum credentials_obtained obt = CRED_SPECIFIED;
322         int _obt = obt;
323
324         if (!PyArg_ParseTuple(args, "s|i", &newval, &_obt)) {
325                 return NULL;
326         }
327         obt = _obt;
328
329         return PyBool_FromLong(cli_credentials_set_workstation(PyCredentials_AsCliCredentials(self), newval, obt));
330 }
331
332 static PyObject *py_creds_is_anonymous(PyObject *self, PyObject *unused)
333 {
334         return PyBool_FromLong(cli_credentials_is_anonymous(PyCredentials_AsCliCredentials(self)));
335 }
336
337 static PyObject *py_creds_set_anonymous(PyObject *self, PyObject *unused)
338 {
339         cli_credentials_set_anonymous(PyCredentials_AsCliCredentials(self));
340         Py_RETURN_NONE;
341 }
342
343 static PyObject *py_creds_authentication_requested(PyObject *self, PyObject *unused)
344 {
345         return PyBool_FromLong(cli_credentials_authentication_requested(PyCredentials_AsCliCredentials(self)));
346 }
347
348 static PyObject *py_creds_wrong_password(PyObject *self, PyObject *unused)
349 {
350         return PyBool_FromLong(cli_credentials_wrong_password(PyCredentials_AsCliCredentials(self)));
351 }
352
353 static PyObject *py_creds_set_cmdline_callbacks(PyObject *self, PyObject *unused)
354 {
355         return PyBool_FromLong(cli_credentials_set_cmdline_callbacks(PyCredentials_AsCliCredentials(self)));
356 }
357
358 static PyObject *py_creds_parse_string(PyObject *self, PyObject *args)
359 {
360         char *newval;
361         enum credentials_obtained obt = CRED_SPECIFIED;
362         int _obt = obt;
363
364         if (!PyArg_ParseTuple(args, "s|i", &newval, &_obt)) {
365                 return NULL;
366         }
367         obt = _obt;
368
369         cli_credentials_parse_string(PyCredentials_AsCliCredentials(self), newval, obt);
370         Py_RETURN_NONE;
371 }
372
373 static PyObject *py_creds_parse_file(PyObject *self, PyObject *args)
374 {
375         char *newval;
376         enum credentials_obtained obt = CRED_SPECIFIED;
377         int _obt = obt;
378
379         if (!PyArg_ParseTuple(args, "s|i", &newval, &_obt)) {
380                 return NULL;
381         }
382         obt = _obt;
383
384         cli_credentials_parse_file(PyCredentials_AsCliCredentials(self), newval, obt);
385         Py_RETURN_NONE;
386 }
387
388 static PyObject *py_cli_credentials_set_password_will_be_nt_hash(PyObject *self, PyObject *args)
389 {
390         struct cli_credentials *creds = PyCredentials_AsCliCredentials(self);
391         PyObject *py_val = NULL;
392         bool val = false;
393
394         if (!PyArg_ParseTuple(args, "O!", &PyBool_Type, &py_val)) {
395                 return NULL;
396         }
397         val = PyObject_IsTrue(py_val);
398
399         cli_credentials_set_password_will_be_nt_hash(creds, val);
400         Py_RETURN_NONE;
401 }
402
403 static PyObject *py_creds_get_nt_hash(PyObject *self, PyObject *unused)
404 {
405         PyObject *ret;
406         struct cli_credentials *creds = PyCredentials_AsCliCredentials(self);
407         struct samr_Password *ntpw = cli_credentials_get_nt_hash(creds, creds);
408
409         ret = PyBytes_FromStringAndSize(discard_const_p(char, ntpw->hash), 16);
410         TALLOC_FREE(ntpw);
411         return ret;
412 }
413
414 static PyObject *py_creds_get_kerberos_state(PyObject *self, PyObject *unused)
415 {
416         int state = cli_credentials_get_kerberos_state(PyCredentials_AsCliCredentials(self));
417         return PyInt_FromLong(state);
418 }
419
420 static PyObject *py_creds_set_kerberos_state(PyObject *self, PyObject *args)
421 {
422         int state;
423         if (!PyArg_ParseTuple(args, "i", &state))
424                 return NULL;
425
426         cli_credentials_set_kerberos_state(PyCredentials_AsCliCredentials(self), state);
427         Py_RETURN_NONE;
428 }
429
430 static PyObject *py_creds_set_krb_forwardable(PyObject *self, PyObject *args)
431 {
432         int state;
433         if (!PyArg_ParseTuple(args, "i", &state))
434                 return NULL;
435
436         cli_credentials_set_krb_forwardable(PyCredentials_AsCliCredentials(self), state);
437         Py_RETURN_NONE;
438 }
439
440
441 static PyObject *py_creds_get_forced_sasl_mech(PyObject *self, PyObject *unused)
442 {
443         return PyString_FromStringOrNULL(cli_credentials_get_forced_sasl_mech(PyCredentials_AsCliCredentials(self)));
444 }
445
446 static PyObject *py_creds_set_forced_sasl_mech(PyObject *self, PyObject *args)
447 {
448         char *newval;
449         enum credentials_obtained obt = CRED_SPECIFIED;
450         int _obt = obt;
451
452         if (!PyArg_ParseTuple(args, "s", &newval)) {
453                 return NULL;
454         }
455         obt = _obt;
456
457         cli_credentials_set_forced_sasl_mech(PyCredentials_AsCliCredentials(self), newval);
458         Py_RETURN_NONE;
459 }
460
461 static PyObject *py_creds_guess(PyObject *self, PyObject *args)
462 {
463         PyObject *py_lp_ctx = Py_None;
464         struct loadparm_context *lp_ctx;
465         TALLOC_CTX *mem_ctx;
466         struct cli_credentials *creds;
467
468         creds = PyCredentials_AsCliCredentials(self);
469
470         if (!PyArg_ParseTuple(args, "|O", &py_lp_ctx))
471                 return NULL;
472
473         mem_ctx = talloc_new(NULL);
474         if (mem_ctx == NULL) {
475                 PyErr_NoMemory();
476                 return NULL;
477         }
478
479         lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
480         if (lp_ctx == NULL) {
481                 talloc_free(mem_ctx);
482                 return NULL;
483         }
484
485         cli_credentials_guess(creds, lp_ctx);
486
487         talloc_free(mem_ctx);
488
489         Py_RETURN_NONE;
490 }
491
492 static PyObject *py_creds_set_machine_account(PyObject *self, PyObject *args)
493 {
494         PyObject *py_lp_ctx = Py_None;
495         struct loadparm_context *lp_ctx;
496         NTSTATUS status;
497         struct cli_credentials *creds;
498         TALLOC_CTX *mem_ctx;
499
500         creds = PyCredentials_AsCliCredentials(self);
501
502         if (!PyArg_ParseTuple(args, "|O", &py_lp_ctx))
503                 return NULL;
504
505         mem_ctx = talloc_new(NULL);
506         if (mem_ctx == NULL) {
507                 PyErr_NoMemory();
508                 return NULL;
509         }
510
511         lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
512         if (lp_ctx == NULL) {
513                 talloc_free(mem_ctx);
514                 return NULL;
515         }
516
517         status = cli_credentials_set_machine_account(creds, lp_ctx);
518         talloc_free(mem_ctx);
519
520         PyErr_NTSTATUS_IS_ERR_RAISE(status);
521
522         Py_RETURN_NONE;
523 }
524
525 static PyObject *PyCredentialCacheContainer_from_ccache_container(struct ccache_container *ccc)
526 {
527         return pytalloc_reference(&PyCredentialCacheContainer, ccc);
528 }
529
530
531 static PyObject *py_creds_get_named_ccache(PyObject *self, PyObject *args)
532 {
533         PyObject *py_lp_ctx = Py_None;
534         char *ccache_name = NULL;
535         struct loadparm_context *lp_ctx;
536         struct ccache_container *ccc;
537         struct tevent_context *event_ctx;
538         int ret;
539         const char *error_string;
540         struct cli_credentials *creds;
541         TALLOC_CTX *mem_ctx;
542
543         creds = PyCredentials_AsCliCredentials(self);
544
545         if (!PyArg_ParseTuple(args, "|Os", &py_lp_ctx, &ccache_name))
546                 return NULL;
547
548         mem_ctx = talloc_new(NULL);
549         if (mem_ctx == NULL) {
550                 PyErr_NoMemory();
551                 return NULL;
552         }
553
554         lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
555         if (lp_ctx == NULL) {
556                 talloc_free(mem_ctx);
557                 return NULL;
558         }
559
560         event_ctx = samba_tevent_context_init(mem_ctx);
561
562         ret = cli_credentials_get_named_ccache(creds, event_ctx, lp_ctx,
563                                                ccache_name, &ccc, &error_string);
564         talloc_unlink(mem_ctx, lp_ctx);
565         if (ret == 0) {
566                 talloc_steal(ccc, event_ctx);
567                 talloc_free(mem_ctx);
568                 return PyCredentialCacheContainer_from_ccache_container(ccc);
569         }
570
571         PyErr_SetString(PyExc_RuntimeError, error_string?error_string:"NULL");
572
573         talloc_free(mem_ctx);
574         return NULL;
575 }
576
577 static PyObject *py_creds_set_named_ccache(PyObject *self, PyObject *args)
578 {
579         struct loadparm_context *lp_ctx = NULL;
580         enum credentials_obtained obt = CRED_SPECIFIED;
581         const char *error_string = NULL;
582         TALLOC_CTX *mem_ctx = NULL;
583         char *newval = NULL;
584         PyObject *py_lp_ctx = Py_None;
585         int _obt = obt;
586         int ret;
587
588         if (!PyArg_ParseTuple(args, "s|iO", &newval, &_obt, &py_lp_ctx))
589                 return NULL;
590
591         mem_ctx = talloc_new(NULL);
592         if (mem_ctx == NULL) {
593                 PyErr_NoMemory();
594                 return NULL;
595         }
596
597         lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
598         if (lp_ctx == NULL) {
599                 talloc_free(mem_ctx);
600                 return NULL;
601         }
602
603         ret = cli_credentials_set_ccache(PyCredentials_AsCliCredentials(self),
604                                          lp_ctx,
605                                          newval, CRED_SPECIFIED,
606                                          &error_string);
607
608         if (ret != 0) {
609                 PyErr_SetString(PyExc_RuntimeError,
610                                 error_string != NULL ? error_string : "NULL");
611                 talloc_free(mem_ctx);
612                 return NULL;
613         }
614
615         talloc_free(mem_ctx);
616         Py_RETURN_NONE;
617 }
618
619 static PyObject *py_creds_set_gensec_features(PyObject *self, PyObject *args)
620 {
621         unsigned int gensec_features;
622
623         if (!PyArg_ParseTuple(args, "I", &gensec_features))
624                 return NULL;
625
626         cli_credentials_set_gensec_features(PyCredentials_AsCliCredentials(self), gensec_features);
627
628         Py_RETURN_NONE;
629 }
630
631 static PyObject *py_creds_get_gensec_features(PyObject *self, PyObject *args)
632 {
633         unsigned int gensec_features;
634
635         gensec_features = cli_credentials_get_gensec_features(PyCredentials_AsCliCredentials(self));
636         return PyInt_FromLong(gensec_features);
637 }
638
639 static PyObject *py_creds_new_client_authenticator(PyObject *self,
640                                                    PyObject *args)
641 {
642         struct netr_Authenticator auth;
643         struct cli_credentials *creds = NULL;
644         struct netlogon_creds_CredentialState *nc = NULL;
645         PyObject *ret = NULL;
646
647         creds = PyCredentials_AsCliCredentials(self);
648         if (creds == NULL) {
649                 PyErr_SetString(PyExc_RuntimeError,
650                                 "Failed to get credentials from python");
651                 return NULL;
652         }
653
654         nc = creds->netlogon_creds;
655         if (nc == NULL) {
656                 PyErr_SetString(PyExc_ValueError,
657                                 "No netlogon credentials cannot make "
658                                 "client authenticator");
659                 return NULL;
660         }
661
662         netlogon_creds_client_authenticator(
663                 nc,
664                 &auth);
665         ret = Py_BuildValue("{s"PYARG_BYTES_LEN"si}",
666                             "credential",
667                             (const char *) &auth.cred, sizeof(auth.cred),
668                             "timestamp", auth.timestamp);
669         return ret;
670 }
671
672 static PyObject *py_creds_set_secure_channel_type(PyObject *self, PyObject *args)
673 {
674         unsigned int channel_type;
675
676         if (!PyArg_ParseTuple(args, "I", &channel_type))
677                 return NULL;
678
679         cli_credentials_set_secure_channel_type(
680                 PyCredentials_AsCliCredentials(self),
681                 channel_type);
682
683         Py_RETURN_NONE;
684 }
685
686 static PyObject *py_creds_get_secure_channel_type(PyObject *self, PyObject *args)
687 {
688         enum netr_SchannelType channel_type = SEC_CHAN_NULL;
689
690         channel_type = cli_credentials_get_secure_channel_type(
691                 PyCredentials_AsCliCredentials(self));
692
693         return PyInt_FromLong(channel_type);
694 }
695
696 static PyObject *py_creds_encrypt_netr_crypt_password(PyObject *self,
697                                                       PyObject *args)
698 {
699         DATA_BLOB data = data_blob_null;
700         struct cli_credentials    *creds  = NULL;
701         struct netr_CryptPassword *pwd    = NULL;
702         NTSTATUS status;
703         PyObject *py_cp = Py_None;
704
705         creds = PyCredentials_AsCliCredentials(self);
706
707         if (!PyArg_ParseTuple(args, "|O", &py_cp)) {
708                 return NULL;
709         }
710         pwd = pytalloc_get_type(py_cp, struct netr_CryptPassword);
711         data.length = sizeof(struct netr_CryptPassword);
712         data.data   = (uint8_t *)pwd;
713         status = netlogon_creds_session_encrypt(creds->netlogon_creds, data);
714
715         PyErr_NTSTATUS_IS_ERR_RAISE(status);
716
717         Py_RETURN_NONE;
718 }
719
720 static PyMethodDef py_creds_methods[] = {
721         {
722                 .ml_name  = "get_username",
723                 .ml_meth  = py_creds_get_username,
724                 .ml_flags = METH_NOARGS,
725                 .ml_doc   = "S.get_username() -> username\nObtain username.",
726         },
727         {
728                 .ml_name  = "set_username",
729                 .ml_meth  = py_creds_set_username,
730                 .ml_flags = METH_VARARGS,
731                 .ml_doc   = "S.set_username(name[, credentials.SPECIFIED]) -> None\n"
732                             "Change username.",
733         },
734         {
735                 .ml_name  = "get_principal",
736                 .ml_meth  = py_creds_get_principal,
737                 .ml_flags = METH_NOARGS,
738                 .ml_doc   = "S.get_principal() -> user@realm\nObtain user principal.",
739         },
740         {
741                 .ml_name  = "set_principal",
742                 .ml_meth  = py_creds_set_principal,
743                 .ml_flags = METH_VARARGS,
744                 .ml_doc   = "S.set_principal(name[, credentials.SPECIFIED]) -> None\n"
745                             "Change principal.",
746         },
747         {
748                 .ml_name  = "get_password",
749                 .ml_meth  = py_creds_get_password,
750                 .ml_flags = METH_NOARGS,
751                 .ml_doc   = "S.get_password() -> password\n"
752                             "Obtain password.",
753         },
754         {
755                 .ml_name  = "get_ntlm_username_domain",
756                 .ml_meth  = py_creds_get_ntlm_username_domain,
757                 .ml_flags = METH_NOARGS,
758                 .ml_doc   = "S.get_ntlm_username_domain() -> (domain, username)\n"
759                             "Obtain NTLM username and domain, split up either as (DOMAIN, user) or (\"\", \"user@realm\").",
760         },
761         {
762                 .ml_name  = "get_ntlm_response",
763                 .ml_meth  = (PyCFunction)py_creds_get_ntlm_response,
764                 .ml_flags = METH_VARARGS | METH_KEYWORDS,
765                 .ml_doc   = "S.get_ntlm_response"
766                             "(flags, challenge[, target_info]) -> "
767                             "(flags, lm_response, nt_response, lm_session_key, nt_session_key)\n"
768                             "Obtain LM or NTLM response.",
769         },
770         {
771                 .ml_name  = "set_password",
772                 .ml_meth  = py_creds_set_password,
773                 .ml_flags = METH_VARARGS,
774                 .ml_doc   = "S.set_password(password[, credentials.SPECIFIED]) -> None\n"
775                             "Change password.",
776         },
777         {
778                 .ml_name  = "set_utf16_password",
779                 .ml_meth  = py_creds_set_utf16_password,
780                 .ml_flags = METH_VARARGS,
781                 .ml_doc   = "S.set_utf16_password(password[, credentials.SPECIFIED]) -> None\n"
782                             "Change password.",
783         },
784         {
785                 .ml_name  = "get_old_password",
786                 .ml_meth  = py_creds_get_old_password,
787                 .ml_flags = METH_NOARGS,
788                 .ml_doc   = "S.get_old_password() -> password\n"
789                             "Obtain old password.",
790         },
791         {
792                 .ml_name  = "set_old_password",
793                 .ml_meth  = py_creds_set_old_password,
794                 .ml_flags = METH_VARARGS,
795                 .ml_doc   = "S.set_old_password(password[, credentials.SPECIFIED]) -> None\n"
796                             "Change old password.",
797         },
798         {
799                 .ml_name  = "set_old_utf16_password",
800                 .ml_meth  = py_creds_set_old_utf16_password,
801                 .ml_flags = METH_VARARGS,
802                 .ml_doc   = "S.set_old_utf16_password(password[, credentials.SPECIFIED]) -> None\n"
803                             "Change old password.",
804         },
805         {
806                 .ml_name  = "get_domain",
807                 .ml_meth  = py_creds_get_domain,
808                 .ml_flags = METH_NOARGS,
809                 .ml_doc   = "S.get_domain() -> domain\n"
810                             "Obtain domain name.",
811         },
812         {
813                 .ml_name  = "set_domain",
814                 .ml_meth  = py_creds_set_domain,
815                 .ml_flags = METH_VARARGS,
816                 .ml_doc   = "S.set_domain(domain[, credentials.SPECIFIED]) -> None\n"
817                             "Change domain name.",
818         },
819         {
820                 .ml_name  = "get_realm",
821                 .ml_meth  = py_creds_get_realm,
822                 .ml_flags = METH_NOARGS,
823                 .ml_doc   = "S.get_realm() -> realm\n"
824                             "Obtain realm name.",
825         },
826         {
827                 .ml_name  = "set_realm",
828                 .ml_meth  = py_creds_set_realm,
829                 .ml_flags = METH_VARARGS,
830                 .ml_doc   = "S.set_realm(realm[, credentials.SPECIFIED]) -> None\n"
831                             "Change realm name.",
832         },
833         {
834                 .ml_name  = "get_bind_dn",
835                 .ml_meth  = py_creds_get_bind_dn,
836                 .ml_flags = METH_NOARGS,
837                 .ml_doc   = "S.get_bind_dn() -> bind dn\n"
838                             "Obtain bind DN.",
839         },
840         {
841                 .ml_name  = "set_bind_dn",
842                 .ml_meth  = py_creds_set_bind_dn,
843                 .ml_flags = METH_VARARGS,
844                 .ml_doc   = "S.set_bind_dn(bind_dn) -> None\n"
845                             "Change bind DN.",
846         },
847         {
848                 .ml_name  = "is_anonymous",
849                 .ml_meth  = py_creds_is_anonymous,
850                 .ml_flags = METH_NOARGS,
851         },
852         {
853                 .ml_name  = "set_anonymous",
854                 .ml_meth  = py_creds_set_anonymous,
855                 .ml_flags = METH_NOARGS,
856                 .ml_doc   = "S.set_anonymous() -> None\n"
857                             "Use anonymous credentials.",
858         },
859         {
860                 .ml_name  = "get_workstation",
861                 .ml_meth  = py_creds_get_workstation,
862                 .ml_flags = METH_NOARGS,
863         },
864         {
865                 .ml_name  = "set_workstation",
866                 .ml_meth  = py_creds_set_workstation,
867                 .ml_flags = METH_VARARGS,
868         },
869         {
870                 .ml_name  = "authentication_requested",
871                 .ml_meth  = py_creds_authentication_requested,
872                 .ml_flags = METH_NOARGS,
873         },
874         {
875                 .ml_name  = "wrong_password",
876                 .ml_meth  = py_creds_wrong_password,
877                 .ml_flags = METH_NOARGS,
878                 .ml_doc   = "S.wrong_password() -> bool\n"
879                             "Indicate the returned password was incorrect.",
880         },
881         {
882                 .ml_name  = "set_cmdline_callbacks",
883                 .ml_meth  = py_creds_set_cmdline_callbacks,
884                 .ml_flags = METH_NOARGS,
885                 .ml_doc   = "S.set_cmdline_callbacks() -> bool\n"
886                             "Use command-line to obtain credentials not explicitly set.",
887         },
888         {
889                 .ml_name  = "parse_string",
890                 .ml_meth  = py_creds_parse_string,
891                 .ml_flags = METH_VARARGS,
892                 .ml_doc   = "S.parse_string(text[, credentials.SPECIFIED]) -> None\n"
893                             "Parse credentials string.",
894         },
895         {
896                 .ml_name  = "parse_file",
897                 .ml_meth  = py_creds_parse_file,
898                 .ml_flags = METH_VARARGS,
899                 .ml_doc   = "S.parse_file(filename[, credentials.SPECIFIED]) -> None\n"
900                             "Parse credentials file.",
901         },
902         {
903                 .ml_name  = "set_password_will_be_nt_hash",
904                 .ml_meth  = py_cli_credentials_set_password_will_be_nt_hash,
905                 .ml_flags = METH_VARARGS,
906                 .ml_doc   = "S.set_password_will_be_nt_hash(bool) -> None\n"
907                             "Alters the behaviour of S.set_password() "
908                             "to expect the NTHASH as hexstring.",
909         },
910         {
911                 .ml_name  = "get_nt_hash",
912                 .ml_meth  = py_creds_get_nt_hash,
913                 .ml_flags = METH_NOARGS,
914         },
915         {
916                 .ml_name  = "get_kerberos_state",
917                 .ml_meth  = py_creds_get_kerberos_state,
918                 .ml_flags = METH_NOARGS,
919         },
920         {
921                 .ml_name  = "set_kerberos_state",
922                 .ml_meth  = py_creds_set_kerberos_state,
923                 .ml_flags = METH_VARARGS,
924         },
925         {
926                 .ml_name  = "set_krb_forwardable",
927                 .ml_meth  = py_creds_set_krb_forwardable,
928                 .ml_flags = METH_VARARGS,
929         },
930         {
931                 .ml_name  = "guess",
932                 .ml_meth  = py_creds_guess,
933                 .ml_flags = METH_VARARGS,
934         },
935         {
936                 .ml_name  = "set_machine_account",
937                 .ml_meth  = py_creds_set_machine_account,
938                 .ml_flags = METH_VARARGS,
939         },
940         {
941                 .ml_name  = "get_named_ccache",
942                 .ml_meth  = py_creds_get_named_ccache,
943                 .ml_flags = METH_VARARGS,
944         },
945         {
946                 .ml_name  = "set_named_ccache",
947                 .ml_meth  = py_creds_set_named_ccache,
948                 .ml_flags = METH_VARARGS,
949                 .ml_doc   = "S.set_named_ccache(krb5_ccache_name, obtained, lp) -> None\n"
950                             "Set credentials to KRB5 Credentials Cache (by name).",
951         },
952         {
953                 .ml_name  = "set_gensec_features",
954                 .ml_meth  = py_creds_set_gensec_features,
955                 .ml_flags = METH_VARARGS,
956         },
957         {
958                 .ml_name  = "get_gensec_features",
959                 .ml_meth  = py_creds_get_gensec_features,
960                 .ml_flags = METH_NOARGS,
961         },
962         {
963                 .ml_name  = "get_forced_sasl_mech",
964                 .ml_meth  = py_creds_get_forced_sasl_mech,
965                 .ml_flags = METH_NOARGS,
966                 .ml_doc   = "S.get_forced_sasl_mech() -> SASL mechanism\nObtain forced SASL mechanism.",
967         },
968         {
969                 .ml_name  = "set_forced_sasl_mech",
970                 .ml_meth  = py_creds_set_forced_sasl_mech,
971                 .ml_flags = METH_VARARGS,
972                 .ml_doc   = "S.set_forced_sasl_mech(name) -> None\n"
973                             "Set forced SASL mechanism.",
974         },
975         {
976                 .ml_name  = "new_client_authenticator",
977                 .ml_meth  = py_creds_new_client_authenticator,
978                 .ml_flags = METH_NOARGS,
979                 .ml_doc   = "S.new_client_authenticator() -> Authenticator\n"
980                             "Get a new client NETLOGON_AUTHENTICATOR"},
981         {
982                 .ml_name  = "set_secure_channel_type",
983                 .ml_meth  = py_creds_set_secure_channel_type,
984                 .ml_flags = METH_VARARGS,
985         },
986         {
987                 .ml_name  = "get_secure_channel_type",
988                 .ml_meth  = py_creds_get_secure_channel_type,
989                 .ml_flags = METH_VARARGS,
990         },
991         {
992                 .ml_name  = "encrypt_netr_crypt_password",
993                 .ml_meth  = py_creds_encrypt_netr_crypt_password,
994                 .ml_flags = METH_VARARGS,
995                 .ml_doc   = "S.encrypt_netr_crypt_password(password) -> NTSTATUS\n"
996                             "Encrypt the supplied password using the session key and\n"
997                             "the negotiated encryption algorithm in place\n"
998                             "i.e. it overwrites the original data"},
999         { .ml_name = NULL }
1000 };
1001
1002 static struct PyModuleDef moduledef = {
1003     PyModuleDef_HEAD_INIT,
1004     .m_name = "credentials",
1005     .m_doc = "Credentials management.",
1006     .m_size = -1,
1007     .m_methods = py_creds_methods,
1008 };
1009
1010 PyTypeObject PyCredentials = {
1011         .tp_name = "credentials.Credentials",
1012         .tp_new = py_creds_new,
1013         .tp_flags = Py_TPFLAGS_DEFAULT,
1014         .tp_methods = py_creds_methods,
1015 };
1016
1017 static PyObject *py_ccache_name(PyObject *self, PyObject *unused)
1018 {
1019         struct ccache_container *ccc = NULL;
1020         char *name = NULL;
1021         PyObject *py_name = NULL;
1022         int ret;
1023
1024         ccc = pytalloc_get_type(self, struct ccache_container);
1025
1026         ret = krb5_cc_get_full_name(ccc->smb_krb5_context->krb5_context,
1027                                     ccc->ccache, &name);
1028         if (ret == 0) {
1029                 py_name = PyString_FromStringOrNULL(name);
1030                 SAFE_FREE(name);
1031         } else {
1032                 PyErr_SetString(PyExc_RuntimeError,
1033                                 "Failed to get ccache name");
1034                 return NULL;
1035         }
1036         return py_name;
1037 }
1038
1039 static PyMethodDef py_ccache_container_methods[] = {
1040         { "get_name", py_ccache_name, METH_NOARGS,
1041           "S.get_name() -> name\nObtain KRB5 credentials cache name." },
1042         { NULL }
1043 };
1044
1045 PyTypeObject PyCredentialCacheContainer = {
1046         .tp_name = "credentials.CredentialCacheContainer",
1047         .tp_flags = Py_TPFLAGS_DEFAULT,
1048         .tp_methods = py_ccache_container_methods,
1049 };
1050
1051 MODULE_INIT_FUNC(credentials)
1052 {
1053         PyObject *m;
1054         if (pytalloc_BaseObject_PyType_Ready(&PyCredentials) < 0)
1055                 return NULL;
1056
1057         if (pytalloc_BaseObject_PyType_Ready(&PyCredentialCacheContainer) < 0)
1058                 return NULL;
1059
1060         m = PyModule_Create(&moduledef);
1061         if (m == NULL)
1062                 return NULL;
1063
1064         PyModule_AddObject(m, "UNINITIALISED", PyInt_FromLong(CRED_UNINITIALISED));
1065         PyModule_AddObject(m, "CALLBACK", PyInt_FromLong(CRED_CALLBACK));
1066         PyModule_AddObject(m, "GUESS_ENV", PyInt_FromLong(CRED_GUESS_ENV));
1067         PyModule_AddObject(m, "GUESS_FILE", PyInt_FromLong(CRED_GUESS_FILE));
1068         PyModule_AddObject(m, "CALLBACK_RESULT", PyInt_FromLong(CRED_CALLBACK_RESULT));
1069         PyModule_AddObject(m, "SPECIFIED", PyInt_FromLong(CRED_SPECIFIED));
1070
1071         PyModule_AddObject(m, "AUTO_USE_KERBEROS", PyInt_FromLong(CRED_AUTO_USE_KERBEROS));
1072         PyModule_AddObject(m, "DONT_USE_KERBEROS", PyInt_FromLong(CRED_DONT_USE_KERBEROS));
1073         PyModule_AddObject(m, "MUST_USE_KERBEROS", PyInt_FromLong(CRED_MUST_USE_KERBEROS));
1074
1075         PyModule_AddObject(m, "AUTO_KRB_FORWARDABLE",  PyInt_FromLong(CRED_AUTO_KRB_FORWARDABLE));
1076         PyModule_AddObject(m, "NO_KRB_FORWARDABLE",    PyInt_FromLong(CRED_NO_KRB_FORWARDABLE));
1077         PyModule_AddObject(m, "FORCE_KRB_FORWARDABLE", PyInt_FromLong(CRED_FORCE_KRB_FORWARDABLE));
1078         PyModule_AddObject(m, "CLI_CRED_NTLM2", PyInt_FromLong(CLI_CRED_NTLM2));
1079         PyModule_AddObject(m, "CLI_CRED_NTLMv2_AUTH", PyInt_FromLong(CLI_CRED_NTLMv2_AUTH));
1080         PyModule_AddObject(m, "CLI_CRED_LANMAN_AUTH", PyInt_FromLong(CLI_CRED_LANMAN_AUTH));
1081         PyModule_AddObject(m, "CLI_CRED_NTLM_AUTH", PyInt_FromLong(CLI_CRED_NTLM_AUTH));
1082         PyModule_AddObject(m, "CLI_CRED_CLEAR_AUTH", PyInt_FromLong(CLI_CRED_CLEAR_AUTH));
1083
1084         Py_INCREF(&PyCredentials);
1085         PyModule_AddObject(m, "Credentials", (PyObject *)&PyCredentials);
1086         Py_INCREF(&PyCredentialCacheContainer);
1087         PyModule_AddObject(m, "CredentialCacheContainer", (PyObject *)&PyCredentialCacheContainer);
1088         return m;
1089 }