root/libcli/nbt/pynbt.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. PyAPI_DATA
  2. py_nbt_node_dealloc
  3. py_nbt_node_init
  4. PyObject_AsDestinationTuple
  5. PyObject_AsNBTName
  6. PyObject_FromNBTName
  7. py_nbt_name_query
  8. py_nbt_name_status
  9. py_nbt_name_register
  10. py_nbt_name_refresh
  11. py_nbt_name_release
  12. initnetbios

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

/* [<][>][^][v][top][bottom][index][help] */