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 "lib/replace/system/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 26934 : static PyObject *PyAuthSession_FromSession(struct auth_session_info *session)
41 : {
42 26934 : return py_return_ndr_struct("samba.dcerpc.auth", "session_info", session, session);
43 : }
44 :
45 1043 : static PyObject *py_copy_session_info(PyObject *module,
46 : PyObject *args,
47 : PyObject *kwargs)
48 : {
49 1043 : PyObject *py_session = Py_None;
50 1043 : PyObject *result = Py_None;
51 1043 : struct auth_session_info *session = NULL;
52 1043 : struct auth_session_info *session_duplicate = NULL;
53 91 : TALLOC_CTX *frame;
54 1043 : int ret = 1;
55 :
56 1043 : const char * const kwnames[] = { "session_info", NULL };
57 :
58 1043 : ret = PyArg_ParseTupleAndKeywords(args,
59 : kwargs,
60 : "O",
61 : discard_const_p(char *, kwnames),
62 : &py_session);
63 1043 : if (!ret) {
64 0 : return NULL;
65 : }
66 :
67 1043 : ret = py_check_dcerpc_type(py_session,
68 : "samba.dcerpc.auth",
69 : "session_info");
70 1043 : if (!ret) {
71 0 : return NULL;
72 : }
73 1043 : session = pytalloc_get_type(py_session,
74 : struct auth_session_info);
75 1043 : 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 1043 : frame = talloc_stackframe();
84 1043 : if (frame == NULL) {
85 0 : return PyErr_NoMemory();
86 : }
87 :
88 1043 : session_duplicate = copy_session_info(frame, session);
89 1043 : if (session_duplicate == NULL) {
90 0 : TALLOC_FREE(frame);
91 0 : return PyErr_NoMemory();
92 : }
93 :
94 1043 : result = PyAuthSession_FromSession(session_duplicate);
95 1043 : TALLOC_FREE(frame);
96 1043 : return result;
97 : }
98 :
99 24470 : static PyObject *py_system_session(PyObject *module, PyObject *args)
100 : {
101 24470 : PyObject *py_lp_ctx = Py_None;
102 24470 : struct loadparm_context *lp_ctx = NULL;
103 419 : struct auth_session_info *session;
104 419 : TALLOC_CTX *mem_ctx;
105 24470 : if (!PyArg_ParseTuple(args, "|O", &py_lp_ctx))
106 0 : return NULL;
107 :
108 24470 : mem_ctx = talloc_new(NULL);
109 24470 : if (mem_ctx == NULL) {
110 0 : PyErr_NoMemory();
111 0 : return NULL;
112 : }
113 :
114 24470 : lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
115 24470 : if (lp_ctx == NULL) {
116 0 : talloc_free(mem_ctx);
117 0 : return NULL;
118 : }
119 :
120 24470 : session = system_session(lp_ctx);
121 :
122 24470 : talloc_free(mem_ctx);
123 :
124 24470 : return PyAuthSession_FromSession(session);
125 : }
126 :
127 :
128 1097 : static PyObject *py_admin_session(PyObject *module, PyObject *args)
129 : {
130 80 : PyObject *py_lp_ctx;
131 80 : const char *sid;
132 1097 : struct loadparm_context *lp_ctx = NULL;
133 80 : struct auth_session_info *session;
134 1097 : struct dom_sid *domain_sid = NULL;
135 80 : TALLOC_CTX *mem_ctx;
136 :
137 1097 : if (!PyArg_ParseTuple(args, "Os", &py_lp_ctx, &sid))
138 0 : return NULL;
139 :
140 1097 : mem_ctx = talloc_new(NULL);
141 1097 : if (mem_ctx == NULL) {
142 0 : PyErr_NoMemory();
143 0 : return NULL;
144 : }
145 :
146 1097 : lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
147 1097 : if (lp_ctx == NULL) {
148 0 : talloc_free(mem_ctx);
149 0 : return NULL;
150 : }
151 :
152 1097 : domain_sid = dom_sid_parse_talloc(mem_ctx, sid);
153 1097 : 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 1097 : session = admin_session(NULL, lp_ctx, domain_sid);
159 1097 : talloc_free(mem_ctx);
160 :
161 1097 : return PyAuthSession_FromSession(session);
162 : }
163 :
164 324 : static PyObject *py_user_session(PyObject *module, PyObject *args, PyObject *kwargs)
165 : {
166 20 : NTSTATUS nt_status;
167 20 : struct auth_session_info *session;
168 20 : TALLOC_CTX *mem_ctx;
169 324 : const char * const kwnames[] = { "ldb", "lp_ctx", "principal", "dn", "session_info_flags", NULL };
170 20 : struct ldb_context *ldb_ctx;
171 324 : PyObject *py_ldb = Py_None;
172 324 : PyObject *py_dn = Py_None;
173 324 : PyObject *py_lp_ctx = Py_None;
174 324 : struct loadparm_context *lp_ctx = NULL;
175 20 : struct ldb_dn *user_dn;
176 324 : char *principal = NULL;
177 324 : int session_info_flags = 0; /* This is an int, because that's
178 : * what we need for the python
179 : * PyArg_ParseTupleAndKeywords */
180 :
181 324 : 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 324 : mem_ctx = talloc_new(NULL);
188 324 : if (mem_ctx == NULL) {
189 0 : PyErr_NoMemory();
190 0 : return NULL;
191 : }
192 :
193 324 : ldb_ctx = pyldb_Ldb_AsLdbContext(py_ldb);
194 324 : if (ldb_ctx == NULL) {
195 0 : talloc_free(mem_ctx);
196 0 : return NULL;
197 : }
198 :
199 324 : if (py_dn == Py_None) {
200 0 : user_dn = NULL;
201 : } else {
202 324 : 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 324 : lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
209 324 : if (lp_ctx == NULL) {
210 0 : talloc_free(mem_ctx);
211 0 : return NULL;
212 : }
213 :
214 324 : nt_status = authsam_get_session_info_principal(mem_ctx, lp_ctx, ldb_ctx, principal, user_dn,
215 : session_info_flags, &session);
216 324 : 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 324 : talloc_steal(NULL, session);
222 324 : talloc_free(mem_ctx);
223 :
224 324 : return PyAuthSession_FromSession(session);
225 : }
226 :
227 1596 : static PyObject *py_session_info_fill_unix(PyObject *module,
228 : PyObject *args,
229 : PyObject *kwargs)
230 : {
231 91 : NTSTATUS nt_status;
232 1596 : char *user_name = NULL;
233 1596 : struct loadparm_context *lp_ctx = NULL;
234 91 : struct auth_session_info *session_info;
235 1596 : PyObject *py_lp_ctx = Py_None;
236 1596 : PyObject *py_session = Py_None;
237 91 : TALLOC_CTX *frame;
238 :
239 1596 : const char * const kwnames[] = { "session_info",
240 : "user_name",
241 : "lp_ctx",
242 : NULL };
243 1596 : 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 1596 : if (!py_check_dcerpc_type(py_session,
252 : "samba.dcerpc.auth",
253 : "session_info")) {
254 0 : return NULL;
255 : }
256 1596 : session_info = pytalloc_get_type(py_session,
257 : struct auth_session_info);
258 1596 : 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 1596 : frame = talloc_stackframe();
266 :
267 1596 : lp_ctx = lpcfg_from_py_object(frame, py_lp_ctx);
268 1596 : if (lp_ctx == NULL) {
269 0 : TALLOC_FREE(frame);
270 0 : return NULL;
271 : }
272 :
273 1596 : nt_status = auth_session_info_fill_unix(lp_ctx,
274 : user_name,
275 : session_info);
276 1596 : TALLOC_FREE(frame);
277 1596 : if (!NT_STATUS_IS_OK(nt_status)) {
278 0 : PyErr_NTSTATUS_IS_ERR_RAISE(nt_status);
279 : }
280 :
281 1596 : Py_RETURN_NONE;
282 : }
283 :
284 :
285 118 : static PyObject *py_session_info_set_unix(PyObject *module,
286 : PyObject *args,
287 : PyObject *kwargs)
288 : {
289 20 : NTSTATUS nt_status;
290 118 : char *user_name = NULL;
291 118 : int uid = -1;
292 118 : int gid = -1;
293 118 : struct loadparm_context *lp_ctx = NULL;
294 20 : struct auth_session_info *session_info;
295 118 : PyObject *py_lp_ctx = Py_None;
296 118 : PyObject *py_session = Py_None;
297 20 : TALLOC_CTX *frame;
298 :
299 118 : const char * const kwnames[] = { "session_info",
300 : "user_name",
301 : "uid",
302 : "gid",
303 : "lp_ctx",
304 : NULL };
305 :
306 118 : 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 118 : if (!py_check_dcerpc_type(py_session,
317 : "samba.dcerpc.auth",
318 : "session_info")) {
319 0 : return NULL;
320 : }
321 118 : session_info = pytalloc_get_type(py_session,
322 : struct auth_session_info);
323 118 : 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 118 : frame = talloc_stackframe();
332 :
333 118 : lp_ctx = lpcfg_from_py_object(frame, py_lp_ctx);
334 118 : if (lp_ctx == NULL) {
335 0 : TALLOC_FREE(frame);
336 0 : return NULL;
337 : }
338 :
339 118 : nt_status = auth_session_info_set_unix(lp_ctx,
340 : user_name,
341 : uid,
342 : gid,
343 : session_info);
344 118 : TALLOC_FREE(frame);
345 118 : if (!NT_STATUS_IS_OK(nt_status)) {
346 0 : PyErr_NTSTATUS_IS_ERR_RAISE(nt_status);
347 : }
348 :
349 118 : Py_RETURN_NONE;
350 : }
351 :
352 :
353 47 : static PyObject *PyAuthContext_FromContext(struct auth4_context *auth_context)
354 : {
355 47 : return pytalloc_reference(&PyAuthContext, auth_context);
356 : }
357 :
358 47 : static PyObject *py_auth_context_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
359 : {
360 47 : PyObject *py_lp_ctx = Py_None;
361 47 : PyObject *py_ldb = Py_None;
362 47 : PyObject *py_auth_context = Py_None;
363 47 : PyObject *py_methods = Py_None;
364 0 : TALLOC_CTX *mem_ctx;
365 0 : struct auth4_context *auth_context;
366 0 : struct loadparm_context *lp_ctx;
367 0 : struct tevent_context *ev;
368 47 : struct ldb_context *ldb = NULL;
369 0 : NTSTATUS nt_status;
370 0 : const char *const *methods;
371 :
372 47 : const char *const kwnames[] = {"lp_ctx", "ldb", "methods", NULL};
373 :
374 47 : if (!PyArg_ParseTupleAndKeywords(args,
375 : kwargs,
376 : "|OOO",
377 : discard_const_p(char *, kwnames),
378 : &py_lp_ctx,
379 : &py_ldb,
380 : &py_methods))
381 0 : return NULL;
382 :
383 47 : mem_ctx = talloc_new(NULL);
384 47 : if (mem_ctx == NULL) {
385 0 : PyErr_NoMemory();
386 0 : return NULL;
387 : }
388 :
389 47 : if (py_ldb != Py_None) {
390 7 : ldb = pyldb_Ldb_AsLdbContext(py_ldb);
391 7 : if (ldb == NULL) {
392 0 : talloc_free(mem_ctx);
393 0 : return NULL;
394 : }
395 : }
396 :
397 47 : lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
398 47 : if (lp_ctx == NULL) {
399 0 : talloc_free(mem_ctx);
400 0 : PyErr_NoMemory();
401 0 : return NULL;
402 : }
403 :
404 47 : ev = s4_event_context_init(mem_ctx);
405 47 : if (ev == NULL) {
406 0 : talloc_free(mem_ctx);
407 0 : PyErr_NoMemory();
408 0 : return NULL;
409 : }
410 :
411 47 : if (py_methods == Py_None && py_ldb == Py_None) {
412 40 : nt_status = auth_context_create(
413 : mem_ctx, ev, NULL, lp_ctx, &auth_context);
414 : } else {
415 7 : if (py_methods != Py_None) {
416 5 : methods = (const char * const *)PyList_AsStringList(mem_ctx, py_methods, "methods");
417 5 : if (methods == NULL) {
418 0 : talloc_free(mem_ctx);
419 0 : return NULL;
420 : }
421 : } else {
422 2 : methods = auth_methods_from_lp(mem_ctx, lp_ctx);
423 : }
424 7 : nt_status = auth_context_create_methods(
425 : mem_ctx, methods, ev, NULL, lp_ctx, ldb, &auth_context);
426 : }
427 :
428 47 : if (!NT_STATUS_IS_OK(nt_status)) {
429 0 : talloc_free(mem_ctx);
430 0 : PyErr_NTSTATUS_IS_ERR_RAISE(nt_status);
431 : }
432 :
433 47 : if (!talloc_reference(auth_context, lp_ctx)) {
434 0 : talloc_free(mem_ctx);
435 0 : PyErr_NoMemory();
436 0 : return NULL;
437 : }
438 :
439 47 : if (!talloc_reference(auth_context, ev)) {
440 0 : talloc_free(mem_ctx);
441 0 : PyErr_NoMemory();
442 0 : return NULL;
443 : }
444 :
445 47 : py_auth_context = PyAuthContext_FromContext(auth_context);
446 :
447 47 : talloc_free(mem_ctx);
448 :
449 47 : return py_auth_context;
450 : }
451 :
452 : static PyTypeObject PyAuthContext = {
453 : .tp_name = "AuthContext",
454 : .tp_flags = Py_TPFLAGS_DEFAULT,
455 : .tp_new = py_auth_context_new,
456 : };
457 :
458 : static PyMethodDef py_auth_methods[] = {
459 : { "system_session", (PyCFunction)py_system_session, METH_VARARGS, NULL },
460 : { "admin_session", (PyCFunction)py_admin_session, METH_VARARGS, NULL },
461 : { "user_session", PY_DISCARD_FUNC_SIG(PyCFunction,py_user_session),
462 : METH_VARARGS|METH_KEYWORDS, NULL },
463 : { "session_info_fill_unix",
464 : PY_DISCARD_FUNC_SIG(PyCFunction,py_session_info_fill_unix),
465 : METH_VARARGS|METH_KEYWORDS,
466 : NULL },
467 : { "session_info_set_unix",
468 : PY_DISCARD_FUNC_SIG(PyCFunction,py_session_info_set_unix),
469 : METH_VARARGS|METH_KEYWORDS,
470 : NULL },
471 : { "copy_session_info",
472 : PY_DISCARD_FUNC_SIG(PyCFunction,py_copy_session_info),
473 : METH_VARARGS|METH_KEYWORDS,
474 : NULL },
475 : {0},
476 : };
477 :
478 : static struct PyModuleDef moduledef = {
479 : PyModuleDef_HEAD_INIT,
480 : .m_name = "auth",
481 : .m_doc = "Authentication and authorization support.",
482 : .m_size = -1,
483 : .m_methods = py_auth_methods,
484 : };
485 :
486 7633 : MODULE_INIT_FUNC(auth)
487 : {
488 192 : PyObject *m;
489 :
490 7633 : if (pytalloc_BaseObject_PyType_Ready(&PyAuthContext) < 0)
491 0 : return NULL;
492 :
493 7633 : m = PyModule_Create(&moduledef);
494 7633 : if (m == NULL)
495 0 : return NULL;
496 :
497 6390 : Py_INCREF(&PyAuthContext);
498 7633 : PyModule_AddObject(m, "AuthContext", (PyObject *)&PyAuthContext);
499 :
500 : #define ADD_FLAG(val) PyModule_AddIntConstant(m, #val, val)
501 7633 : ADD_FLAG(AUTH_SESSION_INFO_DEFAULT_GROUPS);
502 7633 : ADD_FLAG(AUTH_SESSION_INFO_AUTHENTICATED);
503 7633 : ADD_FLAG(AUTH_SESSION_INFO_SIMPLE_PRIVILEGES);
504 7633 : ADD_FLAG(AUTH_SESSION_INFO_NTLM);
505 :
506 7633 : return m;
507 : }
|