mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
3544f1b5d2
With the changes to make samba python code Py2/Py3 compatible there now are many instances where string content is decoded. Decoded string variables in Py2 are returned as the unicode type. Many Py2 c-module functions that take string arguments only check for the string type. However now it's quite possibe the content formally passed as a string argument is now passed as unicode after being decoded, such arguments are rejected and code can fail subtly. This only affects places where the type is directly checked e.g. via PyStr_Check etc. arguments that are parsed by ParseTuple* functions generally already accept both string and unicode (if 's', 'z', 's*' format specifiers are used) Signed-off-by: Noel Power <noel.power@suse.com> Reviewed-by: Alexander Bokovoy <ab@samba.org>
340 lines
8.6 KiB
C
340 lines
8.6 KiB
C
/*
|
|
Unix SMB/CIFS implementation.
|
|
Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2008
|
|
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2011
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <Python.h>
|
|
#include "python/py3compat.h"
|
|
#include "includes.h"
|
|
#include "libcli/util/pyerrors.h"
|
|
#include "param/param.h"
|
|
#include "pyauth.h"
|
|
#include "pyldb.h"
|
|
#include "auth/system_session_proto.h"
|
|
#include "auth/auth.h"
|
|
#include "param/pyparam.h"
|
|
#include "libcli/security/security.h"
|
|
#include "auth/credentials/pycredentials.h"
|
|
#include <tevent.h>
|
|
#include "librpc/rpc/pyrpc_util.h"
|
|
#include "lib/events/events.h"
|
|
|
|
static PyTypeObject PyAuthContext;
|
|
|
|
static PyObject *PyAuthSession_FromSession(struct auth_session_info *session)
|
|
{
|
|
return py_return_ndr_struct("samba.dcerpc.auth", "session_info", session, session);
|
|
}
|
|
|
|
static PyObject *py_system_session(PyObject *module, PyObject *args)
|
|
{
|
|
PyObject *py_lp_ctx = Py_None;
|
|
struct loadparm_context *lp_ctx = NULL;
|
|
struct auth_session_info *session;
|
|
TALLOC_CTX *mem_ctx;
|
|
if (!PyArg_ParseTuple(args, "|O", &py_lp_ctx))
|
|
return NULL;
|
|
|
|
mem_ctx = talloc_new(NULL);
|
|
if (mem_ctx == NULL) {
|
|
PyErr_NoMemory();
|
|
return NULL;
|
|
}
|
|
|
|
lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
|
|
if (lp_ctx == NULL) {
|
|
talloc_free(mem_ctx);
|
|
return NULL;
|
|
}
|
|
|
|
session = system_session(lp_ctx);
|
|
|
|
talloc_free(mem_ctx);
|
|
|
|
return PyAuthSession_FromSession(session);
|
|
}
|
|
|
|
|
|
static PyObject *py_admin_session(PyObject *module, PyObject *args)
|
|
{
|
|
PyObject *py_lp_ctx;
|
|
const char *sid;
|
|
struct loadparm_context *lp_ctx = NULL;
|
|
struct auth_session_info *session;
|
|
struct dom_sid *domain_sid = NULL;
|
|
TALLOC_CTX *mem_ctx;
|
|
|
|
if (!PyArg_ParseTuple(args, "Os", &py_lp_ctx, &sid))
|
|
return NULL;
|
|
|
|
mem_ctx = talloc_new(NULL);
|
|
if (mem_ctx == NULL) {
|
|
PyErr_NoMemory();
|
|
return NULL;
|
|
}
|
|
|
|
lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
|
|
if (lp_ctx == NULL) {
|
|
talloc_free(mem_ctx);
|
|
return NULL;
|
|
}
|
|
|
|
domain_sid = dom_sid_parse_talloc(mem_ctx, sid);
|
|
if (domain_sid == NULL) {
|
|
PyErr_Format(PyExc_RuntimeError, "Unable to parse sid %s", sid);
|
|
talloc_free(mem_ctx);
|
|
return NULL;
|
|
}
|
|
session = admin_session(NULL, lp_ctx, domain_sid);
|
|
talloc_free(mem_ctx);
|
|
|
|
return PyAuthSession_FromSession(session);
|
|
}
|
|
|
|
static PyObject *py_user_session(PyObject *module, PyObject *args, PyObject *kwargs)
|
|
{
|
|
NTSTATUS nt_status;
|
|
struct auth_session_info *session;
|
|
TALLOC_CTX *mem_ctx;
|
|
const char * const kwnames[] = { "ldb", "lp_ctx", "principal", "dn", "session_info_flags", NULL };
|
|
struct ldb_context *ldb_ctx;
|
|
PyObject *py_ldb = Py_None;
|
|
PyObject *py_dn = Py_None;
|
|
PyObject *py_lp_ctx = Py_None;
|
|
struct loadparm_context *lp_ctx = NULL;
|
|
struct ldb_dn *user_dn;
|
|
char *principal = NULL;
|
|
int session_info_flags = 0; /* This is an int, because that's
|
|
* what we need for the python
|
|
* PyArg_ParseTupleAndKeywords */
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OzOi",
|
|
discard_const_p(char *, kwnames),
|
|
&py_ldb, &py_lp_ctx, &principal, &py_dn, &session_info_flags)) {
|
|
return NULL;
|
|
}
|
|
|
|
mem_ctx = talloc_new(NULL);
|
|
if (mem_ctx == NULL) {
|
|
PyErr_NoMemory();
|
|
return NULL;
|
|
}
|
|
|
|
ldb_ctx = pyldb_Ldb_AsLdbContext(py_ldb);
|
|
|
|
if (py_dn == Py_None) {
|
|
user_dn = NULL;
|
|
} else {
|
|
if (!pyldb_Object_AsDn(ldb_ctx, py_dn, ldb_ctx, &user_dn)) {
|
|
talloc_free(mem_ctx);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
|
|
if (lp_ctx == NULL) {
|
|
talloc_free(mem_ctx);
|
|
return NULL;
|
|
}
|
|
|
|
nt_status = authsam_get_session_info_principal(mem_ctx, lp_ctx, ldb_ctx, principal, user_dn,
|
|
session_info_flags, &session);
|
|
if (!NT_STATUS_IS_OK(nt_status)) {
|
|
talloc_free(mem_ctx);
|
|
PyErr_NTSTATUS_IS_ERR_RAISE(nt_status);
|
|
}
|
|
|
|
talloc_steal(NULL, session);
|
|
talloc_free(mem_ctx);
|
|
|
|
return PyAuthSession_FromSession(session);
|
|
}
|
|
|
|
|
|
static const char **PyList_AsStringList(TALLOC_CTX *mem_ctx, PyObject *list,
|
|
const char *paramname)
|
|
{
|
|
const char **ret;
|
|
Py_ssize_t i;
|
|
if (!PyList_Check(list)) {
|
|
PyErr_Format(PyExc_TypeError, "%s is not a list", paramname);
|
|
return NULL;
|
|
}
|
|
ret = talloc_array(NULL, const char *, PyList_Size(list)+1);
|
|
if (ret == NULL) {
|
|
PyErr_NoMemory();
|
|
return NULL;
|
|
}
|
|
|
|
for (i = 0; i < PyList_Size(list); i++) {
|
|
const char *value;
|
|
Py_ssize_t size;
|
|
PyObject *item = PyList_GetItem(list, i);
|
|
if (!(PyStr_Check(item) || PyUnicode_Check(item))) {
|
|
PyErr_Format(PyExc_TypeError, "%s should be strings", paramname);
|
|
return NULL;
|
|
}
|
|
value = PyStr_AsUTF8AndSize(item, &size);
|
|
if (value == NULL) {
|
|
talloc_free(ret);
|
|
return NULL;
|
|
}
|
|
ret[i] = talloc_strndup(ret, value, size);
|
|
}
|
|
ret[i] = NULL;
|
|
return ret;
|
|
}
|
|
|
|
static PyObject *PyAuthContext_FromContext(struct auth4_context *auth_context)
|
|
{
|
|
return pytalloc_reference(&PyAuthContext, auth_context);
|
|
}
|
|
|
|
static PyObject *py_auth_context_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
|
|
{
|
|
PyObject *py_lp_ctx = Py_None;
|
|
PyObject *py_ldb = Py_None;
|
|
PyObject *py_imessaging_ctx = Py_None;
|
|
PyObject *py_auth_context = Py_None;
|
|
PyObject *py_methods = Py_None;
|
|
TALLOC_CTX *mem_ctx;
|
|
struct auth4_context *auth_context;
|
|
struct imessaging_context *imessaging_context = NULL;
|
|
struct loadparm_context *lp_ctx;
|
|
struct tevent_context *ev;
|
|
struct ldb_context *ldb = NULL;
|
|
NTSTATUS nt_status;
|
|
const char **methods;
|
|
|
|
const char * const kwnames[] = { "lp_ctx", "messaging_ctx", "ldb", "methods", NULL };
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOOO",
|
|
discard_const_p(char *, kwnames),
|
|
&py_lp_ctx, &py_imessaging_ctx, &py_ldb, &py_methods))
|
|
return NULL;
|
|
|
|
mem_ctx = talloc_new(NULL);
|
|
if (mem_ctx == NULL) {
|
|
PyErr_NoMemory();
|
|
return NULL;
|
|
}
|
|
|
|
if (py_ldb != Py_None) {
|
|
ldb = pyldb_Ldb_AsLdbContext(py_ldb);
|
|
}
|
|
|
|
lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
|
|
if (lp_ctx == NULL) {
|
|
PyErr_NoMemory();
|
|
return NULL;
|
|
}
|
|
|
|
ev = s4_event_context_init(mem_ctx);
|
|
if (ev == NULL) {
|
|
PyErr_NoMemory();
|
|
return NULL;
|
|
}
|
|
|
|
if (py_imessaging_ctx != Py_None) {
|
|
imessaging_context = pytalloc_get_type(py_imessaging_ctx, struct imessaging_context);
|
|
}
|
|
|
|
if (py_methods == Py_None && py_ldb == Py_None) {
|
|
nt_status = auth_context_create(mem_ctx, ev, imessaging_context, lp_ctx, &auth_context);
|
|
} else {
|
|
if (py_methods != Py_None) {
|
|
methods = PyList_AsStringList(mem_ctx, py_methods, "methods");
|
|
if (methods == NULL) {
|
|
talloc_free(mem_ctx);
|
|
return NULL;
|
|
}
|
|
} else {
|
|
methods = auth_methods_from_lp(mem_ctx, lp_ctx);
|
|
}
|
|
nt_status = auth_context_create_methods(mem_ctx, methods, ev,
|
|
imessaging_context, lp_ctx,
|
|
ldb, &auth_context);
|
|
}
|
|
|
|
if (!NT_STATUS_IS_OK(nt_status)) {
|
|
talloc_free(mem_ctx);
|
|
PyErr_NTSTATUS_IS_ERR_RAISE(nt_status);
|
|
}
|
|
|
|
if (!talloc_reference(auth_context, lp_ctx)) {
|
|
talloc_free(mem_ctx);
|
|
PyErr_NoMemory();
|
|
return NULL;
|
|
}
|
|
|
|
if (!talloc_reference(auth_context, ev)) {
|
|
talloc_free(mem_ctx);
|
|
PyErr_NoMemory();
|
|
return NULL;
|
|
}
|
|
|
|
py_auth_context = PyAuthContext_FromContext(auth_context);
|
|
|
|
talloc_free(mem_ctx);
|
|
|
|
return py_auth_context;
|
|
}
|
|
|
|
static PyTypeObject PyAuthContext = {
|
|
.tp_name = "AuthContext",
|
|
.tp_flags = Py_TPFLAGS_DEFAULT,
|
|
.tp_new = py_auth_context_new,
|
|
};
|
|
|
|
static PyMethodDef py_auth_methods[] = {
|
|
{ "system_session", (PyCFunction)py_system_session, METH_VARARGS, NULL },
|
|
{ "admin_session", (PyCFunction)py_admin_session, METH_VARARGS, NULL },
|
|
{ "user_session", (PyCFunction)py_user_session, METH_VARARGS|METH_KEYWORDS, NULL },
|
|
{ NULL },
|
|
};
|
|
|
|
static struct PyModuleDef moduledef = {
|
|
PyModuleDef_HEAD_INIT,
|
|
.m_name = "auth",
|
|
.m_doc = "Authentication and authorization support.",
|
|
.m_size = -1,
|
|
.m_methods = py_auth_methods,
|
|
};
|
|
|
|
MODULE_INIT_FUNC(auth)
|
|
{
|
|
PyObject *m;
|
|
|
|
if (pytalloc_BaseObject_PyType_Ready(&PyAuthContext) < 0)
|
|
return NULL;
|
|
|
|
m = PyModule_Create(&moduledef);
|
|
if (m == NULL)
|
|
return NULL;
|
|
|
|
Py_INCREF(&PyAuthContext);
|
|
PyModule_AddObject(m, "AuthContext", (PyObject *)&PyAuthContext);
|
|
|
|
#define ADD_FLAG(val) PyModule_AddIntConstant(m, #val, val)
|
|
ADD_FLAG(AUTH_SESSION_INFO_DEFAULT_GROUPS);
|
|
ADD_FLAG(AUTH_SESSION_INFO_AUTHENTICATED);
|
|
ADD_FLAG(AUTH_SESSION_INFO_SIMPLE_PRIVILEGES);
|
|
ADD_FLAG(AUTH_SESSION_INFO_NTLM);
|
|
|
|
return m;
|
|
}
|