2012-05-07 10:24:03 +04:00
/*
Unix SMB / CIFS implementation .
2012-08-02 07:36:43 +04:00
Set NT and POSIX ACLs and other VFS operations from Python
Copyrigyt ( C ) Andrew Bartlett 2012
2012-05-07 10:24:03 +04:00
Copyright ( C ) Jeremy Allison 1994 - 2009.
Copyright ( C ) Andreas Gruenbacher 2002.
Copyright ( C ) Simo Sorce < idra @ samba . org > 2009.
2012-08-02 07:35:24 +04:00
Copyright ( C ) Simo Sorce 2002
Copyright ( C ) Eric Lorimer 2002
2012-05-07 10:24:03 +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 .
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 "includes.h"
# include "smbd/smbd.h"
# include <Python.h>
# include "libcli/util/pyerrors.h"
2012-08-02 07:35:24 +04:00
# include "librpc/rpc/pyrpc_util.h"
# include <pytalloc.h>
# include "system/filesys.h"
2012-05-07 10:24:03 +04:00
extern const struct generic_mapping file_generic_mapping ;
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_ACLS
static NTSTATUS set_sys_acl_no_snum ( const char * fname ,
SMB_ACL_TYPE_T acltype ,
SMB_ACL_T theacl )
{
connection_struct * conn ;
NTSTATUS status = NT_STATUS_OK ;
int ret ;
conn = talloc_zero ( NULL , connection_struct ) ;
if ( conn = = NULL ) {
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
if ( ! ( conn - > params = talloc ( conn , struct share_params ) ) ) {
DEBUG ( 0 , ( " get_nt_acl_no_snum: talloc() failed! \n " ) ) ;
TALLOC_FREE ( conn ) ;
return NT_STATUS_NO_MEMORY ;
}
conn - > params - > service = - 1 ;
set_conn_connectpath ( conn , " / " ) ;
smbd_vfs_init ( conn ) ;
ret = SMB_VFS_SYS_ACL_SET_FILE ( conn , fname , acltype , theacl ) ;
if ( ret ! = 0 ) {
status = map_nt_error_from_unix_common ( ret ) ;
2012-08-02 07:36:55 +04:00
DEBUG ( 0 , ( " set_nt_acl_no_snum: fset_nt_acl returned zero. \n " ) ) ;
2012-05-07 10:24:03 +04:00
}
conn_free ( conn ) ;
return status ;
}
2012-08-02 07:35:24 +04:00
static NTSTATUS set_nt_acl_no_snum ( const char * fname ,
uint32 security_info_sent , const struct security_descriptor * sd )
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
connection_struct * conn ;
NTSTATUS status = NT_STATUS_OK ;
files_struct * fsp ;
struct smb_filename * smb_fname = NULL ;
int flags ;
conn = talloc_zero ( frame , connection_struct ) ;
if ( conn = = NULL ) {
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
if ( ! ( conn - > params = talloc ( conn , struct share_params ) ) ) {
2012-08-03 01:21:27 +04:00
DEBUG ( 0 , ( " set_nt_acl_no_snum: talloc() failed! \n " ) ) ;
2012-08-02 07:35:24 +04:00
TALLOC_FREE ( frame ) ;
return NT_STATUS_NO_MEMORY ;
}
conn - > params - > service = - 1 ;
set_conn_connectpath ( conn , " / " ) ;
smbd_vfs_init ( conn ) ;
2012-08-07 08:18:41 +04:00
fsp = talloc_zero ( frame , struct files_struct ) ;
2012-08-02 07:35:24 +04:00
if ( fsp = = NULL ) {
TALLOC_FREE ( frame ) ;
return NT_STATUS_NO_MEMORY ;
}
fsp - > fh = talloc ( fsp , struct fd_handle ) ;
if ( fsp - > fh = = NULL ) {
TALLOC_FREE ( frame ) ;
return NT_STATUS_NO_MEMORY ;
}
fsp - > conn = conn ;
status = create_synthetic_smb_fname_split ( fsp , fname , NULL ,
& smb_fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( frame ) ;
return status ;
}
fsp - > fsp_name = smb_fname ;
# ifdef O_DIRECTORY
flags = O_RDONLY | O_DIRECTORY ;
# else
/* POSIX allows us to open a directory with O_RDONLY. */
flags = O_RDONLY ;
# endif
2012-08-07 08:19:06 +04:00
fsp - > fh - > fd = SMB_VFS_OPEN ( conn , smb_fname , fsp , O_RDWR , 00400 ) ;
2012-08-02 07:35:24 +04:00
if ( fsp - > fh - > fd = = - 1 & & errno = = EISDIR ) {
2012-08-07 08:19:06 +04:00
fsp - > fh - > fd = SMB_VFS_OPEN ( conn , smb_fname , fsp , flags , 00400 ) ;
2012-08-02 07:35:24 +04:00
}
if ( fsp - > fh - > fd = = - 1 ) {
printf ( " open: error=%d (%s) \n " , errno , strerror ( errno ) ) ;
TALLOC_FREE ( frame ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
status = SMB_VFS_FSET_NT_ACL ( fsp , security_info_sent , sd ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " set_nt_acl_no_snum: fset_nt_acl returned %s. \n " , nt_errstr ( status ) ) ) ;
}
conn_free ( conn ) ;
TALLOC_FREE ( frame ) ;
return status ;
}
2012-05-07 10:24:03 +04:00
2012-08-22 12:35:01 +04:00
static SMB_ACL_T make_simple_acl ( gid_t gid , mode_t chmod_mode )
2012-05-07 10:24:03 +04:00
{
mode_t mode = SMB_ACL_READ | SMB_ACL_WRITE ;
2012-08-22 12:35:01 +04:00
mode_t mode_user = ( chmod_mode & 0700 ) > > 16 ;
mode_t mode_group = ( chmod_mode & 070 ) > > 8 ;
mode_t mode_other = chmod_mode & 07 ;
2012-05-07 10:24:03 +04:00
SMB_ACL_ENTRY_T entry ;
SMB_ACL_T acl = sys_acl_init ( 4 ) ;
if ( ! acl ) {
return NULL ;
}
if ( sys_acl_create_entry ( & acl , & entry ) ! = 0 ) {
2012-08-13 14:51:41 +04:00
TALLOC_FREE ( acl ) ;
2012-05-07 10:24:03 +04:00
return NULL ;
}
if ( sys_acl_set_tag_type ( entry , SMB_ACL_USER_OBJ ) ! = 0 ) {
2012-08-13 14:51:41 +04:00
TALLOC_FREE ( acl ) ;
2012-05-07 10:24:03 +04:00
return NULL ;
}
2012-08-22 12:35:01 +04:00
if ( sys_acl_set_permset ( entry , & mode_user ) ! = 0 ) {
2012-08-13 14:51:41 +04:00
TALLOC_FREE ( acl ) ;
2012-05-07 10:24:03 +04:00
return NULL ;
}
if ( sys_acl_create_entry ( & acl , & entry ) ! = 0 ) {
2012-08-13 14:51:41 +04:00
TALLOC_FREE ( acl ) ;
2012-05-07 10:24:03 +04:00
return NULL ;
}
if ( sys_acl_set_tag_type ( entry , SMB_ACL_GROUP_OBJ ) ! = 0 ) {
2012-08-13 14:51:41 +04:00
TALLOC_FREE ( acl ) ;
2012-05-07 10:24:03 +04:00
return NULL ;
}
2012-08-22 12:35:01 +04:00
if ( sys_acl_set_permset ( entry , & mode_group ) ! = 0 ) {
2012-08-13 14:51:41 +04:00
TALLOC_FREE ( acl ) ;
2012-05-07 10:24:03 +04:00
return NULL ;
}
if ( sys_acl_create_entry ( & acl , & entry ) ! = 0 ) {
2012-08-13 14:51:41 +04:00
TALLOC_FREE ( acl ) ;
2012-05-07 10:24:03 +04:00
return NULL ;
}
if ( sys_acl_set_tag_type ( entry , SMB_ACL_OTHER ) ! = 0 ) {
2012-08-13 14:51:41 +04:00
TALLOC_FREE ( acl ) ;
2012-05-07 10:24:03 +04:00
return NULL ;
}
2012-08-22 12:35:01 +04:00
if ( sys_acl_set_permset ( entry , & mode_other ) ! = 0 ) {
2012-08-13 14:51:41 +04:00
TALLOC_FREE ( acl ) ;
2012-05-07 10:24:03 +04:00
return NULL ;
}
2012-08-22 12:35:01 +04:00
if ( gid ! = - 1 ) {
if ( sys_acl_create_entry ( & acl , & entry ) ! = 0 ) {
TALLOC_FREE ( acl ) ;
return NULL ;
}
if ( sys_acl_set_tag_type ( entry , SMB_ACL_GROUP ) ! = 0 ) {
TALLOC_FREE ( acl ) ;
return NULL ;
}
if ( sys_acl_set_qualifier ( entry , & gid ) ! = 0 ) {
TALLOC_FREE ( acl ) ;
return NULL ;
}
if ( sys_acl_set_permset ( entry , & mode_group ) ! = 0 ) {
TALLOC_FREE ( acl ) ;
return NULL ;
}
2012-05-07 10:24:03 +04:00
}
if ( sys_acl_create_entry ( & acl , & entry ) ! = 0 ) {
2012-08-13 14:51:41 +04:00
TALLOC_FREE ( acl ) ;
2012-05-07 10:24:03 +04:00
return NULL ;
}
if ( sys_acl_set_tag_type ( entry , SMB_ACL_MASK ) ! = 0 ) {
2012-08-13 14:51:41 +04:00
TALLOC_FREE ( acl ) ;
2012-05-07 10:24:03 +04:00
return NULL ;
}
2012-08-22 12:35:01 +04:00
if ( sys_acl_set_permset ( entry , & mode ) ! = 0 ) {
2012-08-13 14:51:41 +04:00
TALLOC_FREE ( acl ) ;
2012-05-07 10:24:03 +04:00
return NULL ;
}
return acl ;
}
/*
set a simple ACL on a file , as a test
*/
static PyObject * py_smbd_set_simple_acl ( PyObject * self , PyObject * args )
{
NTSTATUS status ;
char * fname ;
2012-08-22 12:35:01 +04:00
int mode , gid = - 1 ;
2012-05-07 10:24:03 +04:00
SMB_ACL_T acl ;
2012-08-07 04:45:14 +04:00
TALLOC_CTX * frame ;
2012-05-07 10:24:03 +04:00
2012-08-22 12:35:01 +04:00
if ( ! PyArg_ParseTuple ( args , " si|i " , & fname , & mode , & gid ) )
2012-05-07 10:24:03 +04:00
return NULL ;
2012-08-22 12:35:01 +04:00
acl = make_simple_acl ( gid , mode ) ;
2012-05-07 10:24:03 +04:00
2012-08-07 04:45:14 +04:00
frame = talloc_stackframe ( ) ;
2012-05-07 10:24:03 +04:00
status = set_sys_acl_no_snum ( fname , SMB_ACL_TYPE_ACCESS , acl ) ;
2012-08-13 14:51:41 +04:00
TALLOC_FREE ( acl ) ;
2012-08-07 04:45:14 +04:00
TALLOC_FREE ( frame ) ;
2012-05-07 10:24:03 +04:00
PyErr_NTSTATUS_IS_ERR_RAISE ( status ) ;
Py_RETURN_NONE ;
}
2012-08-21 08:23:35 +04:00
/*
chown a file
*/
static PyObject * py_smbd_chown ( PyObject * self , PyObject * args )
{
connection_struct * conn ;
NTSTATUS status = NT_STATUS_OK ;
int ret ;
char * fname ;
int uid , gid ;
TALLOC_CTX * frame ;
if ( ! PyArg_ParseTuple ( args , " sii " , & fname , & uid , & gid ) )
return NULL ;
frame = talloc_stackframe ( ) ;
conn = talloc_zero ( frame , connection_struct ) ;
if ( conn = = NULL ) {
PyErr_NoMemory ( ) ;
return NULL ;
}
if ( ! ( conn - > params = talloc ( conn , struct share_params ) ) ) {
PyErr_NoMemory ( ) ;
return NULL ;
}
conn - > params - > service = - 1 ;
set_conn_connectpath ( conn , " / " ) ;
smbd_vfs_init ( conn ) ;
ret = SMB_VFS_CHOWN ( conn , fname , uid , gid ) ;
if ( ret ! = 0 ) {
2012-08-22 15:00:17 +04:00
status = map_nt_error_from_unix_common ( errno ) ;
DEBUG ( 0 , ( " chown returned failure: %s \n " , strerror ( errno ) ) ) ;
2012-08-21 08:23:35 +04:00
}
conn_free ( conn ) ;
TALLOC_FREE ( frame ) ;
PyErr_NTSTATUS_IS_ERR_RAISE ( status ) ;
Py_RETURN_NONE ;
}
2012-06-21 10:21:54 +04:00
/*
check if we have ACL support
*/
static PyObject * py_smbd_have_posix_acls ( PyObject * self , PyObject * args )
{
# ifdef HAVE_POSIX_ACLS
return PyBool_FromLong ( true ) ;
# else
return PyBool_FromLong ( false ) ;
# endif
}
2012-08-02 07:35:24 +04:00
/*
2012-08-21 09:10:43 +04:00
set the NT ACL on a file
2012-08-02 07:35:24 +04:00
*/
static PyObject * py_smbd_set_nt_acl ( PyObject * self , PyObject * args )
{
NTSTATUS status ;
char * fname ;
int security_info_sent ;
PyObject * py_sd ;
struct security_descriptor * sd ;
if ( ! PyArg_ParseTuple ( args , " siO " , & fname , & security_info_sent , & py_sd ) )
return NULL ;
if ( ! py_check_dcerpc_type ( py_sd , " samba.dcerpc.security " , " descriptor " ) ) {
return NULL ;
}
sd = pytalloc_get_type ( py_sd , struct security_descriptor ) ;
status = set_nt_acl_no_snum ( fname , security_info_sent , sd ) ;
PyErr_NTSTATUS_IS_ERR_RAISE ( status ) ;
Py_RETURN_NONE ;
}
2012-08-02 09:16:13 +04:00
/*
2012-08-21 09:10:43 +04:00
Return the NT ACL on a file
2012-08-02 09:16:13 +04:00
*/
static PyObject * py_smbd_get_nt_acl ( PyObject * self , PyObject * args )
{
char * fname ;
2012-08-23 03:45:07 +04:00
int security_info_wanted ;
2012-08-02 09:16:13 +04:00
PyObject * py_sd ;
struct security_descriptor * sd ;
TALLOC_CTX * tmp_ctx = talloc_new ( NULL ) ;
2012-08-23 03:45:07 +04:00
if ( ! PyArg_ParseTuple ( args , " si " , & fname , & security_info_wanted ) )
2012-08-02 09:16:13 +04:00
return NULL ;
2012-08-23 03:45:07 +04:00
sd = get_nt_acl_no_snum ( tmp_ctx , fname , security_info_wanted ) ;
2012-08-02 09:16:13 +04:00
2012-08-23 03:39:32 +04:00
py_sd = py_return_ndr_struct ( " samba.dcerpc.security " , " descriptor " , sd , sd ) ;
2012-08-02 09:16:13 +04:00
talloc_free ( tmp_ctx ) ;
return py_sd ;
}
2012-08-21 09:11:30 +04:00
/*
set the posix ( or similar ) ACL on a file
*/
static PyObject * py_smbd_set_sys_acl ( PyObject * self , PyObject * args )
{
NTSTATUS status ;
char * fname ;
PyObject * py_acl ;
struct smb_acl_t * acl ;
int acl_type ;
if ( ! PyArg_ParseTuple ( args , " siO " , & fname , & acl_type , & py_acl ) )
return NULL ;
2012-08-21 16:41:13 +04:00
if ( ! py_check_dcerpc_type ( py_acl , " samba.dcerpc.smb_acl " , " t " ) ) {
2012-08-21 09:11:30 +04:00
return NULL ;
}
acl = pytalloc_get_type ( py_acl , struct smb_acl_t ) ;
status = set_sys_acl_no_snum ( fname , acl_type , acl ) ;
PyErr_NTSTATUS_IS_ERR_RAISE ( status ) ;
Py_RETURN_NONE ;
}
/*
Return the posix ( or similar ) ACL on a file
*/
static PyObject * py_smbd_get_sys_acl ( PyObject * self , PyObject * args )
{
char * fname ;
PyObject * py_acl ;
struct smb_acl_t * acl ;
int acl_type ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
connection_struct * conn ;
NTSTATUS status = NT_STATUS_OK ;
if ( ! PyArg_ParseTuple ( args , " si " , & fname , & acl_type ) ) {
TALLOC_FREE ( frame ) ;
return NULL ;
}
conn = talloc_zero ( frame , connection_struct ) ;
if ( conn = = NULL ) {
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
PyErr_NoMemory ( ) ;
TALLOC_FREE ( frame ) ;
return NULL ;
}
if ( ! ( conn - > params = talloc ( conn , struct share_params ) ) ) {
DEBUG ( 0 , ( " get_nt_acl_no_snum: talloc() failed! \n " ) ) ;
PyErr_NoMemory ( ) ;
TALLOC_FREE ( frame ) ;
return NULL ;
}
conn - > params - > service = - 1 ;
set_conn_connectpath ( conn , " / " ) ;
smbd_vfs_init ( conn ) ;
acl = SMB_VFS_SYS_ACL_GET_FILE ( conn , fname , acl_type ) ;
if ( ! acl ) {
TALLOC_FREE ( frame ) ;
status = map_nt_error_from_unix_common ( errno ) ;
DEBUG ( 0 , ( " sys_acl_get_file returned NULL: %s \n " , strerror ( errno ) ) ) ;
PyErr_NTSTATUS_IS_ERR_RAISE ( status ) ;
}
talloc_steal ( frame , acl ) ;
conn_free ( conn ) ;
2012-08-21 16:41:13 +04:00
py_acl = py_return_ndr_struct ( " samba.dcerpc.smb_acl " , " t " , acl , acl ) ;
2012-08-21 09:11:30 +04:00
TALLOC_FREE ( frame ) ;
return py_acl ;
}
2012-05-07 10:24:03 +04:00
static PyMethodDef py_smbd_methods [ ] = {
2012-06-21 10:21:54 +04:00
{ " have_posix_acls " ,
( PyCFunction ) py_smbd_have_posix_acls , METH_VARARGS ,
NULL } ,
2012-05-07 10:24:03 +04:00
{ " set_simple_acl " ,
( PyCFunction ) py_smbd_set_simple_acl , METH_VARARGS ,
NULL } ,
2012-08-02 07:35:24 +04:00
{ " set_nt_acl " ,
( PyCFunction ) py_smbd_set_nt_acl , METH_VARARGS ,
NULL } ,
2012-08-02 09:16:13 +04:00
{ " get_nt_acl " ,
( PyCFunction ) py_smbd_get_nt_acl , METH_VARARGS ,
NULL } ,
2012-08-21 09:11:30 +04:00
{ " get_sys_acl " ,
( PyCFunction ) py_smbd_get_sys_acl , METH_VARARGS ,
NULL } ,
{ " set_sys_acl " ,
( PyCFunction ) py_smbd_set_sys_acl , METH_VARARGS ,
NULL } ,
2012-08-21 08:23:35 +04:00
{ " chown " ,
( PyCFunction ) py_smbd_chown , METH_VARARGS ,
NULL } ,
2012-05-07 10:24:03 +04:00
{ NULL }
} ;
void initsmbd ( void ) ;
void initsmbd ( void )
{
PyObject * m ;
m = Py_InitModule3 ( " smbd " , py_smbd_methods ,
" Python bindings for the smbd file server. " ) ;
if ( m = = NULL )
return ;
}