2 Unix SMB/CIFS implementation.
3 Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
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.
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.
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/>.
20 #include "python/py3compat.h"
22 #include "pycredentials.h"
23 #include "param/param.h"
24 #include "lib/cmdline/credentials.h"
25 #include "librpc/gen_ndr/samr.h" /* for struct samr_Password */
26 #include "libcli/util/pyerrors.h"
27 #include "param/pyparam.h"
30 void initcredentials(void);
32 static PyObject *PyString_FromStringOrNULL(const char *str)
36 return PyStr_FromString(str);
39 static PyObject *py_creds_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
41 return pytalloc_steal(type, cli_credentials_init(NULL));
44 static PyObject *py_creds_get_username(PyObject *self, PyObject *unused)
46 return PyString_FromStringOrNULL(cli_credentials_get_username(PyCredentials_AsCliCredentials(self)));
49 static PyObject *py_creds_set_username(PyObject *self, PyObject *args)
52 enum credentials_obtained obt = CRED_SPECIFIED;
55 if (!PyArg_ParseTuple(args, "s|i", &newval, &_obt)) {
60 return PyBool_FromLong(cli_credentials_set_username(PyCredentials_AsCliCredentials(self), newval, obt));
63 static PyObject *py_creds_get_ntlm_username_domain(PyObject *self, PyObject *unused)
65 TALLOC_CTX *frame = talloc_stackframe();
66 const char *user = NULL;
67 const char *domain = NULL;
69 cli_credentials_get_ntlm_username_domain(PyCredentials_AsCliCredentials(self),
70 frame, &user, &domain);
71 ret = Py_BuildValue("(OO)",
72 PyString_FromStringOrNULL(user),
73 PyString_FromStringOrNULL(domain));
78 static PyObject *py_creds_get_principal(PyObject *self, PyObject *unused)
80 TALLOC_CTX *frame = talloc_stackframe();
81 PyObject *ret = PyString_FromStringOrNULL(cli_credentials_get_principal(PyCredentials_AsCliCredentials(self), frame));
86 static PyObject *py_creds_set_principal(PyObject *self, PyObject *args)
89 enum credentials_obtained obt = CRED_SPECIFIED;
92 if (!PyArg_ParseTuple(args, "s|i", &newval, &_obt)) {
97 return PyBool_FromLong(cli_credentials_set_principal(PyCredentials_AsCliCredentials(self), newval, obt));
100 static PyObject *py_creds_get_password(PyObject *self, PyObject *unused)
102 return PyString_FromStringOrNULL(cli_credentials_get_password(PyCredentials_AsCliCredentials(self)));
105 static PyObject *py_creds_set_password(PyObject *self, PyObject *args)
108 enum credentials_obtained obt = CRED_SPECIFIED;
111 if (!PyArg_ParseTuple(args, "s|i", &newval, &_obt)) {
116 return PyBool_FromLong(cli_credentials_set_password(PyCredentials_AsCliCredentials(self), newval, obt));
119 static PyObject *py_creds_set_utf16_password(PyObject *self, PyObject *args)
121 enum credentials_obtained obt = CRED_SPECIFIED;
123 PyObject *newval = NULL;
124 DATA_BLOB blob = data_blob_null;
129 if (!PyArg_ParseTuple(args, "O|i", &newval, &_obt)) {
134 result = PyBytes_AsStringAndSize(newval, (char **)&blob.data, &size);
136 PyErr_SetString(PyExc_RuntimeError, "Failed to convert passed value to Bytes");
141 ok = cli_credentials_set_utf16_password(PyCredentials_AsCliCredentials(self),
144 return PyBool_FromLong(ok);
147 static PyObject *py_creds_get_old_password(PyObject *self, PyObject *unused)
149 return PyString_FromStringOrNULL(cli_credentials_get_old_password(PyCredentials_AsCliCredentials(self)));
152 static PyObject *py_creds_set_old_password(PyObject *self, PyObject *args)
155 enum credentials_obtained obt = CRED_SPECIFIED;
158 if (!PyArg_ParseTuple(args, "s|i", &oldval, &_obt)) {
163 return PyBool_FromLong(cli_credentials_set_old_password(PyCredentials_AsCliCredentials(self), oldval, obt));
166 static PyObject *py_creds_set_old_utf16_password(PyObject *self, PyObject *args)
168 PyObject *oldval = NULL;
169 DATA_BLOB blob = data_blob_null;
174 if (!PyArg_ParseTuple(args, "O", &oldval)) {
178 result = PyBytes_AsStringAndSize(oldval, (char **)&blob.data, &size);
180 PyErr_SetString(PyExc_RuntimeError, "Failed to convert passed value to Bytes");
185 ok = cli_credentials_set_old_utf16_password(PyCredentials_AsCliCredentials(self),
188 return PyBool_FromLong(ok);
191 static PyObject *py_creds_get_domain(PyObject *self, PyObject *unused)
193 return PyString_FromStringOrNULL(cli_credentials_get_domain(PyCredentials_AsCliCredentials(self)));
196 static PyObject *py_creds_set_domain(PyObject *self, PyObject *args)
199 enum credentials_obtained obt = CRED_SPECIFIED;
202 if (!PyArg_ParseTuple(args, "s|i", &newval, &_obt)) {
207 return PyBool_FromLong(cli_credentials_set_domain(PyCredentials_AsCliCredentials(self), newval, obt));
210 static PyObject *py_creds_get_realm(PyObject *self, PyObject *unused)
212 return PyString_FromStringOrNULL(cli_credentials_get_realm(PyCredentials_AsCliCredentials(self)));
215 static PyObject *py_creds_set_realm(PyObject *self, PyObject *args)
218 enum credentials_obtained obt = CRED_SPECIFIED;
221 if (!PyArg_ParseTuple(args, "s|i", &newval, &_obt)) {
226 return PyBool_FromLong(cli_credentials_set_realm(PyCredentials_AsCliCredentials(self), newval, obt));
229 static PyObject *py_creds_get_bind_dn(PyObject *self, PyObject *unused)
231 return PyString_FromStringOrNULL(cli_credentials_get_bind_dn(PyCredentials_AsCliCredentials(self)));
234 static PyObject *py_creds_set_bind_dn(PyObject *self, PyObject *args)
237 if (!PyArg_ParseTuple(args, "s", &newval))
240 return PyBool_FromLong(cli_credentials_set_bind_dn(PyCredentials_AsCliCredentials(self), newval));
243 static PyObject *py_creds_get_workstation(PyObject *self, PyObject *unused)
245 return PyString_FromStringOrNULL(cli_credentials_get_workstation(PyCredentials_AsCliCredentials(self)));
248 static PyObject *py_creds_set_workstation(PyObject *self, PyObject *args)
251 enum credentials_obtained obt = CRED_SPECIFIED;
254 if (!PyArg_ParseTuple(args, "s|i", &newval, &_obt)) {
259 return PyBool_FromLong(cli_credentials_set_workstation(PyCredentials_AsCliCredentials(self), newval, obt));
262 static PyObject *py_creds_is_anonymous(PyObject *self, PyObject *unused)
264 return PyBool_FromLong(cli_credentials_is_anonymous(PyCredentials_AsCliCredentials(self)));
267 static PyObject *py_creds_set_anonymous(PyObject *self, PyObject *unused)
269 cli_credentials_set_anonymous(PyCredentials_AsCliCredentials(self));
273 static PyObject *py_creds_authentication_requested(PyObject *self, PyObject *unused)
275 return PyBool_FromLong(cli_credentials_authentication_requested(PyCredentials_AsCliCredentials(self)));
278 static PyObject *py_creds_wrong_password(PyObject *self, PyObject *unused)
280 return PyBool_FromLong(cli_credentials_wrong_password(PyCredentials_AsCliCredentials(self)));
283 static PyObject *py_creds_set_cmdline_callbacks(PyObject *self, PyObject *unused)
285 return PyBool_FromLong(cli_credentials_set_cmdline_callbacks(PyCredentials_AsCliCredentials(self)));
288 static PyObject *py_creds_parse_string(PyObject *self, PyObject *args)
291 enum credentials_obtained obt = CRED_SPECIFIED;
294 if (!PyArg_ParseTuple(args, "s|i", &newval, &_obt)) {
299 cli_credentials_parse_string(PyCredentials_AsCliCredentials(self), newval, obt);
303 static PyObject *py_creds_parse_file(PyObject *self, PyObject *args)
306 enum credentials_obtained obt = CRED_SPECIFIED;
309 if (!PyArg_ParseTuple(args, "s|i", &newval, &_obt)) {
314 cli_credentials_parse_file(PyCredentials_AsCliCredentials(self), newval, obt);
318 static PyObject *py_cli_credentials_set_password_will_be_nt_hash(PyObject *self, PyObject *args)
320 struct cli_credentials *creds = PyCredentials_AsCliCredentials(self);
321 PyObject *py_val = NULL;
324 if (!PyArg_ParseTuple(args, "O!", &PyBool_Type, &py_val)) {
327 val = PyObject_IsTrue(py_val);
329 cli_credentials_set_password_will_be_nt_hash(creds, val);
333 static PyObject *py_creds_get_nt_hash(PyObject *self, PyObject *unused)
336 struct cli_credentials *creds = PyCredentials_AsCliCredentials(self);
337 struct samr_Password *ntpw = cli_credentials_get_nt_hash(creds, creds);
339 ret = PyBytes_FromStringAndSize(discard_const_p(char, ntpw->hash), 16);
344 static PyObject *py_creds_get_kerberos_state(PyObject *self, PyObject *unused)
346 int state = cli_credentials_get_kerberos_state(PyCredentials_AsCliCredentials(self));
347 return PyInt_FromLong(state);
350 static PyObject *py_creds_set_kerberos_state(PyObject *self, PyObject *args)
353 if (!PyArg_ParseTuple(args, "i", &state))
356 cli_credentials_set_kerberos_state(PyCredentials_AsCliCredentials(self), state);
360 static PyObject *py_creds_set_krb_forwardable(PyObject *self, PyObject *args)
363 if (!PyArg_ParseTuple(args, "i", &state))
366 cli_credentials_set_krb_forwardable(PyCredentials_AsCliCredentials(self), state);
371 static PyObject *py_creds_get_forced_sasl_mech(PyObject *self, PyObject *unused)
373 return PyString_FromStringOrNULL(cli_credentials_get_forced_sasl_mech(PyCredentials_AsCliCredentials(self)));
376 static PyObject *py_creds_set_forced_sasl_mech(PyObject *self, PyObject *args)
379 enum credentials_obtained obt = CRED_SPECIFIED;
382 if (!PyArg_ParseTuple(args, "s", &newval)) {
387 cli_credentials_set_forced_sasl_mech(PyCredentials_AsCliCredentials(self), newval);
391 static PyObject *py_creds_guess(PyObject *self, PyObject *args)
393 PyObject *py_lp_ctx = Py_None;
394 struct loadparm_context *lp_ctx;
396 struct cli_credentials *creds;
398 creds = PyCredentials_AsCliCredentials(self);
400 if (!PyArg_ParseTuple(args, "|O", &py_lp_ctx))
403 mem_ctx = talloc_new(NULL);
404 if (mem_ctx == NULL) {
409 lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
410 if (lp_ctx == NULL) {
411 talloc_free(mem_ctx);
415 cli_credentials_guess(creds, lp_ctx);
417 talloc_free(mem_ctx);
422 static PyObject *py_creds_set_machine_account(PyObject *self, PyObject *args)
424 PyObject *py_lp_ctx = Py_None;
425 struct loadparm_context *lp_ctx;
427 struct cli_credentials *creds;
430 creds = PyCredentials_AsCliCredentials(self);
432 if (!PyArg_ParseTuple(args, "|O", &py_lp_ctx))
435 mem_ctx = talloc_new(NULL);
436 if (mem_ctx == NULL) {
441 lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
442 if (lp_ctx == NULL) {
443 talloc_free(mem_ctx);
447 status = cli_credentials_set_machine_account(creds, lp_ctx);
448 talloc_free(mem_ctx);
450 PyErr_NTSTATUS_IS_ERR_RAISE(status);
455 static PyObject *PyCredentialCacheContainer_from_ccache_container(struct ccache_container *ccc)
457 return pytalloc_reference(&PyCredentialCacheContainer, ccc);
461 static PyObject *py_creds_get_named_ccache(PyObject *self, PyObject *args)
463 PyObject *py_lp_ctx = Py_None;
465 struct loadparm_context *lp_ctx;
466 struct ccache_container *ccc;
467 struct tevent_context *event_ctx;
469 const char *error_string;
470 struct cli_credentials *creds;
473 creds = PyCredentials_AsCliCredentials(self);
475 if (!PyArg_ParseTuple(args, "|Os", &py_lp_ctx, &ccache_name))
478 mem_ctx = talloc_new(NULL);
479 if (mem_ctx == NULL) {
484 lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
485 if (lp_ctx == NULL) {
486 talloc_free(mem_ctx);
490 event_ctx = samba_tevent_context_init(mem_ctx);
492 ret = cli_credentials_get_named_ccache(creds, event_ctx, lp_ctx,
493 ccache_name, &ccc, &error_string);
494 talloc_unlink(mem_ctx, lp_ctx);
496 talloc_steal(ccc, event_ctx);
497 talloc_free(mem_ctx);
498 return PyCredentialCacheContainer_from_ccache_container(ccc);
501 PyErr_SetString(PyExc_RuntimeError, error_string?error_string:"NULL");
503 talloc_free(mem_ctx);
507 static PyObject *py_creds_set_gensec_features(PyObject *self, PyObject *args)
509 unsigned int gensec_features;
511 if (!PyArg_ParseTuple(args, "I", &gensec_features))
514 cli_credentials_set_gensec_features(PyCredentials_AsCliCredentials(self), gensec_features);
519 static PyObject *py_creds_get_gensec_features(PyObject *self, PyObject *args)
521 unsigned int gensec_features;
523 gensec_features = cli_credentials_get_gensec_features(PyCredentials_AsCliCredentials(self));
524 return PyInt_FromLong(gensec_features);
528 static PyMethodDef py_creds_methods[] = {
529 { "get_username", py_creds_get_username, METH_NOARGS,
530 "S.get_username() -> username\nObtain username." },
531 { "set_username", py_creds_set_username, METH_VARARGS,
532 "S.set_username(name[, credentials.SPECIFIED]) -> None\n"
533 "Change username." },
534 { "get_principal", py_creds_get_principal, METH_NOARGS,
535 "S.get_principal() -> user@realm\nObtain user principal." },
536 { "set_principal", py_creds_set_principal, METH_VARARGS,
537 "S.set_principal(name[, credentials.SPECIFIED]) -> None\n"
538 "Change principal." },
539 { "get_password", py_creds_get_password, METH_NOARGS,
540 "S.get_password() -> password\n"
541 "Obtain password." },
542 { "get_ntlm_username_domain", py_creds_get_ntlm_username_domain, METH_NOARGS,
543 "S.get_ntlm_username_domain() -> (domain, username)\n"
544 "Obtain NTLM username and domain, split up either as (DOMAIN, user) or (\"\", \"user@realm\")." },
545 { "set_password", py_creds_set_password, METH_VARARGS,
546 "S.set_password(password[, credentials.SPECIFIED]) -> None\n"
547 "Change password." },
548 { "set_utf16_password", py_creds_set_utf16_password, METH_VARARGS,
549 "S.set_utf16_password(password[, credentials.SPECIFIED]) -> None\n"
550 "Change password." },
551 { "get_old_password", py_creds_get_old_password, METH_NOARGS,
552 "S.get_old_password() -> password\n"
553 "Obtain old password." },
554 { "set_old_password", py_creds_set_old_password, METH_VARARGS,
555 "S.set_old_password(password[, credentials.SPECIFIED]) -> None\n"
556 "Change old password." },
557 { "set_old_utf16_password", py_creds_set_old_utf16_password, METH_VARARGS,
558 "S.set_old_utf16_password(password[, credentials.SPECIFIED]) -> None\n"
559 "Change old password." },
560 { "get_domain", py_creds_get_domain, METH_NOARGS,
561 "S.get_domain() -> domain\n"
562 "Obtain domain name." },
563 { "set_domain", py_creds_set_domain, METH_VARARGS,
564 "S.set_domain(domain[, credentials.SPECIFIED]) -> None\n"
565 "Change domain name." },
566 { "get_realm", py_creds_get_realm, METH_NOARGS,
567 "S.get_realm() -> realm\n"
568 "Obtain realm name." },
569 { "set_realm", py_creds_set_realm, METH_VARARGS,
570 "S.set_realm(realm[, credentials.SPECIFIED]) -> None\n"
571 "Change realm name." },
572 { "get_bind_dn", py_creds_get_bind_dn, METH_NOARGS,
573 "S.get_bind_dn() -> bind dn\n"
575 { "set_bind_dn", py_creds_set_bind_dn, METH_VARARGS,
576 "S.set_bind_dn(bind_dn) -> None\n"
578 { "is_anonymous", py_creds_is_anonymous, METH_NOARGS,
580 { "set_anonymous", py_creds_set_anonymous, METH_NOARGS,
581 "S.set_anonymous() -> None\n"
582 "Use anonymous credentials." },
583 { "get_workstation", py_creds_get_workstation, METH_NOARGS,
585 { "set_workstation", py_creds_set_workstation, METH_VARARGS,
587 { "authentication_requested", py_creds_authentication_requested, METH_NOARGS,
589 { "wrong_password", py_creds_wrong_password, METH_NOARGS,
590 "S.wrong_password() -> bool\n"
591 "Indicate the returned password was incorrect." },
592 { "set_cmdline_callbacks", py_creds_set_cmdline_callbacks, METH_NOARGS,
593 "S.set_cmdline_callbacks() -> bool\n"
594 "Use command-line to obtain credentials not explicitly set." },
595 { "parse_string", py_creds_parse_string, METH_VARARGS,
596 "S.parse_string(text[, credentials.SPECIFIED]) -> None\n"
597 "Parse credentials string." },
598 { "parse_file", py_creds_parse_file, METH_VARARGS,
599 "S.parse_file(filename[, credentials.SPECIFIED]) -> None\n"
600 "Parse credentials file." },
601 { "set_password_will_be_nt_hash",
602 py_cli_credentials_set_password_will_be_nt_hash, METH_VARARGS,
603 "S.set_password_will_be_nt_hash(bool) -> None\n"
604 "Alters the behaviour of S.set_password() "
605 "to expect the NTHASH as hexstring." },
606 { "get_nt_hash", py_creds_get_nt_hash, METH_NOARGS,
608 { "get_kerberos_state", py_creds_get_kerberos_state, METH_NOARGS,
610 { "set_kerberos_state", py_creds_set_kerberos_state, METH_VARARGS,
612 { "set_krb_forwardable", py_creds_set_krb_forwardable, METH_VARARGS,
614 { "guess", py_creds_guess, METH_VARARGS, NULL },
615 { "set_machine_account", py_creds_set_machine_account, METH_VARARGS, NULL },
616 { "get_named_ccache", py_creds_get_named_ccache, METH_VARARGS, NULL },
617 { "set_gensec_features", py_creds_set_gensec_features, METH_VARARGS, NULL },
618 { "get_gensec_features", py_creds_get_gensec_features, METH_NOARGS, NULL },
619 { "get_forced_sasl_mech", py_creds_get_forced_sasl_mech, METH_NOARGS,
620 "S.get_forced_sasl_mech() -> SASL mechanism\nObtain forced SASL mechanism." },
621 { "set_forced_sasl_mech", py_creds_set_forced_sasl_mech, METH_VARARGS,
622 "S.set_forced_sasl_mech(name) -> None\n"
623 "Set forced SASL mechanism." },
627 static struct PyModuleDef moduledef = {
628 PyModuleDef_HEAD_INIT,
629 .m_name = "credentials",
630 .m_doc = "Credentials management.",
632 .m_methods = py_creds_methods,
635 PyTypeObject PyCredentials = {
636 .tp_name = "credentials.Credentials",
637 .tp_new = py_creds_new,
638 .tp_flags = Py_TPFLAGS_DEFAULT,
639 .tp_methods = py_creds_methods,
643 PyTypeObject PyCredentialCacheContainer = {
644 .tp_name = "credentials.CredentialCacheContainer",
645 .tp_flags = Py_TPFLAGS_DEFAULT,
648 MODULE_INIT_FUNC(credentials)
651 if (pytalloc_BaseObject_PyType_Ready(&PyCredentials) < 0)
654 if (pytalloc_BaseObject_PyType_Ready(&PyCredentialCacheContainer) < 0)
657 m = PyModule_Create(&moduledef);
661 PyModule_AddObject(m, "UNINITIALISED", PyInt_FromLong(CRED_UNINITIALISED));
662 PyModule_AddObject(m, "CALLBACK", PyInt_FromLong(CRED_CALLBACK));
663 PyModule_AddObject(m, "GUESS_ENV", PyInt_FromLong(CRED_GUESS_ENV));
664 PyModule_AddObject(m, "GUESS_FILE", PyInt_FromLong(CRED_GUESS_FILE));
665 PyModule_AddObject(m, "CALLBACK_RESULT", PyInt_FromLong(CRED_CALLBACK_RESULT));
666 PyModule_AddObject(m, "SPECIFIED", PyInt_FromLong(CRED_SPECIFIED));
668 PyModule_AddObject(m, "AUTO_USE_KERBEROS", PyInt_FromLong(CRED_AUTO_USE_KERBEROS));
669 PyModule_AddObject(m, "DONT_USE_KERBEROS", PyInt_FromLong(CRED_DONT_USE_KERBEROS));
670 PyModule_AddObject(m, "MUST_USE_KERBEROS", PyInt_FromLong(CRED_MUST_USE_KERBEROS));
672 PyModule_AddObject(m, "AUTO_KRB_FORWARDABLE", PyInt_FromLong(CRED_AUTO_KRB_FORWARDABLE));
673 PyModule_AddObject(m, "NO_KRB_FORWARDABLE", PyInt_FromLong(CRED_NO_KRB_FORWARDABLE));
674 PyModule_AddObject(m, "FORCE_KRB_FORWARDABLE", PyInt_FromLong(CRED_FORCE_KRB_FORWARDABLE));
676 Py_INCREF(&PyCredentials);
677 PyModule_AddObject(m, "Credentials", (PyObject *)&PyCredentials);
678 Py_INCREF(&PyCredentialCacheContainer);
679 PyModule_AddObject(m, "CredentialCacheContainer", (PyObject *)&PyCredentialCacheContainer);