2010-08-27 04:17:26 +04:00
/*
Unix SMB / CIFS implementation .
Python interface to DCE / RPC library - utility functions .
Copyright ( C ) 2010 Jelmer Vernooij < jelmer @ samba . org >
Copyright ( C ) 2010 Andrew Tridgell < tridge @ samba . org >
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 .
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 .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include <Python.h>
# include "includes.h"
# include "librpc/rpc/pyrpc_util.h"
2010-09-03 04:39:38 +04:00
# include "librpc/rpc/dcerpc.h"
# include "librpc/rpc/pyrpc.h"
# include "param/pyparam.h"
# include "auth/credentials/pycredentials.h"
# include "lib/events/events.h"
2010-09-17 11:04:28 +04:00
# include "lib/messaging/messaging.h"
# include "lib/messaging/irpc.h"
2010-08-27 04:17:26 +04:00
2010-12-09 11:59:52 +03:00
bool py_check_dcerpc_type ( PyObject * obj , const char * module , const char * type_name )
2010-08-27 04:17:26 +04:00
{
PyObject * mod ;
2010-09-03 04:39:38 +04:00
PyTypeObject * type ;
2010-08-27 04:17:26 +04:00
bool ret ;
mod = PyImport_ImportModule ( module ) ;
if ( mod = = NULL ) {
PyErr_Format ( PyExc_RuntimeError , " Unable to import %s to check type %s " ,
2010-12-09 11:59:52 +03:00
module , type_name ) ;
2010-08-27 04:17:26 +04:00
return NULL ;
}
2010-12-09 11:59:52 +03:00
type = ( PyTypeObject * ) PyObject_GetAttrString ( mod , type_name ) ;
2010-08-27 04:17:26 +04:00
Py_DECREF ( mod ) ;
if ( type = = NULL ) {
PyErr_Format ( PyExc_RuntimeError , " Unable to find type %s in module %s " ,
2010-12-09 11:59:52 +03:00
module , type_name ) ;
2010-08-27 04:17:26 +04:00
return NULL ;
}
ret = PyObject_TypeCheck ( obj , type ) ;
Py_DECREF ( type ) ;
if ( ! ret )
PyErr_Format ( PyExc_TypeError , " Expected type %s.%s, got %s " ,
2010-12-09 11:59:52 +03:00
module , type_name , Py_TYPE ( obj ) - > tp_name ) ;
2010-08-27 04:17:26 +04:00
return ret ;
}
2010-09-03 04:39:38 +04:00
2010-09-17 11:04:28 +04:00
/*
connect to a IRPC pipe from python
*/
static NTSTATUS pyrpc_irpc_connect ( TALLOC_CTX * mem_ctx , const char * irpc_server ,
const struct ndr_interface_table * table ,
struct tevent_context * event_ctx ,
struct loadparm_context * lp_ctx ,
struct dcerpc_binding_handle * * binding_handle )
{
2011-05-03 04:40:33 +04:00
struct imessaging_context * msg ;
2010-09-17 11:04:28 +04:00
2011-10-13 13:01:56 +04:00
msg = imessaging_client_init ( mem_ctx , lp_ctx , event_ctx ) ;
2010-09-17 11:04:28 +04:00
NT_STATUS_HAVE_NO_MEMORY ( msg ) ;
* binding_handle = irpc_binding_handle_by_name ( mem_ctx , msg , irpc_server , table ) ;
if ( * binding_handle = = NULL ) {
talloc_free ( msg ) ;
return NT_STATUS_INVALID_PIPE_STATE ;
}
return NT_STATUS_OK ;
}
PyObject * py_dcerpc_interface_init_helper ( PyTypeObject * type , PyObject * args , PyObject * kwargs ,
const struct ndr_interface_table * table )
2010-09-03 04:39:38 +04:00
{
dcerpc_InterfaceObject * ret ;
const char * binding_string ;
struct cli_credentials * credentials ;
struct loadparm_context * lp_ctx = NULL ;
PyObject * py_lp_ctx = Py_None , * py_credentials = Py_None , * py_basis = Py_None ;
TALLOC_CTX * mem_ctx = NULL ;
struct tevent_context * event_ctx ;
NTSTATUS status ;
const char * kwnames [ ] = {
" binding " , " lp_ctx " , " credentials " , " basis_connection " , NULL
} ;
if ( ! PyArg_ParseTupleAndKeywords ( args , kwargs , " s|OOO:samr " , discard_const_p ( char * , kwnames ) , & binding_string , & py_lp_ctx , & py_credentials , & py_basis ) ) {
return NULL ;
}
mem_ctx = talloc_new ( NULL ) ;
if ( mem_ctx = = NULL ) {
PyErr_NoMemory ( ) ;
return NULL ;
}
lp_ctx = lpcfg_from_py_object ( mem_ctx , py_lp_ctx ) ;
if ( lp_ctx = = NULL ) {
PyErr_SetString ( PyExc_TypeError , " Expected loadparm context " ) ;
talloc_free ( mem_ctx ) ;
return NULL ;
}
2011-06-06 08:58:28 +04:00
status = dcerpc_init ( ) ;
2010-09-03 04:39:38 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
PyErr_SetNTSTATUS ( status ) ;
talloc_free ( mem_ctx ) ;
return NULL ;
}
2010-09-17 11:04:28 +04:00
2010-09-03 04:39:38 +04:00
ret = PyObject_New ( dcerpc_InterfaceObject , type ) ;
ret - > mem_ctx = mem_ctx ;
event_ctx = s4_event_context_init ( ret - > mem_ctx ) ;
2010-09-17 11:04:28 +04:00
if ( strncmp ( binding_string , " irpc: " , 5 ) = = 0 ) {
ret - > pipe = NULL ;
status = pyrpc_irpc_connect ( ret - > mem_ctx , binding_string + 5 , table ,
event_ctx , lp_ctx , & ret - > binding_handle ) ;
} else if ( py_basis ! = Py_None ) {
2010-09-03 04:39:38 +04:00
struct dcerpc_pipe * base_pipe ;
PyObject * py_base ;
PyTypeObject * ClientConnection_Type ;
py_base = PyImport_ImportModule ( " samba.dcerpc.base " ) ;
if ( py_base = = NULL ) {
talloc_free ( mem_ctx ) ;
return NULL ;
}
ClientConnection_Type = ( PyTypeObject * ) PyObject_GetAttrString ( py_base , " ClientConnection " ) ;
if ( ClientConnection_Type = = NULL ) {
PyErr_SetNone ( PyExc_TypeError ) ;
talloc_free ( mem_ctx ) ;
return NULL ;
}
if ( ! PyObject_TypeCheck ( py_basis , ClientConnection_Type ) ) {
PyErr_SetString ( PyExc_TypeError , " basis_connection must be a DCE/RPC connection " ) ;
talloc_free ( mem_ctx ) ;
return NULL ;
}
base_pipe = talloc_reference ( mem_ctx , ( ( dcerpc_InterfaceObject * ) py_basis ) - > pipe ) ;
status = dcerpc_secondary_context ( base_pipe , & ret - > pipe , table ) ;
ret - > pipe = talloc_steal ( ret - > mem_ctx , ret - > pipe ) ;
} else {
2010-09-17 11:04:28 +04:00
credentials = cli_credentials_from_py_object ( py_credentials ) ;
if ( credentials = = NULL ) {
PyErr_SetString ( PyExc_TypeError , " Expected credentials " ) ;
talloc_free ( mem_ctx ) ;
return NULL ;
}
2010-09-03 04:39:38 +04:00
status = dcerpc_pipe_connect ( event_ctx , & ret - > pipe , binding_string ,
table , credentials , event_ctx , lp_ctx ) ;
}
if ( NT_STATUS_IS_ERR ( status ) ) {
PyErr_SetNTSTATUS ( status ) ;
talloc_free ( mem_ctx ) ;
return NULL ;
}
2010-09-17 11:04:28 +04:00
if ( ret - > pipe ) {
ret - > pipe - > conn - > flags | = DCERPC_NDR_REF_ALLOC ;
ret - > binding_handle = ret - > pipe - > binding_handle ;
}
2010-09-03 04:39:38 +04:00
return ( PyObject * ) ret ;
}
static PyObject * py_dcerpc_run_function ( dcerpc_InterfaceObject * iface ,
const struct PyNdrRpcMethodDef * md ,
PyObject * args , PyObject * kwargs )
{
TALLOC_CTX * mem_ctx ;
NTSTATUS status ;
void * r ;
PyObject * result = Py_None ;
if ( md - > pack_in_data = = NULL | | md - > unpack_out_data = = NULL ) {
PyErr_SetString ( PyExc_NotImplementedError , " No marshalling code available yet " ) ;
return NULL ;
}
mem_ctx = talloc_new ( NULL ) ;
if ( mem_ctx = = NULL ) {
PyErr_NoMemory ( ) ;
return NULL ;
}
r = talloc_zero_size ( mem_ctx , md - > table - > calls [ md - > opnum ] . struct_size ) ;
if ( r = = NULL ) {
PyErr_NoMemory ( ) ;
return NULL ;
}
if ( ! md - > pack_in_data ( args , kwargs , r ) ) {
talloc_free ( mem_ctx ) ;
return NULL ;
}
status = md - > call ( iface - > binding_handle , mem_ctx , r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
PyErr_SetDCERPCStatus ( iface - > pipe , status ) ;
talloc_free ( mem_ctx ) ;
return NULL ;
}
result = md - > unpack_out_data ( r ) ;
talloc_free ( mem_ctx ) ;
return result ;
}
static PyObject * py_dcerpc_call_wrapper ( PyObject * self , PyObject * args , void * wrapped , PyObject * kwargs )
{
dcerpc_InterfaceObject * iface = ( dcerpc_InterfaceObject * ) self ;
const struct PyNdrRpcMethodDef * md = ( const struct PyNdrRpcMethodDef * ) wrapped ;
return py_dcerpc_run_function ( iface , md , args , kwargs ) ;
}
bool PyInterface_AddNdrRpcMethods ( PyTypeObject * ifacetype , const struct PyNdrRpcMethodDef * mds )
{
int i ;
for ( i = 0 ; mds [ i ] . name ; i + + ) {
PyObject * ret ;
struct wrapperbase * wb = ( struct wrapperbase * ) calloc ( sizeof ( struct wrapperbase ) , 1 ) ;
wb - > name = discard_const_p ( char , mds [ i ] . name ) ;
wb - > flags = PyWrapperFlag_KEYWORDS ;
wb - > wrapper = ( wrapperfunc ) py_dcerpc_call_wrapper ;
wb - > doc = discard_const_p ( char , mds [ i ] . doc ) ;
ret = PyDescr_NewWrapper ( ifacetype , wb , discard_const_p ( void , & mds [ i ] ) ) ;
PyDict_SetItemString ( ifacetype - > tp_dict , mds [ i ] . name ,
( PyObject * ) ret ) ;
}
return true ;
}
void PyErr_SetDCERPCStatus ( struct dcerpc_pipe * p , NTSTATUS status )
{
if ( p & & NT_STATUS_EQUAL ( status , NT_STATUS_NET_WRITE_FAULT ) ) {
status = dcerpc_fault_to_nt_status ( p - > last_fault_code ) ;
}
PyErr_SetNTSTATUS ( status ) ;
}
2010-09-15 12:49:06 +04:00
/*
take a NDR structure that has a type in a python module and return
it as a python object
r is the NDR structure pointer ( a C structure )
r_ctx is the context that is a parent of r . It will be referenced by
the resulting python object
*/
PyObject * py_return_ndr_struct ( const char * module_name , const char * type_name ,
TALLOC_CTX * r_ctx , void * r )
{
PyTypeObject * py_type ;
PyObject * module ;
if ( r = = NULL ) {
Py_RETURN_NONE ;
}
module = PyImport_ImportModule ( module_name ) ;
if ( module = = NULL ) {
return NULL ;
}
py_type = ( PyTypeObject * ) PyObject_GetAttrString ( module , type_name ) ;
if ( py_type = = NULL ) {
return NULL ;
}
2011-08-10 17:15:18 +04:00
return pytalloc_reference_ex ( py_type , r_ctx , r ) ;
2010-09-15 12:49:06 +04:00
}
2010-12-08 17:07:32 +03:00
PyObject * PyString_FromStringOrNULL ( const char * str )
{
if ( str = = NULL ) {
Py_RETURN_NONE ;
}
return PyString_FromString ( str ) ;
}