Fixes for sample VFS audit code from "Brad Sahr" <bsahr@macromedia.com>.
[sfrench/samba-autobuild/.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, char *svc, char *user);
51 void audit_disconnect(struct connection_struct *conn);
52 DIR *audit_opendir(struct connection_struct *conn, char *fname);
53 int audit_mkdir(struct connection_struct *conn, char *path, mode_t mode);
54 int audit_rmdir(struct connection_struct *conn, char *path);
55 int audit_open(struct connection_struct *conn, 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, char *old, char *new);
58 int audit_unlink(struct connection_struct *conn, char *path);
59 int audit_chmod(struct connection_struct *conn, char *path, mode_t mode);
60
61 /* VFS operations */
62
63 extern struct vfs_ops default_vfs_ops;   /* For passthrough operation */
64
65 struct vfs_ops audit_ops = {
66     
67         /* Disk operations */
68
69         audit_connect,
70         audit_disconnect,
71         NULL,                     /* disk free */
72
73         /* Directory operations */
74
75         audit_opendir,
76         NULL,                     /* readdir */
77         audit_mkdir,
78         audit_rmdir,
79         NULL,                     /* closedir */
80
81         /* File operations */
82
83         audit_open,
84         audit_close,
85         NULL,                     /* read  */
86         NULL,                     /* write */
87         NULL,                     /* lseek */
88         audit_rename,
89         NULL,                     /* fsync */
90         NULL,                     /* stat  */
91         NULL,                     /* fstat */
92         NULL,                     /* lstat */
93         audit_unlink,
94         audit_chmod,
95         NULL,                     /* chown */
96         NULL,                     /* chdir */
97         NULL,                     /* getwd */
98         NULL,                     /* utime */
99         NULL,                     /* ftruncate */
100         NULL,                     /* lock */
101         NULL,                     /* fget_nt_acl */
102         NULL,                     /* get_nt_acl */
103         NULL,                     /* fset_nt_acl */
104         NULL                      /* set_nt_acl */
105 };
106
107 /* VFS initialisation function.  Return initialised vfs_ops structure
108    back to SAMBA. */
109
110 struct vfs_ops *vfs_init(void)
111 {
112         openlog("smbd_audit", LOG_PID, SYSLOG_FACILITY);
113         syslog(SYSLOG_PRIORITY, "VFS_INIT: &audit_ops: 0x%8.8x\n", 
114                &audit_ops);
115         return(&audit_ops);
116 }
117
118 /* Implementation of vfs_ops.  Pass everything on to the default
119    operation but log event first. */
120
121 int audit_connect(struct connection_struct *conn, char *svc, char *user)
122 {
123         syslog(SYSLOG_PRIORITY, "connect to service %s by user %s\n", 
124                svc, user);
125
126         return default_vfs_ops.connect(conn, svc, user);
127 }
128
129 void audit_disconnect(struct connection_struct *conn)
130 {
131         syslog(SYSLOG_PRIORITY, "disconnected\n");
132         default_vfs_ops.disconnect(conn);
133 }
134
135 DIR *audit_opendir(struct connection_struct *conn, char *fname)
136 {
137         DIR *result = default_vfs_ops.opendir(conn, fname);
138
139         syslog(SYSLOG_PRIORITY, "opendir %s %s%s\n",
140                fname,
141                (result == NULL) ? "failed: " : "",
142                (result == NULL) ? strerror(errno) : "");
143
144         return result;
145 }
146
147 int audit_mkdir(struct connection_struct *conn, char *path, mode_t mode)
148 {
149         int result = default_vfs_ops.mkdir(conn, path, mode);
150
151         syslog(SYSLOG_PRIORITY, "mkdir %s %s%s\n", 
152                path,
153                (result < 0) ? "failed: " : "",
154                (result < 0) ? strerror(errno) : "");
155
156         return result;
157 }
158
159 int audit_rmdir(struct connection_struct *conn, char *path)
160 {
161         int result = default_vfs_ops.rmdir(conn, path);
162
163         syslog(SYSLOG_PRIORITY, "rmdir %s %s%s\n", 
164                path, 
165                (result < 0) ? "failed: " : "",
166                (result < 0) ? strerror(errno) : "");
167
168         return result;
169 }
170
171 int audit_open(struct connection_struct *conn, char *fname, int flags, mode_t mode)
172 {
173         int result = default_vfs_ops.open(conn, fname, flags, mode);
174
175         syslog(SYSLOG_PRIORITY, "open %s (fd %d) %s%s%s\n", 
176                fname, result,
177                ((flags & O_WRONLY) || (flags & O_RDWR)) ? "for writing " : "", 
178                (result < 0) ? "failed: " : "",
179                (result < 0) ? strerror(errno) : "");
180
181         return result;
182 }
183
184 int audit_close(struct files_struct *fsp, int fd)
185 {
186         int result = default_vfs_ops.close(fsp, fd);
187
188         syslog(SYSLOG_PRIORITY, "close fd %d %s%s\n",
189                fd,
190                (result < 0) ? "failed: " : "",
191                (result < 0) ? strerror(errno) : "");
192
193         return result;
194 }
195
196 int audit_rename(struct connection_struct *conn, char *old, char *new)
197 {
198         int result = default_vfs_ops.rename(conn, old, new);
199
200         syslog(SYSLOG_PRIORITY, "rename %s -> %s %s%s\n",
201                old, new,
202                (result < 0) ? "failed: " : "",
203                (result < 0) ? strerror(errno) : "");
204
205         return result;    
206 }
207
208 int audit_unlink(struct connection_struct *conn, char *path)
209 {
210         int result = default_vfs_ops.unlink(conn, path);
211
212         syslog(SYSLOG_PRIORITY, "unlink %s %s%s\n",
213                path,
214                (result < 0) ? "failed: " : "",
215                (result < 0) ? strerror(errno) : "");
216
217         return result;
218 }
219
220 int audit_chmod(struct connection_struct *conn, char *path, mode_t mode)
221 {
222         int result = default_vfs_ops.chmod(conn, path, mode);
223
224         syslog(SYSLOG_PRIORITY, "chmod %s mode 0x%x %s%s\n",
225                path, mode,
226                (result < 0) ? "failed: " : "",
227                (result < 0) ? strerror(errno) : "");
228
229         return result;
230 }
231