2000-02-03 07:40:56 +03:00
/*
2000-05-17 06:48:04 +04:00
* Auditing VFS module for samba . Log selected file operations to syslog
2000-02-03 07:40:56 +03:00
* facility .
*
2002-03-19 05:51:48 +03:00
* Copyright ( C ) Tim Potter , 1999 - 2000
2002-07-30 13:59:53 +04:00
* Copyright ( C ) Alexander Bokovoy , 2002
2000-02-03 07:40:56 +03: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 2 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 , write to the Free Software
* Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "config.h"
# include <stdio.h>
# include <sys/stat.h>
# ifdef HAVE_UTIME_H
# include <utime.h>
# endif
# ifdef HAVE_DIRENT_H
# include <dirent.h>
# endif
# include <syslog.h>
# ifdef HAVE_FCNTL_H
# include <fcntl.h>
# endif
# include <errno.h>
# include <string.h>
2000-11-06 23:01:03 +03:00
# include <includes.h>
2000-02-03 07:40:56 +03:00
# include <vfs.h>
# ifndef SYSLOG_FACILITY
# define SYSLOG_FACILITY LOG_USER
# endif
# ifndef SYSLOG_PRIORITY
# define SYSLOG_PRIORITY LOG_NOTICE
# endif
2002-03-19 05:51:48 +03:00
/* Function prototypes */
2002-07-30 13:59:53 +04:00
static int audit_connect ( struct connection_struct * conn , const char * svc , const char * user ) ;
static void audit_disconnect ( struct connection_struct * conn ) ;
static DIR * audit_opendir ( struct connection_struct * conn , const char * fname ) ;
static int audit_mkdir ( struct connection_struct * conn , const char * path , mode_t mode ) ;
static int audit_rmdir ( struct connection_struct * conn , const char * path ) ;
static int audit_open ( struct connection_struct * conn , const char * fname , int flags , mode_t mode ) ;
static int audit_close ( struct files_struct * fsp , int fd ) ;
static int audit_rename ( struct connection_struct * conn , const char * old , const char * new ) ;
static int audit_unlink ( struct connection_struct * conn , const char * path ) ;
static int audit_chmod ( struct connection_struct * conn , const char * path , mode_t mode ) ;
static int audit_chmod_acl ( struct connection_struct * conn , const char * name , mode_t mode ) ;
static int audit_fchmod ( struct files_struct * fsp , int fd , mode_t mode ) ;
static int audit_fchmod_acl ( struct files_struct * fsp , int fd , mode_t mode ) ;
2002-03-19 05:51:48 +03:00
/* VFS operations */
2002-07-30 13:59:53 +04:00
static struct vfs_ops default_vfs_ops ; /* For passthrough operation */
static struct smb_vfs_handle_struct * audit_handle ;
2002-03-19 05:51:48 +03:00
2002-07-30 13:59:53 +04:00
static vfs_op_tuple audit_ops [ ] = {
2002-03-19 05:51:48 +03:00
/* Disk operations */
2002-07-30 13:59:53 +04:00
{ audit_connect , SMB_VFS_OP_CONNECT , SMB_VFS_LAYER_LOGGER } ,
{ audit_disconnect , SMB_VFS_OP_DISCONNECT , SMB_VFS_LAYER_LOGGER } ,
2002-03-19 05:51:48 +03:00
/* Directory operations */
2002-07-30 13:59:53 +04:00
{ audit_opendir , SMB_VFS_OP_OPENDIR , SMB_VFS_LAYER_LOGGER } ,
{ audit_mkdir , SMB_VFS_OP_MKDIR , SMB_VFS_LAYER_LOGGER } ,
{ audit_rmdir , SMB_VFS_OP_RMDIR , SMB_VFS_LAYER_LOGGER } ,
2002-03-19 05:51:48 +03:00
/* File operations */
2002-07-30 13:59:53 +04:00
{ audit_open , SMB_VFS_OP_OPEN , SMB_VFS_LAYER_LOGGER } ,
{ audit_close , SMB_VFS_OP_CLOSE , SMB_VFS_LAYER_LOGGER } ,
{ audit_rename , SMB_VFS_OP_RENAME , SMB_VFS_LAYER_LOGGER } ,
{ audit_unlink , SMB_VFS_OP_UNLINK , SMB_VFS_LAYER_LOGGER } ,
{ audit_chmod , SMB_VFS_OP_CHMOD , SMB_VFS_LAYER_LOGGER } ,
{ audit_fchmod , SMB_VFS_OP_FCHMOD , SMB_VFS_LAYER_LOGGER } ,
{ audit_chmod_acl , SMB_VFS_OP_CHMOD_ACL , SMB_VFS_LAYER_LOGGER } ,
{ audit_fchmod_acl , SMB_VFS_OP_FCHMOD_ACL , SMB_VFS_LAYER_LOGGER } ,
/* Finish VFS operations definition */
{ NULL , SMB_VFS_OP_NOOP , SMB_VFS_LAYER_NOOP }
2002-03-19 05:51:48 +03:00
} ;
2002-07-30 13:59:53 +04:00
/* VFS initialisation function. Return vfs_op_tuple array back to SAMBA. */
2002-03-19 05:51:48 +03:00
2003-04-16 18:45:11 +04:00
static vfs_op_tuple * audit_init ( const struct vfs_ops * def_vfs_ops ,
2002-07-30 13:59:53 +04:00
struct smb_vfs_handle_struct * vfs_handle )
2002-03-19 05:51:48 +03:00
{
2002-07-30 13:59:53 +04:00
memcpy ( & default_vfs_ops , def_vfs_ops , sizeof ( struct vfs_ops ) ) ;
audit_handle = vfs_handle ;
2002-03-19 05:51:48 +03:00
openlog ( " smbd_audit " , LOG_PID , SYSLOG_FACILITY ) ;
syslog ( SYSLOG_PRIORITY , " VFS_INIT: vfs_ops loaded \n " ) ;
2002-07-30 13:59:53 +04:00
return audit_ops ;
}
2000-02-03 07:40:56 +03:00
/* Implementation of vfs_ops. Pass everything on to the default
operation but log event first . */
2002-07-30 13:59:53 +04:00
static int audit_connect ( struct connection_struct * conn , const char * svc , const char * user )
2000-02-03 07:40:56 +03:00
{
2000-05-17 06:48:04 +04:00
syslog ( SYSLOG_PRIORITY , " connect to service %s by user %s \n " ,
svc , user ) ;
2000-02-03 07:40:56 +03:00
2002-03-19 05:51:48 +03:00
return default_vfs_ops . connect ( conn , svc , user ) ;
2000-02-03 07:40:56 +03:00
}
2002-07-30 13:59:53 +04:00
static void audit_disconnect ( struct connection_struct * conn )
2000-02-03 07:40:56 +03:00
{
2000-05-17 06:48:04 +04:00
syslog ( SYSLOG_PRIORITY , " disconnected \n " ) ;
2002-03-19 05:51:48 +03:00
default_vfs_ops . disconnect ( conn ) ;
2000-02-03 07:40:56 +03:00
}
2002-07-30 13:59:53 +04:00
static DIR * audit_opendir ( struct connection_struct * conn , const char * fname )
2000-02-03 07:40:56 +03:00
{
2001-10-24 04:45:41 +04:00
DIR * result = default_vfs_ops . opendir ( conn , fname ) ;
2000-02-03 07:40:56 +03:00
2000-05-17 06:48:04 +04:00
syslog ( SYSLOG_PRIORITY , " opendir %s %s%s \n " ,
fname ,
( result = = NULL ) ? " failed: " : " " ,
( result = = NULL ) ? strerror ( errno ) : " " ) ;
2000-02-03 07:40:56 +03:00
2000-05-17 06:48:04 +04:00
return result ;
2000-02-03 07:40:56 +03:00
}
2002-07-30 13:59:53 +04:00
static int audit_mkdir ( struct connection_struct * conn , const char * path , mode_t mode )
2000-02-03 07:40:56 +03:00
{
2001-10-24 04:45:41 +04:00
int result = default_vfs_ops . mkdir ( conn , path , mode ) ;
2000-02-03 07:40:56 +03:00
2000-05-17 06:48:04 +04:00
syslog ( SYSLOG_PRIORITY , " mkdir %s %s%s \n " ,
path ,
( result < 0 ) ? " failed: " : " " ,
( result < 0 ) ? strerror ( errno ) : " " ) ;
2000-02-03 07:40:56 +03:00
2000-05-17 06:48:04 +04:00
return result ;
2000-02-03 07:40:56 +03:00
}
2002-07-30 13:59:53 +04:00
static int audit_rmdir ( struct connection_struct * conn , const char * path )
2000-02-03 07:40:56 +03:00
{
2001-10-24 04:45:41 +04:00
int result = default_vfs_ops . rmdir ( conn , path ) ;
2000-02-03 07:40:56 +03:00
2000-05-17 06:48:04 +04:00
syslog ( SYSLOG_PRIORITY , " rmdir %s %s%s \n " ,
path ,
( result < 0 ) ? " failed: " : " " ,
( result < 0 ) ? strerror ( errno ) : " " ) ;
2000-02-03 07:40:56 +03:00
2000-05-17 06:48:04 +04:00
return result ;
2000-02-03 07:40:56 +03:00
}
2002-07-30 13:59:53 +04:00
static int audit_open ( struct connection_struct * conn , const char * fname , int flags , mode_t mode )
2000-02-03 07:40:56 +03:00
{
2001-10-24 04:45:41 +04:00
int result = default_vfs_ops . open ( conn , fname , flags , mode ) ;
2000-02-03 07:40:56 +03:00
2000-05-17 06:48:04 +04:00
syslog ( SYSLOG_PRIORITY , " open %s (fd %d) %s%s%s \n " ,
fname , result ,
( ( flags & O_WRONLY ) | | ( flags & O_RDWR ) ) ? " for writing " : " " ,
( result < 0 ) ? " failed: " : " " ,
( result < 0 ) ? strerror ( errno ) : " " ) ;
2000-02-03 07:40:56 +03:00
2000-05-17 06:48:04 +04:00
return result ;
2000-02-03 07:40:56 +03:00
}
2002-07-30 13:59:53 +04:00
static int audit_close ( struct files_struct * fsp , int fd )
2000-02-03 07:40:56 +03:00
{
2001-10-24 04:45:41 +04:00
int result = default_vfs_ops . close ( fsp , fd ) ;
2000-02-03 07:40:56 +03:00
2000-05-17 06:48:04 +04:00
syslog ( SYSLOG_PRIORITY , " close fd %d %s%s \n " ,
fd ,
( result < 0 ) ? " failed: " : " " ,
( result < 0 ) ? strerror ( errno ) : " " ) ;
2000-02-03 07:40:56 +03:00
2000-05-17 06:48:04 +04:00
return result ;
2000-02-03 07:40:56 +03:00
}
2002-07-30 13:59:53 +04:00
static int audit_rename ( struct connection_struct * conn , const char * old , const char * new )
2000-02-03 07:40:56 +03:00
{
2001-10-24 04:45:41 +04:00
int result = default_vfs_ops . rename ( conn , old , new ) ;
2000-02-03 07:40:56 +03:00
2000-05-17 06:48:04 +04:00
syslog ( SYSLOG_PRIORITY , " rename %s -> %s %s%s \n " ,
old , new ,
( result < 0 ) ? " failed: " : " " ,
( result < 0 ) ? strerror ( errno ) : " " ) ;
2000-02-03 07:40:56 +03:00
2000-05-17 06:48:04 +04:00
return result ;
2000-02-03 07:40:56 +03:00
}
2002-07-30 13:59:53 +04:00
static int audit_unlink ( struct connection_struct * conn , const char * path )
2000-02-03 07:40:56 +03:00
{
2001-10-24 04:45:41 +04:00
int result = default_vfs_ops . unlink ( conn , path ) ;
2000-02-03 07:40:56 +03:00
2000-05-17 06:48:04 +04:00
syslog ( SYSLOG_PRIORITY , " unlink %s %s%s \n " ,
path ,
( result < 0 ) ? " failed: " : " " ,
( result < 0 ) ? strerror ( errno ) : " " ) ;
2000-02-03 07:40:56 +03:00
2000-05-17 06:48:04 +04:00
return result ;
2000-02-03 07:40:56 +03:00
}
2000-11-06 23:01:03 +03:00
2002-07-30 13:59:53 +04:00
static int audit_chmod ( struct connection_struct * conn , const char * path , mode_t mode )
2000-11-06 23:01:03 +03:00
{
2001-10-24 04:45:41 +04:00
int result = default_vfs_ops . chmod ( conn , path , mode ) ;
2000-11-06 23:01:03 +03:00
syslog ( SYSLOG_PRIORITY , " chmod %s mode 0x%x %s%s \n " ,
path , mode ,
( result < 0 ) ? " failed: " : " " ,
( result < 0 ) ? strerror ( errno ) : " " ) ;
return result ;
}
2002-07-30 13:59:53 +04:00
static int audit_chmod_acl ( struct connection_struct * conn , const char * path , mode_t mode )
2001-10-18 04:21:48 +04:00
{
2003-02-21 19:15:44 +03:00
int result ;
if ( ! default_vfs_ops . chmod_acl )
return 0 ;
result = default_vfs_ops . chmod_acl ( conn , path , mode ) ;
2001-10-18 04:21:48 +04:00
2002-03-19 05:51:48 +03:00
syslog ( SYSLOG_PRIORITY , " chmod_acl %s mode 0x%x %s%s \n " ,
path , mode ,
( result < 0 ) ? " failed: " : " " ,
( result < 0 ) ? strerror ( errno ) : " " ) ;
return result ;
}
2001-10-18 04:21:48 +04:00
2002-07-30 13:59:53 +04:00
static int audit_fchmod ( struct files_struct * fsp , int fd , mode_t mode )
2002-03-19 05:51:48 +03:00
{
int result = default_vfs_ops . fchmod ( fsp , fd , mode ) ;
syslog ( SYSLOG_PRIORITY , " fchmod %s mode 0x%x %s%s \n " ,
fsp - > fsp_name , mode ,
( result < 0 ) ? " failed: " : " " ,
( result < 0 ) ? strerror ( errno ) : " " ) ;
2001-10-24 04:45:41 +04:00
2002-03-19 05:51:48 +03:00
return result ;
}
2001-10-24 04:45:41 +04:00
2002-07-30 13:59:53 +04:00
static int audit_fchmod_acl ( struct files_struct * fsp , int fd , mode_t mode )
2002-03-19 05:51:48 +03:00
{
2003-02-21 19:15:44 +03:00
int result ;
if ( ! default_vfs_ops . fchmod_acl )
return 0 ;
result = default_vfs_ops . fchmod_acl ( fsp , fd , mode ) ;
2001-10-24 04:45:41 +04:00
2002-03-19 05:51:48 +03:00
syslog ( SYSLOG_PRIORITY , " fchmod_acl %s mode 0x%x %s%s \n " ,
fsp - > fsp_name , mode ,
( result < 0 ) ? " failed: " : " " ,
( result < 0 ) ? strerror ( errno ) : " " ) ;
2001-10-18 04:21:48 +04:00
2002-03-19 05:51:48 +03:00
return result ;
2001-10-18 04:21:48 +04:00
}
2003-04-16 18:45:11 +04:00
int vfs_audit_init ( void )
{
return smb_register_vfs ( " audit " , audit_init , SMB_VFS_INTERFACE_VERSION ) ;
}