The Samba-Bugzilla – Attachment 4860 Details for
Bug 6818
[PATCH] Add MySQL support to vfs_full_audit
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
vfs_full_audit_mysql_support.patch (text/plain), 11.31 KB, created by
Adam Nielsen
on 2009-10-16 02:27:21 UTC
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Adam Nielsen
Created:
2009-10-16 02:27:21 UTC
Size:
11.31 KB
patch
obsolete
>diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c >index 0f6de79..2e2ad59 100644 >--- a/source3/modules/vfs_full_audit.c >+++ b/source3/modules/vfs_full_audit.c >@@ -7,6 +7,7 @@ > * Copyright (C) John H Terpstra, 2003 > * Copyright (C) Stefan (metze) Metzmacher, 2003 > * Copyright (C) Volker Lendecke, 2004 >+ * Copyright (C) Adam Nielsen, 2009 (MySQL support) > * > * 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 >@@ -33,6 +34,12 @@ > * full_audit:prefix = %u|%I > * full_audit:success = open opendir > * full_audit:failure = all >+ * full_audit:dest = syslog mysql >+ * full_audit:myhost = localhost >+ * full_audit:myport = 1234 >+ * full_audit:myuser = samba >+ * full_audit:mypass = secret >+ * full_audit:mydb = sambadb > * > * vfs op can be "all" which means log all operations. > * vfs op can be "none" which means no logging. >@@ -54,8 +61,26 @@ > * > * failure: A list of VFS operations for which failure to complete should be > * logged. Defaults to logging everything. >+ * >+ * dest: Destination for logging messages, valid values are "syslog" and >+ * "mysql". Defaults to "syslog". Separate multiple values with a space to >+ * log the same events to different places. >+ * >+ * The following my* options are only used when "mysql" is included in the >+ * "dest" option: >+ * >+ * myhost: Hostname or IP of MySQL server (default is "localhost") >+ * myport: TCP port (optional, defaults to MySQL standard) >+ * myuser: MySQL username >+ * mypass: MySQL password >+ * mydb : MySQL database name (default to "samba") > */ > >+#define USE_MYSQL >+ >+#ifdef USE_MYSQL >+#include <mysql/mysql.h> >+#endif > > #include "includes.h" > >@@ -64,8 +89,37 @@ static int vfs_full_audit_debug_level = DBGC_VFS; > struct vfs_full_audit_private_data { > struct bitmap *success_ops; > struct bitmap *failure_ops; >+ bool use_syslog; >+#ifdef USE_MYSQL >+ bool use_mysql; >+ MYSQL *mysql; >+ MYSQL_STMT *mysql_insert; >+ MYSQL_BIND mysql_insert_values[10]; >+#endif > }; > >+#define MYSQL_INSERT_STMT "INSERT INTO `audit` (`share`, `ip`, `unix_name`, " \ >+ "`connectpath`, `sanitized_username`, `sam_account`, `op`, `op_msg`, " \ >+ "`utok.gid`, `errno`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" >+ >+/* >+USE `samba`; >+CREATE TABLE `audit` ( >+ `id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, >+ `when` TIMESTAMP DEFAULT NOW() COMMENT 'Time the operation occurred', >+ `share` VARCHAR(255) COMMENT 'Share/service name', >+ `ip` VARCHAR(255) COMMENT 'IP address of connecting user', >+ `unix_name` VARCHAR(255) COMMENT 'Local username user has connected as', >+ `connectpath` VARCHAR(255) COMMENT 'Local path', >+ `sanitized_username` VARCHAR(255) COMMENT 'Remote username', >+ `sam_account` VARCHAR(255) COMMENT 'Remote machine name', >+ `op` VARCHAR(255) COMMENT 'Type of operation performed', >+ `op_msg` VARCHAR(255) COMMENT 'Further operation-specific details', >+ `utok.gid` VARCHAR(255) COMMENT 'Local group ID', >+ `errno` INT COMMENT 'POSIX error code (0 == success)' >+) ENGINE = MYISAM; >+*/ >+ > #undef DBGC_CLASS > #define DBGC_CLASS vfs_full_audit_debug_level > >@@ -400,14 +454,8 @@ static char *audit_prefix(TALLOC_CTX *ctx, connection_struct *conn) > return result; > } > >-static bool log_success(vfs_handle_struct *handle, vfs_op_type op) >+static bool log_success(struct vfs_full_audit_private_data *pd, vfs_op_type op) > { >- struct vfs_full_audit_private_data *pd = NULL; >- >- SMB_VFS_HANDLE_GET_DATA(handle, pd, >- struct vfs_full_audit_private_data, >- return True); >- > if (pd->success_ops == NULL) { > return True; > } >@@ -415,14 +463,8 @@ static bool log_success(vfs_handle_struct *handle, vfs_op_type op) > return bitmap_query(pd->success_ops, op); > } > >-static bool log_failure(vfs_handle_struct *handle, vfs_op_type op) >+static bool log_failure(struct vfs_full_audit_private_data *pd, vfs_op_type op) > { >- struct vfs_full_audit_private_data *pd = NULL; >- >- SMB_VFS_HANDLE_GET_DATA(handle, pd, >- struct vfs_full_audit_private_data, >- return True); >- > if (pd->failure_ops == NULL) > return True; > >@@ -484,6 +526,95 @@ static void init_bitmap(struct bitmap **bm, const char **ops) > } > } > >+#ifdef USE_MYSQL >+/* MySQL logging should be disabled if this function returns false */ >+static bool init_mysql(vfs_handle_struct *handle, struct vfs_full_audit_private_data *pd) >+{ >+ const char *myhost, *mydb; >+ const char *myuser, *mypass; >+ int myport; >+ >+ myhost = lp_parm_const_string(SNUM(handle->conn), "full_audit", >+ "myhost", "localhost"); >+ myport = lp_parm_int(SNUM(handle->conn), "full_audit", >+ "myport", 0); >+ myuser = lp_parm_const_string(SNUM(handle->conn), "full_audit", >+ "myuser", NULL); >+ mypass = lp_parm_const_string(SNUM(handle->conn), "full_audit", >+ "mypass", NULL); >+ mydb = lp_parm_const_string(SNUM(handle->conn), "full_audit", >+ "mydb", "samba"); >+ >+ pd->mysql = mysql_init(NULL); >+ if (pd->mysql == NULL) { >+ DEBUG(0,("Unable to initialise MySQL\n")); >+ return false; >+ } >+ >+ if (!mysql_real_connect(pd->mysql, myhost, myuser, mypass, mydb, myport, NULL, 0)) { >+ DEBUG(0,("Unable to connect to MySQL: [%u] %s\n", >+ mysql_errno(pd->mysql), mysql_error(pd->mysql))); >+ mysql_close(pd->mysql); >+ return false; >+ } >+ >+ pd->mysql_insert = mysql_stmt_init(pd->mysql); >+ if (!pd->mysql_insert) { >+ DEBUG(0,("mysql_stmt_init() failed, logging to MySQL disabled\n")); >+ mysql_close(pd->mysql); >+ return false; >+ } >+ >+ if (mysql_stmt_prepare(pd->mysql_insert, MYSQL_INSERT_STMT, strlen(MYSQL_INSERT_STMT))) { >+ DEBUG(0,("Unable to prepare MySQL INSERT statement, " >+ "logging to MySQL disabled: %s\n", >+ mysql_stmt_error(pd->mysql_insert))); >+ mysql_close(pd->mysql); >+ return false; >+ } >+ >+ /* Preset some values in the INSERT query structure used in do_log() */ >+ memset(pd->mysql_insert_values, 0, sizeof(pd->mysql_insert_values)); >+ >+ pd->mysql_insert_values[0].buffer_type = MYSQL_TYPE_STRING; >+ pd->mysql_insert_values[1].buffer_type = MYSQL_TYPE_STRING; >+ pd->mysql_insert_values[2].buffer_type = MYSQL_TYPE_STRING; >+ pd->mysql_insert_values[3].buffer_type = MYSQL_TYPE_STRING; >+ pd->mysql_insert_values[4].buffer_type = MYSQL_TYPE_STRING; >+ pd->mysql_insert_values[5].buffer_type = MYSQL_TYPE_STRING; >+ pd->mysql_insert_values[6].buffer_type = MYSQL_TYPE_STRING; >+ pd->mysql_insert_values[7].buffer_type = MYSQL_TYPE_STRING; >+ pd->mysql_insert_values[8].buffer_type = MYSQL_TYPE_LONG; >+ pd->mysql_insert_values[9].buffer_type = MYSQL_TYPE_LONG; >+ >+ return true; >+} >+#endif >+ >+static void init_destinations(struct vfs_full_audit_private_data *pd, const char **dests) >+{ >+ >+ while (*dests != NULL) { >+ >+ if (strequal(*dests, "syslog")) { >+ pd->use_syslog = true; >+ } else if (strequal(*dests, "mysql")) { >+#ifdef USE_MYSQL >+ pd->use_mysql = true; >+#else >+ DEBUG(0, ("MySQL support not compiled in, cannot log " >+ "audit data to MySQL\n")); >+#endif >+ } else { >+ DEBUG(0, ("Unknown full_audit log destination %s\n", >+ *dests)); >+ } >+ >+ dests += 1; >+ } >+ >+} >+ > static const char *audit_opname(vfs_op_type op) > { > if (op >= SMB_VFS_OP_LAST) >@@ -511,17 +642,21 @@ static void do_log(vfs_op_type op, bool success, vfs_handle_struct *handle, > va_list ap; > char *op_msg = NULL; > int priority; >+ struct vfs_full_audit_private_data *pd = NULL; >+#ifdef USE_MYSQL >+ int i; >+ int my_errno; >+#endif > >- if (success && (!log_success(handle, op))) >- goto out; >+ SMB_VFS_HANDLE_GET_DATA(handle, pd, >+ struct vfs_full_audit_private_data, >+ return); > >- if (!success && (!log_failure(handle, op))) >+ if (success && (!log_success(pd, op))) > goto out; > >- if (success) >- fstrcpy(err_msg, "ok"); >- else >- fstr_sprintf(err_msg, "fail (%s)", strerror(errno)); >+ if (!success && (!log_failure(pd, op))) >+ goto out; > > va_start(ap, format); > op_msg = talloc_vasprintf(talloc_tos(), format, ap); >@@ -531,20 +666,57 @@ static void do_log(vfs_op_type op, bool success, vfs_handle_struct *handle, > goto out; > } > >- /* >- * Specify the facility to interoperate with other syslog callers >- * (smbd for example). >- */ >- priority = audit_syslog_priority(handle) | >- audit_syslog_facility(handle); >+ if (pd->use_syslog) { >+ if (success) >+ fstrcpy(err_msg, "ok"); >+ else >+ fstr_sprintf(err_msg, "fail (%s)", strerror(errno)); >+ >+ /* >+ * Specify the facility to interoperate with other syslog >+ * callers (smbd for example). >+ */ >+ priority = audit_syslog_priority(handle) | >+ audit_syslog_facility(handle); >+ >+ audit_pre = audit_prefix(talloc_tos(), handle->conn); >+ syslog(priority, "%s|%s|%s|%s\n", >+ audit_pre ? audit_pre : "", >+ audit_opname(op), err_msg, op_msg); >+ TALLOC_FREE(audit_pre); >+ } > >- audit_pre = audit_prefix(talloc_tos(), handle->conn); >- syslog(priority, "%s|%s|%s|%s\n", >- audit_pre ? audit_pre : "", >- audit_opname(op), err_msg, op_msg); >+#ifdef USE_MYSQL >+ if (pd->use_mysql) { >+ pd->mysql_insert_values[0].buffer = lp_servicename(SNUM(handle->conn)); >+ pd->mysql_insert_values[1].buffer = handle->conn->client_address; >+ pd->mysql_insert_values[2].buffer = handle->conn->server_info->unix_name; >+ pd->mysql_insert_values[3].buffer = handle->conn->connectpath; >+ pd->mysql_insert_values[4].buffer = handle->conn->server_info->sanitized_username; >+ pd->mysql_insert_values[5].buffer = (char *)pdb_get_domain(handle->conn->server_info->sam_account); >+ pd->mysql_insert_values[6].buffer = (char *)audit_opname(op); >+ pd->mysql_insert_values[7].buffer = op_msg; >+ /* non-char variables are last so we don't strlen() them */ >+ pd->mysql_insert_values[8].buffer = &handle->conn->server_info->utok.gid; >+ pd->mysql_insert_values[9].buffer = &my_errno; >+ for (i = 0; i < 8; i++) { /* This loop is meant to stop at i==7 */ >+ pd->mysql_insert_values[i].buffer_length = >+ strlen(pd->mysql_insert_values[i].buffer); >+ } >+ /* Need to do this because errno is not always 0 on success */ >+ if (success) my_errno = 0; else my_errno = errno; >+ >+ if (mysql_stmt_bind_param(pd->mysql_insert, pd->mysql_insert_values)) { >+ DEBUG(0,("Unable to bind values to MySQL INSERT statement: %s\n", >+ mysql_stmt_error(pd->mysql_insert))); >+ } else if (mysql_stmt_execute(pd->mysql_insert)) { >+ DEBUG(0,("Unable to INSERT into MySQL: %s\n", >+ mysql_stmt_error(pd->mysql_insert))); >+ } >+ } >+#endif > > out: >- TALLOC_FREE(audit_pre); > TALLOC_FREE(op_msg); > TALLOC_FREE(tmp_do_log_ctx); > >@@ -589,6 +761,11 @@ static void free_private_data(void **p_data) > if (pd->failure_ops) { > bitmap_free(pd->failure_ops); > } >+#ifdef USE_MYSQL >+ if (pd->use_mysql) { >+ mysql_close(pd->mysql); >+ } >+#endif > SAFE_FREE(pd); > *p_data = NULL; > } >@@ -603,6 +780,7 @@ static int smb_full_audit_connect(vfs_handle_struct *handle, > struct vfs_full_audit_private_data *pd = NULL; > const char *none[] = { NULL }; > const char *all [] = { "all" }; >+ const char *dest_default[] = { "syslog" }; > > if (!handle) { > return -1; >@@ -614,10 +792,23 @@ static int smb_full_audit_connect(vfs_handle_struct *handle, > } > ZERO_STRUCTP(pd); > >+ init_destinations(pd, lp_parm_string_list(SNUM(handle->conn), >+ "full_audit", "dest", dest_default)); >+ > #ifndef WITH_SYSLOG >- openlog("smbd_audit", 0, audit_syslog_facility(handle)); >+ if (pd->use_syslog) { >+ openlog("smbd_audit", 0, audit_syslog_facility(handle)); >+ } > #endif > >+#ifdef USE_MYSQL >+ if (pd->use_mysql) { >+ if (!init_mysql(handle, pd)) { >+ /* Just ignore MySQL if it couldn't be initialised */ >+ pd->use_mysql = false; >+ } >+ } >+#endif > init_bitmap(&pd->success_ops, > lp_parm_string_list(SNUM(handle->conn), "full_audit", "success", > none));
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 6818
: 4860