Line data Source code
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
5 :
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.
10 :
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.
15 :
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/>.
18 : */
19 :
20 : #include <Python.h>
21 : #include "python/py3compat.h"
22 : #include "includes.h"
23 : #include "python/modules.h"
24 : #include "libcli/util/pyerrors.h"
25 : #include "param/param.h"
26 : #include "pyauth.h"
27 : #include "pyldb.h"
28 : #include "auth/system_session_proto.h"
29 : #include "auth/auth.h"
30 : #include "auth/auth_util.h"
31 : #include "param/pyparam.h"
32 : #include "libcli/security/security.h"
33 : #include "auth/credentials/pycredentials.h"
34 : #include <tevent.h>
35 : #include "librpc/rpc/pyrpc_util.h"
36 : #include "lib/events/events.h"
37 :
38 : static PyTypeObject PyAuthContext;
39 :
40 15899 : static PyObject *PyAuthSession_FromSession(struct auth_session_info *session)
41 : {
42 15899 : return py_return_ndr_struct("samba.dcerpc.auth", "session_info", session, session);
43 : }
44 :
45 308 : static PyObject *py_copy_session_info(PyObject *module,
46 : PyObject *args,
47 : PyObject *kwargs)
48 : {
49 308 : PyObject *py_session = Py_None;
50 308 : PyObject *result = Py_None;
51 308 : struct auth_session_info *session = NULL;
52 308 : struct auth_session_info *session_duplicate = NULL;
53 : TALLOC_CTX *frame;
54 308 : int ret = 1;
55 :
56 308 : const char * const kwnames[] = { "session_info", NULL };
57 :
58 308 : ret = PyArg_ParseTupleAndKeywords(args,
59 : kwargs,
60 : "O",
61 : discard_const_p(char *, kwnames),
62 : &py_session);
63 308 : if (!ret) {
64 0 : return NULL;
65 : }
66 :
67 308 : ret = py_check_dcerpc_type(py_session,
68 : "samba.dcerpc.auth",
69 : "session_info");
70 308 : if (!ret) {
71 0 : return NULL;
72 : }
73 308 : session = pytalloc_get_type(py_session,
74 : struct auth_session_info);
75 308 : if (!session) {
76 0 : PyErr_Format(PyExc_TypeError,
77 : "Expected auth_session_info for session_info "
78 : "argument got %s",
79 : pytalloc_get_name(py_session));
80 0 : return NULL;
81 : }
82 :
83 308 : frame = talloc_stackframe();
84 308 : if (frame == NULL) {
85 0 : return PyErr_NoMemory();
86 : }
87 :
88 308 : session_duplicate = copy_session_info(frame, session);
89 308 : if (session_duplicate == NULL) {
90 0 : TALLOC_FREE(frame);
91 0 : return PyErr_NoMemory();
92 : }
93 :
94 308 : result = PyAuthSession_FromSession(session_duplicate);
95 308 : TALLOC_FREE(frame);
96 308 : return result;
97 : }
98 :
99 15125 : static PyObject *py_system_session(PyObject *module, PyObject *args)
100 : {
101 15125 : PyObject *py_lp_ctx = Py_None;
102 15125 : struct loadparm_context *lp_ctx = NULL;
103 : struct auth_session_info *session;
104 : TALLOC_CTX *mem_ctx;
105 15125 : if (!PyArg_ParseTuple(args, "|O", &py_lp_ctx))
106 0 : return NULL;
107 :
108 15125 : mem_ctx = talloc_new(NULL);
109 15125 : if (mem_ctx == NULL) {
110 0 : PyErr_NoMemory();
111 0 : return NULL;
112 : }
113 :
114 15125 : lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
115 15125 : if (lp_ctx == NULL) {
116 0 : talloc_free(mem_ctx);
117 0 : return NULL;
118 : }
119 :
120 15125 : session = system_session(lp_ctx);
121 :
122 15125 : talloc_free(mem_ctx);
123 :
124 15125 : return PyAuthSession_FromSession(session);
125 : }
126 :
127 :
128 391 : static PyObject *py_admin_session(PyObject *module, PyObject *args)
129 : {
130 : PyObject *py_lp_ctx;
131 : const char *sid;
132 391 : struct loadparm_context *lp_ctx = NULL;
133 : struct auth_session_info *session;
134 391 : struct dom_sid *domain_sid = NULL;
135 : TALLOC_CTX *mem_ctx;
136 :
137 391 : if (!PyArg_ParseTuple(args, "Os", &py_lp_ctx, &sid))
138 0 : return NULL;
139 :
140 391 : mem_ctx = talloc_new(NULL);
141 391 : if (mem_ctx == NULL) {
142 0 : PyErr_NoMemory();
143 0 : return NULL;
144 : }
145 :
146 391 : lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
147 391 : if (lp_ctx == NULL) {
148 0 : talloc_free(mem_ctx);
149 0 : return NULL;
150 : }
151 :
152 391 : domain_sid = dom_sid_parse_talloc(mem_ctx, sid);
153 391 : if (domain_sid == NULL) {
154 0 : PyErr_Format(PyExc_RuntimeError, "Unable to parse sid %s", sid);
155 0 : talloc_free(mem_ctx);
156 0 : return NULL;
157 : }
158 391 : session = admin_session(NULL, lp_ctx, domain_sid);
159 391 : talloc_free(mem_ctx);
160 :
161 391 : return PyAuthSession_FromSession(session);
162 : }
163 :
164 75 : static PyObject *py_user_session(PyObject *module, PyObject *args, PyObject *kwargs)
165 : {
166 : NTSTATUS nt_status;
167 : struct auth_session_info *session;
168 : TALLOC_CTX *mem_ctx;
169 75 : const char * const kwnames[] = { "ldb", "lp_ctx", "principal", "dn", "session_info_flags", NULL };
170 : struct ldb_context *ldb_ctx;
171 75 : PyObject *py_ldb = Py_None;
172 75 : PyObject *py_dn = Py_None;
173 75 : PyObject *py_lp_ctx = Py_None;
174 75 : struct loadparm_context *lp_ctx = NULL;
175 : struct ldb_dn *user_dn;
176 75 : char *principal = NULL;
177 75 : int session_info_flags = 0; /* This is an int, because that's
178 : * what we need for the python
179 : * PyArg_ParseTupleAndKeywords */
180 :
181 75 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OzOi",
182 : discard_const_p(char *, kwnames),
183 : &py_ldb, &py_lp_ctx, &principal, &py_dn, &session_info_flags)) {
184 0 : return NULL;
185 : }
186 :
187 75 : mem_ctx = talloc_new(NULL);
188 75 : if (mem_ctx == NULL) {
189 0 : PyErr_NoMemory();
190 0 : return NULL;
191 : }
192 :
193 75 : ldb_ctx = pyldb_Ldb_AsLdbContext(py_ldb);
194 75 : if (ldb_ctx == NULL) {
195 0 : talloc_free(mem_ctx);
196 0 : return NULL;
197 : }
198 :
199 75 : if (py_dn == Py_None) {
200 0 : user_dn = NULL;
201 : } else {
202 75 : if (!pyldb_Object_AsDn(ldb_ctx, py_dn, ldb_ctx, &user_dn)) {
203 0 : talloc_free(mem_ctx);
204 0 : return NULL;
205 : }
206 : }
207 :
208 75 : lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
209 75 : if (lp_ctx == NULL) {
210 0 : talloc_free(mem_ctx);
211 0 : return NULL;
212 : }
213 :
214 75 : nt_status = authsam_get_session_info_principal(mem_ctx, lp_ctx, ldb_ctx, principal, user_dn,
215 : session_info_flags, &session);
216 75 : if (!NT_STATUS_IS_OK(nt_status)) {
217 0 : talloc_free(mem_ctx);
218 0 : PyErr_NTSTATUS_IS_ERR_RAISE(nt_status);
219 : }
220 :
221 75 : talloc_steal(NULL, session);
222 75 : talloc_free(mem_ctx);
223 :
224 75 : return PyAuthSession_FromSession(session);
225 : }
226 :
227 309 : static PyObject *py_session_info_fill_unix(PyObject *module,
228 : PyObject *args,
229 : PyObject *kwargs)
230 : {
231 : NTSTATUS nt_status;
232 309 : char *user_name = NULL;
233 309 : struct loadparm_context *lp_ctx = NULL;
234 : struct auth_session_info *session_info;
235 309 : PyObject *py_lp_ctx = Py_None;
236 309 : PyObject *py_session = Py_None;
237 : TALLOC_CTX *frame;
238 :
239 309 : const char * const kwnames[] = { "session_info",
240 : "user_name",
241 : "lp_ctx",
242 : NULL };
243 309 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oz|O",
244 : discard_const_p(char *, kwnames),
245 : &py_session,
246 : &user_name,
247 : &py_lp_ctx)) {
248 0 : return NULL;
249 : }
250 :
251 309 : if (!py_check_dcerpc_type(py_session,
252 : "samba.dcerpc.auth",
253 : "session_info")) {
254 0 : return NULL;
255 : }
256 309 : session_info = pytalloc_get_type(py_session,
257 : struct auth_session_info);
258 309 : if (!session_info) {
259 0 : PyErr_Format(PyExc_TypeError,
260 : "Expected auth_session_info for session_info argument got %s",
261 : pytalloc_get_name(py_session));
262 0 : return NULL;
263 : }
264 :
265 309 : frame = talloc_stackframe();
266 :
267 309 : lp_ctx = lpcfg_from_py_object(frame, py_lp_ctx);
268 309 : if (lp_ctx == NULL) {
269 0 : TALLOC_FREE(frame);
270 0 : return NULL;
271 : }
272 :
273 309 : nt_status = auth_session_info_fill_unix(lp_ctx,
274 : user_name,
275 : session_info);
276 309 : TALLOC_FREE(frame);
277 309 : if (!NT_STATUS_IS_OK(nt_status)) {
278 0 : PyErr_NTSTATUS_IS_ERR_RAISE(nt_status);
279 : }
280 :
281 309 : Py_RETURN_NONE;
282 : }
283 :
284 :
285 55 : static PyObject *py_session_info_set_unix(PyObject *module,
286 : PyObject *args,
287 : PyObject *kwargs)
288 : {
289 : NTSTATUS nt_status;
290 55 : char *user_name = NULL;
291 55 : int uid = -1;
292 55 : int gid = -1;
293 55 : struct loadparm_context *lp_ctx = NULL;
294 : struct auth_session_info *session_info;
295 55 : PyObject *py_lp_ctx = Py_None;
296 55 : PyObject *py_session = Py_None;
297 : TALLOC_CTX *frame;
298 :
299 55 : const char * const kwnames[] = { "session_info",
300 : "user_name",
301 : "uid",
302 : "gid",
303 : "lp_ctx",
304 : NULL };
305 :
306 55 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Ozii|O",
307 : discard_const_p(char *, kwnames),
308 : &py_session,
309 : &user_name,
310 : &uid,
311 : &gid,
312 : &py_lp_ctx)) {
313 0 : return NULL;
314 : }
315 :
316 55 : if (!py_check_dcerpc_type(py_session,
317 : "samba.dcerpc.auth",
318 : "session_info")) {
319 0 : return NULL;
320 : }
321 55 : session_info = pytalloc_get_type(py_session,
322 : struct auth_session_info);
323 55 : if (!session_info) {
324 0 : PyErr_Format(PyExc_TypeError,
325 : "Expected auth_session_info for session_info "
326 : "argument got %s",
327 : pytalloc_get_name(py_session));
328 0 : return NULL;
329 : }
330 :
331 55 : frame = talloc_stackframe();
332 :
333 55 : lp_ctx = lpcfg_from_py_object(frame, py_lp_ctx);
334 55 : if (lp_ctx == NULL) {
335 0 : TALLOC_FREE(frame);
336 0 : return NULL;
337 : }
338 :
339 55 : nt_status = auth_session_info_set_unix(lp_ctx,
340 : user_name,
341 : uid,
342 : gid,
343 : session_info);
344 55 : TALLOC_FREE(frame);
345 55 : if (!NT_STATUS_IS_OK(nt_status)) {
346 0 : PyErr_NTSTATUS_IS_ERR_RAISE(nt_status);
347 : }
348 :
349 55 : Py_RETURN_NONE;
350 : }
351 :
352 :
353 5 : static const char **PyList_AsStringList(TALLOC_CTX *mem_ctx, PyObject *list,
354 : const char *paramname)
355 : {
356 : const char **ret;
357 : Py_ssize_t i;
358 5 : if (!PyList_Check(list)) {
359 0 : PyErr_Format(PyExc_TypeError, "%s is not a list", paramname);
360 0 : return NULL;
361 : }
362 5 : ret = talloc_array(NULL, const char *, PyList_Size(list)+1);
363 5 : if (ret == NULL) {
364 0 : PyErr_NoMemory();
365 0 : return NULL;
366 : }
367 :
368 10 : for (i = 0; i < PyList_Size(list); i++) {
369 : const char *value;
370 : Py_ssize_t size;
371 0 : PyObject *item = PyList_GetItem(list, i);
372 0 : if (!PyUnicode_Check(item)) {
373 0 : PyErr_Format(PyExc_TypeError, "%s should be strings", paramname);
374 0 : return NULL;
375 : }
376 0 : value = PyUnicode_AsUTF8AndSize(item, &size);
377 0 : if (value == NULL) {
378 0 : talloc_free(ret);
379 0 : return NULL;
380 : }
381 0 : ret[i] = talloc_strndup(ret, value, size);
382 : }
383 5 : ret[i] = NULL;
384 5 : return ret;
385 : }
386 :
387 15 : static PyObject *PyAuthContext_FromContext(struct auth4_context *auth_context)
388 : {
389 15 : return pytalloc_reference(&PyAuthContext, auth_context);
390 : }
391 :
392 15 : static PyObject *py_auth_context_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
393 : {
394 15 : PyObject *py_lp_ctx = Py_None;
395 15 : PyObject *py_ldb = Py_None;
396 15 : PyObject *py_auth_context = Py_None;
397 15 : PyObject *py_methods = Py_None;
398 : TALLOC_CTX *mem_ctx;
399 : struct auth4_context *auth_context;
400 : struct loadparm_context *lp_ctx;
401 : struct tevent_context *ev;
402 15 : struct ldb_context *ldb = NULL;
403 : NTSTATUS nt_status;
404 : const char **methods;
405 :
406 15 : const char *const kwnames[] = {"lp_ctx", "ldb", "methods", NULL};
407 :
408 15 : if (!PyArg_ParseTupleAndKeywords(args,
409 : kwargs,
410 : "|OOO",
411 : discard_const_p(char *, kwnames),
412 : &py_lp_ctx,
413 : &py_ldb,
414 : &py_methods))
415 0 : return NULL;
416 :
417 15 : mem_ctx = talloc_new(NULL);
418 15 : if (mem_ctx == NULL) {
419 0 : PyErr_NoMemory();
420 0 : return NULL;
421 : }
422 :
423 15 : if (py_ldb != Py_None) {
424 5 : ldb = pyldb_Ldb_AsLdbContext(py_ldb);
425 5 : if (ldb == NULL) {
426 0 : talloc_free(mem_ctx);
427 0 : return NULL;
428 : }
429 : }
430 :
431 15 : lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
432 15 : if (lp_ctx == NULL) {
433 0 : talloc_free(mem_ctx);
434 0 : PyErr_NoMemory();
435 0 : return NULL;
436 : }
437 :
438 15 : ev = s4_event_context_init(mem_ctx);
439 15 : if (ev == NULL) {
440 0 : talloc_free(mem_ctx);
441 0 : PyErr_NoMemory();
442 0 : return NULL;
443 : }
444 :
445 15 : if (py_methods == Py_None && py_ldb == Py_None) {
446 10 : nt_status = auth_context_create(
447 : mem_ctx, ev, NULL, lp_ctx, &auth_context);
448 : } else {
449 5 : if (py_methods != Py_None) {
450 5 : methods = PyList_AsStringList(mem_ctx, py_methods, "methods");
451 5 : if (methods == NULL) {
452 0 : talloc_free(mem_ctx);
453 0 : return NULL;
454 : }
455 : } else {
456 0 : methods = auth_methods_from_lp(mem_ctx, lp_ctx);
457 : }
458 5 : nt_status = auth_context_create_methods(
459 : mem_ctx, methods, ev, NULL, lp_ctx, ldb, &auth_context);
460 : }
461 :
462 15 : if (!NT_STATUS_IS_OK(nt_status)) {
463 0 : talloc_free(mem_ctx);
464 0 : PyErr_NTSTATUS_IS_ERR_RAISE(nt_status);
465 : }
466 :
467 15 : if (!talloc_reference(auth_context, lp_ctx)) {
468 0 : talloc_free(mem_ctx);
469 0 : PyErr_NoMemory();
470 0 : return NULL;
471 : }
472 :
473 15 : if (!talloc_reference(auth_context, ev)) {
474 0 : talloc_free(mem_ctx);
475 0 : PyErr_NoMemory();
476 0 : return NULL;
477 : }
478 :
479 15 : py_auth_context = PyAuthContext_FromContext(auth_context);
480 :
481 15 : talloc_free(mem_ctx);
482 :
483 15 : return py_auth_context;
484 : }
485 :
486 : static PyTypeObject PyAuthContext = {
487 : .tp_name = "AuthContext",
488 : .tp_flags = Py_TPFLAGS_DEFAULT,
489 : .tp_new = py_auth_context_new,
490 : };
491 :
492 : static PyMethodDef py_auth_methods[] = {
493 : { "system_session", (PyCFunction)py_system_session, METH_VARARGS, NULL },
494 : { "admin_session", (PyCFunction)py_admin_session, METH_VARARGS, NULL },
495 : { "user_session", PY_DISCARD_FUNC_SIG(PyCFunction,py_user_session),
496 : METH_VARARGS|METH_KEYWORDS, NULL },
497 : { "session_info_fill_unix",
498 : PY_DISCARD_FUNC_SIG(PyCFunction,py_session_info_fill_unix),
499 : METH_VARARGS|METH_KEYWORDS,
500 : NULL },
501 : { "session_info_set_unix",
502 : PY_DISCARD_FUNC_SIG(PyCFunction,py_session_info_set_unix),
503 : METH_VARARGS|METH_KEYWORDS,
504 : NULL },
505 : { "copy_session_info",
506 : PY_DISCARD_FUNC_SIG(PyCFunction,py_copy_session_info),
507 : METH_VARARGS|METH_KEYWORDS,
508 : NULL },
509 : {0},
510 : };
511 :
512 : static struct PyModuleDef moduledef = {
513 : PyModuleDef_HEAD_INIT,
514 : .m_name = "auth",
515 : .m_doc = "Authentication and authorization support.",
516 : .m_size = -1,
517 : .m_methods = py_auth_methods,
518 : };
519 :
520 3500 : MODULE_INIT_FUNC(auth)
521 : {
522 : PyObject *m;
523 :
524 3500 : if (pytalloc_BaseObject_PyType_Ready(&PyAuthContext) < 0)
525 0 : return NULL;
526 :
527 3500 : m = PyModule_Create(&moduledef);
528 3500 : if (m == NULL)
529 0 : return NULL;
530 :
531 3500 : Py_INCREF(&PyAuthContext);
532 3500 : PyModule_AddObject(m, "AuthContext", (PyObject *)&PyAuthContext);
533 :
534 : #define ADD_FLAG(val) PyModule_AddIntConstant(m, #val, val)
535 3500 : ADD_FLAG(AUTH_SESSION_INFO_DEFAULT_GROUPS);
536 3500 : ADD_FLAG(AUTH_SESSION_INFO_AUTHENTICATED);
537 3500 : ADD_FLAG(AUTH_SESSION_INFO_SIMPLE_PRIVILEGES);
538 3500 : ADD_FLAG(AUTH_SESSION_INFO_NTLM);
539 :
540 3500 : return m;
541 : }
|