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);
116 if (settings
->lp_ctx
== NULL
) {
123 ev
= tevent_context_init(self
->talloc_ctx
);
130 status
= gensec_init();
131 if (!NT_STATUS_IS_OK(status
)) {
132 PyErr_SetNTSTATUS(status
);
137 status
= gensec_client_start(self
->talloc_ctx
, &gensec
, ev
, settings
);
138 if (!NT_STATUS_IS_OK(status
)) {
139 PyErr_SetNTSTATUS(status
);
146 return (PyObject
*)self
;
149 static PyObject
*py_gensec_start_server(PyTypeObject
*type
, PyObject
*args
, PyObject
*kwargs
)
152 py_talloc_Object
*self
;
153 struct gensec_settings
*settings
= NULL
;
154 const char *kwnames
[] = { "settings", "auth_context", NULL
};
155 PyObject
*py_settings
= Py_None
;
156 PyObject
*py_auth_context
= Py_None
;
157 struct tevent_context
*ev
;
158 struct gensec_security
*gensec
;
159 struct auth4_context
*auth_context
= NULL
;
161 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|OO", discard_const_p(char *, kwnames
), &py_settings
, &py_auth_context
))
164 self
= (py_talloc_Object
*)type
->tp_alloc(type
, 0);
169 self
->talloc_ctx
= talloc_new(NULL
);
170 if (self
->talloc_ctx
== NULL
) {
175 if (py_settings
!= Py_None
) {
176 settings
= settings_from_object(self
->talloc_ctx
, py_settings
);
177 if (settings
== NULL
) {
182 settings
= talloc_zero(self
->talloc_ctx
, struct gensec_settings
);
183 if (settings
== NULL
) {
188 settings
->lp_ctx
= loadparm_init_global(true);
189 if (settings
->lp_ctx
== NULL
) {
196 ev
= tevent_context_init(self
->talloc_ctx
);
203 if (py_auth_context
!= Py_None
) {
204 auth_context
= py_talloc_get_type(py_auth_context
, struct auth4_context
);
206 PyErr_Format(PyExc_TypeError
,
207 "Expected auth.AuthContext for auth_context argument, got %s",
208 talloc_get_name(py_talloc_get_ptr(py_auth_context
)));
213 status
= gensec_init();
214 if (!NT_STATUS_IS_OK(status
)) {
215 PyErr_SetNTSTATUS(status
);
220 status
= gensec_server_start(self
->talloc_ctx
, ev
, settings
, auth_context
, &gensec
);
221 if (!NT_STATUS_IS_OK(status
)) {
222 PyErr_SetNTSTATUS(status
);
229 return (PyObject
*)self
;
232 static PyObject
*py_gensec_set_credentials(PyObject
*self
, PyObject
*args
)
234 PyObject
*py_creds
= Py_None
;
235 struct cli_credentials
*creds
;
236 struct gensec_security
*security
= py_talloc_get_type(self
, struct gensec_security
);
239 if (!PyArg_ParseTuple(args
, "O", &py_creds
))
242 creds
= PyCredentials_AsCliCredentials(py_creds
);
244 PyErr_Format(PyExc_TypeError
,
245 "Expected samba.credentaials for credentials argument got %s",
246 talloc_get_name(py_talloc_get_ptr(py_creds
)));
249 status
= gensec_set_credentials(security
, creds
);
250 if (!NT_STATUS_IS_OK(status
)) {
251 PyErr_SetNTSTATUS(status
);
258 static PyObject
*py_gensec_session_info(PyObject
*self
)
261 PyObject
*py_session_info
;
262 struct gensec_security
*security
= py_talloc_get_type(self
, struct gensec_security
);
263 struct auth_session_info
*info
;
264 if (security
->ops
== NULL
) {
265 PyErr_SetString(PyExc_RuntimeError
, "no mechanism selected");
268 status
= gensec_session_info(security
, &info
);
269 if (NT_STATUS_IS_ERR(status
)) {
270 PyErr_SetNTSTATUS(status
);
274 py_session_info
= py_return_ndr_struct("samba.dcerpc.auth", "session_info",
276 return py_session_info
;
279 static PyObject
*py_gensec_start_mech_by_name(PyObject
*self
, PyObject
*args
)
282 struct gensec_security
*security
= py_talloc_get_type(self
, struct gensec_security
);
285 if (!PyArg_ParseTuple(args
, "s", &name
))
288 status
= gensec_start_mech_by_name(security
, name
);
289 if (!NT_STATUS_IS_OK(status
)) {
290 PyErr_SetNTSTATUS(status
);
297 static PyObject
*py_gensec_start_mech_by_sasl_name(PyObject
*self
, PyObject
*args
)
300 struct gensec_security
*security
= py_talloc_get_type(self
, struct gensec_security
);
303 if (!PyArg_ParseTuple(args
, "s", &sasl_name
))
306 status
= gensec_start_mech_by_sasl_name(security
, sasl_name
);
307 if (!NT_STATUS_IS_OK(status
)) {
308 PyErr_SetNTSTATUS(status
);
315 static PyObject
*py_gensec_start_mech_by_authtype(PyObject
*self
, PyObject
*args
)
318 struct gensec_security
*security
= py_talloc_get_type(self
, struct gensec_security
);
320 if (!PyArg_ParseTuple(args
, "ii", &authtype
, &level
))
323 status
= gensec_start_mech_by_authtype(security
, authtype
, level
);
324 if (!NT_STATUS_IS_OK(status
)) {
325 PyErr_SetNTSTATUS(status
);
332 static PyObject
*py_gensec_want_feature(PyObject
*self
, PyObject
*args
)
335 struct gensec_security
*security
= py_talloc_get_type(self
, struct gensec_security
);
336 /* This is i (and declared as an int above) by design, as they are handled as an integer in python */
337 if (!PyArg_ParseTuple(args
, "i", &feature
))
340 gensec_want_feature(security
, feature
);
345 static PyObject
*py_gensec_have_feature(PyObject
*self
, PyObject
*args
)
348 struct gensec_security
*security
= py_talloc_get_type(self
, struct gensec_security
);
349 /* This is i (and declared as an int above) by design, as they are handled as an integer in python */
350 if (!PyArg_ParseTuple(args
, "i", &feature
))
353 if (gensec_have_feature(security
, feature
)) {
359 static PyObject
*py_gensec_update(PyObject
*self
, PyObject
*args
)
364 PyObject
*ret
, *py_in
;
365 struct gensec_security
*security
= py_talloc_get_type(self
, struct gensec_security
);
366 PyObject
*finished_processing
;
368 if (!PyArg_ParseTuple(args
, "O", &py_in
))
371 mem_ctx
= talloc_new(NULL
);
373 if (!PyString_Check(py_in
)) {
374 PyErr_Format(PyExc_TypeError
, "expected a string");
378 in
.data
= (uint8_t *)PyString_AsString(py_in
);
379 in
.length
= PyString_Size(py_in
);
381 status
= gensec_update(security
, mem_ctx
, in
, &out
);
383 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)
384 && !NT_STATUS_IS_OK(status
)) {
385 PyErr_SetNTSTATUS(status
);
386 talloc_free(mem_ctx
);
389 ret
= PyString_FromStringAndSize((const char *)out
.data
, out
.length
);
390 talloc_free(mem_ctx
);
392 if (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
393 finished_processing
= Py_False
;
395 finished_processing
= Py_True
;
398 return PyTuple_Pack(2, finished_processing
, ret
);
401 static PyObject
*py_gensec_wrap(PyObject
*self
, PyObject
*args
)
407 PyObject
*ret
, *py_in
;
408 struct gensec_security
*security
= py_talloc_get_type(self
, struct gensec_security
);
410 if (!PyArg_ParseTuple(args
, "O", &py_in
))
413 mem_ctx
= talloc_new(NULL
);
415 if (!PyString_Check(py_in
)) {
416 PyErr_Format(PyExc_TypeError
, "expected a string");
419 in
.data
= (uint8_t *)PyString_AsString(py_in
);
420 in
.length
= PyString_Size(py_in
);
422 status
= gensec_wrap(security
, mem_ctx
, &in
, &out
);
424 if (!NT_STATUS_IS_OK(status
)) {
425 PyErr_SetNTSTATUS(status
);
426 talloc_free(mem_ctx
);
430 ret
= PyString_FromStringAndSize((const char *)out
.data
, out
.length
);
431 talloc_free(mem_ctx
);
435 static PyObject
*py_gensec_unwrap(PyObject
*self
, PyObject
*args
)
441 PyObject
*ret
, *py_in
;
442 struct gensec_security
*security
= py_talloc_get_type(self
, struct gensec_security
);
444 if (!PyArg_ParseTuple(args
, "O", &py_in
))
447 mem_ctx
= talloc_new(NULL
);
449 if (!PyString_Check(py_in
)) {
450 PyErr_Format(PyExc_TypeError
, "expected a string");
454 in
.data
= (uint8_t *)PyString_AsString(py_in
);
455 in
.length
= PyString_Size(py_in
);
457 status
= gensec_unwrap(security
, mem_ctx
, &in
, &out
);
459 if (!NT_STATUS_IS_OK(status
)) {
460 PyErr_SetNTSTATUS(status
);
461 talloc_free(mem_ctx
);
465 ret
= PyString_FromStringAndSize((const char *)out
.data
, out
.length
);
466 talloc_free(mem_ctx
);
470 static PyMethodDef py_gensec_security_methods
[] = {
471 { "start_client", (PyCFunction
)py_gensec_start_client
, METH_VARARGS
|METH_KEYWORDS
|METH_CLASS
,
472 "S.start_client(settings) -> gensec" },
473 { "start_server", (PyCFunction
)py_gensec_start_server
, METH_VARARGS
|METH_KEYWORDS
|METH_CLASS
,
474 "S.start_server(auth_ctx, settings) -> gensec" },
475 { "set_credentials", (PyCFunction
)py_gensec_set_credentials
, METH_VARARGS
,
476 "S.start_client(credentials)" },
477 { "session_info", (PyCFunction
)py_gensec_session_info
, METH_NOARGS
,
478 "S.session_info() -> info" },
479 { "start_mech_by_name", (PyCFunction
)py_gensec_start_mech_by_name
, METH_VARARGS
,
480 "S.start_mech_by_name(name)" },
481 { "start_mech_by_sasl_name", (PyCFunction
)py_gensec_start_mech_by_sasl_name
, METH_VARARGS
,
482 "S.start_mech_by_sasl_name(name)" },
483 { "start_mech_by_authtype", (PyCFunction
)py_gensec_start_mech_by_authtype
, METH_VARARGS
, "S.start_mech_by_authtype(authtype, level)" },
484 { "get_name_by_authtype", (PyCFunction
)py_get_name_by_authtype
, METH_VARARGS
,
485 "S.get_name_by_authtype(authtype) -> name\nLookup an auth type." },
486 { "want_feature", (PyCFunction
)py_gensec_want_feature
, METH_VARARGS
,
487 "S.want_feature(feature)\n Request that GENSEC negotiate a particular feature." },
488 { "have_feature", (PyCFunction
)py_gensec_have_feature
, METH_VARARGS
,
489 "S.have_feature()\n Return True if GENSEC negotiated a particular feature." },
490 { "update", (PyCFunction
)py_gensec_update
, METH_VARARGS
,
491 "S.update(blob_in) -> (finished, blob_out)\nPerform one step in a GENSEC dance. Repeat with new packets until finished is true or exception." },
492 { "wrap", (PyCFunction
)py_gensec_wrap
, METH_VARARGS
,
493 "S.wrap(blob_in) -> blob_out\nPackage one clear packet into a wrapped GENSEC packet." },
494 { "unwrap", (PyCFunction
)py_gensec_unwrap
, METH_VARARGS
,
495 "S.unwrap(blob_in) -> blob_out\nPerform one wrapped GENSEC packet into a clear packet." },
500 static PyTypeObject Py_Security
= {
501 .tp_name
= "gensec.Security",
502 .tp_flags
= Py_TPFLAGS_DEFAULT
,
503 .tp_methods
= py_gensec_security_methods
,
504 .tp_basicsize
= sizeof(py_talloc_Object
),
507 void initgensec(void);
508 void initgensec(void)
512 Py_Security
.tp_base
= PyTalloc_GetObjectType();
513 if (Py_Security
.tp_base
== NULL
)
516 if (PyType_Ready(&Py_Security
) < 0)
519 m
= Py_InitModule3("gensec", NULL
, "Generic Security Interface.");
523 PyModule_AddObject(m
, "FEATURE_SESSION_KEY", PyInt_FromLong(GENSEC_FEATURE_SESSION_KEY
));
524 PyModule_AddObject(m
, "FEATURE_SIGN", PyInt_FromLong(GENSEC_FEATURE_SIGN
));
525 PyModule_AddObject(m
, "FEATURE_SEAL", PyInt_FromLong(GENSEC_FEATURE_SEAL
));
526 PyModule_AddObject(m
, "FEATURE_DCE_STYLE", PyInt_FromLong(GENSEC_FEATURE_DCE_STYLE
));
527 PyModule_AddObject(m
, "FEATURE_ASYNC_REPLIES", PyInt_FromLong(GENSEC_FEATURE_ASYNC_REPLIES
));
528 PyModule_AddObject(m
, "FEATURE_DATAGRAM_MODE", PyInt_FromLong(GENSEC_FEATURE_DATAGRAM_MODE
));
529 PyModule_AddObject(m
, "FEATURE_SIGN_PKT_HEADER", PyInt_FromLong(GENSEC_FEATURE_SIGN_PKT_HEADER
));
530 PyModule_AddObject(m
, "FEATURE_NEW_SPNEGO", PyInt_FromLong(GENSEC_FEATURE_NEW_SPNEGO
));
532 Py_INCREF(&Py_Security
);
533 PyModule_AddObject(m
, "Security", (PyObject
*)&Py_Security
);