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 "python/modules.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
= pytalloc_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 pytalloc_Object
*self
;
82 struct gensec_settings
*settings
;
83 const char *kwnames
[] = { "settings", NULL
};
84 PyObject
*py_settings
= Py_None
;
85 struct gensec_security
*gensec
;
87 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|O", discard_const_p(char *, kwnames
), &py_settings
))
90 self
= (pytalloc_Object
*)type
->tp_alloc(type
, 0);
95 self
->talloc_ctx
= talloc_new(NULL
);
96 if (self
->talloc_ctx
== NULL
) {
101 if (py_settings
!= Py_None
) {
102 settings
= settings_from_object(self
->talloc_ctx
, py_settings
);
103 if (settings
== NULL
) {
108 settings
= talloc_zero(self
->talloc_ctx
, struct gensec_settings
);
109 if (settings
== NULL
) {
114 settings
->lp_ctx
= loadparm_init_global(true);
115 if (settings
->lp_ctx
== NULL
) {
122 status
= gensec_init();
123 if (!NT_STATUS_IS_OK(status
)) {
124 PyErr_SetNTSTATUS(status
);
129 status
= gensec_client_start(self
->talloc_ctx
, &gensec
, settings
);
130 if (!NT_STATUS_IS_OK(status
)) {
131 PyErr_SetNTSTATUS(status
);
138 return (PyObject
*)self
;
141 static PyObject
*py_gensec_start_server(PyTypeObject
*type
, PyObject
*args
, PyObject
*kwargs
)
144 pytalloc_Object
*self
;
145 struct gensec_settings
*settings
= NULL
;
146 const char *kwnames
[] = { "settings", "auth_context", NULL
};
147 PyObject
*py_settings
= Py_None
;
148 PyObject
*py_auth_context
= Py_None
;
149 struct gensec_security
*gensec
;
150 struct auth4_context
*auth_context
= NULL
;
152 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|OO", discard_const_p(char *, kwnames
), &py_settings
, &py_auth_context
))
155 self
= (pytalloc_Object
*)type
->tp_alloc(type
, 0);
160 self
->talloc_ctx
= talloc_new(NULL
);
161 if (self
->talloc_ctx
== NULL
) {
166 if (py_settings
!= Py_None
) {
167 settings
= settings_from_object(self
->talloc_ctx
, py_settings
);
168 if (settings
== NULL
) {
173 settings
= talloc_zero(self
->talloc_ctx
, struct gensec_settings
);
174 if (settings
== NULL
) {
179 settings
->lp_ctx
= loadparm_init_global(true);
180 if (settings
->lp_ctx
== NULL
) {
187 if (py_auth_context
!= Py_None
) {
188 auth_context
= pytalloc_get_type(py_auth_context
, struct auth4_context
);
190 PyErr_Format(PyExc_TypeError
,
191 "Expected auth.AuthContext for auth_context argument, got %s",
192 talloc_get_name(pytalloc_get_ptr(py_auth_context
)));
197 status
= gensec_init();
198 if (!NT_STATUS_IS_OK(status
)) {
199 PyErr_SetNTSTATUS(status
);
204 status
= gensec_server_start(self
->talloc_ctx
, settings
, auth_context
, &gensec
);
205 if (!NT_STATUS_IS_OK(status
)) {
206 PyErr_SetNTSTATUS(status
);
213 return (PyObject
*)self
;
216 static PyObject
*py_gensec_set_credentials(PyObject
*self
, PyObject
*args
)
218 PyObject
*py_creds
= Py_None
;
219 struct cli_credentials
*creds
;
220 struct gensec_security
*security
= pytalloc_get_type(self
, struct gensec_security
);
223 if (!PyArg_ParseTuple(args
, "O", &py_creds
))
226 creds
= PyCredentials_AsCliCredentials(py_creds
);
228 PyErr_Format(PyExc_TypeError
,
229 "Expected samba.credentaials for credentials argument got %s",
230 talloc_get_name(pytalloc_get_ptr(py_creds
)));
233 status
= gensec_set_credentials(security
, creds
);
234 if (!NT_STATUS_IS_OK(status
)) {
235 PyErr_SetNTSTATUS(status
);
242 static PyObject
*py_gensec_session_info(PyObject
*self
)
246 PyObject
*py_session_info
;
247 struct gensec_security
*security
= pytalloc_get_type(self
, struct gensec_security
);
248 struct auth_session_info
*info
;
249 if (security
->ops
== NULL
) {
250 PyErr_SetString(PyExc_RuntimeError
, "no mechanism selected");
253 mem_ctx
= talloc_new(NULL
);
255 status
= gensec_session_info(security
, mem_ctx
, &info
);
256 if (NT_STATUS_IS_ERR(status
)) {
257 PyErr_SetNTSTATUS(status
);
261 py_session_info
= py_return_ndr_struct("samba.dcerpc.auth", "session_info",
263 talloc_free(mem_ctx
);
264 return py_session_info
;
267 static PyObject
*py_gensec_session_key(PyObject
*self
)
271 struct gensec_security
*security
= pytalloc_get_type(self
, struct gensec_security
);
272 DATA_BLOB session_key
= data_blob_null
;
273 static PyObject
*session_key_obj
= NULL
;
275 if (security
->ops
== NULL
) {
276 PyErr_SetString(PyExc_RuntimeError
, "no mechanism selected");
279 mem_ctx
= talloc_new(NULL
);
281 status
= gensec_session_key(security
, mem_ctx
, &session_key
);
282 if (!NT_STATUS_IS_OK(status
)) {
283 talloc_free(mem_ctx
);
284 PyErr_SetNTSTATUS(status
);
288 session_key_obj
= PyString_FromStringAndSize((const char *)session_key
.data
,
290 talloc_free(mem_ctx
);
291 return session_key_obj
;
294 static PyObject
*py_gensec_start_mech_by_name(PyObject
*self
, PyObject
*args
)
297 struct gensec_security
*security
= pytalloc_get_type(self
, struct gensec_security
);
300 if (!PyArg_ParseTuple(args
, "s", &name
))
303 status
= gensec_start_mech_by_name(security
, name
);
304 if (!NT_STATUS_IS_OK(status
)) {
305 PyErr_SetNTSTATUS(status
);
312 static PyObject
*py_gensec_start_mech_by_sasl_name(PyObject
*self
, PyObject
*args
)
315 struct gensec_security
*security
= pytalloc_get_type(self
, struct gensec_security
);
318 if (!PyArg_ParseTuple(args
, "s", &sasl_name
))
321 status
= gensec_start_mech_by_sasl_name(security
, sasl_name
);
322 if (!NT_STATUS_IS_OK(status
)) {
323 PyErr_SetNTSTATUS(status
);
330 static PyObject
*py_gensec_start_mech_by_authtype(PyObject
*self
, PyObject
*args
)
333 struct gensec_security
*security
= pytalloc_get_type(self
, struct gensec_security
);
335 if (!PyArg_ParseTuple(args
, "ii", &authtype
, &level
))
338 status
= gensec_start_mech_by_authtype(security
, authtype
, level
);
339 if (!NT_STATUS_IS_OK(status
)) {
340 PyErr_SetNTSTATUS(status
);
347 static PyObject
*py_gensec_want_feature(PyObject
*self
, PyObject
*args
)
350 struct gensec_security
*security
= pytalloc_get_type(self
, struct gensec_security
);
351 /* This is i (and declared as an int above) by design, as they are handled as an integer in python */
352 if (!PyArg_ParseTuple(args
, "i", &feature
))
355 gensec_want_feature(security
, feature
);
360 static PyObject
*py_gensec_have_feature(PyObject
*self
, PyObject
*args
)
363 struct gensec_security
*security
= pytalloc_get_type(self
, struct gensec_security
);
364 /* This is i (and declared as an int above) by design, as they are handled as an integer in python */
365 if (!PyArg_ParseTuple(args
, "i", &feature
))
368 if (gensec_have_feature(security
, feature
)) {
374 static PyObject
*py_gensec_set_max_update_size(PyObject
*self
, PyObject
*args
)
376 struct gensec_security
*security
= pytalloc_get_type(self
, struct gensec_security
);
377 unsigned int max_update_size
= 0;
379 if (!PyArg_ParseTuple(args
, "I", &max_update_size
))
382 gensec_set_max_update_size(security
, max_update_size
);
387 static PyObject
*py_gensec_max_update_size(PyObject
*self
)
389 struct gensec_security
*security
= pytalloc_get_type(self
, struct gensec_security
);
390 unsigned int max_update_size
= gensec_max_update_size(security
);
392 return PyInt_FromLong(max_update_size
);
395 static PyObject
*py_gensec_update(PyObject
*self
, PyObject
*args
)
400 PyObject
*ret
, *py_in
;
401 struct gensec_security
*security
= pytalloc_get_type(self
, struct gensec_security
);
402 PyObject
*finished_processing
;
403 struct tevent_context
*ev
;
405 if (!PyArg_ParseTuple(args
, "O", &py_in
))
408 mem_ctx
= talloc_new(NULL
);
410 if (!PyString_Check(py_in
)) {
411 PyErr_Format(PyExc_TypeError
, "expected a string");
415 in
.data
= (uint8_t *)PyString_AsString(py_in
);
416 in
.length
= PyString_Size(py_in
);
418 ev
= samba_tevent_context_init(mem_ctx
);
425 status
= gensec_update(security
, mem_ctx
, ev
, in
, &out
);
427 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)
428 && !NT_STATUS_IS_OK(status
)) {
429 PyErr_SetNTSTATUS(status
);
430 talloc_free(mem_ctx
);
433 ret
= PyString_FromStringAndSize((const char *)out
.data
, out
.length
);
434 talloc_free(mem_ctx
);
436 if (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
437 finished_processing
= Py_False
;
439 finished_processing
= Py_True
;
442 return PyTuple_Pack(2, finished_processing
, ret
);
445 static PyObject
*py_gensec_wrap(PyObject
*self
, PyObject
*args
)
451 PyObject
*ret
, *py_in
;
452 struct gensec_security
*security
= pytalloc_get_type(self
, struct gensec_security
);
454 if (!PyArg_ParseTuple(args
, "O", &py_in
))
457 mem_ctx
= talloc_new(NULL
);
459 if (!PyString_Check(py_in
)) {
460 PyErr_Format(PyExc_TypeError
, "expected a string");
463 in
.data
= (uint8_t *)PyString_AsString(py_in
);
464 in
.length
= PyString_Size(py_in
);
466 status
= gensec_wrap(security
, mem_ctx
, &in
, &out
);
468 if (!NT_STATUS_IS_OK(status
)) {
469 PyErr_SetNTSTATUS(status
);
470 talloc_free(mem_ctx
);
474 ret
= PyString_FromStringAndSize((const char *)out
.data
, out
.length
);
475 talloc_free(mem_ctx
);
479 static PyObject
*py_gensec_unwrap(PyObject
*self
, PyObject
*args
)
485 PyObject
*ret
, *py_in
;
486 struct gensec_security
*security
= pytalloc_get_type(self
, struct gensec_security
);
488 if (!PyArg_ParseTuple(args
, "O", &py_in
))
491 mem_ctx
= talloc_new(NULL
);
493 if (!PyString_Check(py_in
)) {
494 PyErr_Format(PyExc_TypeError
, "expected a string");
498 in
.data
= (uint8_t *)PyString_AsString(py_in
);
499 in
.length
= PyString_Size(py_in
);
501 status
= gensec_unwrap(security
, mem_ctx
, &in
, &out
);
503 if (!NT_STATUS_IS_OK(status
)) {
504 PyErr_SetNTSTATUS(status
);
505 talloc_free(mem_ctx
);
509 ret
= PyString_FromStringAndSize((const char *)out
.data
, out
.length
);
510 talloc_free(mem_ctx
);
514 static PyMethodDef py_gensec_security_methods
[] = {
515 { "start_client", (PyCFunction
)py_gensec_start_client
, METH_VARARGS
|METH_KEYWORDS
|METH_CLASS
,
516 "S.start_client(settings) -> gensec" },
517 { "start_server", (PyCFunction
)py_gensec_start_server
, METH_VARARGS
|METH_KEYWORDS
|METH_CLASS
,
518 "S.start_server(auth_ctx, settings) -> gensec" },
519 { "set_credentials", (PyCFunction
)py_gensec_set_credentials
, METH_VARARGS
,
520 "S.start_client(credentials)" },
521 { "session_info", (PyCFunction
)py_gensec_session_info
, METH_NOARGS
,
522 "S.session_info() -> info" },
523 { "session_key", (PyCFunction
)py_gensec_session_key
, METH_NOARGS
,
524 "S.session_key() -> key" },
525 { "start_mech_by_name", (PyCFunction
)py_gensec_start_mech_by_name
, METH_VARARGS
,
526 "S.start_mech_by_name(name)" },
527 { "start_mech_by_sasl_name", (PyCFunction
)py_gensec_start_mech_by_sasl_name
, METH_VARARGS
,
528 "S.start_mech_by_sasl_name(name)" },
529 { "start_mech_by_authtype", (PyCFunction
)py_gensec_start_mech_by_authtype
, METH_VARARGS
,
530 "S.start_mech_by_authtype(authtype, level)" },
531 { "get_name_by_authtype", (PyCFunction
)py_get_name_by_authtype
, METH_VARARGS
,
532 "S.get_name_by_authtype(authtype) -> name\nLookup an auth type." },
533 { "want_feature", (PyCFunction
)py_gensec_want_feature
, METH_VARARGS
,
534 "S.want_feature(feature)\n Request that GENSEC negotiate a particular feature." },
535 { "have_feature", (PyCFunction
)py_gensec_have_feature
, METH_VARARGS
,
536 "S.have_feature()\n Return True if GENSEC negotiated a particular feature." },
537 { "set_max_update_size", (PyCFunction
)py_gensec_set_max_update_size
, METH_VARARGS
,
538 "S.set_max_update_size(max_size) \n Some mechs can fragment update packets, needs to be use before the mech is started." },
539 { "max_update_size", (PyCFunction
)py_gensec_max_update_size
, 0,
540 "S.max_update_size() \n Return the current max_update_size." },
541 { "update", (PyCFunction
)py_gensec_update
, METH_VARARGS
,
542 "S.update(blob_in) -> (finished, blob_out)\nPerform one step in a GENSEC dance. Repeat with new packets until finished is true or exception." },
543 { "wrap", (PyCFunction
)py_gensec_wrap
, METH_VARARGS
,
544 "S.wrap(blob_in) -> blob_out\nPackage one clear packet into a wrapped GENSEC packet." },
545 { "unwrap", (PyCFunction
)py_gensec_unwrap
, METH_VARARGS
,
546 "S.unwrap(blob_in) -> blob_out\nPerform one wrapped GENSEC packet into a clear packet." },
550 static PyTypeObject Py_Security
= {
551 .tp_name
= "gensec.Security",
552 .tp_flags
= Py_TPFLAGS_DEFAULT
,
553 .tp_methods
= py_gensec_security_methods
,
554 .tp_basicsize
= sizeof(pytalloc_Object
),
557 void initgensec(void);
558 void initgensec(void)
562 Py_Security
.tp_base
= pytalloc_GetObjectType();
563 if (Py_Security
.tp_base
== NULL
)
566 if (PyType_Ready(&Py_Security
) < 0)
569 m
= Py_InitModule3("gensec", NULL
, "Generic Security Interface.");
573 PyModule_AddObject(m
, "FEATURE_SESSION_KEY", PyInt_FromLong(GENSEC_FEATURE_SESSION_KEY
));
574 PyModule_AddObject(m
, "FEATURE_SIGN", PyInt_FromLong(GENSEC_FEATURE_SIGN
));
575 PyModule_AddObject(m
, "FEATURE_SEAL", PyInt_FromLong(GENSEC_FEATURE_SEAL
));
576 PyModule_AddObject(m
, "FEATURE_DCE_STYLE", PyInt_FromLong(GENSEC_FEATURE_DCE_STYLE
));
577 PyModule_AddObject(m
, "FEATURE_ASYNC_REPLIES", PyInt_FromLong(GENSEC_FEATURE_ASYNC_REPLIES
));
578 PyModule_AddObject(m
, "FEATURE_DATAGRAM_MODE", PyInt_FromLong(GENSEC_FEATURE_DATAGRAM_MODE
));
579 PyModule_AddObject(m
, "FEATURE_SIGN_PKT_HEADER", PyInt_FromLong(GENSEC_FEATURE_SIGN_PKT_HEADER
));
580 PyModule_AddObject(m
, "FEATURE_NEW_SPNEGO", PyInt_FromLong(GENSEC_FEATURE_NEW_SPNEGO
));
582 Py_INCREF(&Py_Security
);
583 PyModule_AddObject(m
, "Security", (PyObject
*)&Py_Security
);