r378: Add an option extd_audit:parseable=True. This gives messages of the form
[samba.git] / source3 / modules / vfs_extd_audit.c
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
28 extern struct current_user current_user;
29
30 static int vfs_extd_audit_debug_level = DBGC_VFS;
31
32 #undef DBGC_CLASS
33 #define DBGC_CLASS vfs_extd_audit_debug_level
34
35 /* Function prototypes */
36
37 static int audit_connect(vfs_handle_struct *handle, connection_struct *conn, const char *svc, const char *user);
38 static void audit_disconnect(vfs_handle_struct *handle, connection_struct *conn);
39 static DIR *audit_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname);
40 static int audit_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode);
41 static int audit_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path);
42 static int audit_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode);
43 static int audit_close(vfs_handle_struct *handle, files_struct *fsp, int fd);
44 static int audit_rename(vfs_handle_struct *handle, connection_struct *conn, const char *old, const char *new);
45 static int audit_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path);
46 static int audit_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode);
47 static int audit_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *name, mode_t mode);
48 static int audit_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode);
49 static int audit_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode);
50
51 /* VFS operations */
52
53 static vfs_op_tuple audit_op_tuples[] = {
54     
55         /* Disk operations */
56
57         {SMB_VFS_OP(audit_connect),     SMB_VFS_OP_CONNECT,     SMB_VFS_LAYER_LOGGER},
58         {SMB_VFS_OP(audit_disconnect),  SMB_VFS_OP_DISCONNECT,  SMB_VFS_LAYER_LOGGER},
59
60         /* Directory operations */
61
62         {SMB_VFS_OP(audit_opendir),     SMB_VFS_OP_OPENDIR,     SMB_VFS_LAYER_LOGGER},
63         {SMB_VFS_OP(audit_mkdir),               SMB_VFS_OP_MKDIR,       SMB_VFS_LAYER_LOGGER},
64         {SMB_VFS_OP(audit_rmdir),               SMB_VFS_OP_RMDIR,       SMB_VFS_LAYER_LOGGER},
65
66         /* File operations */
67
68         {SMB_VFS_OP(audit_open),                SMB_VFS_OP_OPEN,        SMB_VFS_LAYER_LOGGER},
69         {SMB_VFS_OP(audit_close),               SMB_VFS_OP_CLOSE,       SMB_VFS_LAYER_LOGGER},
70         {SMB_VFS_OP(audit_rename),              SMB_VFS_OP_RENAME,      SMB_VFS_LAYER_LOGGER},
71         {SMB_VFS_OP(audit_unlink),              SMB_VFS_OP_UNLINK,      SMB_VFS_LAYER_LOGGER},
72         {SMB_VFS_OP(audit_chmod),               SMB_VFS_OP_CHMOD,       SMB_VFS_LAYER_LOGGER},
73         {SMB_VFS_OP(audit_fchmod),              SMB_VFS_OP_FCHMOD,      SMB_VFS_LAYER_LOGGER},
74         {SMB_VFS_OP(audit_chmod_acl),   SMB_VFS_OP_CHMOD_ACL,   SMB_VFS_LAYER_LOGGER},
75         {SMB_VFS_OP(audit_fchmod_acl),  SMB_VFS_OP_FCHMOD_ACL,  SMB_VFS_LAYER_LOGGER},
76         
77         /* Finish VFS operations definition */
78         
79         {SMB_VFS_OP(NULL),                      SMB_VFS_OP_NOOP,        SMB_VFS_LAYER_NOOP}
80 };
81
82
83 static int audit_syslog_facility(vfs_handle_struct *handle)
84 {
85         /* fix me: let this be configurable by:
86          *      lp_param_enum(SNUM(handle->conn),(handle->param?handle->param:"extd_audit"),"syslog facility",
87          *              audit_enum_facility,LOG_USER); 
88          */
89         return LOG_USER;
90 }
91
92
93 static int audit_syslog_priority(vfs_handle_struct *handle)
94 {
95         /* fix me: let this be configurable by:
96          *      lp_param_enum(SNUM(handle->conn),(handle->param?handle->param:"extd_audit"),"syslog priority",
97          *              audit_enum_priority,LOG_NOTICE); 
98          */
99         return LOG_NOTICE;
100 }
101
102 /* Implementation of vfs_ops.  Pass everything on to the default
103    operation but log event first. */
104
105 static int audit_connect(vfs_handle_struct *handle, connection_struct *conn, const char *svc, const char *user)
106 {
107         int result;
108
109         openlog("smbd_audit", LOG_PID, audit_syslog_facility(handle));
110
111         if (lp_parm_bool(SNUM(handle->conn), "extd_audit", "parseable",
112                          False)) {
113                 syslog(audit_syslog_priority(handle),
114                        "%d|%s|connect|%s\n", current_user.uid,
115                        handle->conn->client_address, svc);
116         } else {
117                 syslog(audit_syslog_priority(handle),
118                        "connect to service %s by user %s\n",  svc, user);
119                 DEBUG(10, ("Connected to service %s as user %s\n",
120                            svc, user));
121         }
122
123         result = SMB_VFS_NEXT_CONNECT(handle, conn, svc, user);
124
125         return result;
126 }
127
128 static void audit_disconnect(vfs_handle_struct *handle, connection_struct *conn)
129 {
130         if (lp_parm_bool(SNUM(handle->conn), "extd_audit", "parseable",
131                          False)) {
132                 syslog(audit_syslog_priority(handle),
133                        "%d|%s|disconnect|%s\n", current_user.uid,
134                        handle->conn->client_address,
135                        lp_servicename(SNUM(conn)));
136         } else {
137                 syslog(audit_syslog_priority(handle), "disconnected\n");
138                 DEBUG(10, ("Disconnected from VFS module extd_audit\n"));
139         }
140
141         SMB_VFS_NEXT_DISCONNECT(handle, conn);
142
143         return;
144 }
145
146 static DIR *audit_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname)
147 {
148         DIR *result;
149
150         result = SMB_VFS_NEXT_OPENDIR(handle, conn, fname);
151
152         if (lp_parm_bool(SNUM(handle->conn), "extd_audit", "parseable",
153                          False)) {
154                 syslog(audit_syslog_priority(handle),
155                        "%d|%s|opendir|%s\n", current_user.uid,
156                        handle->conn->client_address, fname);
157         } else {
158                 syslog(audit_syslog_priority(handle), "opendir %s %s%s\n",
159                        fname,
160                        (result == NULL) ? "failed: " : "",
161                        (result == NULL) ? strerror(errno) : "");
162                 DEBUG(1, ("vfs_extd_audit: opendir %s %s %s\n",
163                           fname,
164                           (result == NULL) ? "failed: " : "",
165                           (result == NULL) ? strerror(errno) : ""));
166         }
167
168         return result;
169 }
170
171 static int audit_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
172 {
173         int result;
174         
175         result = SMB_VFS_NEXT_MKDIR(handle, conn, path, mode);
176         
177         if (lp_parm_bool(SNUM(handle->conn), "extd_audit", "parseable",
178                          False)) {
179                 syslog(audit_syslog_priority(handle),
180                        "%d|%s|mkdir|%s\n", current_user.uid,
181                        handle->conn->client_address, path);
182         } else {
183                 syslog(audit_syslog_priority(handle), "mkdir %s %s%s\n", 
184                        path,
185                        (result < 0) ? "failed: " : "",
186                        (result < 0) ? strerror(errno) : "");
187                 DEBUG(0, ("vfs_extd_audit: mkdir %s %s %s\n",
188                           path,
189                           (result < 0) ? "failed: " : "",
190                           (result < 0) ? strerror(errno) : ""));
191         }
192
193         return result;
194 }
195
196 static int audit_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path)
197 {
198         int result;
199         
200         result = SMB_VFS_NEXT_RMDIR(handle, conn, path);
201
202         if (lp_parm_bool(SNUM(handle->conn), "extd_audit", "parseable",
203                          False)) {
204                 syslog(audit_syslog_priority(handle),
205                        "%d|%s|rmdir|%s\n", current_user.uid,
206                        handle->conn->client_address, path);
207         } else {
208                 syslog(audit_syslog_priority(handle), "rmdir %s %s%s\n", 
209                        path, 
210                        (result < 0) ? "failed: " : "",
211                        (result < 0) ? strerror(errno) : "");
212                 DEBUG(0, ("vfs_extd_audit: rmdir %s %s %s\n",
213                           path,
214                           (result < 0) ? "failed: " : "",
215                           (result < 0) ? strerror(errno) : ""));
216         }
217
218         return result;
219 }
220
221 static int audit_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode)
222 {
223         int result;
224         
225         result = SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode);
226
227         if (lp_parm_bool(SNUM(handle->conn), "extd_audit", "parseable",
228                          False)) {
229                 syslog(audit_syslog_priority(handle),
230                        "%d|%s|open|%s|%s\n", current_user.uid,
231                        handle->conn->client_address,
232                        ((flags & O_WRONLY) || (flags & O_RDWR))?"w":"r",
233                        fname);
234         } else {
235                 syslog(audit_syslog_priority(handle),
236                        "open %s (fd %d) %s%s%s\n", 
237                        fname, result,
238                        ((flags & O_WRONLY) || (flags & O_RDWR))
239                        ? "for writing " : "", 
240                        (result < 0) ? "failed: " : "",
241                        (result < 0) ? strerror(errno) : "");
242                 DEBUG(2, ("vfs_extd_audit: open %s %s %s\n",
243                           fname,
244                           (result < 0) ? "failed: " : "",
245                           (result < 0) ? strerror(errno) : ""));
246         }
247
248         return result;
249 }
250
251 static int audit_close(vfs_handle_struct *handle, files_struct *fsp, int fd)
252 {
253         int result;
254         
255         result = SMB_VFS_NEXT_CLOSE(handle, fsp, fd);
256
257         if (lp_parm_bool(SNUM(handle->conn), "extd_audit", "parseable",
258                          False)) {
259                 syslog(audit_syslog_priority(handle),
260                        "%d|%s|close|%s\n", current_user.uid,
261                        handle->conn->client_address, fsp->fsp_name);
262         } else {
263                 syslog(audit_syslog_priority(handle), "close fd %d %s%s\n",
264                        fd,
265                        (result < 0) ? "failed: " : "",
266                        (result < 0) ? strerror(errno) : "");
267                 DEBUG(2, ("vfs_extd_audit: close fd %d %s %s\n",
268                           fd,
269                           (result < 0) ? "failed: " : "",
270                           (result < 0) ? strerror(errno) : ""));
271         }
272
273         return result;
274 }
275
276 static int audit_rename(vfs_handle_struct *handle, connection_struct *conn, const char *old, const char *new)
277 {
278         int result;
279         
280         result = SMB_VFS_NEXT_RENAME(handle, conn, old, new);
281
282         if (lp_parm_bool(SNUM(handle->conn), "extd_audit", "parseable",
283                          False)) {
284                 syslog(audit_syslog_priority(handle),
285                        "%d|%s|rename|%s|%s\n", current_user.uid,
286                        handle->conn->client_address, old, new);
287         } else {
288                 syslog(audit_syslog_priority(handle), "rename %s -> %s %s%s\n",
289                        old, new,
290                        (result < 0) ? "failed: " : "",
291                        (result < 0) ? strerror(errno) : "");
292                 DEBUG(1, ("vfs_extd_audit: rename old: %s new: %s  %s %s\n",
293                           old, new,
294                           (result < 0) ? "failed: " : "",
295                           (result < 0) ? strerror(errno) : ""));
296         }
297
298         return result;    
299 }
300
301 static int audit_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path)
302 {
303         int result;
304         
305         result = SMB_VFS_NEXT_UNLINK(handle, conn, path);
306
307         if (lp_parm_bool(SNUM(handle->conn), "extd_audit", "parseable",
308                          False)) {
309                 syslog(audit_syslog_priority(handle),
310                        "%d|%s|unlink|%s\n", current_user.uid,
311                        handle->conn->client_address, path);
312         } else {
313                 syslog(audit_syslog_priority(handle), "unlink %s %s%s\n",
314                        path,
315                        (result < 0) ? "failed: " : "",
316                        (result < 0) ? strerror(errno) : "");
317                 DEBUG(0, ("vfs_extd_audit: unlink %s %s %s\n",
318                           path,
319                           (result < 0) ? "failed: " : "",
320                           (result < 0) ? strerror(errno) : ""));
321         }
322
323         return result;
324 }
325
326 static int audit_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
327 {
328         int result;
329
330         result = SMB_VFS_NEXT_CHMOD(handle, conn, path, mode);
331
332         if (lp_parm_bool(SNUM(handle->conn), "extd_audit", "parseable",
333                          False)) {
334                 syslog(audit_syslog_priority(handle),
335                        "%d|%s|chmod|%s|%o\n", current_user.uid,
336                        handle->conn->client_address, path, mode);
337         } else {
338                 syslog(audit_syslog_priority(handle),
339                        "chmod %s mode 0x%x %s%s\n",
340                        path, mode,
341                        (result < 0) ? "failed: " : "",
342                        (result < 0) ? strerror(errno) : "");
343                 DEBUG(1, ("vfs_extd_audit: chmod %s mode 0x%x %s %s\n",
344                           path, mode,
345                           (result < 0) ? "failed: " : "",
346                           (result < 0) ? strerror(errno) : ""));
347         }
348
349         return result;
350 }
351
352 static int audit_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
353 {
354         int result;
355         
356         result = SMB_VFS_NEXT_CHMOD_ACL(handle, conn, path, mode);
357
358         if (lp_parm_bool(SNUM(handle->conn), "extd_audit", "parseable",
359                          False)) {
360                 syslog(audit_syslog_priority(handle),
361                        "%d|%s|chmod_acl|%s|%o\n", current_user.uid,
362                        handle->conn->client_address, path, mode);
363         } else {
364                 syslog(audit_syslog_priority(handle),
365                        "chmod_acl %s mode 0x%x %s%s\n",
366                        path, mode,
367                        (result < 0) ? "failed: " : "",
368                        (result < 0) ? strerror(errno) : "");
369                 DEBUG(1, ("vfs_extd_audit: chmod_acl %s mode 0x%x %s %s\n",
370                           path, mode,
371                           (result < 0) ? "failed: " : "",
372                           (result < 0) ? strerror(errno) : ""));
373         }
374
375         return result;
376 }
377
378 static int audit_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode)
379 {
380         int result;
381         
382         result = SMB_VFS_NEXT_FCHMOD(handle, fsp, fd, mode);
383
384         if (lp_parm_bool(SNUM(handle->conn), "extd_audit", "parseable",
385                          False)) {
386                 syslog(audit_syslog_priority(handle),
387                        "%d|%s|fchmod|%s|%o\n", current_user.uid,
388                        handle->conn->client_address, fsp->fsp_name, mode);
389         } else {
390                 syslog(audit_syslog_priority(handle),
391                        "fchmod %s mode 0x%x %s%s\n",
392                        fsp->fsp_name, mode,
393                        (result < 0) ? "failed: " : "",
394                        (result < 0) ? strerror(errno) : "");
395                 DEBUG(1, ("vfs_extd_audit: fchmod %s mode 0x%x %s %s",
396                           fsp->fsp_name,  mode,
397                           (result < 0) ? "failed: " : "",
398                           (result < 0) ? strerror(errno) : ""));
399         }
400
401         return result;
402 }
403
404 static int audit_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode)
405 {
406         int result;
407         
408         result = SMB_VFS_NEXT_FCHMOD_ACL(handle, fsp, fd, mode);
409
410         if (lp_parm_bool(SNUM(handle->conn), "extd_audit", "parseable",
411                          False)) {
412                 syslog(audit_syslog_priority(handle),
413                        "%d|%s|fchmod_acl|%s|%o\n", current_user.uid,
414                        handle->conn->client_address, fsp->fsp_name, mode);
415         } else {
416                 syslog(audit_syslog_priority(handle),
417                        "fchmod_acl %s mode 0x%x %s%s\n",
418                        fsp->fsp_name, mode,
419                        (result < 0) ? "failed: " : "",
420                        (result < 0) ? strerror(errno) : "");
421                 DEBUG(1, ("vfs_extd_audit: fchmod_acl %s mode 0x%x %s %s",
422                           fsp->fsp_name,  mode,
423                           (result < 0) ? "failed: " : "",
424                           (result < 0) ? strerror(errno) : ""));
425         }
426
427         return result;
428 }
429
430 NTSTATUS vfs_extd_audit_init(void)
431 {
432         NTSTATUS ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "extd_audit", audit_op_tuples);
433         
434         if (!NT_STATUS_IS_OK(ret))
435                 return ret;
436
437         vfs_extd_audit_debug_level = debug_add_class("extd_audit");
438         if (vfs_extd_audit_debug_level == -1) {
439                 vfs_extd_audit_debug_level = DBGC_VFS;
440                 DEBUG(0, ("vfs_extd_audit: Couldn't register custom debugging class!\n"));
441         } else {
442                 DEBUG(10, ("vfs_extd_audit: Debug class number of 'extd_audit': %d\n", vfs_extd_audit_debug_level));
443         }
444         
445         return ret;
446 }