Allow "security = share" with SMB2. We already handle this in smb2/smb2_server.c
[Samba.git] / source4 / auth / pyauth.c
blob26de2c336d534fd272fddc770e9845bdc39f783b
1 /*
2 Unix SMB/CIFS implementation.
3 Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2008
4 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2011
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <Python.h>
21 #include "includes.h"
22 #include "libcli/util/pyerrors.h"
23 #include "param/param.h"
24 #include "pyauth.h"
25 #include "pyldb.h"
26 #include "auth/system_session_proto.h"
27 #include "auth/auth.h"
28 #include "param/pyparam.h"
29 #include "libcli/security/security.h"
30 #include "auth/credentials/pycredentials.h"
31 #include <tevent.h>
32 #include "librpc/rpc/pyrpc_util.h"
34 staticforward PyTypeObject PyAuthContext;
36 static PyObject *py_auth_session_get_security_token(PyObject *self, void *closure)
38 struct auth_session_info *session = py_talloc_get_type(self, struct auth_session_info);
39 PyObject *py_security_token;
40 py_security_token = py_return_ndr_struct("samba.dcerpc.security", "token",
41 session->security_token, session->security_token);
42 return py_security_token;
45 static int py_auth_session_set_security_token(PyObject *self, PyObject *value, void *closure)
47 struct auth_session_info *session = py_talloc_get_type(self, struct auth_session_info);
48 session->security_token = talloc_reference(session, py_talloc_get_ptr(value));
49 return 0;
52 static PyObject *py_auth_session_get_session_key(PyObject *self, void *closure)
54 struct auth_session_info *session = py_talloc_get_type(self, struct auth_session_info);
55 return PyString_FromStringAndSize((char *)session->session_key.data, session->session_key.length);
58 static int py_auth_session_set_session_key(PyObject *self, PyObject *value, void *closure)
60 DATA_BLOB val;
61 struct auth_session_info *session = py_talloc_get_type(self, struct auth_session_info);
62 val.data = (uint8_t *)PyString_AsString(value);
63 val.length = PyString_Size(value);
65 session->session_key = data_blob_talloc(session, val.data, val.length);
66 return 0;
69 static PyObject *py_auth_session_get_credentials(PyObject *self, void *closure)
71 struct auth_session_info *session = py_talloc_get_type(self, struct auth_session_info);
72 PyObject *py_credentials;
73 /* This is evil, as the credentials are not IDL structures */
74 py_credentials = py_return_ndr_struct("samba.credentials", "Credentials", session->credentials, session->credentials);
75 return py_credentials;
78 static int py_auth_session_set_credentials(PyObject *self, PyObject *value, void *closure)
80 struct auth_session_info *session = py_talloc_get_type(self, struct auth_session_info);
81 session->credentials = talloc_reference(session, PyCredentials_AsCliCredentials(value));
82 return 0;
85 static PyGetSetDef py_auth_session_getset[] = {
86 { discard_const_p(char, "security_token"), (getter)py_auth_session_get_security_token, (setter)py_auth_session_set_security_token, NULL },
87 { discard_const_p(char, "session_key"), (getter)py_auth_session_get_session_key, (setter)py_auth_session_set_session_key, NULL },
88 { discard_const_p(char, "credentials"), (getter)py_auth_session_get_credentials, (setter)py_auth_session_set_credentials, NULL },
89 { NULL }
92 static PyTypeObject PyAuthSession = {
93 .tp_name = "AuthSession",
94 .tp_basicsize = sizeof(py_talloc_Object),
95 .tp_flags = Py_TPFLAGS_DEFAULT,
96 .tp_getset = py_auth_session_getset,
99 PyObject *PyAuthSession_FromSession(struct auth_session_info *session)
101 return py_talloc_reference(&PyAuthSession, session);
104 static PyObject *py_system_session(PyObject *module, PyObject *args)
106 PyObject *py_lp_ctx = Py_None;
107 struct loadparm_context *lp_ctx = NULL;
108 struct auth_session_info *session;
109 TALLOC_CTX *mem_ctx;
110 if (!PyArg_ParseTuple(args, "|O", &py_lp_ctx))
111 return NULL;
113 mem_ctx = talloc_new(NULL);
114 if (mem_ctx == NULL) {
115 PyErr_NoMemory();
116 return NULL;
119 lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
120 if (lp_ctx == NULL) {
121 talloc_free(mem_ctx);
122 return NULL;
125 session = system_session(lp_ctx);
127 talloc_free(mem_ctx);
129 return PyAuthSession_FromSession(session);
133 static PyObject *py_admin_session(PyObject *module, PyObject *args)
135 PyObject *py_lp_ctx;
136 PyObject *py_sid;
137 struct loadparm_context *lp_ctx = NULL;
138 struct auth_session_info *session;
139 struct dom_sid *domain_sid = NULL;
140 TALLOC_CTX *mem_ctx;
142 if (!PyArg_ParseTuple(args, "OO", &py_lp_ctx, &py_sid))
143 return NULL;
145 mem_ctx = talloc_new(NULL);
146 if (mem_ctx == NULL) {
147 PyErr_NoMemory();
148 return NULL;
151 lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
152 if (lp_ctx == NULL) {
153 talloc_free(mem_ctx);
154 return NULL;
157 domain_sid = dom_sid_parse_talloc(mem_ctx, PyString_AsString(py_sid));
158 if (domain_sid == NULL) {
159 PyErr_Format(PyExc_RuntimeError, "Unable to parse sid %s",
160 PyString_AsString(py_sid));
161 talloc_free(mem_ctx);
162 return NULL;
164 session = admin_session(NULL, lp_ctx, domain_sid);
165 talloc_free(mem_ctx);
167 return PyAuthSession_FromSession(session);
170 static PyObject *py_user_session(PyObject *module, PyObject *args, PyObject *kwargs)
172 NTSTATUS nt_status;
173 struct auth_session_info *session;
174 TALLOC_CTX *mem_ctx;
175 const char * const kwnames[] = { "ldb", "lp_ctx", "principal", "dn", "session_info_flags", NULL };
176 struct ldb_context *ldb_ctx;
177 PyObject *py_ldb = Py_None;
178 PyObject *py_dn = Py_None;
179 PyObject *py_lp_ctx = Py_None;
180 struct loadparm_context *lp_ctx = NULL;
181 struct ldb_dn *user_dn;
182 char *principal = NULL;
183 int session_info_flags = 0; /* This is an int, because that's
184 * what we need for the python
185 * PyArg_ParseTupleAndKeywords */
187 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OzOi",
188 discard_const_p(char *, kwnames),
189 &py_ldb, &py_lp_ctx, &principal, &py_dn, &session_info_flags)) {
190 return NULL;
193 mem_ctx = talloc_new(NULL);
194 if (mem_ctx == NULL) {
195 PyErr_NoMemory();
196 return NULL;
199 ldb_ctx = PyLdb_AsLdbContext(py_ldb);
201 if (py_dn == Py_None) {
202 user_dn = NULL;
203 } else {
204 if (!PyObject_AsDn(ldb_ctx, py_dn, ldb_ctx, &user_dn)) {
205 talloc_free(mem_ctx);
206 return NULL;
210 lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
211 if (lp_ctx == NULL) {
212 talloc_free(mem_ctx);
213 return NULL;
216 nt_status = authsam_get_session_info_principal(mem_ctx, lp_ctx, ldb_ctx, principal, user_dn,
217 session_info_flags, &session);
218 if (!NT_STATUS_IS_OK(nt_status)) {
219 talloc_free(mem_ctx);
220 PyErr_NTSTATUS_IS_ERR_RAISE(nt_status);
223 talloc_steal(NULL, session);
224 talloc_free(mem_ctx);
226 return PyAuthSession_FromSession(session);
230 static const char **PyList_AsStringList(TALLOC_CTX *mem_ctx, PyObject *list,
231 const char *paramname)
233 const char **ret;
234 Py_ssize_t i;
235 if (!PyList_Check(list)) {
236 PyErr_Format(PyExc_TypeError, "%s is not a list", paramname);
237 return NULL;
239 ret = talloc_array(NULL, const char *, PyList_Size(list)+1);
240 if (ret == NULL) {
241 PyErr_NoMemory();
242 return NULL;
245 for (i = 0; i < PyList_Size(list); i++) {
246 PyObject *item = PyList_GetItem(list, i);
247 if (!PyString_Check(item)) {
248 PyErr_Format(PyExc_TypeError, "%s should be strings", paramname);
249 return NULL;
251 ret[i] = talloc_strndup(ret, PyString_AsString(item),
252 PyString_Size(item));
254 ret[i] = NULL;
255 return ret;
258 static PyObject *PyAuthContext_FromContext(struct auth_context *auth_context)
260 return py_talloc_reference(&PyAuthContext, auth_context);
263 static PyObject *py_auth_context_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
265 PyObject *py_lp_ctx = Py_None;
266 PyObject *py_ldb = Py_None;
267 PyObject *py_messaging_ctx = Py_None;
268 PyObject *py_auth_context = Py_None;
269 PyObject *py_methods = Py_None;
270 TALLOC_CTX *mem_ctx;
271 struct auth_context *auth_context;
272 struct messaging_context *messaging_context = NULL;
273 struct loadparm_context *lp_ctx;
274 struct tevent_context *ev;
275 struct ldb_context *ldb;
276 NTSTATUS nt_status;
277 const char **methods;
279 const char * const kwnames[] = { "lp_ctx", "messaging_ctx", "ldb", "methods", NULL };
281 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOOO",
282 discard_const_p(char *, kwnames),
283 &py_lp_ctx, &py_messaging_ctx, &py_ldb, &py_methods))
284 return NULL;
286 mem_ctx = talloc_new(NULL);
287 if (mem_ctx == NULL) {
288 PyErr_NoMemory();
289 return NULL;
292 if (py_ldb != Py_None) {
293 ldb = PyLdb_AsLdbContext(py_ldb);
296 lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
298 ev = tevent_context_init(mem_ctx);
299 if (ev == NULL) {
300 PyErr_NoMemory();
301 return NULL;
304 if (py_messaging_ctx != Py_None) {
305 messaging_context = py_talloc_get_type(py_messaging_ctx, struct messaging_context);
308 if (py_methods == Py_None && py_ldb == Py_None) {
309 nt_status = auth_context_create(mem_ctx, ev, messaging_context, lp_ctx, &auth_context);
310 } else {
311 if (py_methods != Py_None) {
312 methods = PyList_AsStringList(mem_ctx, py_methods, "methods");
313 if (methods == NULL) {
314 talloc_free(mem_ctx);
315 return NULL;
317 } else {
318 methods = auth_methods_from_lp(mem_ctx, lp_ctx);
320 nt_status = auth_context_create_methods(mem_ctx, methods, ev,
321 messaging_context, lp_ctx,
322 ldb, &auth_context);
325 if (!NT_STATUS_IS_OK(nt_status)) {
326 talloc_free(mem_ctx);
327 PyErr_NTSTATUS_IS_ERR_RAISE(nt_status);
330 if (!talloc_reference(auth_context, lp_ctx)) {
331 talloc_free(mem_ctx);
332 PyErr_NoMemory();
333 return NULL;
336 if (!talloc_reference(auth_context, ev)) {
337 talloc_free(mem_ctx);
338 PyErr_NoMemory();
339 return NULL;
342 py_auth_context = PyAuthContext_FromContext(auth_context);
344 talloc_free(mem_ctx);
346 return py_auth_context;
349 static PyTypeObject PyAuthContext = {
350 .tp_name = "AuthContext",
351 .tp_basicsize = sizeof(py_talloc_Object),
352 .tp_flags = Py_TPFLAGS_DEFAULT,
353 .tp_new = py_auth_context_new,
354 .tp_basicsize = sizeof(py_talloc_Object),
357 static PyMethodDef py_auth_methods[] = {
358 { "system_session", (PyCFunction)py_system_session, METH_VARARGS, NULL },
359 { "admin_session", (PyCFunction)py_admin_session, METH_VARARGS, NULL },
360 { "user_session", (PyCFunction)py_user_session, METH_VARARGS|METH_KEYWORDS, NULL },
361 { NULL },
364 void initauth(void)
366 PyObject *m;
368 PyAuthSession.tp_base = PyTalloc_GetObjectType();
369 if (PyAuthSession.tp_base == NULL)
370 return;
372 if (PyType_Ready(&PyAuthSession) < 0)
373 return;
375 PyAuthContext.tp_base = PyTalloc_GetObjectType();
376 if (PyAuthContext.tp_base == NULL)
377 return;
379 if (PyType_Ready(&PyAuthContext) < 0)
380 return;
382 m = Py_InitModule3("auth", py_auth_methods,
383 "Authentication and authorization support.");
384 if (m == NULL)
385 return;
387 Py_INCREF(&PyAuthSession);
388 PyModule_AddObject(m, "AuthSession", (PyObject *)&PyAuthSession);
389 Py_INCREF(&PyAuthContext);
390 PyModule_AddObject(m, "AuthContext", (PyObject *)&PyAuthContext);
392 #define ADD_FLAG(val) PyModule_AddObject(m, #val, PyInt_FromLong(val))
393 ADD_FLAG(AUTH_SESSION_INFO_DEFAULT_GROUPS);
394 ADD_FLAG(AUTH_SESSION_INFO_AUTHENTICATED);
395 ADD_FLAG(AUTH_SESSION_INFO_SIMPLE_PRIVILEGES);