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