2008-09-23 08:58:17 +04:00
/*
2008-06-11 02:05:58 +04:00
Unix SMB / CIFS implementation .
Samba utility functions
Copyright © Jelmer Vernooij < jelmer @ samba . org > 2008
2008-09-23 08:58:17 +04:00
2008-06-11 02:05:58 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 3 of the License , or
( at your option ) any later version .
2008-09-23 08:58:17 +04:00
2008-06-11 02:05:58 +04:00
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
2008-09-23 08:58:17 +04:00
2008-06-11 02:05:58 +04:00
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
2009-01-08 14:20:20 +03:00
# include <Python.h>
2009-10-23 09:23:01 +04:00
# include "includes.h"
2018-02-02 20:08:00 +03:00
# include "python/py3compat.h"
2008-06-11 02:05:58 +04:00
# include "libcli/util/pyerrors.h"
2012-12-28 18:37:14 +04:00
# include "python/modules.h"
2008-09-23 08:58:17 +04:00
# include "../libcli/nbt/libnbt.h"
2008-06-11 02:05:58 +04:00
# include "lib/events/events.h"
2010-12-29 20:09:09 +03:00
void initnetbios ( void ) ;
2010-11-22 02:07:21 +03:00
extern PyTypeObject nbt_node_Type ;
2008-06-11 02:05:58 +04:00
typedef struct {
PyObject_HEAD
TALLOC_CTX * mem_ctx ;
struct nbt_name_socket * socket ;
} nbt_node_Object ;
2010-12-29 20:56:13 +03:00
static void py_nbt_node_dealloc ( nbt_node_Object * self )
2008-06-11 02:05:58 +04:00
{
2010-12-29 20:56:13 +03:00
talloc_free ( self - > mem_ctx ) ;
2018-02-02 20:08:00 +03:00
Py_TYPE ( self ) - > tp_free ( self ) ;
2008-06-11 02:05:58 +04:00
}
2008-06-27 11:12:57 +04:00
static PyObject * py_nbt_node_init ( PyTypeObject * self , PyObject * args , PyObject * kwargs )
2008-06-11 02:05:58 +04:00
{
2008-12-29 22:24:57 +03:00
struct tevent_context * ev ;
2008-06-11 02:05:58 +04:00
nbt_node_Object * ret = PyObject_New ( nbt_node_Object , & nbt_node_Type ) ;
ret - > mem_ctx = talloc_new ( NULL ) ;
if ( ret - > mem_ctx = = NULL )
return NULL ;
2008-06-14 21:00:53 +04:00
ev = s4_event_context_init ( ret - > mem_ctx ) ;
2010-05-09 19:20:01 +04:00
ret - > socket = nbt_name_socket_init ( ret - > mem_ctx , ev ) ;
2008-06-11 02:05:58 +04:00
return ( PyObject * ) ret ;
}
static bool PyObject_AsDestinationTuple ( PyObject * obj , const char * * dest_addr , uint16_t * dest_port )
{
2019-06-15 14:14:49 +03:00
if ( PyUnicode_Check ( obj ) ) {
2019-06-07 12:16:25 +03:00
* dest_addr = PyUnicode_AsUTF8 ( obj ) ;
2008-06-11 02:05:58 +04:00
* dest_port = NBT_NAME_SERVICE_PORT ;
return true ;
2008-09-23 08:58:17 +04:00
}
2008-06-11 02:05:58 +04:00
if ( PyTuple_Check ( obj ) ) {
if ( PyTuple_Size ( obj ) < 1 ) {
PyErr_SetString ( PyExc_TypeError , " Destination tuple size invalid " ) ;
return false ;
}
2008-09-23 08:58:17 +04:00
2019-06-15 14:14:49 +03:00
if ( ! PyUnicode_Check ( PyTuple_GetItem ( obj , 0 ) ) ) {
2008-06-11 02:05:58 +04:00
PyErr_SetString ( PyExc_TypeError , " Destination tuple first element not string " ) ;
return false ;
}
2019-06-07 12:16:25 +03:00
* dest_addr = PyUnicode_AsUTF8 ( obj ) ;
2008-06-11 02:05:58 +04:00
if ( PyTuple_Size ( obj ) = = 1 ) {
* dest_port = NBT_NAME_SERVICE_PORT ;
return true ;
2020-03-15 00:04:52 +03:00
} else if ( PyLong_Check ( PyTuple_GetItem ( obj , 1 ) ) ) {
2020-03-15 00:32:11 +03:00
* dest_port = PyLong_AsLong ( PyTuple_GetItem ( obj , 1 ) ) ;
2008-06-11 02:05:58 +04:00
return true ;
} else {
PyErr_SetString ( PyExc_TypeError , " Destination tuple second element not a port " ) ;
return false ;
}
}
PyErr_SetString ( PyExc_TypeError , " Destination tuple second element not a port " ) ;
return false ;
}
2008-12-24 01:22:57 +03:00
static bool PyObject_AsNBTName ( PyObject * obj , struct nbt_name_socket * name_socket , struct nbt_name * name )
2008-06-11 02:05:58 +04:00
{
if ( PyTuple_Check ( obj ) ) {
if ( PyTuple_Size ( obj ) = = 2 ) {
2019-06-07 12:16:25 +03:00
name - > name = PyUnicode_AsUTF8 ( PyTuple_GetItem ( obj , 0 ) ) ;
2018-04-24 03:34:50 +03:00
if ( name - > name = = NULL ) {
goto err ;
}
2020-03-15 00:32:11 +03:00
name - > type = PyLong_AsLong ( PyTuple_GetItem ( obj , 1 ) ) ;
2018-04-24 03:34:50 +03:00
if ( name - > type = = - 1 & & PyErr_Occurred ( ) ) {
goto err ;
}
2008-06-11 02:05:58 +04:00
name - > scope = NULL ;
return true ;
} else if ( PyTuple_Size ( obj ) = = 3 ) {
2019-06-07 12:16:25 +03:00
name - > name = PyUnicode_AsUTF8 ( PyTuple_GetItem ( obj , 0 ) ) ;
2018-04-24 03:34:50 +03:00
if ( name - > name = = NULL ) {
goto err ;
}
2019-06-07 12:16:25 +03:00
name - > scope = PyUnicode_AsUTF8 ( PyTuple_GetItem ( obj , 1 ) ) ;
2018-04-24 03:34:50 +03:00
if ( name - > scope = = NULL ) {
goto err ;
}
2020-03-15 00:32:11 +03:00
name - > type = PyLong_AsLong ( PyTuple_GetItem ( obj , 2 ) ) ;
2018-04-24 03:34:50 +03:00
if ( name - > type = = - 1 & & PyErr_Occurred ( ) ) {
goto err ;
}
2008-06-11 02:05:58 +04:00
return true ;
} else {
PyErr_SetString ( PyExc_TypeError , " Invalid tuple size " ) ;
return false ;
}
}
2019-06-15 14:14:49 +03:00
if ( PyUnicode_Check ( obj ) ) {
2008-06-11 02:05:58 +04:00
/* FIXME: Parse string to be able to interpret things like RHONWYN<02> ? */
2019-06-07 12:16:25 +03:00
name - > name = PyUnicode_AsUTF8 ( obj ) ;
2018-04-24 03:34:50 +03:00
if ( name - > name = = NULL ) {
goto err ;
}
2008-06-11 02:05:58 +04:00
name - > scope = NULL ;
name - > type = 0 ;
return true ;
}
2018-04-24 03:34:50 +03:00
err :
2008-06-11 02:05:58 +04:00
PyErr_SetString ( PyExc_TypeError , " Invalid type for object " ) ;
return false ;
}
2010-05-09 19:20:01 +04:00
static PyObject * PyObject_FromNBTName ( struct nbt_name_socket * name_socket ,
2008-06-11 02:05:58 +04:00
struct nbt_name * name )
{
if ( name - > scope ) {
return Py_BuildValue ( " (ssi) " , name->name, name->scope, name->type) ;
} else {
return Py_BuildValue ( " (si) " , name->name, name->type) ;
}
}
static PyObject * py_nbt_name_query ( PyObject * self , PyObject * args , PyObject * kwargs )
{
nbt_node_Object * node = ( nbt_node_Object * ) self ;
PyObject * ret , * reply_addrs , * py_dest , * py_name ;
struct nbt_name_query io ;
NTSTATUS status ;
int i ;
const char * kwnames [ ] = { " name " , " dest " , " broadcast " , " wins " , " timeout " ,
" retries " , NULL } ;
io . in . broadcast = true ;
io . in . wins_lookup = false ;
io . in . timeout = 0 ;
io . in . retries = 3 ;
2008-09-23 08:58:17 +04:00
if ( ! PyArg_ParseTupleAndKeywords ( args , kwargs , " OO|bbii:query_name " ,
2008-06-11 02:05:58 +04:00
discard_const_p ( char * , kwnames ) ,
2008-09-23 08:58:17 +04:00
& py_name , & py_dest ,
& io . in . broadcast , & io . in . wins_lookup ,
2008-06-11 02:05:58 +04:00
& io . in . timeout , & io . in . retries ) ) {
return NULL ;
}
if ( ! PyObject_AsDestinationTuple ( py_dest , & io . in . dest_addr , & io . in . dest_port ) )
return NULL ;
if ( ! PyObject_AsNBTName ( py_name , node - > socket , & io . in . name ) )
return NULL ;
status = nbt_name_query ( node - > socket , NULL , & io ) ;
if ( NT_STATUS_IS_ERR ( status ) ) {
PyErr_SetNTSTATUS ( status ) ;
return NULL ;
}
ret = PyTuple_New ( 3 ) ;
if ( ret = = NULL )
return NULL ;
2019-06-07 11:45:52 +03:00
PyTuple_SetItem ( ret , 0 , PyUnicode_FromString ( io . out . reply_from ) ) ;
2008-06-11 02:05:58 +04:00
2010-05-09 19:20:01 +04:00
py_name = PyObject_FromNBTName ( node - > socket , & io . out . name ) ;
2008-06-11 02:05:58 +04:00
if ( py_name = = NULL )
return NULL ;
PyTuple_SetItem ( ret , 1 , py_name ) ;
reply_addrs = PyList_New ( io . out . num_addrs ) ;
if ( reply_addrs = = NULL ) {
Py_DECREF ( ret ) ;
return NULL ;
}
2008-09-23 08:58:17 +04:00
2008-06-11 02:05:58 +04:00
for ( i = 0 ; i < io . out . num_addrs ; i + + ) {
2019-06-07 11:45:52 +03:00
PyList_SetItem ( reply_addrs , i , PyUnicode_FromString ( io . out . reply_addrs [ i ] ) ) ;
2008-06-11 02:05:58 +04:00
}
PyTuple_SetItem ( ret , 2 , reply_addrs ) ;
return ret ;
}
static PyObject * py_nbt_name_status ( PyObject * self , PyObject * args , PyObject * kwargs )
{
nbt_node_Object * node = ( nbt_node_Object * ) self ;
PyObject * ret , * py_dest , * py_name , * py_names ;
struct nbt_name_status io ;
int i ;
NTSTATUS status ;
const char * kwnames [ ] = { " name " , " dest " , " timeout " , " retries " , NULL } ;
io . in . timeout = 0 ;
io . in . retries = 0 ;
2008-09-23 08:58:17 +04:00
if ( ! PyArg_ParseTupleAndKeywords ( args , kwargs , " OO|ii:name_status " ,
2008-06-11 02:05:58 +04:00
discard_const_p ( char * , kwnames ) ,
2008-09-23 08:58:17 +04:00
& py_name , & py_dest ,
2008-06-11 02:05:58 +04:00
& io . in . timeout , & io . in . retries ) ) {
return NULL ;
}
if ( ! PyObject_AsDestinationTuple ( py_dest , & io . in . dest_addr , & io . in . dest_port ) )
return NULL ;
if ( ! PyObject_AsNBTName ( py_name , node - > socket , & io . in . name ) )
return NULL ;
status = nbt_name_status ( node - > socket , NULL , & io ) ;
if ( NT_STATUS_IS_ERR ( status ) ) {
PyErr_SetNTSTATUS ( status ) ;
return NULL ;
}
ret = PyTuple_New ( 3 ) ;
if ( ret = = NULL )
return NULL ;
2019-06-07 11:45:52 +03:00
PyTuple_SetItem ( ret , 0 , PyUnicode_FromString ( io . out . reply_from ) ) ;
2008-06-11 02:05:58 +04:00
2010-05-09 19:20:01 +04:00
py_name = PyObject_FromNBTName ( node - > socket , & io . out . name ) ;
2008-06-11 02:05:58 +04:00
if ( py_name = = NULL )
return NULL ;
PyTuple_SetItem ( ret , 1 , py_name ) ;
py_names = PyList_New ( io . out . status . num_names ) ;
for ( i = 0 ; i < io . out . status . num_names ; i + + ) {
2008-09-23 08:58:17 +04:00
PyList_SetItem ( py_names , i , Py_BuildValue ( " (sii) " ,
2008-06-11 02:05:58 +04:00
io . out . status . names [ i ] . name ,
2008-09-23 08:58:17 +04:00
io . out . status . names [ i ] . nb_flags ,
2008-06-11 02:05:58 +04:00
io . out . status . names [ i ] . type ) ) ;
}
PyTuple_SetItem ( ret , 2 , py_names ) ;
return ret ;
}
static PyObject * py_nbt_name_register ( PyObject * self , PyObject * args , PyObject * kwargs )
{
nbt_node_Object * node = ( nbt_node_Object * ) self ;
PyObject * ret , * py_dest , * py_name ;
struct nbt_name_register io ;
NTSTATUS status ;
2008-09-23 08:58:17 +04:00
const char * kwnames [ ] = { " name " , " address " , " dest " , " register_demand " , " broadcast " ,
2008-06-11 02:05:58 +04:00
" multi_homed " , " ttl " , " timeout " , " retries " , NULL } ;
io . in . broadcast = true ;
io . in . multi_homed = true ;
io . in . register_demand = true ;
2018-04-12 08:09:45 +03:00
io . in . ttl = 0 ;
2008-06-11 02:05:58 +04:00
io . in . timeout = 0 ;
io . in . retries = 0 ;
2008-09-23 08:58:17 +04:00
if ( ! PyArg_ParseTupleAndKeywords ( args , kwargs , " OsO|bbbiii:query_name " ,
2008-06-11 02:05:58 +04:00
discard_const_p ( char * , kwnames ) ,
2008-09-23 08:58:17 +04:00
& py_name , & io . in . address , & py_dest ,
& io . in . register_demand ,
& io . in . broadcast , & io . in . multi_homed ,
2008-06-11 02:05:58 +04:00
& io . in . ttl , & io . in . timeout , & io . in . retries ) ) {
return NULL ;
}
if ( ! PyObject_AsDestinationTuple ( py_dest , & io . in . dest_addr , & io . in . dest_port ) )
return NULL ;
if ( ! PyObject_AsNBTName ( py_name , node - > socket , & io . in . name ) )
return NULL ;
status = nbt_name_register ( node - > socket , NULL , & io ) ;
if ( NT_STATUS_IS_ERR ( status ) ) {
PyErr_SetNTSTATUS ( status ) ;
return NULL ;
}
2018-02-15 18:02:58 +03:00
ret = PyTuple_New ( 4 ) ;
2008-06-11 02:05:58 +04:00
if ( ret = = NULL )
return NULL ;
2019-06-07 11:45:52 +03:00
PyTuple_SetItem ( ret , 0 , PyUnicode_FromString ( io . out . reply_from ) ) ;
2008-06-11 02:05:58 +04:00
2010-05-09 19:20:01 +04:00
py_name = PyObject_FromNBTName ( node - > socket , & io . out . name ) ;
2008-06-11 02:05:58 +04:00
if ( py_name = = NULL )
return NULL ;
PyTuple_SetItem ( ret , 1 , py_name ) ;
2019-06-07 11:45:52 +03:00
PyTuple_SetItem ( ret , 2 , PyUnicode_FromString ( io . out . reply_addr ) ) ;
2008-06-11 02:05:58 +04:00
2020-03-15 00:36:59 +03:00
PyTuple_SetItem ( ret , 3 , PyLong_FromLong ( io . out . rcode ) ) ;
2008-06-11 02:05:58 +04:00
return ret ;
}
static PyObject * py_nbt_name_refresh ( PyObject * self , PyObject * args , PyObject * kwargs )
{
nbt_node_Object * node = ( nbt_node_Object * ) self ;
PyObject * ret , * py_dest , * py_name ;
struct nbt_name_refresh io ;
NTSTATUS status ;
2008-09-23 08:58:17 +04:00
const char * kwnames [ ] = { " name " , " address " , " dest " , " nb_flags " , " broadcast " ,
2008-06-11 02:05:58 +04:00
" ttl " , " timeout " , " retries " , NULL } ;
io . in . broadcast = true ;
io . in . nb_flags = 0 ;
2018-04-12 08:10:10 +03:00
io . in . ttl = 0 ;
2008-06-11 02:05:58 +04:00
io . in . timeout = 0 ;
io . in . retries = 0 ;
2008-09-23 08:58:17 +04:00
if ( ! PyArg_ParseTupleAndKeywords ( args , kwargs , " OsO|ibiii:query_name " ,
2008-06-11 02:05:58 +04:00
discard_const_p ( char * , kwnames ) ,
2008-09-23 08:58:17 +04:00
& py_name , & io . in . address , & py_dest ,
& io . in . nb_flags ,
& io . in . broadcast ,
2008-06-11 02:05:58 +04:00
& io . in . ttl , & io . in . timeout , & io . in . retries ) ) {
return NULL ;
}
if ( ! PyObject_AsDestinationTuple ( py_dest , & io . in . dest_addr , & io . in . dest_port ) )
return NULL ;
if ( ! PyObject_AsNBTName ( py_name , node - > socket , & io . in . name ) )
return NULL ;
status = nbt_name_refresh ( node - > socket , NULL , & io ) ;
if ( NT_STATUS_IS_ERR ( status ) ) {
PyErr_SetNTSTATUS ( status ) ;
return NULL ;
}
ret = PyTuple_New ( 3 ) ;
if ( ret = = NULL )
return NULL ;
2019-06-07 11:45:52 +03:00
PyTuple_SetItem ( ret , 0 , PyUnicode_FromString ( io . out . reply_from ) ) ;
2008-06-11 02:05:58 +04:00
2010-05-09 19:20:01 +04:00
py_name = PyObject_FromNBTName ( node - > socket , & io . out . name ) ;
2008-06-11 02:05:58 +04:00
if ( py_name = = NULL )
return NULL ;
PyTuple_SetItem ( ret , 1 , py_name ) ;
2019-06-07 11:45:52 +03:00
PyTuple_SetItem ( ret , 2 , PyUnicode_FromString ( io . out . reply_addr ) ) ;
2008-06-11 02:05:58 +04:00
2020-03-15 00:36:59 +03:00
PyTuple_SetItem ( ret , 3 , PyLong_FromLong ( io . out . rcode ) ) ;
2008-06-11 02:05:58 +04:00
return ret ;
}
static PyObject * py_nbt_name_release ( PyObject * self , PyObject * args , PyObject * kwargs )
{
2009-01-06 06:13:57 +03:00
Py_RETURN_NONE ; /* FIXME */
2008-06-11 02:05:58 +04:00
}
static PyMethodDef py_nbt_methods [ ] = {
2019-05-02 21:47:29 +03:00
{ " query_name " , PY_DISCARD_FUNC_SIG ( PyCFunction , py_nbt_name_query ) ,
METH_VARARGS | METH_KEYWORDS ,
2008-06-11 02:05:58 +04:00
" S.query_name(name, dest, broadcast=True, wins=False, timeout=0, retries=3) -> (reply_from, name, reply_addr) \n "
" Query for a NetBIOS name " } ,
2019-05-02 21:47:29 +03:00
{ " register_name " , PY_DISCARD_FUNC_SIG ( PyCFunction ,
py_nbt_name_register ) ,
METH_VARARGS | METH_KEYWORDS ,
2008-06-11 02:05:58 +04:00
" 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 "
" Register a new name " } ,
2019-05-02 21:47:29 +03:00
{ " release_name " , PY_DISCARD_FUNC_SIG ( 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 "
2008-06-11 02:05:58 +04:00
" release a previously registered name " } ,
2019-05-02 21:47:29 +03:00
{ " refresh_name " , PY_DISCARD_FUNC_SIG ( 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 "
2008-06-11 02:05:58 +04:00
" release a previously registered name " } ,
2019-05-02 21:47:29 +03:00
{ " name_status " , PY_DISCARD_FUNC_SIG ( PyCFunction , py_nbt_name_status ) ,
METH_VARARGS | METH_KEYWORDS ,
2008-06-11 02:05:58 +04:00
" S.name_status(name, dest, timeout=0, retries=0) -> (reply_from, name, status) \n "
" Find the status of a name " } ,
2020-05-05 04:47:39 +03:00
{ 0 }
2008-06-11 02:05:58 +04:00
} ;
PyTypeObject nbt_node_Type = {
2018-02-02 20:08:00 +03:00
PyVarObject_HEAD_INIT ( NULL , 0 )
2008-06-11 02:05:58 +04:00
. tp_name = " netbios.Node " ,
. tp_basicsize = sizeof ( nbt_node_Object ) ,
. tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE ,
. tp_new = py_nbt_node_init ,
2010-12-29 20:56:13 +03:00
. tp_dealloc = ( destructor ) py_nbt_node_dealloc ,
2008-06-11 02:05:58 +04:00
. tp_methods = py_nbt_methods ,
. tp_doc = " Node() \n "
" Create a new NetBIOS node \n "
} ;
2018-02-02 20:08:00 +03:00
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT ,
. m_name = " netbios " ,
. m_doc = " NetBIOS over TCP/IP support " ,
. m_size = - 1 ,
. m_methods = NULL ,
} ;
MODULE_INIT_FUNC ( netbios )
2008-06-11 02:05:58 +04:00
{
2018-02-02 20:08:00 +03:00
PyObject * mod = NULL ;
2008-06-11 02:05:58 +04:00
if ( PyType_Ready ( & nbt_node_Type ) < 0 )
2018-02-02 20:08:00 +03:00
return mod ;
mod = PyModule_Create ( & moduledef ) ;
2008-06-11 02:05:58 +04:00
Py_INCREF ( ( PyObject * ) & nbt_node_Type ) ;
PyModule_AddObject ( mod , " Node " , ( PyObject * ) & nbt_node_Type ) ;
2018-02-02 20:08:00 +03:00
return mod ;
2008-06-11 02:05:58 +04:00
}