summaryrefslogtreecommitdiff
path: root/source4/auth
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2011-01-18 19:14:45 +1100
committerAndrew Bartlett <abartlet@samba.org>2011-01-18 11:41:26 +0100
commita1e1f02efea3a6c1f419a7d93498718d46636d2b (patch)
tree1eb6102caf0c0e134d07c19148934f03585a7ba0 /source4/auth
parent24a4b9a7387f75c6d6a922800bef9b2178747f86 (diff)
downloadsamba-a1e1f02efea3a6c1f419a7d93498718d46636d2b.tar.gz
samba-a1e1f02efea3a6c1f419a7d93498718d46636d2b.tar.bz2
samba-a1e1f02efea3a6c1f419a7d93498718d46636d2b.zip
s4-gensec Extend python bindings for GENSEC and the associated test
This now tests a real GENSEC exchange, including wrap and unwrap, using GSSAPI. Therefore, it now needs to access a KDC. Andrew Bartlett Autobuild-User: Andrew Bartlett <abartlet@samba.org> Autobuild-Date: Tue Jan 18 11:41:26 CET 2011 on sn-devel-104
Diffstat (limited to 'source4/auth')
-rw-r--r--source4/auth/gensec/pygensec.c244
1 files changed, 223 insertions, 21 deletions
diff --git a/source4/auth/gensec/pygensec.c b/source4/auth/gensec/pygensec.c
index 80fdd728e0..da62018eeb 100644
--- a/source4/auth/gensec/pygensec.c
+++ b/source4/auth/gensec/pygensec.c
@@ -20,6 +20,7 @@
#include "includes.h"
#include "param/pyparam.h"
#include "auth/gensec/gensec.h"
+#include "auth/credentials/pycredentials.h"
#include "libcli/util/pyerrors.h"
#include "scripting/python/modules.h"
#include "lib/talloc/pytalloc.h"
@@ -84,7 +85,7 @@ static PyObject *py_gensec_start_client(PyTypeObject *type, PyObject *args, PyOb
struct tevent_context *ev;
struct gensec_security *gensec;
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O", discard_const_p(char *, kwnames), &py_settings))
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", discard_const_p(char *, kwnames), &py_settings))
return NULL;
self = (py_talloc_Object*)type->tp_alloc(type, 0);
@@ -98,10 +99,20 @@ static PyObject *py_gensec_start_client(PyTypeObject *type, PyObject *args, PyOb
return NULL;
}
- settings = settings_from_object(self->talloc_ctx, py_settings);
- if (settings == NULL) {
- PyObject_DEL(self);
- return NULL;
+ if (py_settings != Py_None) {
+ settings = settings_from_object(self->talloc_ctx, py_settings);
+ if (settings == NULL) {
+ PyObject_DEL(self);
+ return NULL;
+ }
+ } else {
+ settings = talloc_zero(self->talloc_ctx, struct gensec_settings);
+ if (settings == NULL) {
+ PyObject_DEL(self);
+ return NULL;
+ }
+
+ settings->lp_ctx = loadparm_init_global(true);
}
ev = tevent_context_init(self->talloc_ctx);
@@ -134,15 +145,15 @@ static PyObject *py_gensec_start_server(PyTypeObject *type, PyObject *args, PyOb
{
NTSTATUS status;
py_talloc_Object *self;
- struct gensec_settings *settings;
- const char *kwnames[] = { "auth_context", "settings", NULL };
- PyObject *py_settings;
- PyObject *py_auth_context;
+ struct gensec_settings *settings = NULL;
+ const char *kwnames[] = { "settings", "auth_context", NULL };
+ PyObject *py_settings = Py_None;
+ PyObject *py_auth_context = Py_None;
struct tevent_context *ev;
struct gensec_security *gensec;
- struct auth_context *auth_context;
+ struct auth_context *auth_context = NULL;
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO", discard_const_p(char *, kwnames), &py_auth_context, &py_settings))
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OO", discard_const_p(char *, kwnames), &py_settings, &py_auth_context))
return NULL;
self = (py_talloc_Object*)type->tp_alloc(type, 0);
@@ -156,10 +167,20 @@ static PyObject *py_gensec_start_server(PyTypeObject *type, PyObject *args, PyOb
return NULL;
}
- settings = settings_from_object(self->talloc_ctx, py_settings);
- if (settings == NULL) {
- PyObject_DEL(self);
- return NULL;
+ if (py_settings != Py_None) {
+ settings = settings_from_object(self->talloc_ctx, py_settings);
+ if (settings == NULL) {
+ PyObject_DEL(self);
+ return NULL;
+ }
+ } else {
+ settings = talloc_zero(self->talloc_ctx, struct gensec_settings);
+ if (settings == NULL) {
+ PyObject_DEL(self);
+ return NULL;
+ }
+
+ settings->lp_ctx = loadparm_init_global(true);
}
ev = tevent_context_init(self->talloc_ctx);
@@ -169,7 +190,15 @@ static PyObject *py_gensec_start_server(PyTypeObject *type, PyObject *args, PyOb
return NULL;
}
- auth_context = py_talloc_get_type(self, struct auth_context);
+ if (py_auth_context != Py_None) {
+ auth_context = py_talloc_get_type(py_auth_context, struct auth_context);
+ if (!auth_context) {
+ PyErr_Format(PyExc_TypeError,
+ "Expected auth.AuthContext for auth_context argument, got %s",
+ talloc_get_name(py_talloc_get_ptr(py_auth_context)));
+ return NULL;
+ }
+ }
status = gensec_init(settings->lp_ctx);
if (!NT_STATUS_IS_OK(status)) {
@@ -190,6 +219,32 @@ static PyObject *py_gensec_start_server(PyTypeObject *type, PyObject *args, PyOb
return (PyObject *)self;
}
+static PyObject *py_gensec_set_credentials(PyObject *self, PyObject *args)
+{
+ PyObject *py_creds = Py_None;
+ struct cli_credentials *creds;
+ struct gensec_security *security = py_talloc_get_type(self, struct gensec_security);
+ NTSTATUS status;
+
+ if (!PyArg_ParseTuple(args, "O", &py_creds))
+ return NULL;
+
+ creds = PyCredentials_AsCliCredentials(py_creds);
+ if (!creds) {
+ PyErr_Format(PyExc_TypeError,
+ "Expected samba.credentaials for credentials argument got %s",
+ talloc_get_name(py_talloc_get_ptr(py_creds)));
+ }
+
+ status = gensec_set_credentials(security, creds);
+ if (!NT_STATUS_IS_OK(status)) {
+ PyErr_SetNTSTATUS(status);
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
static PyObject *py_gensec_session_info(PyObject *self)
{
NTSTATUS status;
@@ -206,7 +261,7 @@ static PyObject *py_gensec_session_info(PyObject *self)
return NULL;
}
- py_session_info = py_return_ndr_struct("samba.auth", "session_info",
+ py_session_info = py_return_ndr_struct("samba.auth", "AuthSession",
info, info);
return py_session_info;
}
@@ -229,6 +284,24 @@ static PyObject *py_gensec_start_mech_by_name(PyObject *self, PyObject *args)
Py_RETURN_NONE;
}
+static PyObject *py_gensec_start_mech_by_sasl_name(PyObject *self, PyObject *args)
+{
+ char *sasl_name;
+ struct gensec_security *security = py_talloc_get_type(self, struct gensec_security);
+ NTSTATUS status;
+
+ if (!PyArg_ParseTuple(args, "s", &sasl_name))
+ return NULL;
+
+ status = gensec_start_mech_by_sasl_name(security, sasl_name);
+ if (!NT_STATUS_IS_OK(status)) {
+ PyErr_SetNTSTATUS(status);
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
static PyObject *py_gensec_start_mech_by_authtype(PyObject *self, PyObject *args)
{
int authtype, level;
@@ -246,6 +319,33 @@ static PyObject *py_gensec_start_mech_by_authtype(PyObject *self, PyObject *args
Py_RETURN_NONE;
}
+static PyObject *py_gensec_want_feature(PyObject *self, PyObject *args)
+{
+ int feature;
+ struct gensec_security *security = py_talloc_get_type(self, struct gensec_security);
+ /* This is i (and declared as an int above) by design, as they are handled as an integer in python */
+ if (!PyArg_ParseTuple(args, "i", &feature))
+ return NULL;
+
+ gensec_want_feature(security, feature);
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *py_gensec_have_feature(PyObject *self, PyObject *args)
+{
+ int feature;
+ struct gensec_security *security = py_talloc_get_type(self, struct gensec_security);
+ /* This is i (and declared as an int above) by design, as they are handled as an integer in python */
+ if (!PyArg_ParseTuple(args, "i", &feature))
+ return NULL;
+
+ if (gensec_have_feature(security, feature)) {
+ return Py_True;
+ }
+ return Py_False;
+}
+
static PyObject *py_gensec_update(PyObject *self, PyObject *args)
{
NTSTATUS status;
@@ -260,18 +360,107 @@ static PyObject *py_gensec_update(PyObject *self, PyObject *args)
mem_ctx = talloc_new(NULL);
- in.data = (uint8_t *)PyString_AsString(py_in);
- in.length = PyString_Size(py_in);
+ if (py_in == Py_None) {
+ in = data_blob_null;
+ } else {
+ in.data = (uint8_t *)PyString_AsString(py_in);
+ in.length = PyString_Size(py_in);
+ }
status = gensec_update(security, mem_ctx, in, &out);
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)
+ && !NT_STATUS_IS_OK(status)) {
+ PyErr_SetNTSTATUS(status);
+ talloc_free(mem_ctx);
+ return NULL;
+ }
+ if (out.length != 0) {
+ ret = PyString_FromStringAndSize((const char *)out.data, out.length);
+ } else {
+ ret = Py_None;
+ }
+ talloc_free(mem_ctx);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
+ {
+ return PyTuple_Pack(2, Py_False, ret);
+ } else {
+ return PyTuple_Pack(2, Py_True, ret);
+ }
+}
+
+static PyObject *py_gensec_wrap(PyObject *self, PyObject *args)
+{
+ NTSTATUS status;
+
+ TALLOC_CTX *mem_ctx;
+ DATA_BLOB in, out;
+ PyObject *ret, *py_in;
+ struct gensec_security *security = py_talloc_get_type(self, struct gensec_security);
+
+ if (!PyArg_ParseTuple(args, "O", &py_in))
+ return NULL;
+
+ mem_ctx = talloc_new(NULL);
+
+ if (py_in == Py_None) {
+ in = data_blob_null;
+ } else {
+ in.data = (uint8_t *)PyString_AsString(py_in);
+ in.length = PyString_Size(py_in);
+ }
+
+ status = gensec_wrap(security, mem_ctx, &in, &out);
+
if (!NT_STATUS_IS_OK(status)) {
PyErr_SetNTSTATUS(status);
talloc_free(mem_ctx);
return NULL;
}
- ret = PyString_FromStringAndSize((const char *)out.data, out.length);
+ if (out.length != 0) {
+ ret = PyString_FromStringAndSize((const char *)out.data, out.length);
+ } else {
+ ret = Py_None;
+ }
+ talloc_free(mem_ctx);
+ return ret;
+}
+
+static PyObject *py_gensec_unwrap(PyObject *self, PyObject *args)
+{
+ NTSTATUS status;
+
+ TALLOC_CTX *mem_ctx;
+ DATA_BLOB in, out;
+ PyObject *ret, *py_in;
+ struct gensec_security *security = py_talloc_get_type(self, struct gensec_security);
+
+ if (!PyArg_ParseTuple(args, "O", &py_in))
+ return NULL;
+
+ mem_ctx = talloc_new(NULL);
+
+ if (py_in == Py_None) {
+ in = data_blob_null;
+ } else {
+ in.data = (uint8_t *)PyString_AsString(py_in);
+ in.length = PyString_Size(py_in);
+ }
+
+ status = gensec_unwrap(security, mem_ctx, &in, &out);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ PyErr_SetNTSTATUS(status);
+ talloc_free(mem_ctx);
+ return NULL;
+ }
+
+ if (out.length != 0) {
+ ret = PyString_FromStringAndSize((const char *)out.data, out.length);
+ } else {
+ ret = Py_None;
+ }
talloc_free(mem_ctx);
return ret;
}
@@ -281,15 +470,28 @@ static PyMethodDef py_gensec_security_methods[] = {
"S.start_client(settings) -> gensec" },
{ "start_server", (PyCFunction)py_gensec_start_server, METH_VARARGS|METH_KEYWORDS|METH_CLASS,
"S.start_server(auth_ctx, settings) -> gensec" },
+ { "set_credentials", (PyCFunction)py_gensec_set_credentials, METH_VARARGS,
+ "S.start_client(credentials)" },
{ "session_info", (PyCFunction)py_gensec_session_info, METH_NOARGS,
"S.session_info() -> info" },
{ "start_mech_by_name", (PyCFunction)py_gensec_start_mech_by_name, METH_VARARGS,
"S.start_mech_by_name(name)" },
+ { "start_mech_by_sasl_name", (PyCFunction)py_gensec_start_mech_by_sasl_name, METH_VARARGS,
+ "S.start_mech_by_sasl_name(name)" },
{ "start_mech_by_authtype", (PyCFunction)py_gensec_start_mech_by_authtype, METH_VARARGS, "S.start_mech_by_authtype(authtype, level)" },
{ "get_name_by_authtype", (PyCFunction)py_get_name_by_authtype, METH_VARARGS,
"S.get_name_by_authtype(authtype) -> name\nLookup an auth type." },
+ { "want_feature", (PyCFunction)py_gensec_want_feature, METH_VARARGS,
+ "S.want_feature(feature)\n Request that GENSEC negotiate a particular feature." },
+ { "have_feature", (PyCFunction)py_gensec_have_feature, METH_VARARGS,
+ "S.have_feature()\n Return True if GENSEC negotiated a particular feature." },
{ "update", (PyCFunction)py_gensec_update, METH_VARARGS,
- "S.update(blob_in) -> blob_out\nPerform one step in a GENSEC dance." },
+ "S.update(blob_in) -> (finished, blob_out)\nPerform one step in a GENSEC dance. Repeat with new packets until finished is true or exception." },
+ { "wrap", (PyCFunction)py_gensec_wrap, METH_VARARGS,
+ "S.wrap(blob_in) -> blob_out\nPackage one clear packet into a wrapped GENSEC packet." },
+ { "unwrap", (PyCFunction)py_gensec_unwrap, METH_VARARGS,
+ "S.unwrap(blob_in) -> blob_out\nPerform one wrapped GENSEC packet into a clear packet." },
+
{ NULL }
};