LCOV - code coverage report
Current view: top level - source4/auth - pyauth.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 165 241 68.5 %
Date: 2024-02-28 12:06:22 Functions: 10 10 100.0 %

          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       26611 : static PyObject *PyAuthSession_FromSession(struct auth_session_info *session)
      41             : {
      42       26611 :         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       24147 : static PyObject *py_system_session(PyObject *module, PyObject *args)
     100             : {
     101       24147 :         PyObject *py_lp_ctx = Py_None;
     102       24147 :         struct loadparm_context *lp_ctx = NULL;
     103         419 :         struct auth_session_info *session;
     104         419 :         TALLOC_CTX *mem_ctx;
     105       24147 :         if (!PyArg_ParseTuple(args, "|O", &py_lp_ctx))
     106           0 :                 return NULL;
     107             : 
     108       24147 :         mem_ctx = talloc_new(NULL);
     109       24147 :         if (mem_ctx == NULL) {
     110           0 :                 PyErr_NoMemory();
     111           0 :                 return NULL;
     112             :         }
     113             : 
     114       24147 :         lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
     115       24147 :         if (lp_ctx == NULL) {
     116           0 :                 talloc_free(mem_ctx);
     117           0 :                 return NULL;
     118             :         }
     119             : 
     120       24147 :         session = system_session(lp_ctx);
     121             : 
     122       24147 :         talloc_free(mem_ctx);
     123             : 
     124       24147 :         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          45 : static PyObject *PyAuthContext_FromContext(struct auth4_context *auth_context)
     354             : {
     355          45 :         return pytalloc_reference(&PyAuthContext, auth_context);
     356             : }
     357             : 
     358          45 : static PyObject *py_auth_context_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
     359             : {
     360          45 :         PyObject *py_lp_ctx = Py_None;
     361          45 :         PyObject *py_ldb = Py_None;
     362          45 :         PyObject *py_auth_context = Py_None;
     363          45 :         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          45 :         struct ldb_context *ldb = NULL;
     369           0 :         NTSTATUS nt_status;
     370           0 :         const char *const *methods;
     371             : 
     372          45 :         const char *const kwnames[] = {"lp_ctx", "ldb", "methods", NULL};
     373             : 
     374          45 :         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          45 :         mem_ctx = talloc_new(NULL);
     384          45 :         if (mem_ctx == NULL) {
     385           0 :                 PyErr_NoMemory();
     386           0 :                 return NULL;
     387             :         }
     388             : 
     389          45 :         if (py_ldb != Py_None) {
     390           5 :                 ldb = pyldb_Ldb_AsLdbContext(py_ldb);
     391           5 :                 if (ldb == NULL) {
     392           0 :                         talloc_free(mem_ctx);
     393           0 :                         return NULL;
     394             :                 }
     395             :         }
     396             : 
     397          45 :         lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
     398          45 :         if (lp_ctx == NULL) {
     399           0 :                 talloc_free(mem_ctx);
     400           0 :                 PyErr_NoMemory();
     401           0 :                 return NULL;
     402             :         }
     403             : 
     404          45 :         ev = s4_event_context_init(mem_ctx);
     405          45 :         if (ev == NULL) {
     406           0 :                 talloc_free(mem_ctx);
     407           0 :                 PyErr_NoMemory();
     408           0 :                 return NULL;
     409             :         }
     410             : 
     411          45 :         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           5 :                 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           0 :                         methods = auth_methods_from_lp(mem_ctx, lp_ctx);
     423             :                 }
     424           5 :                 nt_status = auth_context_create_methods(
     425             :                     mem_ctx, methods, ev, NULL, lp_ctx, ldb, &auth_context);
     426             :         }
     427             : 
     428          45 :         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          45 :         if (!talloc_reference(auth_context, lp_ctx)) {
     434           0 :                 talloc_free(mem_ctx);
     435           0 :                 PyErr_NoMemory();
     436           0 :                 return NULL;
     437             :         }
     438             : 
     439          45 :         if (!talloc_reference(auth_context, ev)) {
     440           0 :                 talloc_free(mem_ctx);
     441           0 :                 PyErr_NoMemory();
     442           0 :                 return NULL;
     443             :         }
     444             : 
     445          45 :         py_auth_context = PyAuthContext_FromContext(auth_context);
     446             : 
     447          45 :         talloc_free(mem_ctx);
     448             : 
     449          45 :         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        7889 : MODULE_INIT_FUNC(auth)
     487             : {
     488         192 :         PyObject *m;
     489             : 
     490        7889 :         if (pytalloc_BaseObject_PyType_Ready(&PyAuthContext) < 0)
     491           0 :                 return NULL;
     492             : 
     493        7889 :         m = PyModule_Create(&moduledef);
     494        7889 :         if (m == NULL)
     495           0 :                 return NULL;
     496             : 
     497        6646 :         Py_INCREF(&PyAuthContext);
     498        7889 :         PyModule_AddObject(m, "AuthContext", (PyObject *)&PyAuthContext);
     499             : 
     500             : #define ADD_FLAG(val)  PyModule_AddIntConstant(m, #val, val)
     501        7889 :         ADD_FLAG(AUTH_SESSION_INFO_DEFAULT_GROUPS);
     502        7889 :         ADD_FLAG(AUTH_SESSION_INFO_AUTHENTICATED);
     503        7889 :         ADD_FLAG(AUTH_SESSION_INFO_SIMPLE_PRIVILEGES);
     504        7889 :         ADD_FLAG(AUTH_SESSION_INFO_NTLM);
     505             : 
     506        7889 :         return m;
     507             : }

Generated by: LCOV version 1.14