LCOV - code coverage report
Current view: top level - source4/auth - pyauth.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 153 236 64.8 %
Date: 2021-09-23 10:06:22 Functions: 11 12 91.7 %

          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       20085 : static PyObject *PyAuthSession_FromSession(struct auth_session_info *session)
      41             : {
      42       20667 :         return py_return_ndr_struct("samba.dcerpc.auth", "session_info", session, session);
      43             : }
      44             : 
      45         942 : static PyObject *py_copy_session_info(PyObject *module,
      46             :                                       PyObject *args,
      47             :                                       PyObject *kwargs)
      48             : {
      49         942 :         PyObject *py_session = Py_None;
      50         942 :         PyObject *result = Py_None;
      51         942 :         struct auth_session_info *session = NULL;
      52         942 :         struct auth_session_info *session_duplicate = NULL;
      53             :         TALLOC_CTX *frame;
      54         942 :         int ret = 1;
      55             : 
      56         942 :         const char * const kwnames[] = { "session_info", NULL };
      57             : 
      58         942 :         ret = PyArg_ParseTupleAndKeywords(args,
      59             :                                           kwargs,
      60             :                                           "O",
      61             :                                           discard_const_p(char *, kwnames),
      62             :                                           &py_session);
      63         942 :         if (!ret) {
      64           0 :                 return NULL;
      65             :         }
      66             : 
      67         942 :         ret = py_check_dcerpc_type(py_session,
      68             :                                    "samba.dcerpc.auth",
      69             :                                    "session_info");
      70         942 :         if (!ret) {
      71           0 :                 return NULL;
      72             :         }
      73         942 :         session = pytalloc_get_type(py_session,
      74             :                                     struct auth_session_info);
      75         942 :         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         942 :         frame = talloc_stackframe();
      84         942 :         if (frame == NULL) {
      85           0 :                 return PyErr_NoMemory();
      86             :         }
      87             : 
      88         942 :         session_duplicate = copy_session_info(frame, session);
      89         942 :         if (session_duplicate == NULL) {
      90           0 :                 TALLOC_FREE(frame);
      91           0 :                 return PyErr_NoMemory();
      92             :         }
      93             : 
      94         942 :         result = PyAuthSession_FromSession(session_duplicate);
      95         942 :         TALLOC_FREE(frame);
      96         942 :         return result;
      97             : }
      98             : 
      99       18499 : static PyObject *py_system_session(PyObject *module, PyObject *args)
     100             : {
     101       18499 :         PyObject *py_lp_ctx = Py_None;
     102       18499 :         struct loadparm_context *lp_ctx = NULL;
     103             :         struct auth_session_info *session;
     104             :         TALLOC_CTX *mem_ctx;
     105       18499 :         if (!PyArg_ParseTuple(args, "|O", &py_lp_ctx))
     106           0 :                 return NULL;
     107             : 
     108       18499 :         mem_ctx = talloc_new(NULL);
     109       18499 :         if (mem_ctx == NULL) {
     110           0 :                 PyErr_NoMemory();
     111           0 :                 return NULL;
     112             :         }
     113             : 
     114       18499 :         lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
     115       18499 :         if (lp_ctx == NULL) {
     116           0 :                 talloc_free(mem_ctx);
     117           0 :                 return NULL;
     118             :         }
     119             : 
     120       18499 :         session = system_session(lp_ctx);
     121             : 
     122       18499 :         talloc_free(mem_ctx);
     123             : 
     124       18499 :         return PyAuthSession_FromSession(session);
     125             : }
     126             : 
     127             : 
     128        1068 : static PyObject *py_admin_session(PyObject *module, PyObject *args)
     129             : {
     130             :         PyObject *py_lp_ctx;
     131             :         const char *sid;
     132        1068 :         struct loadparm_context *lp_ctx = NULL;
     133             :         struct auth_session_info *session;
     134        1068 :         struct dom_sid *domain_sid = NULL;
     135             :         TALLOC_CTX *mem_ctx;
     136             : 
     137        1068 :         if (!PyArg_ParseTuple(args, "Os", &py_lp_ctx, &sid))
     138           0 :                 return NULL;
     139             : 
     140        1068 :         mem_ctx = talloc_new(NULL);
     141        1068 :         if (mem_ctx == NULL) {
     142           0 :                 PyErr_NoMemory();
     143           0 :                 return NULL;
     144             :         }
     145             : 
     146        1068 :         lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
     147        1068 :         if (lp_ctx == NULL) {
     148           0 :                 talloc_free(mem_ctx);
     149           0 :                 return NULL;
     150             :         }
     151             : 
     152        1068 :         domain_sid = dom_sid_parse_talloc(mem_ctx, sid);
     153        1068 :         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        1068 :         session = admin_session(NULL, lp_ctx, domain_sid);
     159        1068 :         talloc_free(mem_ctx);
     160             : 
     161        1068 :         return PyAuthSession_FromSession(session);
     162             : }
     163             : 
     164         158 : 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         158 :         const char * const kwnames[] = { "ldb", "lp_ctx", "principal", "dn", "session_info_flags", NULL };
     170             :         struct ldb_context *ldb_ctx;
     171         158 :         PyObject *py_ldb = Py_None;
     172         158 :         PyObject *py_dn = Py_None;
     173         158 :         PyObject *py_lp_ctx = Py_None;
     174         158 :         struct loadparm_context *lp_ctx = NULL;
     175             :         struct ldb_dn *user_dn;
     176         158 :         char *principal = NULL;
     177         158 :         int session_info_flags = 0; /* This is an int, because that's
     178             :                                  * what we need for the python
     179             :                                  * PyArg_ParseTupleAndKeywords */
     180             : 
     181         158 :         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         158 :         mem_ctx = talloc_new(NULL);
     188         158 :         if (mem_ctx == NULL) {
     189           0 :                 PyErr_NoMemory();
     190           0 :                 return NULL;
     191             :         }
     192             : 
     193         158 :         ldb_ctx = pyldb_Ldb_AsLdbContext(py_ldb);
     194         158 :         if (ldb_ctx == NULL) {
     195           0 :                 talloc_free(mem_ctx);
     196           0 :                 return NULL;
     197             :         }
     198             : 
     199         158 :         if (py_dn == Py_None) {
     200           0 :                 user_dn = NULL;
     201             :         } else {
     202         158 :                 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         158 :         lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
     209         158 :         if (lp_ctx == NULL) {
     210           0 :                 talloc_free(mem_ctx);
     211           0 :                 return NULL;
     212             :         }
     213             : 
     214         158 :         nt_status = authsam_get_session_info_principal(mem_ctx, lp_ctx, ldb_ctx, principal, user_dn,
     215             :                                                        session_info_flags, &session);
     216         158 :         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         158 :         talloc_steal(NULL, session);
     222         158 :         talloc_free(mem_ctx);
     223             : 
     224         177 :         return PyAuthSession_FromSession(session);
     225             : }
     226             : 
     227        1495 : static PyObject *py_session_info_fill_unix(PyObject *module,
     228             :                                            PyObject *args,
     229             :                                            PyObject *kwargs)
     230             : {
     231             :         NTSTATUS nt_status;
     232        1495 :         char *user_name = NULL;
     233        1495 :         struct loadparm_context *lp_ctx = NULL;
     234             :         struct auth_session_info *session_info;
     235        1495 :         PyObject *py_lp_ctx = Py_None;
     236        1495 :         PyObject *py_session = Py_None;
     237             :         TALLOC_CTX *frame;
     238             : 
     239        1495 :         const char * const kwnames[] = { "session_info",
     240             :                                          "user_name",
     241             :                                          "lp_ctx",
     242             :                                          NULL };
     243        1495 :         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        1495 :         if (!py_check_dcerpc_type(py_session,
     252             :                                   "samba.dcerpc.auth",
     253             :                                   "session_info")) {
     254           0 :                 return NULL;
     255             :         }
     256        1495 :         session_info = pytalloc_get_type(py_session,
     257             :                                          struct auth_session_info);
     258        1495 :         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        1495 :         frame = talloc_stackframe();
     266             :         
     267        1495 :         lp_ctx = lpcfg_from_py_object(frame, py_lp_ctx);
     268        1495 :         if (lp_ctx == NULL) {
     269           0 :                 TALLOC_FREE(frame);
     270           0 :                 return NULL;
     271             :         }
     272             : 
     273        1495 :         nt_status = auth_session_info_fill_unix(lp_ctx,
     274             :                                                user_name,
     275             :                                                session_info);
     276        1495 :         TALLOC_FREE(frame);
     277        1495 :         if (!NT_STATUS_IS_OK(nt_status)) {
     278           0 :                 PyErr_NTSTATUS_IS_ERR_RAISE(nt_status);
     279             :         }
     280             : 
     281        1495 :         Py_RETURN_NONE;
     282             : }
     283             : 
     284             : 
     285         106 : static PyObject *py_session_info_set_unix(PyObject *module,
     286             :                                           PyObject *args,
     287             :                                           PyObject *kwargs)
     288             : {
     289             :         NTSTATUS nt_status;
     290         106 :         char *user_name = NULL;
     291         106 :         int uid = -1;
     292         106 :         int gid = -1;
     293         106 :         struct loadparm_context *lp_ctx = NULL;
     294             :         struct auth_session_info *session_info;
     295         106 :         PyObject *py_lp_ctx = Py_None;
     296         106 :         PyObject *py_session = Py_None;
     297             :         TALLOC_CTX *frame;
     298             : 
     299         106 :         const char * const kwnames[] = { "session_info",
     300             :                                          "user_name",
     301             :                                          "uid",
     302             :                                          "gid",
     303             :                                          "lp_ctx",
     304             :                                          NULL };
     305             : 
     306         106 :         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         106 :         if (!py_check_dcerpc_type(py_session,
     317             :                                   "samba.dcerpc.auth",
     318             :                                   "session_info")) {
     319           0 :                 return NULL;
     320             :         }
     321         106 :         session_info = pytalloc_get_type(py_session,
     322             :                                          struct auth_session_info);
     323         106 :         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         106 :         frame = talloc_stackframe();
     332             : 
     333         106 :         lp_ctx = lpcfg_from_py_object(frame, py_lp_ctx);
     334         106 :         if (lp_ctx == NULL) {
     335           0 :                 TALLOC_FREE(frame);
     336           0 :                 return NULL;
     337             :         }
     338             : 
     339         106 :         nt_status = auth_session_info_set_unix(lp_ctx,
     340             :                                                user_name,
     341             :                                                uid,
     342             :                                                gid,
     343             :                                                session_info);
     344         106 :         TALLOC_FREE(frame);
     345         106 :         if (!NT_STATUS_IS_OK(nt_status)) {
     346           0 :                 PyErr_NTSTATUS_IS_ERR_RAISE(nt_status);
     347             :         }
     348             : 
     349         106 :         Py_RETURN_NONE;
     350             : }
     351             : 
     352             : 
     353           4 : 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           4 :         if (!PyList_Check(list)) {
     359           0 :                 PyErr_Format(PyExc_TypeError, "%s is not a list", paramname);
     360           0 :                 return NULL;
     361             :         }
     362           4 :         ret = talloc_array(NULL, const char *, PyList_Size(list)+1);
     363           4 :         if (ret == NULL) {
     364           0 :                 PyErr_NoMemory();
     365           0 :                 return NULL;
     366             :         }
     367             : 
     368           8 :         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           4 :         ret[i] = NULL;
     384           4 :         return ret;
     385             : }
     386             : 
     387          14 : static PyObject *PyAuthContext_FromContext(struct auth4_context *auth_context)
     388             : {
     389          14 :         return pytalloc_reference(&PyAuthContext, auth_context);
     390             : }
     391             : 
     392          14 : static PyObject *py_auth_context_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
     393             : {
     394          14 :         PyObject *py_lp_ctx = Py_None;
     395          14 :         PyObject *py_ldb = Py_None;
     396          14 :         PyObject *py_auth_context = Py_None;
     397          14 :         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          14 :         struct ldb_context *ldb = NULL;
     403             :         NTSTATUS nt_status;
     404             :         const char **methods;
     405             : 
     406          14 :         const char *const kwnames[] = {"lp_ctx", "ldb", "methods", NULL};
     407             : 
     408          14 :         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          14 :         mem_ctx = talloc_new(NULL);
     418          14 :         if (mem_ctx == NULL) {
     419           0 :                 PyErr_NoMemory();
     420           0 :                 return NULL;
     421             :         }
     422             : 
     423          14 :         if (py_ldb != Py_None) {
     424           4 :                 ldb = pyldb_Ldb_AsLdbContext(py_ldb);
     425           4 :                 if (ldb == NULL) {
     426           0 :                         talloc_free(mem_ctx);
     427           0 :                         return NULL;
     428             :                 }
     429             :         }
     430             : 
     431          14 :         lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
     432          14 :         if (lp_ctx == NULL) {
     433           0 :                 talloc_free(mem_ctx);
     434           0 :                 PyErr_NoMemory();
     435           0 :                 return NULL;
     436             :         }
     437             : 
     438          14 :         ev = s4_event_context_init(mem_ctx);
     439          14 :         if (ev == NULL) {
     440           0 :                 talloc_free(mem_ctx);
     441           0 :                 PyErr_NoMemory();
     442           0 :                 return NULL;
     443             :         }
     444             : 
     445          14 :         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           4 :                 if (py_methods != Py_None) {
     450           4 :                         methods = PyList_AsStringList(mem_ctx, py_methods, "methods");
     451           4 :                         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           4 :                 nt_status = auth_context_create_methods(
     459             :                     mem_ctx, methods, ev, NULL, lp_ctx, ldb, &auth_context);
     460             :         }
     461             : 
     462          14 :         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          14 :         if (!talloc_reference(auth_context, lp_ctx)) {
     468           0 :                 talloc_free(mem_ctx);
     469           0 :                 PyErr_NoMemory();
     470           0 :                 return NULL;
     471             :         }
     472             : 
     473          14 :         if (!talloc_reference(auth_context, ev)) {
     474           0 :                 talloc_free(mem_ctx);
     475           0 :                 PyErr_NoMemory();
     476           0 :                 return NULL;
     477             :         }
     478             : 
     479          14 :         py_auth_context = PyAuthContext_FromContext(auth_context);
     480             : 
     481          14 :         talloc_free(mem_ctx);
     482             : 
     483          14 :         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        4883 : MODULE_INIT_FUNC(auth)
     521             : {
     522             :         PyObject *m;
     523             : 
     524        4883 :         if (pytalloc_BaseObject_PyType_Ready(&PyAuthContext) < 0)
     525           0 :                 return NULL;
     526             : 
     527        4883 :         m = PyModule_Create(&moduledef);
     528        4883 :         if (m == NULL)
     529           0 :                 return NULL;
     530             : 
     531        4883 :         Py_INCREF(&PyAuthContext);
     532        4883 :         PyModule_AddObject(m, "AuthContext", (PyObject *)&PyAuthContext);
     533             : 
     534             : #define ADD_FLAG(val)  PyModule_AddIntConstant(m, #val, val)
     535        4883 :         ADD_FLAG(AUTH_SESSION_INFO_DEFAULT_GROUPS);
     536        4883 :         ADD_FLAG(AUTH_SESSION_INFO_AUTHENTICATED);
     537        4883 :         ADD_FLAG(AUTH_SESSION_INFO_SIMPLE_PRIVILEGES);
     538        4883 :         ADD_FLAG(AUTH_SESSION_INFO_NTLM);
     539             : 
     540        4883 :         return m;
     541             : }

Generated by: LCOV version 1.13