1/*
2 * Auditing VFS module for samba.  Log selected file operations to syslog
3 * facility.
4 *
5 * Copyright (C) Tim Potter, 1999-2000
6 * Copyright (C) Alexander Bokovoy, 2002
7 * Copyright (C) John H Terpstra, 2003
8 * Copyright (C) Stefan (metze) Metzmacher, 2003
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25
26#include "includes.h"
27
28static int vfs_extd_audit_debug_level = DBGC_VFS;
29
30#undef DBGC_CLASS
31#define DBGC_CLASS vfs_extd_audit_debug_level
32
33/* Function prototypes */
34
35static int audit_connect(vfs_handle_struct *handle, connection_struct *conn, const char *svc, const char *user);
36static void audit_disconnect(vfs_handle_struct *handle, connection_struct *conn);
37static DIR *audit_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname);
38static int audit_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode);
39static int audit_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path);
40static int audit_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode);
41static int audit_close(vfs_handle_struct *handle, files_struct *fsp, int fd);
42static int audit_rename(vfs_handle_struct *handle, connection_struct *conn, const char *old, const char *new);
43static int audit_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path);
44static int audit_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode);
45static int audit_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *name, mode_t mode);
46static int audit_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode);
47static int audit_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode);
48
49/* VFS operations */
50
51static vfs_op_tuple audit_op_tuples[] = {
52
53	/* Disk operations */
54
55	{SMB_VFS_OP(audit_connect), 	SMB_VFS_OP_CONNECT, 	SMB_VFS_LAYER_LOGGER},
56	{SMB_VFS_OP(audit_disconnect), 	SMB_VFS_OP_DISCONNECT, 	SMB_VFS_LAYER_LOGGER},
57
58	/* Directory operations */
59
60	{SMB_VFS_OP(audit_opendir), 	SMB_VFS_OP_OPENDIR, 	SMB_VFS_LAYER_LOGGER},
61	{SMB_VFS_OP(audit_mkdir), 		SMB_VFS_OP_MKDIR, 	SMB_VFS_LAYER_LOGGER},
62	{SMB_VFS_OP(audit_rmdir), 		SMB_VFS_OP_RMDIR, 	SMB_VFS_LAYER_LOGGER},
63
64	/* File operations */
65
66	{SMB_VFS_OP(audit_open), 		SMB_VFS_OP_OPEN, 	SMB_VFS_LAYER_LOGGER},
67	{SMB_VFS_OP(audit_close), 		SMB_VFS_OP_CLOSE, 	SMB_VFS_LAYER_LOGGER},
68	{SMB_VFS_OP(audit_rename), 		SMB_VFS_OP_RENAME, 	SMB_VFS_LAYER_LOGGER},
69	{SMB_VFS_OP(audit_unlink), 		SMB_VFS_OP_UNLINK, 	SMB_VFS_LAYER_LOGGER},
70	{SMB_VFS_OP(audit_chmod), 		SMB_VFS_OP_CHMOD, 	SMB_VFS_LAYER_LOGGER},
71	{SMB_VFS_OP(audit_fchmod), 		SMB_VFS_OP_FCHMOD, 	SMB_VFS_LAYER_LOGGER},
72	{SMB_VFS_OP(audit_chmod_acl), 	SMB_VFS_OP_CHMOD_ACL, 	SMB_VFS_LAYER_LOGGER},
73	{SMB_VFS_OP(audit_fchmod_acl), 	SMB_VFS_OP_FCHMOD_ACL, 	SMB_VFS_LAYER_LOGGER},
74
75	/* Finish VFS operations definition */
76
77	{SMB_VFS_OP(NULL), 			SMB_VFS_OP_NOOP, 	SMB_VFS_LAYER_NOOP}
78};
79
80
81static int audit_syslog_facility(vfs_handle_struct *handle)
82{
83	/* fix me: let this be configurable by:
84	 *	lp_param_enum(SNUM(handle->conn),(handle->param?handle->param:"extd_audit"),"syslog facility",
85	 *		audit_enum_facility,LOG_USER);
86	 */
87	return LOG_USER;
88}
89
90
91static int audit_syslog_priority(vfs_handle_struct *handle)
92{
93	/* fix me: let this be configurable by:
94	 *	lp_param_enum(SNUM(handle->conn),(handle->param?handle->param:"extd_audit"),"syslog priority",
95	 *		audit_enum_priority,LOG_NOTICE);
96	 */
97	return LOG_NOTICE;
98}
99
100/* Implementation of vfs_ops.  Pass everything on to the default
101   operation but log event first. */
102
103static int audit_connect(vfs_handle_struct *handle, connection_struct *conn, const char *svc, const char *user)
104{
105	int result;
106
107	openlog("smbd_audit", LOG_PID, audit_syslog_facility(handle));
108
109	syslog(audit_syslog_priority(handle), "connect to service %s by user %s\n",
110	       svc, user);
111	DEBUG(10, ("Connected to service %s as user %s\n",
112	       svc, user));
113
114	result = SMB_VFS_NEXT_CONNECT(handle, conn, svc, user);
115
116	return result;
117}
118
119static void audit_disconnect(vfs_handle_struct *handle, connection_struct *conn)
120{
121	syslog(audit_syslog_priority(handle), "disconnected\n");
122	DEBUG(10, ("Disconnected from VFS module extd_audit\n"));
123	SMB_VFS_NEXT_DISCONNECT(handle, conn);
124
125	return;
126}
127
128static DIR *audit_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname)
129{
130	DIR *result;
131
132	result = SMB_VFS_NEXT_OPENDIR(handle, conn, fname);
133
134	syslog(audit_syslog_priority(handle), "opendir %s %s%s\n",
135	       fname,
136	       (result == NULL) ? "failed: " : "",
137	       (result == NULL) ? strerror(errno) : "");
138	DEBUG(1, ("vfs_extd_audit: opendir %s %s %s\n",
139	       fname,
140	       (result == NULL) ? "failed: " : "",
141	       (result == NULL) ? strerror(errno) : ""));
142
143	return result;
144}
145
146static int audit_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
147{
148	int result;
149
150	result = SMB_VFS_NEXT_MKDIR(handle, conn, path, mode);
151
152	syslog(audit_syslog_priority(handle), "mkdir %s %s%s\n",
153	       path,
154	       (result < 0) ? "failed: " : "",
155	       (result < 0) ? strerror(errno) : "");
156	DEBUG(0, ("vfs_extd_audit: mkdir %s %s %s\n",
157	       path,
158	       (result < 0) ? "failed: " : "",
159	       (result < 0) ? strerror(errno) : ""));
160
161	return result;
162}
163
164static int audit_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path)
165{
166	int result;
167
168	result = SMB_VFS_NEXT_RMDIR(handle, conn, path);
169
170	syslog(audit_syslog_priority(handle), "rmdir %s %s%s\n",
171	       path,
172	       (result < 0) ? "failed: " : "",
173	       (result < 0) ? strerror(errno) : "");
174	DEBUG(0, ("vfs_extd_audit: rmdir %s %s %s\n",
175               path,
176	       (result < 0) ? "failed: " : "",
177	       (result < 0) ? strerror(errno) : ""));
178
179	return result;
180}
181
182static int audit_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode)
183{
184	int result;
185
186	result = SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode);
187
188	syslog(audit_syslog_priority(handle), "open %s (fd %d) %s%s%s\n",
189	       fname, result,
190	       ((flags & O_WRONLY) || (flags & O_RDWR)) ? "for writing " : "",
191	       (result < 0) ? "failed: " : "",
192	       (result < 0) ? strerror(errno) : "");
193	DEBUG(2, ("vfs_extd_audit: open %s %s %s\n",
194	       fname,
195	       (result < 0) ? "failed: " : "",
196	       (result < 0) ? strerror(errno) : ""));
197
198	return result;
199}
200
201static int audit_close(vfs_handle_struct *handle, files_struct *fsp, int fd)
202{
203	int result;
204
205	result = SMB_VFS_NEXT_CLOSE(handle, fsp, fd);
206
207	syslog(audit_syslog_priority(handle), "close fd %d %s%s\n",
208	       fd,
209	       (result < 0) ? "failed: " : "",
210	       (result < 0) ? strerror(errno) : "");
211	DEBUG(2, ("vfs_extd_audit: close fd %d %s %s\n",
212	       fd,
213	       (result < 0) ? "failed: " : "",
214	       (result < 0) ? strerror(errno) : ""));
215
216	return result;
217}
218
219static int audit_rename(vfs_handle_struct *handle, connection_struct *conn, const char *old, const char *new)
220{
221	int result;
222
223	result = SMB_VFS_NEXT_RENAME(handle, conn, old, new);
224
225	syslog(audit_syslog_priority(handle), "rename %s -> %s %s%s\n",
226	       old, new,
227	       (result < 0) ? "failed: " : "",
228	       (result < 0) ? strerror(errno) : "");
229	DEBUG(1, ("vfs_extd_audit: rename old: %s new: %s  %s %s\n",
230	       old, new,
231	       (result < 0) ? "failed: " : "",
232	       (result < 0) ? strerror(errno) : ""));
233
234	return result;
235}
236
237static int audit_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path)
238{
239	int result;
240
241	result = SMB_VFS_NEXT_UNLINK(handle, conn, path);
242
243	syslog(audit_syslog_priority(handle), "unlink %s %s%s\n",
244	       path,
245	       (result < 0) ? "failed: " : "",
246	       (result < 0) ? strerror(errno) : "");
247	DEBUG(0, ("vfs_extd_audit: unlink %s %s %s\n",
248	       path,
249	       (result < 0) ? "failed: " : "",
250	       (result < 0) ? strerror(errno) : ""));
251
252	return result;
253}
254
255static int audit_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
256{
257	int result;
258
259	result = SMB_VFS_NEXT_CHMOD(handle, conn, path, mode);
260
261	syslog(audit_syslog_priority(handle), "chmod %s mode 0x%x %s%s\n",
262	       path, mode,
263	       (result < 0) ? "failed: " : "",
264	       (result < 0) ? strerror(errno) : "");
265	DEBUG(1, ("vfs_extd_audit: chmod %s mode 0x%x %s %s\n",
266	       path, mode,
267	       (result < 0) ? "failed: " : "",
268	       (result < 0) ? strerror(errno) : ""));
269
270	return result;
271}
272
273static int audit_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
274{
275	int result;
276
277	result = SMB_VFS_NEXT_CHMOD_ACL(handle, conn, path, mode);
278
279	syslog(audit_syslog_priority(handle), "chmod_acl %s mode 0x%x %s%s\n",
280	       path, mode,
281	       (result < 0) ? "failed: " : "",
282	       (result < 0) ? strerror(errno) : "");
283	DEBUG(1, ("vfs_extd_audit: chmod_acl %s mode 0x%x %s %s\n",
284	        path, mode,
285	       (result < 0) ? "failed: " : "",
286	       (result < 0) ? strerror(errno) : ""));
287
288	return result;
289}
290
291static int audit_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode)
292{
293	int result;
294
295	result = SMB_VFS_NEXT_FCHMOD(handle, fsp, fd, mode);
296
297	syslog(audit_syslog_priority(handle), "fchmod %s mode 0x%x %s%s\n",
298	       fsp->fsp_name, mode,
299	       (result < 0) ? "failed: " : "",
300	       (result < 0) ? strerror(errno) : "");
301	DEBUG(1, ("vfs_extd_audit: fchmod %s mode 0x%x %s %s",
302	       fsp->fsp_name,  mode,
303	       (result < 0) ? "failed: " : "",
304	       (result < 0) ? strerror(errno) : ""));
305
306	return result;
307}
308
309static int audit_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode)
310{
311	int result;
312
313	result = SMB_VFS_NEXT_FCHMOD_ACL(handle, fsp, fd, mode);
314
315	syslog(audit_syslog_priority(handle), "fchmod_acl %s mode 0x%x %s%s\n",
316	       fsp->fsp_name, mode,
317	       (result < 0) ? "failed: " : "",
318	       (result < 0) ? strerror(errno) : "");
319	DEBUG(1, ("vfs_extd_audit: fchmod_acl %s mode 0x%x %s %s",
320	       fsp->fsp_name,  mode,
321	       (result < 0) ? "failed: " : "",
322	       (result < 0) ? strerror(errno) : ""));
323
324	return result;
325}
326
327NTSTATUS vfs_extd_audit_init(void)
328{
329	NTSTATUS ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "extd_audit", audit_op_tuples);
330
331	if (!NT_STATUS_IS_OK(ret))
332		return ret;
333
334	vfs_extd_audit_debug_level = debug_add_class("extd_audit");
335	if (vfs_extd_audit_debug_level == -1) {
336		vfs_extd_audit_debug_level = DBGC_VFS;
337		DEBUG(0, ("vfs_extd_audit: Couldn't register custom debugging class!\n"));
338	} else {
339		DEBUG(10, ("vfs_extd_audit: Debug class number of 'extd_audit': %d\n", vfs_extd_audit_debug_level));
340	}
341
342	return ret;
343}
344