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