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