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"
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
;
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
= (pytalloc_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 pytalloc_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
= (pytalloc_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
= pytalloc_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(pytalloc_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
= pytalloc_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(pytalloc_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
)
262 PyObject
*py_session_info
;
263 struct gensec_security
*security
= pytalloc_get_type(self
, struct gensec_security
);
264 struct auth_session_info
*info
;
265 if (security
->ops
== NULL
) {
266 PyErr_SetString(PyExc_RuntimeError
, "no mechanism selected");
269 mem_ctx
= talloc_new(NULL
);
271 status
= gensec_session_info(security
, mem_ctx
, &info
);
272 if (NT_STATUS_IS_ERR(status
)) {
273 PyErr_SetNTSTATUS(status
);
277 py_session_info
= py_return_ndr_struct("samba.dcerpc.auth", "session_info",
279 talloc_free(mem_ctx
);
280 return py_session_info
;
283 static PyObject
*py_gensec_start_mech_by_name(PyObject
*self
, PyObject
*args
)
286 struct gensec_security
*security
= pytalloc_get_type(self
, struct gensec_security
);
289 if (!PyArg_ParseTuple(args
, "s", &name
))
292 status
= gensec_start_mech_by_name(security
, name
);
293 if (!NT_STATUS_IS_OK(status
)) {
294 PyErr_SetNTSTATUS(status
);
301 static PyObject
*py_gensec_start_mech_by_sasl_name(PyObject
*self
, PyObject
*args
)
304 struct gensec_security
*security
= pytalloc_get_type(self
, struct gensec_security
);
307 if (!PyArg_ParseTuple(args
, "s", &sasl_name
))
310 status
= gensec_start_mech_by_sasl_name(security
, sasl_name
);
311 if (!NT_STATUS_IS_OK(status
)) {
312 PyErr_SetNTSTATUS(status
);
319 static PyObject
*py_gensec_start_mech_by_authtype(PyObject
*self
, PyObject
*args
)
322 struct gensec_security
*security
= pytalloc_get_type(self
, struct gensec_security
);
324 if (!PyArg_ParseTuple(args
, "ii", &authtype
, &level
))
327 status
= gensec_start_mech_by_authtype(security
, authtype
, level
);
328 if (!NT_STATUS_IS_OK(status
)) {
329 PyErr_SetNTSTATUS(status
);
336 static PyObject
*py_gensec_want_feature(PyObject
*self
, PyObject
*args
)
339 struct gensec_security
*security
= pytalloc_get_type(self
, struct gensec_security
);
340 /* This is i (and declared as an int above) by design, as they are handled as an integer in python */
341 if (!PyArg_ParseTuple(args
, "i", &feature
))
344 gensec_want_feature(security
, feature
);
349 static PyObject
*py_gensec_have_feature(PyObject
*self
, PyObject
*args
)
352 struct gensec_security
*security
= pytalloc_get_type(self
, struct gensec_security
);
353 /* This is i (and declared as an int above) by design, as they are handled as an integer in python */
354 if (!PyArg_ParseTuple(args
, "i", &feature
))
357 if (gensec_have_feature(security
, feature
)) {
363 static PyObject
*py_gensec_update(PyObject
*self
, PyObject
*args
)
368 PyObject
*ret
, *py_in
;
369 struct gensec_security
*security
= pytalloc_get_type(self
, struct gensec_security
);
370 PyObject
*finished_processing
;
372 if (!PyArg_ParseTuple(args
, "O", &py_in
))
375 mem_ctx
= talloc_new(NULL
);
377 if (!PyString_Check(py_in
)) {
378 PyErr_Format(PyExc_TypeError
, "expected a string");
382 in
.data
= (uint8_t *)PyString_AsString(py_in
);
383 in
.length
= PyString_Size(py_in
);
385 status
= gensec_update(security
, mem_ctx
, in
, &out
);
387 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)
388 && !NT_STATUS_IS_OK(status
)) {
389 PyErr_SetNTSTATUS(status
);
390 talloc_free(mem_ctx
);
393 ret
= PyString_FromStringAndSize((const char *)out
.data
, out
.length
);
394 talloc_free(mem_ctx
);
396 if (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
397 finished_processing
= Py_False
;
399 finished_processing
= Py_True
;
402 return PyTuple_Pack(2, finished_processing
, ret
);
405 static PyObject
*py_gensec_wrap(PyObject
*self
, PyObject
*args
)
411 PyObject
*ret
, *py_in
;
412 struct gensec_security
*security
= pytalloc_get_type(self
, struct gensec_security
);
414 if (!PyArg_ParseTuple(args
, "O", &py_in
))
417 mem_ctx
= talloc_new(NULL
);
419 if (!PyString_Check(py_in
)) {
420 PyErr_Format(PyExc_TypeError
, "expected a string");
423 in
.data
= (uint8_t *)PyString_AsString(py_in
);
424 in
.length
= PyString_Size(py_in
);
426 status
= gensec_wrap(security
, mem_ctx
, &in
, &out
);
428 if (!NT_STATUS_IS_OK(status
)) {
429 PyErr_SetNTSTATUS(status
);
430 talloc_free(mem_ctx
);
434 ret
= PyString_FromStringAndSize((const char *)out
.data
, out
.length
);
435 talloc_free(mem_ctx
);
439 static PyObject
*py_gensec_unwrap(PyObject
*self
, PyObject
*args
)
445 PyObject
*ret
, *py_in
;
446 struct gensec_security
*security
= pytalloc_get_type(self
, struct gensec_security
);
448 if (!PyArg_ParseTuple(args
, "O", &py_in
))
451 mem_ctx
= talloc_new(NULL
);
453 if (!PyString_Check(py_in
)) {
454 PyErr_Format(PyExc_TypeError
, "expected a string");
458 in
.data
= (uint8_t *)PyString_AsString(py_in
);
459 in
.length
= PyString_Size(py_in
);
461 status
= gensec_unwrap(security
, mem_ctx
, &in
, &out
);
463 if (!NT_STATUS_IS_OK(status
)) {
464 PyErr_SetNTSTATUS(status
);
465 talloc_free(mem_ctx
);
469 ret
= PyString_FromStringAndSize((const char *)out
.data
, out
.length
);
470 talloc_free(mem_ctx
);
474 static PyMethodDef py_gensec_security_methods
[] = {
475 { "start_client", (PyCFunction
)py_gensec_start_client
, METH_VARARGS
|METH_KEYWORDS
|METH_CLASS
,
476 "S.start_client(settings) -> gensec" },
477 { "start_server", (PyCFunction
)py_gensec_start_server
, METH_VARARGS
|METH_KEYWORDS
|METH_CLASS
,
478 "S.start_server(auth_ctx, settings) -> gensec" },
479 { "set_credentials", (PyCFunction
)py_gensec_set_credentials
, METH_VARARGS
,
480 "S.start_client(credentials)" },
481 { "session_info", (PyCFunction
)py_gensec_session_info
, METH_NOARGS
,
482 "S.session_info() -> info" },
483 { "start_mech_by_name", (PyCFunction
)py_gensec_start_mech_by_name
, METH_VARARGS
,
484 "S.start_mech_by_name(name)" },
485 { "start_mech_by_sasl_name", (PyCFunction
)py_gensec_start_mech_by_sasl_name
, METH_VARARGS
,
486 "S.start_mech_by_sasl_name(name)" },
487 { "start_mech_by_authtype", (PyCFunction
)py_gensec_start_mech_by_authtype
, METH_VARARGS
, "S.start_mech_by_authtype(authtype, level)" },
488 { "get_name_by_authtype", (PyCFunction
)py_get_name_by_authtype
, METH_VARARGS
,
489 "S.get_name_by_authtype(authtype) -> name\nLookup an auth type." },
490 { "want_feature", (PyCFunction
)py_gensec_want_feature
, METH_VARARGS
,
491 "S.want_feature(feature)\n Request that GENSEC negotiate a particular feature." },
492 { "have_feature", (PyCFunction
)py_gensec_have_feature
, METH_VARARGS
,
493 "S.have_feature()\n Return True if GENSEC negotiated a particular feature." },
494 { "update", (PyCFunction
)py_gensec_update
, METH_VARARGS
,
495 "S.update(blob_in) -> (finished, blob_out)\nPerform one step in a GENSEC dance. Repeat with new packets until finished is true or exception." },
496 { "wrap", (PyCFunction
)py_gensec_wrap
, METH_VARARGS
,
497 "S.wrap(blob_in) -> blob_out\nPackage one clear packet into a wrapped GENSEC packet." },
498 { "unwrap", (PyCFunction
)py_gensec_unwrap
, METH_VARARGS
,
499 "S.unwrap(blob_in) -> blob_out\nPerform one wrapped GENSEC packet into a clear packet." },
504 static PyTypeObject Py_Security
= {
505 .tp_name
= "gensec.Security",
506 .tp_flags
= Py_TPFLAGS_DEFAULT
,
507 .tp_methods
= py_gensec_security_methods
,
508 .tp_basicsize
= sizeof(pytalloc_Object
),
511 void initgensec(void);
512 void initgensec(void)
516 Py_Security
.tp_base
= pytalloc_GetObjectType();
517 if (Py_Security
.tp_base
== NULL
)
520 if (PyType_Ready(&Py_Security
) < 0)
523 m
= Py_InitModule3("gensec", NULL
, "Generic Security Interface.");
527 PyModule_AddObject(m
, "FEATURE_SESSION_KEY", PyInt_FromLong(GENSEC_FEATURE_SESSION_KEY
));
528 PyModule_AddObject(m
, "FEATURE_SIGN", PyInt_FromLong(GENSEC_FEATURE_SIGN
));
529 PyModule_AddObject(m
, "FEATURE_SEAL", PyInt_FromLong(GENSEC_FEATURE_SEAL
));
530 PyModule_AddObject(m
, "FEATURE_DCE_STYLE", PyInt_FromLong(GENSEC_FEATURE_DCE_STYLE
));
531 PyModule_AddObject(m
, "FEATURE_ASYNC_REPLIES", PyInt_FromLong(GENSEC_FEATURE_ASYNC_REPLIES
));
532 PyModule_AddObject(m
, "FEATURE_DATAGRAM_MODE", PyInt_FromLong(GENSEC_FEATURE_DATAGRAM_MODE
));
533 PyModule_AddObject(m
, "FEATURE_SIGN_PKT_HEADER", PyInt_FromLong(GENSEC_FEATURE_SIGN_PKT_HEADER
));
534 PyModule_AddObject(m
, "FEATURE_NEW_SPNEGO", PyInt_FromLong(GENSEC_FEATURE_NEW_SPNEGO
));
536 Py_INCREF(&Py_Security
);
537 PyModule_AddObject(m
, "Security", (PyObject
*)&Py_Security
);