2 Unix SMB/CIFS implementation.
3 Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2009
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/>.
21 #include "param/pyparam.h"
22 #include "auth/gensec/gensec.h"
23 #include "auth/credentials/pycredentials.h"
24 #include "libcli/util/pyerrors.h"
25 #include "scripting/python/modules.h"
26 #include "lib/talloc/pytalloc.h"
28 #include "librpc/rpc/pyrpc_util.h"
30 static PyObject
*py_get_name_by_authtype(PyObject
*self
, PyObject
*args
)
34 struct gensec_security
*security
;
36 if (!PyArg_ParseTuple(args
, "i", &type
))
39 security
= py_talloc_get_type(self
, struct gensec_security
);
41 name
= gensec_get_name_by_authtype(security
, type
);
45 return PyString_FromString(name
);
48 static struct gensec_settings
*settings_from_object(TALLOC_CTX
*mem_ctx
, PyObject
*object
)
50 struct gensec_settings
*s
;
51 PyObject
*py_hostname
, *py_lp_ctx
;
53 if (!PyDict_Check(object
)) {
54 PyErr_SetString(PyExc_ValueError
, "settings should be a dictionary");
58 s
= talloc_zero(mem_ctx
, struct gensec_settings
);
61 py_hostname
= PyDict_GetItemString(object
, "target_hostname");
63 PyErr_SetString(PyExc_ValueError
, "settings.target_hostname not found");
67 py_lp_ctx
= PyDict_GetItemString(object
, "lp_ctx");
69 PyErr_SetString(PyExc_ValueError
, "settings.lp_ctx not found");
73 s
->target_hostname
= PyString_AsString(py_hostname
);
74 s
->lp_ctx
= lpcfg_from_py_object(s
, py_lp_ctx
);
78 static PyObject
*py_gensec_start_client(PyTypeObject
*type
, PyObject
*args
, PyObject
*kwargs
)
81 py_talloc_Object
*self
;
82 struct gensec_settings
*settings
;
83 const char *kwnames
[] = { "settings", NULL
};
84 PyObject
*py_settings
;
85 struct tevent_context
*ev
;
86 struct gensec_security
*gensec
;
88 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|O", discard_const_p(char *, kwnames
), &py_settings
))
91 self
= (py_talloc_Object
*)type
->tp_alloc(type
, 0);
96 self
->talloc_ctx
= talloc_new(NULL
);
97 if (self
->talloc_ctx
== NULL
) {
102 if (py_settings
!= Py_None
) {
103 settings
= settings_from_object(self
->talloc_ctx
, py_settings
);
104 if (settings
== NULL
) {
109 settings
= talloc_zero(self
->talloc_ctx
, struct gensec_settings
);
110 if (settings
== NULL
) {
115 settings
->lp_ctx
= loadparm_init_global(true);
118 ev
= tevent_context_init(self
->talloc_ctx
);
125 status
= gensec_init(settings
->lp_ctx
);
126 if (!NT_STATUS_IS_OK(status
)) {
127 PyErr_SetNTSTATUS(status
);
132 status
= gensec_client_start(self
->talloc_ctx
, &gensec
, ev
, settings
);
133 if (!NT_STATUS_IS_OK(status
)) {
134 PyErr_SetNTSTATUS(status
);
141 return (PyObject
*)self
;
144 static PyObject
*py_gensec_start_server(PyTypeObject
*type
, PyObject
*args
, PyObject
*kwargs
)
147 py_talloc_Object
*self
;
148 struct gensec_settings
*settings
= NULL
;
149 const char *kwnames
[] = { "settings", "auth_context", NULL
};
150 PyObject
*py_settings
= Py_None
;
151 PyObject
*py_auth_context
= Py_None
;
152 struct tevent_context
*ev
;
153 struct gensec_security
*gensec
;
154 struct auth_context
*auth_context
= NULL
;
156 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|OO", discard_const_p(char *, kwnames
), &py_settings
, &py_auth_context
))
159 self
= (py_talloc_Object
*)type
->tp_alloc(type
, 0);
164 self
->talloc_ctx
= talloc_new(NULL
);
165 if (self
->talloc_ctx
== NULL
) {
170 if (py_settings
!= Py_None
) {
171 settings
= settings_from_object(self
->talloc_ctx
, py_settings
);
172 if (settings
== NULL
) {
177 settings
= talloc_zero(self
->talloc_ctx
, struct gensec_settings
);
178 if (settings
== NULL
) {
183 settings
->lp_ctx
= loadparm_init_global(true);
186 ev
= tevent_context_init(self
->talloc_ctx
);
193 if (py_auth_context
!= Py_None
) {
194 auth_context
= py_talloc_get_type(py_auth_context
, struct auth_context
);
196 PyErr_Format(PyExc_TypeError
,
197 "Expected auth.AuthContext for auth_context argument, got %s",
198 talloc_get_name(py_talloc_get_ptr(py_auth_context
)));
203 status
= gensec_init(settings
->lp_ctx
);
204 if (!NT_STATUS_IS_OK(status
)) {
205 PyErr_SetNTSTATUS(status
);
210 status
= gensec_server_start(self
->talloc_ctx
, ev
, settings
, auth_context
, &gensec
);
211 if (!NT_STATUS_IS_OK(status
)) {
212 PyErr_SetNTSTATUS(status
);
219 return (PyObject
*)self
;
222 static PyObject
*py_gensec_set_credentials(PyObject
*self
, PyObject
*args
)
224 PyObject
*py_creds
= Py_None
;
225 struct cli_credentials
*creds
;
226 struct gensec_security
*security
= py_talloc_get_type(self
, struct gensec_security
);
229 if (!PyArg_ParseTuple(args
, "O", &py_creds
))
232 creds
= PyCredentials_AsCliCredentials(py_creds
);
234 PyErr_Format(PyExc_TypeError
,
235 "Expected samba.credentaials for credentials argument got %s",
236 talloc_get_name(py_talloc_get_ptr(py_creds
)));
239 status
= gensec_set_credentials(security
, creds
);
240 if (!NT_STATUS_IS_OK(status
)) {
241 PyErr_SetNTSTATUS(status
);
248 static PyObject
*py_gensec_session_info(PyObject
*self
)
251 PyObject
*py_session_info
;
252 struct gensec_security
*security
= py_talloc_get_type(self
, struct gensec_security
);
253 struct auth_session_info
*info
;
254 if (security
->ops
== NULL
) {
255 PyErr_SetString(PyExc_RuntimeError
, "no mechanism selected");
258 status
= gensec_session_info(security
, &info
);
259 if (NT_STATUS_IS_ERR(status
)) {
260 PyErr_SetNTSTATUS(status
);
264 py_session_info
= py_return_ndr_struct("samba.auth", "AuthSession",
266 return py_session_info
;
269 static PyObject
*py_gensec_start_mech_by_name(PyObject
*self
, PyObject
*args
)
272 struct gensec_security
*security
= py_talloc_get_type(self
, struct gensec_security
);
275 if (!PyArg_ParseTuple(args
, "s", &name
))
278 status
= gensec_start_mech_by_name(security
, name
);
279 if (!NT_STATUS_IS_OK(status
)) {
280 PyErr_SetNTSTATUS(status
);
287 static PyObject
*py_gensec_start_mech_by_sasl_name(PyObject
*self
, PyObject
*args
)
290 struct gensec_security
*security
= py_talloc_get_type(self
, struct gensec_security
);
293 if (!PyArg_ParseTuple(args
, "s", &sasl_name
))
296 status
= gensec_start_mech_by_sasl_name(security
, sasl_name
);
297 if (!NT_STATUS_IS_OK(status
)) {
298 PyErr_SetNTSTATUS(status
);
305 static PyObject
*py_gensec_start_mech_by_authtype(PyObject
*self
, PyObject
*args
)
308 struct gensec_security
*security
= py_talloc_get_type(self
, struct gensec_security
);
310 if (!PyArg_ParseTuple(args
, "ii", &authtype
, &level
))
313 status
= gensec_start_mech_by_authtype(security
, authtype
, level
);
314 if (!NT_STATUS_IS_OK(status
)) {
315 PyErr_SetNTSTATUS(status
);
322 static PyObject
*py_gensec_want_feature(PyObject
*self
, PyObject
*args
)
325 struct gensec_security
*security
= py_talloc_get_type(self
, struct gensec_security
);
326 /* This is i (and declared as an int above) by design, as they are handled as an integer in python */
327 if (!PyArg_ParseTuple(args
, "i", &feature
))
330 gensec_want_feature(security
, feature
);
335 static PyObject
*py_gensec_have_feature(PyObject
*self
, PyObject
*args
)
338 struct gensec_security
*security
= py_talloc_get_type(self
, struct gensec_security
);
339 /* This is i (and declared as an int above) by design, as they are handled as an integer in python */
340 if (!PyArg_ParseTuple(args
, "i", &feature
))
343 if (gensec_have_feature(security
, feature
)) {
349 static PyObject
*py_gensec_update(PyObject
*self
, PyObject
*args
)
354 PyObject
*ret
, *py_in
;
355 struct gensec_security
*security
= py_talloc_get_type(self
, struct gensec_security
);
356 PyObject
*finished_processing
;
358 if (!PyArg_ParseTuple(args
, "O", &py_in
))
361 mem_ctx
= talloc_new(NULL
);
363 if (!PyString_Check(py_in
)) {
364 PyErr_Format(PyExc_TypeError
, "expected a string");
368 in
.data
= (uint8_t *)PyString_AsString(py_in
);
369 in
.length
= PyString_Size(py_in
);
371 status
= gensec_update(security
, mem_ctx
, in
, &out
);
373 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)
374 && !NT_STATUS_IS_OK(status
)) {
375 PyErr_SetNTSTATUS(status
);
376 talloc_free(mem_ctx
);
379 ret
= PyString_FromStringAndSize((const char *)out
.data
, out
.length
);
380 talloc_free(mem_ctx
);
382 if (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
383 finished_processing
= Py_False
;
385 finished_processing
= Py_True
;
388 return PyTuple_Pack(2, finished_processing
, ret
);
391 static PyObject
*py_gensec_wrap(PyObject
*self
, PyObject
*args
)
397 PyObject
*ret
, *py_in
;
398 struct gensec_security
*security
= py_talloc_get_type(self
, struct gensec_security
);
400 if (!PyArg_ParseTuple(args
, "O", &py_in
))
403 mem_ctx
= talloc_new(NULL
);
405 if (!PyString_Check(py_in
)) {
406 PyErr_Format(PyExc_TypeError
, "expected a string");
409 in
.data
= (uint8_t *)PyString_AsString(py_in
);
410 in
.length
= PyString_Size(py_in
);
412 status
= gensec_wrap(security
, mem_ctx
, &in
, &out
);
414 if (!NT_STATUS_IS_OK(status
)) {
415 PyErr_SetNTSTATUS(status
);
416 talloc_free(mem_ctx
);
420 ret
= PyString_FromStringAndSize((const char *)out
.data
, out
.length
);
421 talloc_free(mem_ctx
);
425 static PyObject
*py_gensec_unwrap(PyObject
*self
, PyObject
*args
)
431 PyObject
*ret
, *py_in
;
432 struct gensec_security
*security
= py_talloc_get_type(self
, struct gensec_security
);
434 if (!PyArg_ParseTuple(args
, "O", &py_in
))
437 mem_ctx
= talloc_new(NULL
);
439 if (!PyString_Check(py_in
)) {
440 PyErr_Format(PyExc_TypeError
, "expected a string");
444 in
.data
= (uint8_t *)PyString_AsString(py_in
);
445 in
.length
= PyString_Size(py_in
);
447 status
= gensec_unwrap(security
, mem_ctx
, &in
, &out
);
449 if (!NT_STATUS_IS_OK(status
)) {
450 PyErr_SetNTSTATUS(status
);
451 talloc_free(mem_ctx
);
455 ret
= PyString_FromStringAndSize((const char *)out
.data
, out
.length
);
456 talloc_free(mem_ctx
);
460 static PyMethodDef py_gensec_security_methods
[] = {
461 { "start_client", (PyCFunction
)py_gensec_start_client
, METH_VARARGS
|METH_KEYWORDS
|METH_CLASS
,
462 "S.start_client(settings) -> gensec" },
463 { "start_server", (PyCFunction
)py_gensec_start_server
, METH_VARARGS
|METH_KEYWORDS
|METH_CLASS
,
464 "S.start_server(auth_ctx, settings) -> gensec" },
465 { "set_credentials", (PyCFunction
)py_gensec_set_credentials
, METH_VARARGS
,
466 "S.start_client(credentials)" },
467 { "session_info", (PyCFunction
)py_gensec_session_info
, METH_NOARGS
,
468 "S.session_info() -> info" },
469 { "start_mech_by_name", (PyCFunction
)py_gensec_start_mech_by_name
, METH_VARARGS
,
470 "S.start_mech_by_name(name)" },
471 { "start_mech_by_sasl_name", (PyCFunction
)py_gensec_start_mech_by_sasl_name
, METH_VARARGS
,
472 "S.start_mech_by_sasl_name(name)" },
473 { "start_mech_by_authtype", (PyCFunction
)py_gensec_start_mech_by_authtype
, METH_VARARGS
, "S.start_mech_by_authtype(authtype, level)" },
474 { "get_name_by_authtype", (PyCFunction
)py_get_name_by_authtype
, METH_VARARGS
,
475 "S.get_name_by_authtype(authtype) -> name\nLookup an auth type." },
476 { "want_feature", (PyCFunction
)py_gensec_want_feature
, METH_VARARGS
,
477 "S.want_feature(feature)\n Request that GENSEC negotiate a particular feature." },
478 { "have_feature", (PyCFunction
)py_gensec_have_feature
, METH_VARARGS
,
479 "S.have_feature()\n Return True if GENSEC negotiated a particular feature." },
480 { "update", (PyCFunction
)py_gensec_update
, METH_VARARGS
,
481 "S.update(blob_in) -> (finished, blob_out)\nPerform one step in a GENSEC dance. Repeat with new packets until finished is true or exception." },
482 { "wrap", (PyCFunction
)py_gensec_wrap
, METH_VARARGS
,
483 "S.wrap(blob_in) -> blob_out\nPackage one clear packet into a wrapped GENSEC packet." },
484 { "unwrap", (PyCFunction
)py_gensec_unwrap
, METH_VARARGS
,
485 "S.unwrap(blob_in) -> blob_out\nPerform one wrapped GENSEC packet into a clear packet." },
490 static PyTypeObject Py_Security
= {
491 .tp_name
= "Security",
492 .tp_flags
= Py_TPFLAGS_DEFAULT
,
493 .tp_methods
= py_gensec_security_methods
,
494 .tp_basicsize
= sizeof(py_talloc_Object
),
497 void initgensec(void);
498 void initgensec(void)
502 Py_Security
.tp_base
= PyTalloc_GetObjectType();
503 if (Py_Security
.tp_base
== NULL
)
506 if (PyType_Ready(&Py_Security
) < 0)
509 m
= Py_InitModule3("gensec", NULL
, "Generic Security Interface.");
513 PyModule_AddObject(m
, "FEATURE_SESSION_KEY", PyInt_FromLong(GENSEC_FEATURE_SESSION_KEY
));
514 PyModule_AddObject(m
, "FEATURE_SIGN", PyInt_FromLong(GENSEC_FEATURE_SIGN
));
515 PyModule_AddObject(m
, "FEATURE_SEAL", PyInt_FromLong(GENSEC_FEATURE_SEAL
));
516 PyModule_AddObject(m
, "FEATURE_DCE_STYLE", PyInt_FromLong(GENSEC_FEATURE_DCE_STYLE
));
517 PyModule_AddObject(m
, "FEATURE_ASYNC_REPLIES", PyInt_FromLong(GENSEC_FEATURE_ASYNC_REPLIES
));
518 PyModule_AddObject(m
, "FEATURE_DATAGRAM_MODE", PyInt_FromLong(GENSEC_FEATURE_DATAGRAM_MODE
));
519 PyModule_AddObject(m
, "FEATURE_SIGN_PKT_HEADER", PyInt_FromLong(GENSEC_FEATURE_SIGN_PKT_HEADER
));
520 PyModule_AddObject(m
, "FEATURE_NEW_SPNEGO", PyInt_FromLong(GENSEC_FEATURE_NEW_SPNEGO
));
522 Py_INCREF(&Py_Security
);
523 PyModule_AddObject(m
, "Security", (PyObject
*)&Py_Security
);