LCOV - code coverage report
Current view: top level - libcli/nbt - pynbt.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 114 206 55.3 %
Date: 2024-04-21 15:09:00 Functions: 9 11 81.8 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Samba utility functions
       4             :    Copyright © Jelmer Vernooij <jelmer@samba.org> 2008
       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 "includes.h"
      22             : #include "python/py3compat.h"
      23             : #include "libcli/util/pyerrors.h"
      24             : #include "python/modules.h"
      25             : #include "../libcli/nbt/libnbt.h"
      26             : #include "lib/events/events.h"
      27             : 
      28             : void initnetbios(void);
      29             : 
      30             : extern PyTypeObject nbt_node_Type;
      31             : 
      32             : typedef struct {
      33             :         PyObject_HEAD
      34             :         TALLOC_CTX *mem_ctx;
      35             :         struct nbt_name_socket *socket;
      36             : } nbt_node_Object;
      37             : 
      38           8 : static void py_nbt_node_dealloc(nbt_node_Object *self)
      39             : {
      40           8 :         talloc_free(self->mem_ctx);
      41           8 :         Py_TYPE(self)->tp_free(self);
      42           8 : }
      43             : 
      44           8 : static PyObject *py_nbt_node_init(PyTypeObject *self, PyObject *args, PyObject *kwargs)
      45             : {
      46             :         struct tevent_context *ev;
      47           8 :         nbt_node_Object *ret = PyObject_New(nbt_node_Object, &nbt_node_Type);
      48             : 
      49           8 :         ret->mem_ctx = talloc_new(NULL);
      50           8 :         if (ret->mem_ctx == NULL)
      51           0 :                 return NULL;
      52             : 
      53           8 :         ev = s4_event_context_init(ret->mem_ctx);
      54           8 :         ret->socket = nbt_name_socket_init(ret->mem_ctx, ev);
      55           8 :         return (PyObject *)ret;
      56             : }
      57             : 
      58           8 : static bool PyObject_AsDestinationTuple(PyObject *obj, const char **dest_addr, uint16_t *dest_port)
      59             : {
      60           8 :         if (PyUnicode_Check(obj)) {
      61           8 :                 *dest_addr = PyUnicode_AsUTF8(obj);
      62           8 :                 *dest_port = NBT_NAME_SERVICE_PORT;
      63           8 :                 return true;
      64             :         }
      65             : 
      66           0 :         if (PyTuple_Check(obj)) {
      67           0 :                 if (PyTuple_Size(obj) < 1) {
      68           0 :                         PyErr_SetString(PyExc_TypeError, "Destination tuple size invalid");
      69           0 :                         return false;
      70             :                 }
      71             : 
      72           0 :                 if (!PyUnicode_Check(PyTuple_GetItem(obj, 0))) {
      73           0 :                         PyErr_SetString(PyExc_TypeError, "Destination tuple first element not string");
      74           0 :                         return false;
      75             :                 }
      76             : 
      77           0 :                 *dest_addr = PyUnicode_AsUTF8(obj);
      78             : 
      79           0 :                 if (PyTuple_Size(obj) == 1) {
      80           0 :                         *dest_port = NBT_NAME_SERVICE_PORT;
      81           0 :                         return true;
      82           0 :                 } else if (PyLong_Check(PyTuple_GetItem(obj, 1))) {
      83           0 :                         *dest_port = PyLong_AsLong(PyTuple_GetItem(obj, 1));
      84           0 :                         return true;
      85             :                 } else {
      86           0 :                         PyErr_SetString(PyExc_TypeError, "Destination tuple second element not a port");
      87           0 :                         return false;
      88             :                 }
      89             :         }
      90             : 
      91           0 :         PyErr_SetString(PyExc_TypeError, "Destination tuple second element not a port");
      92           0 :         return false;
      93             : }
      94             : 
      95           8 : static bool PyObject_AsNBTName(PyObject *obj, struct nbt_name_socket *name_socket, struct nbt_name *name)
      96             : {
      97           8 :         if (PyTuple_Check(obj)) {
      98           2 :                 if (PyTuple_Size(obj) == 2) {
      99           2 :                         name->name = PyUnicode_AsUTF8(PyTuple_GetItem(obj, 0));
     100           2 :                         if (name->name == NULL) {
     101           0 :                                 goto err;
     102             :                         }
     103           2 :                         name->type = PyLong_AsLong(PyTuple_GetItem(obj, 1));
     104           2 :                         if (name->type == -1 && PyErr_Occurred()) {
     105           0 :                                 goto err;
     106             :                         }
     107           2 :                         name->scope = NULL;
     108           2 :                         return true;
     109           0 :                 } else if (PyTuple_Size(obj) == 3) {
     110           0 :                         name->name = PyUnicode_AsUTF8(PyTuple_GetItem(obj, 0));
     111           0 :                         if (name->name == NULL) {
     112           0 :                                 goto err;
     113             :                         }
     114           0 :                         name->scope = PyUnicode_AsUTF8(PyTuple_GetItem(obj, 1));
     115           0 :                         if (name->scope == NULL) {
     116           0 :                                 goto err;
     117             :                         }
     118           0 :                         name->type = PyLong_AsLong(PyTuple_GetItem(obj, 2));
     119           0 :                         if (name->type == -1 && PyErr_Occurred()) {
     120           0 :                                 goto err;
     121             :                         }
     122           0 :                         return true;
     123             :                 } else {
     124           0 :                         PyErr_SetString(PyExc_TypeError, "Invalid tuple size");
     125           0 :                         return false;
     126             :                 }
     127             :         }
     128             : 
     129           6 :         if (PyUnicode_Check(obj)) {
     130             :                 /* FIXME: Parse string to be able to interpret things like RHONWYN<02> ? */
     131           6 :                 name->name = PyUnicode_AsUTF8(obj);
     132           6 :                 if (name->name == NULL) {
     133           0 :                         goto err;
     134             :                 }
     135           6 :                 name->scope = NULL;
     136           6 :                 name->type = 0;
     137           6 :                 return true;
     138             :         }
     139           0 : err:
     140           0 :         PyErr_SetString(PyExc_TypeError, "Invalid type for object");
     141           0 :         return false;
     142             : }
     143             : 
     144           6 : static PyObject *PyObject_FromNBTName(struct nbt_name_socket *name_socket, 
     145             :                                       struct nbt_name *name)
     146             : {
     147           6 :         if (name->scope) {
     148           0 :                 return Py_BuildValue("(ssi)", name->name, name->scope, name->type);
     149             :         } else {
     150           6 :                 return Py_BuildValue("(si)", name->name, name->type);
     151             :         }
     152             : }
     153             : 
     154           4 : static PyObject *py_nbt_name_query(PyObject *self, PyObject *args, PyObject *kwargs)
     155             : {
     156           4 :         nbt_node_Object *node = (nbt_node_Object *)self;
     157             :         PyObject *ret, *reply_addrs, *py_dest, *py_name;
     158             :         struct nbt_name_query io;
     159             :         NTSTATUS status;
     160             :         int i;
     161             : 
     162           4 :         const char *kwnames[] = { "name", "dest", "broadcast", "wins", "timeout",
     163             :                                   "retries", NULL };
     164           4 :         io.in.broadcast = true;
     165           4 :         io.in.wins_lookup = false;
     166           4 :         io.in.timeout = 0;
     167           4 :         io.in.retries = 3;
     168             : 
     169           4 :         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|bbii:query_name",
     170             :                                          discard_const_p(char *, kwnames),
     171             :                                          &py_name, &py_dest,
     172             :                                          &io.in.broadcast, &io.in.wins_lookup,
     173             :                                          &io.in.timeout, &io.in.retries)) {
     174           0 :                 return NULL;
     175             :         }
     176             : 
     177           4 :         if (!PyObject_AsDestinationTuple(py_dest, &io.in.dest_addr, &io.in.dest_port))
     178           0 :                 return NULL;
     179             : 
     180           4 :         if (!PyObject_AsNBTName(py_name, node->socket, &io.in.name))
     181           0 :                 return NULL;
     182             : 
     183           4 :         status = nbt_name_query(node->socket, NULL, &io);
     184             : 
     185           4 :         if (NT_STATUS_IS_ERR(status)) {
     186           2 :                 PyErr_SetNTSTATUS(status);
     187           2 :                 return NULL;
     188             :         }
     189             : 
     190           2 :         ret = PyTuple_New(3);
     191           2 :         if (ret == NULL)
     192           0 :                 return NULL;
     193           2 :         PyTuple_SetItem(ret, 0, PyUnicode_FromString(io.out.reply_from));
     194             : 
     195           2 :         py_name = PyObject_FromNBTName(node->socket, &io.out.name);
     196           2 :         if (py_name == NULL)
     197           0 :                 return NULL;
     198             : 
     199           2 :         PyTuple_SetItem(ret, 1, py_name);
     200             : 
     201           2 :         reply_addrs = PyList_New(io.out.num_addrs);
     202           2 :         if (reply_addrs == NULL) {
     203           0 :                 Py_DECREF(ret);
     204           0 :                 return NULL;
     205             :         }
     206             : 
     207           4 :         for (i = 0; i < io.out.num_addrs; i++) {
     208           2 :                 PyList_SetItem(reply_addrs, i, PyUnicode_FromString(io.out.reply_addrs[i]));
     209             :         }
     210             : 
     211           2 :         PyTuple_SetItem(ret, 2, reply_addrs);
     212           2 :         return ret;
     213             : }
     214             : 
     215           2 : static PyObject *py_nbt_name_status(PyObject *self, PyObject *args, PyObject *kwargs)
     216             : {
     217           2 :         nbt_node_Object *node = (nbt_node_Object *)self;
     218             :         PyObject *ret, *py_dest, *py_name, *py_names;
     219             :         struct nbt_name_status io;
     220             :         int i;
     221             :         NTSTATUS status;
     222             : 
     223           2 :         const char *kwnames[] = { "name", "dest", "timeout", "retries", NULL };
     224             : 
     225           2 :         io.in.timeout = 0;
     226           2 :         io.in.retries = 0;
     227             : 
     228           2 :         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|ii:name_status",
     229             :                                          discard_const_p(char *, kwnames),
     230             :                                          &py_name, &py_dest,
     231             :                                          &io.in.timeout, &io.in.retries)) {
     232           0 :                 return NULL;
     233             :         }
     234             : 
     235           2 :         if (!PyObject_AsDestinationTuple(py_dest, &io.in.dest_addr, &io.in.dest_port))
     236           0 :                 return NULL;
     237             : 
     238           2 :         if (!PyObject_AsNBTName(py_name, node->socket, &io.in.name))
     239           0 :                 return NULL;
     240             : 
     241           2 :         status = nbt_name_status(node->socket, NULL, &io);
     242             : 
     243           2 :         if (NT_STATUS_IS_ERR(status)) {
     244           0 :                 PyErr_SetNTSTATUS(status);
     245           0 :                 return NULL;
     246             :         }
     247             : 
     248           2 :         ret = PyTuple_New(3);
     249           2 :         if (ret == NULL)
     250           0 :                 return NULL;
     251           2 :         PyTuple_SetItem(ret, 0, PyUnicode_FromString(io.out.reply_from));
     252             : 
     253           2 :         py_name = PyObject_FromNBTName(node->socket, &io.out.name);
     254           2 :         if (py_name == NULL)
     255           0 :                 return NULL;
     256             : 
     257           2 :         PyTuple_SetItem(ret, 1, py_name);
     258             : 
     259           2 :         py_names = PyList_New(io.out.status.num_names);
     260             : 
     261          20 :         for (i = 0; i < io.out.status.num_names; i++) {
     262          18 :                 PyList_SetItem(py_names, i, Py_BuildValue("(sii)",
     263          18 :                                 io.out.status.names[i].name,
     264          18 :                                 io.out.status.names[i].nb_flags,
     265          18 :                                 io.out.status.names[i].type));
     266             :         }
     267             : 
     268           2 :         PyTuple_SetItem(ret, 2, py_names);
     269             : 
     270           2 :         return ret;
     271             : }
     272             : 
     273           2 : static PyObject *py_nbt_name_register(PyObject *self, PyObject *args, PyObject *kwargs)
     274             : {
     275           2 :         nbt_node_Object *node = (nbt_node_Object *)self;
     276             :         PyObject *ret, *py_dest, *py_name;
     277             :         struct nbt_name_register io;
     278             :         NTSTATUS status;
     279             : 
     280           2 :         const char *kwnames[] = { "name", "address", "dest", "register_demand", "broadcast",
     281             :                                   "multi_homed", "ttl", "timeout", "retries", NULL };
     282             : 
     283           2 :         io.in.broadcast = true;
     284           2 :         io.in.multi_homed = true;
     285           2 :         io.in.register_demand = true;
     286           2 :         io.in.ttl = 0;
     287           2 :         io.in.timeout = 0;
     288           2 :         io.in.retries = 0;
     289             : 
     290           2 :         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OsO|bbbiii:query_name",
     291             :                                          discard_const_p(char *, kwnames),
     292             :                                          &py_name, &io.in.address, &py_dest,
     293             :                                          &io.in.register_demand,
     294             :                                          &io.in.broadcast, &io.in.multi_homed,
     295             :                                          &io.in.ttl, &io.in.timeout, &io.in.retries)) {
     296           0 :                 return NULL;
     297             :         }
     298             : 
     299           2 :         if (!PyObject_AsDestinationTuple(py_dest, &io.in.dest_addr, &io.in.dest_port))
     300           0 :                 return NULL;
     301             : 
     302           2 :         if (!PyObject_AsNBTName(py_name, node->socket, &io.in.name))
     303           0 :                 return NULL;
     304             : 
     305           2 :         status = nbt_name_register(node->socket, NULL, &io);
     306             : 
     307           2 :         if (NT_STATUS_IS_ERR(status)) {
     308           0 :                 PyErr_SetNTSTATUS(status);
     309           0 :                 return NULL;
     310             :         }
     311             : 
     312           2 :         ret = PyTuple_New(4);
     313           2 :         if (ret == NULL)
     314           0 :                 return NULL;
     315           2 :         PyTuple_SetItem(ret, 0, PyUnicode_FromString(io.out.reply_from));
     316             : 
     317           2 :         py_name = PyObject_FromNBTName(node->socket, &io.out.name);
     318           2 :         if (py_name == NULL)
     319           0 :                 return NULL;
     320             : 
     321           2 :         PyTuple_SetItem(ret, 1, py_name);
     322             : 
     323           2 :         PyTuple_SetItem(ret, 2, PyUnicode_FromString(io.out.reply_addr));
     324             : 
     325           2 :         PyTuple_SetItem(ret, 3, PyLong_FromLong(io.out.rcode));
     326             : 
     327           2 :         return ret;
     328             : }
     329             : 
     330           0 : static PyObject *py_nbt_name_refresh(PyObject *self, PyObject *args, PyObject *kwargs)
     331             : {
     332           0 :         nbt_node_Object *node = (nbt_node_Object *)self;
     333             :         PyObject *ret, *py_dest, *py_name;
     334             :         struct nbt_name_refresh io;
     335             :         NTSTATUS status;
     336             : 
     337           0 :         const char *kwnames[] = { "name", "address", "dest", "nb_flags", "broadcast",
     338             :                                   "ttl", "timeout", "retries", NULL };
     339             : 
     340           0 :         io.in.broadcast = true;
     341           0 :         io.in.nb_flags = 0;
     342           0 :         io.in.ttl = 0;
     343           0 :         io.in.timeout = 0;
     344           0 :         io.in.retries = 0;
     345             : 
     346           0 :         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OsO|ibiii:query_name",
     347             :                                          discard_const_p(char *, kwnames),
     348             :                                          &py_name, &io.in.address, &py_dest,
     349             :                                          &io.in.nb_flags,
     350             :                                          &io.in.broadcast,
     351             :                                          &io.in.ttl, &io.in.timeout, &io.in.retries)) {
     352           0 :                 return NULL;
     353             :         }
     354             : 
     355           0 :         if (!PyObject_AsDestinationTuple(py_dest, &io.in.dest_addr, &io.in.dest_port))
     356           0 :                 return NULL;
     357             : 
     358           0 :         if (!PyObject_AsNBTName(py_name, node->socket, &io.in.name))
     359           0 :                 return NULL;
     360             : 
     361           0 :         status = nbt_name_refresh(node->socket, NULL, &io);
     362             : 
     363           0 :         if (NT_STATUS_IS_ERR(status)) {
     364           0 :                 PyErr_SetNTSTATUS(status);
     365           0 :                 return NULL;
     366             :         }
     367             : 
     368           0 :         ret = PyTuple_New(3);
     369           0 :         if (ret == NULL)
     370           0 :                 return NULL;
     371           0 :         PyTuple_SetItem(ret, 0, PyUnicode_FromString(io.out.reply_from));
     372             : 
     373           0 :         py_name = PyObject_FromNBTName(node->socket, &io.out.name);
     374           0 :         if (py_name == NULL)
     375           0 :                 return NULL;
     376             : 
     377           0 :         PyTuple_SetItem(ret, 1, py_name);
     378             : 
     379           0 :         PyTuple_SetItem(ret, 2, PyUnicode_FromString(io.out.reply_addr));
     380             : 
     381           0 :         PyTuple_SetItem(ret, 3, PyLong_FromLong(io.out.rcode));
     382             : 
     383           0 :         return ret;
     384             : }
     385             : 
     386           0 : static PyObject *py_nbt_name_release(PyObject *self, PyObject *args, PyObject *kwargs)
     387             : {
     388           0 :         Py_RETURN_NONE; /* FIXME */
     389             : }
     390             : 
     391             : static PyMethodDef py_nbt_methods[] = {
     392             :         { "query_name", PY_DISCARD_FUNC_SIG(PyCFunction, py_nbt_name_query),
     393             :                 METH_VARARGS|METH_KEYWORDS,
     394             :                 "S.query_name(name, dest, broadcast=True, wins=False, timeout=0, retries=3) -> (reply_from, name, reply_addr)\n"
     395             :                 "Query for a NetBIOS name" },
     396             :         { "register_name", PY_DISCARD_FUNC_SIG(PyCFunction,
     397             :                                                py_nbt_name_register),
     398             :                 METH_VARARGS|METH_KEYWORDS,
     399             :                 "S.register_name(name, address, dest, register_demand=True, broadcast=True, multi_homed=True, ttl=0, timeout=0, retries=0) -> (reply_from, name, reply_addr, rcode)\n"
     400             :                 "Register a new name" },
     401             :         { "release_name", PY_DISCARD_FUNC_SIG(PyCFunction, py_nbt_name_release),
     402             :                 METH_VARARGS|METH_KEYWORDS, "S.release_name(name, address, dest, nb_flags=0, broadcast=true, timeout=0, retries=3) -> (reply_from, name, reply_addr, rcode)\n"
     403             :                 "release a previously registered name" },
     404             :         { "refresh_name", PY_DISCARD_FUNC_SIG(PyCFunction, py_nbt_name_refresh),
     405             :                 METH_VARARGS|METH_KEYWORDS, "S.refresh_name(name, address, dest, nb_flags=0, broadcast=True, ttl=0, timeout=0, retries=0) -> (reply_from, name, reply_addr, rcode)\n"
     406             :                 "release a previously registered name" },
     407             :         { "name_status", PY_DISCARD_FUNC_SIG(PyCFunction, py_nbt_name_status),
     408             :                 METH_VARARGS|METH_KEYWORDS,
     409             :                 "S.name_status(name, dest, timeout=0, retries=0) -> (reply_from, name, status)\n"
     410             :                 "Find the status of a name" },
     411             : 
     412             :         {0}
     413             : };
     414             : 
     415             : PyTypeObject nbt_node_Type = {
     416             :         PyVarObject_HEAD_INIT(NULL, 0)
     417             :         .tp_name = "netbios.Node",
     418             :         .tp_basicsize = sizeof(nbt_node_Object),
     419             :         .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
     420             :         .tp_new = py_nbt_node_init,
     421             :         .tp_dealloc = (destructor)py_nbt_node_dealloc,
     422             :         .tp_methods = py_nbt_methods,
     423             :         .tp_doc = "Node()\n"
     424             :                   "Create a new NetBIOS node\n"
     425             : };
     426             : 
     427             : static struct PyModuleDef moduledef = {
     428             :     PyModuleDef_HEAD_INIT,
     429             :     .m_name = "netbios",
     430             :     .m_doc = "NetBIOS over TCP/IP support",
     431             :     .m_size = -1,
     432             :     .m_methods = NULL,
     433             : };
     434             : 
     435          30 : MODULE_INIT_FUNC(netbios)
     436             : {
     437          30 :         PyObject *mod = NULL;
     438          30 :         if (PyType_Ready(&nbt_node_Type) < 0)
     439           0 :                 return mod;
     440             : 
     441          30 :         mod = PyModule_Create(&moduledef);
     442             : 
     443             : 
     444          29 :         Py_INCREF((PyObject *)&nbt_node_Type);
     445          30 :         PyModule_AddObject(mod, "Node", (PyObject *)&nbt_node_Type);
     446          30 :         return mod;
     447             : }

Generated by: LCOV version 1.14