s3:libsmb: allow store_cldap_reply() to work with a ipv6 response
[samba.git] / source4 / auth / pyauth.c
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 static PyObject *PyAuthSession_FromSession(struct auth_session_info *session)
41 {
42         return py_return_ndr_struct("samba.dcerpc.auth", "session_info", session, session);
43 }
44
45 static PyObject *py_copy_session_info(PyObject *module,
46                                       PyObject *args,
47                                       PyObject *kwargs)
48 {
49         PyObject *py_session = Py_None;
50         PyObject *result = Py_None;
51         struct auth_session_info *session = NULL;
52         struct auth_session_info *session_duplicate = NULL;
53         TALLOC_CTX *frame;
54         int ret = 1;
55
56         const char * const kwnames[] = { "session_info", NULL };
57
58         ret = PyArg_ParseTupleAndKeywords(args,
59                                           kwargs,
60                                           "O",
61                                           discard_const_p(char *, kwnames),
62                                           &py_session);
63         if (!ret) {
64                 return NULL;
65         }
66
67         ret = py_check_dcerpc_type(py_session,
68                                    "samba.dcerpc.auth",
69                                    "session_info");
70         if (!ret) {
71                 return NULL;
72         }
73         session = pytalloc_get_type(py_session,
74                                     struct auth_session_info);
75         if (!session) {
76                 PyErr_Format(PyExc_TypeError,
77                              "Expected auth_session_info for session_info "
78                              "argument got %s",
79                              pytalloc_get_name(py_session));
80                 return NULL;
81         }
82
83         frame = talloc_stackframe();
84         if (frame == NULL) {
85                 return PyErr_NoMemory();
86         }
87
88         session_duplicate = copy_session_info(frame, session);
89         if (session_duplicate == NULL) {
90                 TALLOC_FREE(frame);
91                 return PyErr_NoMemory();
92         }
93
94         result = PyAuthSession_FromSession(session_duplicate);
95         TALLOC_FREE(frame);
96         return result;
97 }
98
99 static PyObject *py_system_session(PyObject *module, PyObject *args)
100 {
101         PyObject *py_lp_ctx = Py_None;
102         struct loadparm_context *lp_ctx = NULL;
103         struct auth_session_info *session;
104         TALLOC_CTX *mem_ctx;
105         if (!PyArg_ParseTuple(args, "|O", &py_lp_ctx))
106                 return NULL;
107
108         mem_ctx = talloc_new(NULL);
109         if (mem_ctx == NULL) {
110                 PyErr_NoMemory();
111                 return NULL;
112         }
113
114         lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
115         if (lp_ctx == NULL) {
116                 talloc_free(mem_ctx);
117                 return NULL;
118         }
119
120         session = system_session(lp_ctx);
121
122         talloc_free(mem_ctx);
123
124         return PyAuthSession_FromSession(session);
125 }
126
127
128 static PyObject *py_admin_session(PyObject *module, PyObject *args)
129 {
130         PyObject *py_lp_ctx;
131         const char *sid;
132         struct loadparm_context *lp_ctx = NULL;
133         struct auth_session_info *session;
134         struct dom_sid *domain_sid = NULL;
135         TALLOC_CTX *mem_ctx;
136
137         if (!PyArg_ParseTuple(args, "Os", &py_lp_ctx, &sid))
138                 return NULL;
139
140         mem_ctx = talloc_new(NULL);
141         if (mem_ctx == NULL) {
142                 PyErr_NoMemory();
143                 return NULL;
144         }
145
146         lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
147         if (lp_ctx == NULL) {
148                 talloc_free(mem_ctx);
149                 return NULL;
150         }
151
152         domain_sid = dom_sid_parse_talloc(mem_ctx, sid);
153         if (domain_sid == NULL) {
154                 PyErr_Format(PyExc_RuntimeError, "Unable to parse sid %s", sid);
155                 talloc_free(mem_ctx);
156                 return NULL;
157         }
158         session = admin_session(NULL, lp_ctx, domain_sid);
159         talloc_free(mem_ctx);
160
161         return PyAuthSession_FromSession(session);
162 }
163
164 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         const char * const kwnames[] = { "ldb", "lp_ctx", "principal", "dn", "session_info_flags", NULL };
170         struct ldb_context *ldb_ctx;
171         PyObject *py_ldb = Py_None;
172         PyObject *py_dn = Py_None;
173         PyObject *py_lp_ctx = Py_None;
174         struct loadparm_context *lp_ctx = NULL;
175         struct ldb_dn *user_dn;
176         char *principal = NULL;
177         int session_info_flags = 0; /* This is an int, because that's
178                                  * what we need for the python
179                                  * PyArg_ParseTupleAndKeywords */
180
181         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                 return NULL;
185         }
186
187         mem_ctx = talloc_new(NULL);
188         if (mem_ctx == NULL) {
189                 PyErr_NoMemory();
190                 return NULL;
191         }
192
193         ldb_ctx = pyldb_Ldb_AsLdbContext(py_ldb);
194         if (ldb_ctx == NULL) {
195                 talloc_free(mem_ctx);
196                 return NULL;
197         }
198
199         if (py_dn == Py_None) {
200                 user_dn = NULL;
201         } else {
202                 if (!pyldb_Object_AsDn(ldb_ctx, py_dn, ldb_ctx, &user_dn)) {
203                         talloc_free(mem_ctx);
204                         return NULL;
205                 }
206         }
207
208         lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
209         if (lp_ctx == NULL) {
210                 talloc_free(mem_ctx);
211                 return NULL;
212         }
213
214         nt_status = authsam_get_session_info_principal(mem_ctx, lp_ctx, ldb_ctx, principal, user_dn,
215                                                        session_info_flags, &session);
216         if (!NT_STATUS_IS_OK(nt_status)) {
217                 talloc_free(mem_ctx);
218                 PyErr_NTSTATUS_IS_ERR_RAISE(nt_status);
219         }
220
221         talloc_steal(NULL, session);
222         talloc_free(mem_ctx);
223
224         return PyAuthSession_FromSession(session);
225 }
226
227 static PyObject *py_session_info_fill_unix(PyObject *module,
228                                            PyObject *args,
229                                            PyObject *kwargs)
230 {
231         NTSTATUS nt_status;
232         char *user_name = NULL;
233         struct loadparm_context *lp_ctx = NULL;
234         struct auth_session_info *session_info;
235         PyObject *py_lp_ctx = Py_None;
236         PyObject *py_session = Py_None;
237         TALLOC_CTX *frame;
238
239         const char * const kwnames[] = { "session_info",
240                                          "user_name",
241                                          "lp_ctx",
242                                          NULL };
243         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oz|O",
244                                          discard_const_p(char *, kwnames),
245                                          &py_session,
246                                          &user_name,
247                                          &py_lp_ctx)) {
248                 return NULL;
249         }
250
251         if (!py_check_dcerpc_type(py_session,
252                                   "samba.dcerpc.auth",
253                                   "session_info")) {
254                 return NULL;
255         }
256         session_info = pytalloc_get_type(py_session,
257                                          struct auth_session_info);
258         if (!session_info) {
259                 PyErr_Format(PyExc_TypeError,
260                              "Expected auth_session_info for session_info argument got %s",
261                              pytalloc_get_name(py_session));
262                 return NULL;
263         }
264
265         frame = talloc_stackframe();
266         
267         lp_ctx = lpcfg_from_py_object(frame, py_lp_ctx);
268         if (lp_ctx == NULL) {
269                 TALLOC_FREE(frame);
270                 return NULL;
271         }
272
273         nt_status = auth_session_info_fill_unix(lp_ctx,
274                                                user_name,
275                                                session_info);
276         TALLOC_FREE(frame);
277         if (!NT_STATUS_IS_OK(nt_status)) {
278                 PyErr_NTSTATUS_IS_ERR_RAISE(nt_status);
279         }
280
281         Py_RETURN_NONE;
282 }
283
284
285 static PyObject *py_session_info_set_unix(PyObject *module,
286                                           PyObject *args,
287                                           PyObject *kwargs)
288 {
289         NTSTATUS nt_status;
290         char *user_name = NULL;
291         int uid = -1;
292         int gid = -1;
293         struct loadparm_context *lp_ctx = NULL;
294         struct auth_session_info *session_info;
295         PyObject *py_lp_ctx = Py_None;
296         PyObject *py_session = Py_None;
297         TALLOC_CTX *frame;
298
299         const char * const kwnames[] = { "session_info",
300                                          "user_name",
301                                          "uid",
302                                          "gid",
303                                          "lp_ctx",
304                                          NULL };
305
306         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                 return NULL;
314         }
315
316         if (!py_check_dcerpc_type(py_session,
317                                   "samba.dcerpc.auth",
318                                   "session_info")) {
319                 return NULL;
320         }
321         session_info = pytalloc_get_type(py_session,
322                                          struct auth_session_info);
323         if (!session_info) {
324                 PyErr_Format(PyExc_TypeError,
325                              "Expected auth_session_info for session_info "
326                              "argument got %s",
327                              pytalloc_get_name(py_session));
328                 return NULL;
329         }
330
331         frame = talloc_stackframe();
332
333         lp_ctx = lpcfg_from_py_object(frame, py_lp_ctx);
334         if (lp_ctx == NULL) {
335                 TALLOC_FREE(frame);
336                 return NULL;
337         }
338
339         nt_status = auth_session_info_set_unix(lp_ctx,
340                                                user_name,
341                                                uid,
342                                                gid,
343                                                session_info);
344         TALLOC_FREE(frame);
345         if (!NT_STATUS_IS_OK(nt_status)) {
346                 PyErr_NTSTATUS_IS_ERR_RAISE(nt_status);
347         }
348
349         Py_RETURN_NONE;
350 }
351
352
353 static PyObject *PyAuthContext_FromContext(struct auth4_context *auth_context)
354 {
355         return pytalloc_reference(&PyAuthContext, auth_context);
356 }
357
358 static PyObject *py_auth_context_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
359 {
360         PyObject *py_lp_ctx = Py_None;
361         PyObject *py_ldb = Py_None;
362         PyObject *py_auth_context = Py_None;
363         PyObject *py_methods = Py_None;
364         TALLOC_CTX *mem_ctx;
365         struct auth4_context *auth_context;
366         struct loadparm_context *lp_ctx;
367         struct tevent_context *ev;
368         struct ldb_context *ldb = NULL;
369         NTSTATUS nt_status;
370         const char *const *methods;
371
372         const char *const kwnames[] = {"lp_ctx", "ldb", "methods", NULL};
373
374         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                 return NULL;
382
383         mem_ctx = talloc_new(NULL);
384         if (mem_ctx == NULL) {
385                 PyErr_NoMemory();
386                 return NULL;
387         }
388
389         if (py_ldb != Py_None) {
390                 ldb = pyldb_Ldb_AsLdbContext(py_ldb);
391                 if (ldb == NULL) {
392                         talloc_free(mem_ctx);
393                         return NULL;
394                 }
395         }
396
397         lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
398         if (lp_ctx == NULL) {
399                 talloc_free(mem_ctx);
400                 PyErr_NoMemory();
401                 return NULL;
402         }
403
404         ev = s4_event_context_init(mem_ctx);
405         if (ev == NULL) {
406                 talloc_free(mem_ctx);
407                 PyErr_NoMemory();
408                 return NULL;
409         }
410
411         if (py_methods == Py_None && py_ldb == Py_None) {
412                 nt_status = auth_context_create(
413                     mem_ctx, ev, NULL, lp_ctx, &auth_context);
414         } else {
415                 if (py_methods != Py_None) {
416                         methods = (const char * const *)PyList_AsStringList(mem_ctx, py_methods, "methods");
417                         if (methods == NULL) {
418                                 talloc_free(mem_ctx);
419                                 return NULL;
420                         }
421                 } else {
422                         methods = auth_methods_from_lp(mem_ctx, lp_ctx);
423                 }
424                 nt_status = auth_context_create_methods(
425                     mem_ctx, methods, ev, NULL, lp_ctx, ldb, &auth_context);
426         }
427
428         if (!NT_STATUS_IS_OK(nt_status)) {
429                 talloc_free(mem_ctx);
430                 PyErr_NTSTATUS_IS_ERR_RAISE(nt_status);
431         }
432
433         if (!talloc_reference(auth_context, lp_ctx)) {
434                 talloc_free(mem_ctx);
435                 PyErr_NoMemory();
436                 return NULL;
437         }
438
439         if (!talloc_reference(auth_context, ev)) {
440                 talloc_free(mem_ctx);
441                 PyErr_NoMemory();
442                 return NULL;
443         }
444
445         py_auth_context = PyAuthContext_FromContext(auth_context);
446
447         talloc_free(mem_ctx);
448
449         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 MODULE_INIT_FUNC(auth)
487 {
488         PyObject *m;
489
490         if (pytalloc_BaseObject_PyType_Ready(&PyAuthContext) < 0)
491                 return NULL;
492
493         m = PyModule_Create(&moduledef);
494         if (m == NULL)
495                 return NULL;
496
497         Py_INCREF(&PyAuthContext);
498         PyModule_AddObject(m, "AuthContext", (PyObject *)&PyAuthContext);
499
500 #define ADD_FLAG(val)  PyModule_AddIntConstant(m, #val, val)
501         ADD_FLAG(AUTH_SESSION_INFO_DEFAULT_GROUPS);
502         ADD_FLAG(AUTH_SESSION_INFO_AUTHENTICATED);
503         ADD_FLAG(AUTH_SESSION_INFO_SIMPLE_PRIVILEGES);
504         ADD_FLAG(AUTH_SESSION_INFO_NTLM);
505
506         return m;
507 }