LCOV - code coverage report
Current view: top level - source4/auth/gensec - pygensec.c (source / functions) Hit Total Coverage
Test: coverage report for master 6248eab5 Lines: 228 372 61.3 %
Date: 2021-08-25 13:27:56 Functions: 20 24 83.3 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2009
       4             :    
       5             :    This program is free software; you can redistribute it and/or modify
       6             :    it under the terms of the GNU General Public License as published by
       7             :    the Free Software Foundation; either version 3 of the License, or
       8             :    (at your option) any later version.
       9             :    
      10             :    This program is distributed in the hope that it will be useful,
      11             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13             :    GNU General Public License for more details.
      14             :    
      15             :    You should have received a copy of the GNU General Public License
      16             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      17             : */
      18             : 
      19             : #include <Python.h>
      20             : #include "python/py3compat.h"
      21             : #include "includes.h"
      22             : #include "python/modules.h"
      23             : #include "param/pyparam.h"
      24             : #include "auth/gensec/gensec.h"
      25             : #include "auth/gensec/gensec_internal.h" /* TODO: remove this */
      26             : #include "auth/credentials/pycredentials.h"
      27             : #include "libcli/util/pyerrors.h"
      28             : #include "python/modules.h"
      29             : #include <pytalloc.h>
      30             : #include <tevent.h>
      31             : #include "librpc/rpc/pyrpc_util.h"
      32             : 
      33           0 : static PyObject *py_get_name_by_authtype(PyObject *self, PyObject *args)
      34             : {
      35             :         int type;
      36             :         const char *name;
      37             :         struct gensec_security *security;
      38             : 
      39           0 :         if (!PyArg_ParseTuple(args, "i", &type))
      40           0 :                 return NULL;
      41             : 
      42           0 :         security = pytalloc_get_type(self, struct gensec_security);
      43             : 
      44           0 :         name = gensec_get_name_by_authtype(security, type);
      45           0 :         if (name == NULL)
      46           0 :                 Py_RETURN_NONE;
      47             : 
      48           0 :         return PyUnicode_FromString(name);
      49             : }
      50             : 
      51         541 : static struct gensec_settings *settings_from_object(TALLOC_CTX *mem_ctx, PyObject *object)
      52             : {
      53             :         struct gensec_settings *s;
      54             :         PyObject *py_hostname, *py_lp_ctx;
      55             : 
      56         541 :         if (!PyDict_Check(object)) {
      57           0 :                 PyErr_SetString(PyExc_ValueError, "settings should be a dictionary");
      58           0 :                 return NULL;
      59             :         }
      60             : 
      61         541 :         s = talloc_zero(mem_ctx, struct gensec_settings);
      62         541 :         if (!s) return NULL;
      63             : 
      64         541 :         py_hostname = PyDict_GetItemString(object, "target_hostname");
      65         541 :         if (!py_hostname) {
      66           0 :                 PyErr_SetString(PyExc_ValueError, "settings.target_hostname not found");
      67           0 :                 return NULL;
      68             :         }
      69             : 
      70         541 :         py_lp_ctx = PyDict_GetItemString(object, "lp_ctx");
      71         541 :         if (!py_lp_ctx) {
      72           0 :                 PyErr_SetString(PyExc_ValueError, "settings.lp_ctx not found");
      73           0 :                 return NULL;
      74             :         }
      75             : 
      76         541 :         s->target_hostname = PyUnicode_AsUTF8(py_hostname);
      77         541 :         s->lp_ctx = lpcfg_from_py_object(s, py_lp_ctx);
      78         541 :         return s;
      79             : }
      80             : 
      81         527 : static PyObject *py_gensec_start_client(PyTypeObject *type, PyObject *args, PyObject *kwargs)
      82             : {
      83             :         NTSTATUS status;
      84             :         PyObject *self;
      85             :         struct gensec_settings *settings;
      86         527 :         const char *kwnames[] = { "settings", NULL };
      87         527 :         PyObject *py_settings = Py_None;
      88             :         struct gensec_security *gensec;
      89             :         TALLOC_CTX *frame;
      90             : 
      91         527 :         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", discard_const_p(char *, kwnames), &py_settings))
      92           0 :                 return NULL;
      93             : 
      94         527 :         frame = talloc_stackframe();
      95             : 
      96         527 :         if (py_settings != Py_None) {
      97         527 :                 settings = settings_from_object(frame, py_settings);
      98         527 :                 if (settings == NULL) {
      99           0 :                         PyErr_NoMemory();
     100           0 :                         TALLOC_FREE(frame);
     101           0 :                         return NULL;
     102             :                 }
     103             :         } else {
     104           0 :                 settings = talloc_zero(frame, struct gensec_settings);
     105           0 :                 if (settings == NULL) {
     106           0 :                         PyErr_NoMemory();
     107           0 :                         TALLOC_FREE(frame);
     108           0 :                         return NULL;
     109             :                 }
     110             : 
     111           0 :                 settings->lp_ctx = loadparm_init_global(true);
     112           0 :                 if (settings->lp_ctx == NULL) {
     113           0 :                         PyErr_NoMemory();
     114           0 :                         TALLOC_FREE(frame);
     115           0 :                         return NULL;
     116             :                 }
     117             :         }
     118             : 
     119         527 :         status = gensec_init();
     120         527 :         if (!NT_STATUS_IS_OK(status)) {
     121           0 :                 PyErr_SetNTSTATUS(status);
     122           0 :                 TALLOC_FREE(frame);
     123           0 :                 return NULL;
     124             :         }
     125             : 
     126         527 :         status = gensec_client_start(frame, &gensec, settings);
     127         527 :         if (!NT_STATUS_IS_OK(status)) {
     128           0 :                 PyErr_SetNTSTATUS(status);
     129           0 :                 TALLOC_FREE(frame);
     130           0 :                 return NULL;
     131             :         }
     132             : 
     133         527 :         self = pytalloc_steal(type, gensec);
     134         527 :         TALLOC_FREE(frame);
     135             : 
     136         527 :         return (PyObject *)self;
     137             : }
     138             : 
     139          14 : static PyObject *py_gensec_start_server(PyTypeObject *type, PyObject *args, PyObject *kwargs)
     140             : {
     141             :         NTSTATUS status;
     142             :         PyObject *self;
     143          14 :         struct gensec_settings *settings = NULL;
     144          14 :         const char *kwnames[] = { "settings", "auth_context", NULL };
     145          14 :         PyObject *py_settings = Py_None;
     146          14 :         PyObject *py_auth_context = Py_None;
     147             :         struct gensec_security *gensec;
     148          14 :         struct auth4_context *auth_context = NULL;
     149             :         TALLOC_CTX *frame;
     150             : 
     151          14 :         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OO", discard_const_p(char *, kwnames), &py_settings, &py_auth_context))
     152           0 :                 return NULL;
     153             : 
     154          14 :         frame = talloc_stackframe();
     155             : 
     156          14 :         if (py_settings != Py_None) {
     157          14 :                 settings = settings_from_object(frame, py_settings);
     158          14 :                 if (settings == NULL) {
     159           0 :                         PyErr_NoMemory();
     160           0 :                         TALLOC_FREE(frame);
     161           0 :                         return NULL;
     162             :                 }
     163             :         } else {
     164           0 :                 settings = talloc_zero(frame, struct gensec_settings);
     165           0 :                 if (settings == NULL) {
     166           0 :                         PyErr_NoMemory();
     167           0 :                         TALLOC_FREE(frame);
     168           0 :                         return NULL;
     169             :                 }
     170             : 
     171           0 :                 settings->lp_ctx = loadparm_init_global(true);
     172           0 :                 if (settings->lp_ctx == NULL) {
     173           0 :                         PyErr_NoMemory();
     174           0 :                         TALLOC_FREE(frame);
     175           0 :                         return NULL;
     176             :                 }
     177             :         }
     178             : 
     179          14 :         if (py_auth_context != Py_None) {
     180          14 :                 bool ok = py_check_dcerpc_type(py_auth_context,
     181             :                                                "samba.auth",
     182             :                                                "AuthContext");
     183          14 :                 if (!ok) {
     184           0 :                         return NULL;
     185             :                 }
     186             : 
     187          14 :                 auth_context = pytalloc_get_type(py_auth_context,
     188             :                                                  struct auth4_context);
     189          14 :                 if (!auth_context) {
     190           0 :                         PyErr_Format(PyExc_TypeError,
     191             :                                      "Expected auth.AuthContext for auth_context argument, got %s",
     192             :                                      pytalloc_get_name(py_auth_context));
     193           0 :                         return NULL;
     194             :                 }
     195             :         }
     196             : 
     197          14 :         status = gensec_init();
     198          14 :         if (!NT_STATUS_IS_OK(status)) {
     199           0 :                 PyErr_SetNTSTATUS(status);
     200           0 :                 TALLOC_FREE(frame);
     201           0 :                 return NULL;
     202             :         }
     203             : 
     204          14 :         status = gensec_server_start(frame, settings, auth_context, &gensec);
     205          14 :         if (!NT_STATUS_IS_OK(status)) {
     206           0 :                 PyErr_SetNTSTATUS(status);
     207           0 :                 TALLOC_FREE(frame);
     208           0 :                 return NULL;
     209             :         }
     210             : 
     211          14 :         self = pytalloc_steal(type, gensec);
     212          14 :         TALLOC_FREE(frame);
     213             : 
     214          14 :         return self;
     215             : }
     216             : 
     217         221 : static PyObject *py_gensec_set_target_hostname(PyObject *self, PyObject *args)
     218             : {
     219         221 :         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
     220             :         char *target_hostname;
     221             :         NTSTATUS status;
     222             : 
     223         221 :         if (!PyArg_ParseTuple(args, "s", &target_hostname))
     224           0 :                 return NULL;
     225             : 
     226         221 :         status = gensec_set_target_hostname(security, target_hostname);
     227         221 :         if (!NT_STATUS_IS_OK(status)) {
     228           0 :                 PyErr_SetNTSTATUS(status);
     229           0 :                 return NULL;
     230             :         }
     231             :         
     232         221 :         Py_RETURN_NONE;
     233             : }
     234             : 
     235         221 : static PyObject *py_gensec_set_target_service(PyObject *self, PyObject *args)
     236             : {
     237         221 :         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
     238             :         char *target_service;
     239             :         NTSTATUS status;
     240             : 
     241         221 :         if (!PyArg_ParseTuple(args, "s", &target_service))
     242           0 :                 return NULL;
     243             : 
     244         221 :         status = gensec_set_target_service(security, target_service);
     245         221 :         if (!NT_STATUS_IS_OK(status)) {
     246           0 :                 PyErr_SetNTSTATUS(status);
     247           0 :                 return NULL;
     248             :         }
     249             :         
     250         221 :         Py_RETURN_NONE;
     251             : }
     252             : 
     253           0 : static PyObject *py_gensec_set_target_service_description(PyObject *self, PyObject *args)
     254             : {
     255           0 :         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
     256             :         char *target_service_description;
     257             :         NTSTATUS status;
     258             : 
     259           0 :         if (!PyArg_ParseTuple(args, "s", &target_service_description))
     260           0 :                 return NULL;
     261             : 
     262           0 :         status = gensec_set_target_service_description(security,
     263             :                                                        target_service_description);
     264           0 :         if (!NT_STATUS_IS_OK(status)) {
     265           0 :                 PyErr_SetNTSTATUS(status);
     266           0 :                 return NULL;
     267             :         }
     268             : 
     269           0 :         Py_RETURN_NONE;
     270             : }
     271             : 
     272         525 : static PyObject *py_gensec_set_credentials(PyObject *self, PyObject *args)
     273             : {
     274         525 :         PyObject *py_creds = Py_None;
     275             :         struct cli_credentials *creds;
     276         525 :         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
     277             :         NTSTATUS status;
     278             : 
     279         525 :         if (!PyArg_ParseTuple(args, "O", &py_creds))
     280           0 :                 return NULL;
     281             : 
     282         525 :         creds = PyCredentials_AsCliCredentials(py_creds);
     283         525 :         if (!creds) {
     284           0 :                 PyErr_Format(
     285             :                         PyExc_TypeError,
     286             :                         "Expected samba.credentials for credentials argument, "
     287             :                         "got %s", pytalloc_get_name(py_creds));
     288           0 :                 return NULL;
     289             :         }
     290             : 
     291         525 :         status = gensec_set_credentials(security, creds);
     292         525 :         if (!NT_STATUS_IS_OK(status)) {
     293           0 :                 PyErr_SetNTSTATUS(status);
     294           0 :                 return NULL;
     295             :         }
     296             : 
     297         525 :         Py_RETURN_NONE;
     298             : }
     299             : 
     300          15 : static PyObject *py_gensec_session_info(PyObject *self,
     301             :                 PyObject *Py_UNUSED(ignored))
     302             : {
     303             :         TALLOC_CTX *mem_ctx;
     304             :         NTSTATUS status;
     305             :         PyObject *py_session_info;
     306          15 :         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
     307             :         struct auth_session_info *info;
     308          15 :         if (security->ops == NULL) {
     309           1 :                 PyErr_SetString(PyExc_RuntimeError, "no mechanism selected");
     310           1 :                 return NULL;
     311             :         }
     312          14 :         mem_ctx = talloc_new(NULL);
     313          14 :         if (mem_ctx == NULL) {
     314           0 :                 return PyErr_NoMemory();
     315             :         }
     316             : 
     317          14 :         status = gensec_session_info(security, mem_ctx, &info);
     318          14 :         if (NT_STATUS_IS_ERR(status)) {
     319           0 :                 talloc_free(mem_ctx);
     320           0 :                 PyErr_SetNTSTATUS(status);
     321           0 :                 return NULL;
     322             :         }
     323             : 
     324          14 :         py_session_info = py_return_ndr_struct("samba.dcerpc.auth", "session_info",
     325             :                                                  info, info);
     326          14 :         talloc_free(mem_ctx);
     327          14 :         return py_session_info;
     328             : }
     329             : 
     330          20 : static PyObject *py_gensec_session_key(PyObject *self,
     331             :                 PyObject *Py_UNUSED(ignored))
     332             : {
     333             :         TALLOC_CTX *mem_ctx;
     334             :         NTSTATUS status;
     335          20 :         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
     336          20 :         DATA_BLOB session_key = data_blob_null;
     337             :         static PyObject *session_key_obj = NULL;
     338             : 
     339          20 :         if (security->ops == NULL) {
     340           0 :                 PyErr_SetString(PyExc_RuntimeError, "no mechanism selected");
     341           0 :                 return NULL;
     342             :         }
     343          20 :         mem_ctx = talloc_new(NULL);
     344          20 :         if (mem_ctx == NULL) {
     345           0 :                 return PyErr_NoMemory();
     346             :         }
     347             : 
     348          20 :         status = gensec_session_key(security, mem_ctx, &session_key);
     349          20 :         if (!NT_STATUS_IS_OK(status)) {
     350           0 :                 talloc_free(mem_ctx);
     351           0 :                 PyErr_SetNTSTATUS(status);
     352           0 :                 return NULL;
     353             :         }
     354             : 
     355          20 :         session_key_obj = PyBytes_FromStringAndSize((const char *)session_key.data,
     356          20 :                                                      session_key.length);
     357          20 :         talloc_free(mem_ctx);
     358          20 :         return session_key_obj;
     359             : }
     360             : 
     361          14 : static PyObject *py_gensec_start_mech_by_name(PyObject *self, PyObject *args)
     362             : {
     363             :         char *name;
     364          14 :         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
     365             :         NTSTATUS status;
     366             : 
     367          14 :         if (!PyArg_ParseTuple(args, "s", &name))
     368           0 :                 return NULL;
     369             : 
     370          14 :         status = gensec_start_mech_by_name(security, name);
     371          14 :         if (!NT_STATUS_IS_OK(status)) {
     372           1 :                 PyErr_SetNTSTATUS(status);
     373           1 :                 return NULL;
     374             :         }
     375             : 
     376          13 :         Py_RETURN_NONE;
     377             : }
     378             : 
     379         237 : static PyObject *py_gensec_start_mech_by_sasl_name(PyObject *self, PyObject *args)
     380             : {
     381             :         char *sasl_name;
     382         237 :         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
     383             :         NTSTATUS status;
     384             : 
     385         237 :         if (!PyArg_ParseTuple(args, "s", &sasl_name))
     386           0 :                 return NULL;
     387             : 
     388         237 :         status = gensec_start_mech_by_sasl_name(security, sasl_name);
     389         237 :         if (!NT_STATUS_IS_OK(status)) {
     390           0 :                 PyErr_SetNTSTATUS(status);
     391           0 :                 return NULL;
     392             :         }
     393             : 
     394         237 :         Py_RETURN_NONE;
     395             : }
     396             : 
     397         276 : static PyObject *py_gensec_start_mech_by_authtype(PyObject *self, PyObject *args)
     398             : {
     399             :         int authtype, level;
     400         276 :         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
     401             :         NTSTATUS status;
     402         276 :         if (!PyArg_ParseTuple(args, "ii", &authtype, &level))
     403           0 :                 return NULL;
     404             : 
     405         276 :         status = gensec_start_mech_by_authtype(security, authtype, level);
     406         276 :         if (!NT_STATUS_IS_OK(status)) {
     407           0 :                 PyErr_SetNTSTATUS(status);
     408           0 :                 return NULL;
     409             :         }
     410             : 
     411         276 :         Py_RETURN_NONE;
     412             : }
     413             : 
     414         554 : static PyObject *py_gensec_want_feature(PyObject *self, PyObject *args)
     415             : {
     416             :         int feature;
     417         554 :         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
     418             :         /* This is i (and declared as an int above) by design, as they are handled as an integer in python */
     419         554 :         if (!PyArg_ParseTuple(args, "i", &feature))
     420           0 :                 return NULL;
     421             : 
     422         554 :         gensec_want_feature(security, feature);
     423             : 
     424         554 :         Py_RETURN_NONE;
     425             : }
     426             : 
     427           0 : static PyObject *py_gensec_have_feature(PyObject *self, PyObject *args)
     428             : {
     429             :         int feature;
     430           0 :         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
     431             :         /* This is i (and declared as an int above) by design, as they are handled as an integer in python */
     432           0 :         if (!PyArg_ParseTuple(args, "i", &feature))
     433           0 :                 return NULL;
     434             : 
     435           0 :         if (gensec_have_feature(security, feature)) {
     436           0 :                 Py_RETURN_TRUE;
     437             :         } 
     438           0 :         Py_RETURN_FALSE;
     439             : }
     440             : 
     441           2 : static PyObject *py_gensec_set_max_update_size(PyObject *self, PyObject *args)
     442             : {
     443           2 :         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
     444           2 :         unsigned int max_update_size = 0;
     445             : 
     446           2 :         if (!PyArg_ParseTuple(args, "I", &max_update_size))
     447           0 :                 return NULL;
     448             : 
     449           2 :         gensec_set_max_update_size(security, max_update_size);
     450             : 
     451           2 :         Py_RETURN_NONE;
     452             : }
     453             : 
     454           0 : static PyObject *py_gensec_max_update_size(PyObject *self,
     455             :                 PyObject *Py_UNUSED(ignored))
     456             : {
     457           0 :         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
     458           0 :         unsigned int max_update_size = gensec_max_update_size(security);
     459             : 
     460           0 :         return PyLong_FromLong(max_update_size);
     461             : }
     462             : 
     463        2245 : static PyObject *py_gensec_update(PyObject *self, PyObject *args)
     464             : {
     465             :         NTSTATUS status;
     466             :         TALLOC_CTX *mem_ctx;
     467             :         DATA_BLOB in, out;
     468             :         PyObject *py_bytes, *result, *py_in;
     469        2245 :         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
     470             :         PyObject *finished_processing;
     471        2245 :         char *data = NULL;
     472             :         Py_ssize_t len;
     473             :         int err;
     474             : 
     475        2245 :         if (!PyArg_ParseTuple(args, "O", &py_in))
     476           0 :                 return NULL;
     477             : 
     478        2245 :         mem_ctx = talloc_new(NULL);
     479        2245 :         if (mem_ctx == NULL) {
     480           0 :                 return PyErr_NoMemory();
     481             :         }
     482             : 
     483        2245 :         err = PyBytes_AsStringAndSize(py_in, &data, &len);
     484        2245 :         if (err) {
     485           0 :                 talloc_free(mem_ctx);
     486           0 :                 return NULL;
     487             :         }
     488             : 
     489             :         /*
     490             :          * Make a copy of the input buffer, as gensec_update may modify its
     491             :          * input argument.
     492             :          */
     493        2245 :         in = data_blob_talloc(mem_ctx, data, len);
     494        2245 :         if (!in.data) {
     495           0 :                 talloc_free(mem_ctx);
     496           0 :                 return PyErr_NoMemory();
     497             :         }
     498             : 
     499        2245 :         status = gensec_update(security, mem_ctx, in, &out);
     500             : 
     501        2245 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)
     502         250 :             && !NT_STATUS_IS_OK(status)) {
     503           0 :                 PyErr_SetNTSTATUS(status);
     504           0 :                 talloc_free(mem_ctx);
     505           0 :                 return NULL;
     506             :         }
     507        2245 :         py_bytes = PyBytes_FromStringAndSize((const char *)out.data,
     508        2245 :                                              out.length);
     509        2245 :         talloc_free(mem_ctx);
     510             : 
     511        2245 :         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     512        1995 :                 finished_processing = Py_False;
     513             :         } else {
     514         250 :                 finished_processing = Py_True;
     515             :         }
     516             : 
     517        2245 :         result = PyTuple_Pack(2, finished_processing, py_bytes);
     518        2245 :         Py_XDECREF(py_bytes);
     519        2245 :         return result;
     520             : }
     521             : 
     522          20 : static PyObject *py_gensec_wrap(PyObject *self, PyObject *args)
     523             : {
     524             :         NTSTATUS status;
     525             : 
     526             :         TALLOC_CTX *mem_ctx;
     527             :         DATA_BLOB in, out;
     528             :         PyObject *ret, *py_in;
     529          20 :         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
     530             : 
     531          20 :         if (!PyArg_ParseTuple(args, "O", &py_in))
     532           0 :                 return NULL;
     533             : 
     534          20 :         mem_ctx = talloc_new(NULL);
     535          20 :         if (mem_ctx == NULL) {
     536           0 :                 return PyErr_NoMemory();
     537             :         }
     538             : 
     539          20 :         if (!PyBytes_Check(py_in)) {
     540           0 :                 talloc_free(mem_ctx);
     541           0 :                 PyErr_Format(PyExc_TypeError, "bytes expected");
     542           0 :                 return NULL;
     543             :         }
     544          20 :         in.data = (uint8_t *)PyBytes_AsString(py_in);
     545          20 :         in.length = PyBytes_Size(py_in);
     546             : 
     547          20 :         status = gensec_wrap(security, mem_ctx, &in, &out);
     548             : 
     549          20 :         if (!NT_STATUS_IS_OK(status)) {
     550           0 :                 PyErr_SetNTSTATUS(status);
     551           0 :                 talloc_free(mem_ctx);
     552           0 :                 return NULL;
     553             :         }
     554             : 
     555          20 :         ret = PyBytes_FromStringAndSize((const char *)out.data, out.length);
     556          20 :         talloc_free(mem_ctx);
     557          20 :         return ret;
     558             : }
     559             : 
     560             : 
     561          20 : static PyObject *py_gensec_unwrap(PyObject *self, PyObject *args)
     562             : {
     563             :         NTSTATUS status;
     564             : 
     565             :         TALLOC_CTX *mem_ctx;
     566             :         DATA_BLOB in, out;
     567             :         PyObject *ret, *py_in;
     568          20 :         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
     569          20 :         char *data = NULL;
     570             :         Py_ssize_t len;
     571             :         int err;
     572             : 
     573          20 :         if (!PyArg_ParseTuple(args, "O", &py_in))
     574           0 :                 return NULL;
     575             : 
     576          20 :         mem_ctx = talloc_new(NULL);
     577          20 :         if (mem_ctx == NULL) {
     578           0 :                 return PyErr_NoMemory();
     579             :         }
     580             : 
     581          20 :         err = PyBytes_AsStringAndSize(py_in, &data, &len);
     582          20 :         if (err) {
     583           0 :                 talloc_free(mem_ctx);
     584           0 :                 return NULL;
     585             :         }
     586             : 
     587             :         /*
     588             :          * Make a copy of the input buffer, as gensec_unwrap may modify its
     589             :          * input argument.
     590             :          */
     591          20 :         in = data_blob_talloc(mem_ctx, data, len);
     592          20 :         if (!in.data) {
     593           0 :                 talloc_free(mem_ctx);
     594           0 :                 return PyErr_NoMemory();
     595             :         }
     596             : 
     597          20 :         status = gensec_unwrap(security, mem_ctx, &in, &out);
     598             : 
     599          20 :         if (!NT_STATUS_IS_OK(status)) {
     600           0 :                 PyErr_SetNTSTATUS(status);
     601           0 :                 talloc_free(mem_ctx);
     602           0 :                 return NULL;
     603             :         }
     604             : 
     605          20 :         ret = PyBytes_FromStringAndSize((const char *)out.data, out.length);
     606          20 :         talloc_free(mem_ctx);
     607          20 :         return ret;
     608             : }
     609             : 
     610         246 : static PyObject *py_gensec_sig_size(PyObject *self, PyObject *args)
     611             : {
     612         246 :         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
     613         246 :         Py_ssize_t data_size = 0;
     614         246 :         size_t sig_size = 0;
     615             : 
     616         246 :         if (!PyArg_ParseTuple(args, "n", &data_size)) {
     617           0 :                 return NULL;
     618             :         }
     619             : 
     620         246 :         sig_size = gensec_sig_size(security, data_size);
     621             : 
     622         246 :         return PyLong_FromSize_t(sig_size);
     623             : }
     624             : 
     625         252 : static PyObject *py_gensec_sign_packet(PyObject *self, PyObject *args)
     626             : {
     627             :         NTSTATUS status;
     628         252 :         TALLOC_CTX *mem_ctx = NULL;
     629         252 :         Py_ssize_t data_length = 0;
     630         252 :         Py_ssize_t pdu_length = 0;
     631             :         DATA_BLOB data, pdu, sig;
     632             :         PyObject *py_sig;
     633         252 :         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
     634             : 
     635         252 :         if (!PyArg_ParseTuple(args, "z#z#", &data.data, &data_length, &pdu.data, &pdu_length)) {
     636           0 :                 return NULL;
     637             :         }
     638         252 :         data.length = data_length;
     639         252 :         pdu.length = pdu_length;
     640             : 
     641         252 :         mem_ctx = talloc_new(NULL);
     642         252 :         if (mem_ctx == NULL) {
     643           0 :                 return PyErr_NoMemory();
     644             :         }
     645             : 
     646         756 :         status = gensec_sign_packet(security, mem_ctx,
     647         252 :                                     data.data, data.length,
     648         252 :                                     pdu.data, pdu.length, &sig);
     649         252 :         if (!NT_STATUS_IS_OK(status)) {
     650           0 :                 PyErr_SetNTSTATUS(status);
     651           0 :                 talloc_free(mem_ctx);
     652           0 :                 return NULL;
     653             :         }
     654             : 
     655         252 :         py_sig = PyBytes_FromStringAndSize((const char *)sig.data, sig.length);
     656         252 :         talloc_free(mem_ctx);
     657         252 :         return py_sig;
     658             : }
     659             : 
     660         197 : static PyObject *py_gensec_check_packet(PyObject *self, PyObject *args)
     661             : {
     662             :         NTSTATUS status;
     663         197 :         Py_ssize_t data_length = 0;
     664         197 :         Py_ssize_t pdu_length = 0;
     665         197 :         Py_ssize_t sig_length = 0;
     666             :         DATA_BLOB data, pdu, sig;
     667         197 :         struct gensec_security *security = pytalloc_get_type(self, struct gensec_security);
     668             : 
     669         197 :         if (!PyArg_ParseTuple(args, "z#z#z#",
     670             :                               &data.data, &data_length,
     671             :                               &pdu.data, &pdu_length,
     672             :                               &sig.data, &sig_length)) {
     673           0 :                 return NULL;
     674             :         }
     675         197 :         data.length = data_length;
     676         197 :         pdu.length = pdu_length;
     677         197 :         sig.length = sig_length;
     678             : 
     679         591 :         status = gensec_check_packet(security,
     680         197 :                                      data.data, data.length,
     681         197 :                                      pdu.data, pdu.length, &sig);
     682         197 :         if (!NT_STATUS_IS_OK(status)) {
     683           0 :                 PyErr_SetNTSTATUS(status);
     684           0 :                 return NULL;
     685             :         }
     686             : 
     687         197 :         Py_RETURN_NONE;
     688             : }
     689             : 
     690             : static PyMethodDef py_gensec_security_methods[] = {
     691             :         { "start_client", PY_DISCARD_FUNC_SIG(PyCFunction,
     692             :                                               py_gensec_start_client),
     693             :                 METH_VARARGS|METH_KEYWORDS|METH_CLASS,
     694             :                 "S.start_client(settings) -> gensec" },
     695             :         { "start_server", PY_DISCARD_FUNC_SIG(PyCFunction,
     696             :                                               py_gensec_start_server),
     697             :                 METH_VARARGS|METH_KEYWORDS|METH_CLASS,
     698             :                 "S.start_server(auth_ctx, settings) -> gensec" },
     699             :         { "set_credentials", (PyCFunction)py_gensec_set_credentials, METH_VARARGS, 
     700             :                 "S.set_credentials(credentials)" },
     701             :         { "set_target_hostname", (PyCFunction)py_gensec_set_target_hostname, METH_VARARGS, 
     702             :                 "S.set_target_hostname(target_hostname) \n This sets the Kerberos target hostname to obtain a ticket for." },
     703             :         { "set_target_service", (PyCFunction)py_gensec_set_target_service, METH_VARARGS, 
     704             :                 "S.set_target_service(target_service) \n This sets the Kerberos target service to obtain a ticket for.  The default value is 'host'" },
     705             :         { "set_target_service_description", (PyCFunction)py_gensec_set_target_service_description, METH_VARARGS,
     706             :                 "S.set_target_service_description(target_service_description) \n This description is set server-side and used in authentication and authorization logs.  The default value is that provided to set_target_service() or None."},
     707             :         { "session_info", (PyCFunction)py_gensec_session_info, METH_NOARGS,
     708             :                 "S.session_info() -> info" },
     709             :         { "session_key", (PyCFunction)py_gensec_session_key, METH_NOARGS,
     710             :                 "S.session_key() -> key" },
     711             :         { "start_mech_by_name", (PyCFunction)py_gensec_start_mech_by_name, METH_VARARGS,
     712             :                 "S.start_mech_by_name(name)" },
     713             :         { "start_mech_by_sasl_name", (PyCFunction)py_gensec_start_mech_by_sasl_name, METH_VARARGS,
     714             :                 "S.start_mech_by_sasl_name(name)" },
     715             :         { "start_mech_by_authtype", (PyCFunction)py_gensec_start_mech_by_authtype, METH_VARARGS,
     716             :                 "S.start_mech_by_authtype(authtype, level)" },
     717             :         { "get_name_by_authtype", (PyCFunction)py_get_name_by_authtype, METH_VARARGS,
     718             :                 "S.get_name_by_authtype(authtype) -> name\nLookup an auth type." },
     719             :         { "want_feature", (PyCFunction)py_gensec_want_feature, METH_VARARGS,
     720             :                 "S.want_feature(feature)\n Request that GENSEC negotiate a particular feature." },
     721             :         { "have_feature", (PyCFunction)py_gensec_have_feature, METH_VARARGS,
     722             :                 "S.have_feature()\n Return True if GENSEC negotiated a particular feature." },
     723             :         { "set_max_update_size",  (PyCFunction)py_gensec_set_max_update_size, METH_VARARGS,
     724             :                 "S.set_max_update_size(max_size) \n Some mechs can fragment update packets, needs to be use before the mech is started." },
     725             :         { "max_update_size",  (PyCFunction)py_gensec_max_update_size, METH_NOARGS,
     726             :                 "S.max_update_size() \n Return the current max_update_size." },
     727             :         { "update",  (PyCFunction)py_gensec_update, METH_VARARGS,
     728             :                 "S.update(blob_in) -> (finished, blob_out)\nPerform one step in a GENSEC dance.  Repeat with new packets until finished is true or exception." },
     729             :         { "wrap",  (PyCFunction)py_gensec_wrap, METH_VARARGS,
     730             :                 "S.wrap(blob_in) -> blob_out\nPackage one clear packet into a wrapped GENSEC packet." },
     731             :         { "unwrap",  (PyCFunction)py_gensec_unwrap, METH_VARARGS,
     732             :                 "S.unwrap(blob_in) -> blob_out\nPerform one wrapped GENSEC packet into a clear packet." },
     733             :         { "sig_size",  (PyCFunction)py_gensec_sig_size, METH_VARARGS,
     734             :                 "S.sig_size(data_size) -> sig_size\nSize of the DCERPC packet signature" },
     735             :         { "sign_packet",  (PyCFunction)py_gensec_sign_packet, METH_VARARGS,
     736             :                 "S.sign_packet(data, whole_pdu) -> sig\nSign a DCERPC packet." },
     737             :         { "check_packet",  (PyCFunction)py_gensec_check_packet, METH_VARARGS,
     738             :                 "S.check_packet(data, whole_pdu, sig)\nCheck a DCERPC packet." },
     739             :         {0}
     740             : };
     741             : 
     742             : static struct PyModuleDef moduledef = {
     743             :     PyModuleDef_HEAD_INIT,
     744             :     .m_name = "gensec",
     745             :     .m_doc = "Generic Security Interface.",
     746             :     .m_size = -1,
     747             : };
     748             : 
     749             : static PyTypeObject Py_Security = {
     750             :         .tp_name = "gensec.Security",
     751             :         .tp_flags = Py_TPFLAGS_DEFAULT,
     752             :         .tp_methods = py_gensec_security_methods,
     753             : };
     754             : 
     755        2681 : MODULE_INIT_FUNC(gensec)
     756             : {
     757             :         PyObject *m;
     758             : 
     759        2681 :         if (pytalloc_BaseObject_PyType_Ready(&Py_Security) < 0)
     760           0 :                 return NULL;
     761             : 
     762        2681 :         m = PyModule_Create(&moduledef);
     763        2681 :         if (m == NULL)
     764           0 :                 return NULL;
     765             : 
     766        2681 :         PyModule_AddObject(m, "FEATURE_SESSION_KEY",     PyLong_FromLong(GENSEC_FEATURE_SESSION_KEY));
     767        2681 :         PyModule_AddObject(m, "FEATURE_SIGN",            PyLong_FromLong(GENSEC_FEATURE_SIGN));
     768        2681 :         PyModule_AddObject(m, "FEATURE_SEAL",            PyLong_FromLong(GENSEC_FEATURE_SEAL));
     769        2681 :         PyModule_AddObject(m, "FEATURE_DCE_STYLE",       PyLong_FromLong(GENSEC_FEATURE_DCE_STYLE));
     770        2681 :         PyModule_AddObject(m, "FEATURE_ASYNC_REPLIES",   PyLong_FromLong(GENSEC_FEATURE_ASYNC_REPLIES));
     771        2681 :         PyModule_AddObject(m, "FEATURE_DATAGRAM_MODE",   PyLong_FromLong(GENSEC_FEATURE_DATAGRAM_MODE));
     772        2681 :         PyModule_AddObject(m, "FEATURE_SIGN_PKT_HEADER", PyLong_FromLong(GENSEC_FEATURE_SIGN_PKT_HEADER));
     773        2681 :         PyModule_AddObject(m, "FEATURE_NEW_SPNEGO",      PyLong_FromLong(GENSEC_FEATURE_NEW_SPNEGO));
     774             : 
     775        2681 :         Py_INCREF(&Py_Security);
     776        2681 :         PyModule_AddObject(m, "Security", (PyObject *)&Py_Security);
     777             : 
     778        2681 :         return m;
     779             : }

Generated by: LCOV version 1.13