aad483c295ae5ce12b3384e05e188ecb31a1e931
[samba.git] / examples / VFS / 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  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *  
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *  
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 #include "config.h"
23 #include <stdio.h>
24 #include <sys/stat.h>
25 #ifdef HAVE_UTIME_H
26 #include <utime.h>
27 #endif
28 #ifdef HAVE_DIRENT_H
29 #include <dirent.h>
30 #endif
31 #include <syslog.h>
32 #ifdef HAVE_FCNTL_H
33 #include <fcntl.h>
34 #endif
35 #include <errno.h>
36 #include <string.h>
37 #include <includes.h>
38 #include <vfs.h>
39
40 #ifndef SYSLOG_FACILITY
41 #define SYSLOG_FACILITY   LOG_USER
42 #endif
43
44 #ifndef SYSLOG_PRIORITY
45 #define SYSLOG_PRIORITY   LOG_NOTICE
46 #endif
47
48 /* Function prototypes */
49
50 int audit_connect(struct connection_struct *conn, const char *svc, const char *user);
51 void audit_disconnect(struct connection_struct *conn);
52 DIR *audit_opendir(struct connection_struct *conn, const char *fname);
53 int audit_mkdir(struct connection_struct *conn, const char *path, mode_t mode);
54 int audit_rmdir(struct connection_struct *conn, const char *path);
55 int audit_open(struct connection_struct *conn, const char *fname, int flags, mode_t mode);
56 int audit_close(struct files_struct *fsp, int fd);
57 int audit_rename(struct connection_struct *conn, const char *old, const char *new);
58 int audit_unlink(struct connection_struct *conn, const char *path);
59 int audit_chmod(struct connection_struct *conn, const char *path, mode_t mode);
60 int audit_chmod_acl(struct connection_struct *conn, const char *name, mode_t mode);
61 int audit_fchmod(struct files_struct *fsp, int fd, mode_t mode);
62 int audit_fchmod_acl(struct files_struct *fsp, int fd, mode_t mode);
63
64 /* VFS operations */
65
66 extern struct vfs_ops default_vfs_ops;   /* For passthrough operation */
67
68 struct vfs_ops audit_ops = {
69     
70         /* Disk operations */
71
72         audit_connect,
73         audit_disconnect,
74         NULL,                     /* disk free */
75
76         /* Directory operations */
77
78         audit_opendir,
79         NULL,                     /* readdir */
80         audit_mkdir,
81         audit_rmdir,
82         NULL,                     /* closedir */
83
84         /* File operations */
85
86         audit_open,
87         audit_close,
88         NULL,                     /* read  */
89         NULL,                     /* write */
90         NULL,                     /* lseek */
91         audit_rename,
92         NULL,                     /* fsync */
93         NULL,                     /* stat  */
94         NULL,                     /* fstat */
95         NULL,                     /* lstat */
96         audit_unlink,
97         audit_chmod,
98         audit_fchmod,
99         NULL,                     /* chown */
100         NULL,                     /* fchown */
101         NULL,                     /* chdir */
102         NULL,                     /* getwd */
103         NULL,                     /* utime */
104         NULL,                     /* ftruncate */
105         NULL,                     /* lock */
106         NULL,                     /* symlink */
107         NULL,                     /* readlink */
108         NULL,                     /* link */
109         NULL,                     /* mknod */
110         NULL,                     /* realpath */
111         NULL,                     /* fget_nt_acl */
112         NULL,                     /* get_nt_acl */
113         NULL,                     /* fset_nt_acl */
114         NULL,                      /* set_nt_acl */
115
116         audit_chmod_acl,                /* chmod_acl */
117         audit_fchmod_acl,               /* fchmod_acl */
118
119         NULL,                   /* sys_acl_get_entry */
120         NULL,                   /* sys_acl_get_tag_type */
121         NULL,                   /* sys_acl_get_permset */
122         NULL,                   /*sys_acl_get_qualifier */
123         NULL,                   /* sys_acl_get_file */
124         NULL,                   /* sys_acl_get_fd */
125         NULL,                   /* sys_acl_clear_perms */
126         NULL,                   /* sys_acl_add_perm */
127         NULL,                   /* sys_acl_to_text */
128         NULL,                   /* sys_acl_init */
129         NULL,                   /* sys_acl_create_entry */
130         NULL,                   /* sys_acl_set_tag_type */
131         NULL,                   /* sys_acl_set_qualifier */
132         NULL,                   /* sys_acl_set_permset */
133         NULL,                   /* sys_acl_valid */
134         NULL,                   /* sys_acl_set_file */
135         NULL,                   /* sys_acl_set_fd */
136         NULL,                   /* sys_acl_delete_def_file */
137         NULL,                   /* sys_acl_get_perm */
138         NULL,                   /* sys_acl_free_text */
139         NULL,                   /* sys_acl_free_acl */
140         NULL                    /* sys_acl_free_qualifier */
141 };
142
143 /* VFS initialisation function.  Return initialised vfs_ops structure
144    back to SAMBA. */
145
146 struct vfs_ops *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops)
147 {
148         struct vfs_ops tmp_ops;
149
150         *vfs_version = SMB_VFS_INTERFACE_VERSION;
151         memcpy(&tmp_ops, def_vfs_ops, sizeof(struct vfs_ops));
152
153         tmp_ops.connect = audit_connect;
154         tmp_ops.disconnect = audit_disconnect;
155         tmp_ops.opendir = audit_opendir;
156         tmp_ops.mkdir = audit_mkdir;
157         tmp_ops.rmdir = audit_rmdir;
158         tmp_ops.open = audit_open;
159         tmp_ops.close = audit_close;
160         tmp_ops.rename = audit_rename;
161         tmp_ops.unlink = audit_unlink;
162         tmp_ops.chmod = audit_chmod;
163         tmp_ops.chmod_acl = audit_chmod_acl;
164         tmp_ops.fchmod = audit_fchmod;
165         tmp_ops.fchmod_acl = audit_fchmod_acl;
166
167         memcpy(&audit_ops, &tmp_ops, sizeof(struct vfs_ops));
168
169         openlog("smbd_audit", LOG_PID, SYSLOG_FACILITY);
170         syslog(SYSLOG_PRIORITY, "VFS_INIT: vfs_ops loaded\n");
171         return &audit_ops;
172 }
173
174 /* Implementation of vfs_ops.  Pass everything on to the default
175    operation but log event first. */
176
177 int audit_connect(struct connection_struct *conn, const char *svc, const char *user)
178 {
179         syslog(SYSLOG_PRIORITY, "connect to service %s by user %s\n", 
180                svc, user);
181
182         return default_vfs_ops.connect(conn, svc, user);
183 }
184
185 void audit_disconnect(struct connection_struct *conn)
186 {
187         syslog(SYSLOG_PRIORITY, "disconnected\n");
188         default_vfs_ops.disconnect(conn);
189 }
190
191 DIR *audit_opendir(struct connection_struct *conn, const char *fname)
192 {
193         DIR *result = default_vfs_ops.opendir(conn, fname);
194
195         syslog(SYSLOG_PRIORITY, "opendir %s %s%s\n",
196                fname,
197                (result == NULL) ? "failed: " : "",
198                (result == NULL) ? strerror(errno) : "");
199
200         return result;
201 }
202
203 int audit_mkdir(struct connection_struct *conn, const char *path, mode_t mode)
204 {
205         int result = default_vfs_ops.mkdir(conn, path, mode);
206
207         syslog(SYSLOG_PRIORITY, "mkdir %s %s%s\n", 
208                path,
209                (result < 0) ? "failed: " : "",
210                (result < 0) ? strerror(errno) : "");
211
212         return result;
213 }
214
215 int audit_rmdir(struct connection_struct *conn, const char *path)
216 {
217         int result = default_vfs_ops.rmdir(conn, path);
218
219         syslog(SYSLOG_PRIORITY, "rmdir %s %s%s\n", 
220                path, 
221                (result < 0) ? "failed: " : "",
222                (result < 0) ? strerror(errno) : "");
223
224         return result;
225 }
226
227 int audit_open(struct connection_struct *conn, const char *fname, int flags, mode_t mode)
228 {
229         int result = default_vfs_ops.open(conn, fname, flags, mode);
230
231         syslog(SYSLOG_PRIORITY, "open %s (fd %d) %s%s%s\n", 
232                fname, result,
233                ((flags & O_WRONLY) || (flags & O_RDWR)) ? "for writing " : "", 
234                (result < 0) ? "failed: " : "",
235                (result < 0) ? strerror(errno) : "");
236
237         return result;
238 }
239
240 int audit_close(struct files_struct *fsp, int fd)
241 {
242         int result = default_vfs_ops.close(fsp, fd);
243
244         syslog(SYSLOG_PRIORITY, "close fd %d %s%s\n",
245                fd,
246                (result < 0) ? "failed: " : "",
247                (result < 0) ? strerror(errno) : "");
248
249         return result;
250 }
251
252 int audit_rename(struct connection_struct *conn, const char *old, const char *new)
253 {
254         int result = default_vfs_ops.rename(conn, old, new);
255
256         syslog(SYSLOG_PRIORITY, "rename %s -> %s %s%s\n",
257                old, new,
258                (result < 0) ? "failed: " : "",
259                (result < 0) ? strerror(errno) : "");
260
261         return result;    
262 }
263
264 int audit_unlink(struct connection_struct *conn, const char *path)
265 {
266         int result = default_vfs_ops.unlink(conn, path);
267
268         syslog(SYSLOG_PRIORITY, "unlink %s %s%s\n",
269                path,
270                (result < 0) ? "failed: " : "",
271                (result < 0) ? strerror(errno) : "");
272
273         return result;
274 }
275
276 int audit_chmod(struct connection_struct *conn, const char *path, mode_t mode)
277 {
278         int result = default_vfs_ops.chmod(conn, path, mode);
279
280         syslog(SYSLOG_PRIORITY, "chmod %s mode 0x%x %s%s\n",
281                path, mode,
282                (result < 0) ? "failed: " : "",
283                (result < 0) ? strerror(errno) : "");
284
285         return result;
286 }
287
288 int audit_chmod_acl(struct connection_struct *conn, const char *path, mode_t mode)
289 {
290         int result = default_vfs_ops.chmod_acl(conn, path, mode);
291
292         syslog(SYSLOG_PRIORITY, "chmod_acl %s mode 0x%x %s%s\n",
293                path, mode,
294                (result < 0) ? "failed: " : "",
295                (result < 0) ? strerror(errno) : "");
296
297         return result;
298 }
299
300 int audit_fchmod(struct files_struct *fsp, int fd, mode_t mode)
301 {
302         int result = default_vfs_ops.fchmod(fsp, fd, mode);
303
304         syslog(SYSLOG_PRIORITY, "fchmod %s mode 0x%x %s%s\n",
305                fsp->fsp_name, mode,
306                (result < 0) ? "failed: " : "",
307                (result < 0) ? strerror(errno) : "");
308
309         return result;
310 }
311
312 int audit_fchmod_acl(struct files_struct *fsp, int fd, mode_t mode)
313 {
314         int result = default_vfs_ops.fchmod_acl(fsp, fd, mode);
315
316         syslog(SYSLOG_PRIORITY, "fchmod_acl %s mode 0x%x %s%s\n",
317                fsp->fsp_name, mode,
318                (result < 0) ? "failed: " : "",
319                (result < 0) ? strerror(errno) : "");
320
321         return result;
322 }