Browse code

add ClamAuth to contrib

Tomasz Kojm authored on 2012/03/15 03:15:10
Showing 10 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,43 @@
0
+<?xml version="1.0" encoding="UTF-8"?>
1
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
2
+<plist version="1.0">
3
+<dict>
4
+	<key>BuildMachineOSBuild</key>
5
+	<string>11D50</string>
6
+	<key>CFBundleDevelopmentRegion</key>
7
+	<string>English</string>
8
+	<key>CFBundleExecutable</key>
9
+	<string>ClamAuth</string>
10
+	<key>CFBundleIdentifier</key>
11
+	<string>com.apple.dts.kext.ClamAuth</string>
12
+	<key>CFBundleInfoDictionaryVersion</key>
13
+	<string>6.0</string>
14
+	<key>CFBundlePackageType</key>
15
+	<string>KEXT</string>
16
+	<key>CFBundleSignature</key>
17
+	<string>????</string>
18
+	<key>CFBundleVersion</key>
19
+	<string>0.1</string>
20
+	<key>DTCompiler</key>
21
+	<string></string>
22
+	<key>DTPlatformBuild</key>
23
+	<string>4D502</string>
24
+	<key>DTPlatformVersion</key>
25
+	<string>GM</string>
26
+	<key>DTSDKBuild</key>
27
+	<string>11C63</string>
28
+	<key>DTSDKName</key>
29
+	<string>macosx10.7</string>
30
+	<key>DTXcode</key>
31
+	<string>0421</string>
32
+	<key>DTXcodeBuild</key>
33
+	<string>4D502</string>
34
+	<key>OSBundleLibraries</key>
35
+	<dict>
36
+		<key>com.apple.kpi.bsd</key>
37
+		<string>8.0.0</string>
38
+		<key>com.apple.kpi.libkern</key>
39
+		<string>8.0.0</string>
40
+	</dict>
41
+</dict>
42
+</plist>
0 43
new file mode 100644
1 44
Binary files /dev/null and b/contrib/ClamAuth/ClamAuth.kext/Contents/MacOS/ClamAuth differ
2 45
new file mode 100644
... ...
@@ -0,0 +1,40 @@
0
+Copyright (C) 2011 Sourcefire, Inc., All Rights Reserved.
1
+
2
+The KAuth code is based on KauthORama:
3
+       
4
+Copyright (c) 2007 by Apple Computer, Inc., All Rights Reserved.
5
+
6
+Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
7
+                ("Apple") in consideration of your agreement to the following terms, and your
8
+                use, installation, modification or redistribution of this Apple software
9
+                constitutes acceptance of these terms.  If you do not agree with these terms,
10
+                please do not use, install, modify or redistribute this Apple software.
11
+
12
+                In consideration of your agreement to abide by the following terms, and subject
13
+                to these terms, Apple grants you a personal, non-exclusive license, under Apple's
14
+                copyrights in this original Apple software (the "Apple Software"), to use,
15
+                reproduce, modify and redistribute the Apple Software, with or without
16
+                modifications, in source and/or binary forms; provided that if you redistribute
17
+                the Apple Software in its entirety and without modifications, you must retain
18
+                this notice and the following text and disclaimers in all such redistributions of
19
+                the Apple Software.  Neither the name, trademarks, service marks or logos of
20
+                Apple Computer, Inc. may be used to endorse or promote products derived from the
21
+                Apple Software without specific prior written permission from Apple.  Except as
22
+                expressly stated in this notice, no other rights or licenses, express or implied,
23
+                are granted by Apple herein, including but not limited to any patent rights that
24
+                may be infringed by your derivative works or by other works in which the Apple
25
+                Software may be incorporated.
26
+
27
+                The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
28
+                WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
29
+                WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30
+                PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
31
+                COMBINATION WITH YOUR PRODUCTS.
32
+
33
+                IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
34
+                CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
35
+                GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36
+                ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
37
+                OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
38
+                (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
39
+                ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0 40
\ No newline at end of file
1 41
new file mode 100755
... ...
@@ -0,0 +1,4 @@
0
+sudo chown -R root ClamAuth.kext
1
+sudo chgrp -R wheel ClamAuth.kext
2
+sudo kextload ClamAuth.kext
3
+sudo sysctl -w kern.com_apple_dts_kext_ClamAuth="monitor /bin /usr/bin /Applications"
0 4
new file mode 100755
... ...
@@ -0,0 +1 @@
0
+sudo kextunload ClamAuth.kext
0 1
new file mode 100644
... ...
@@ -0,0 +1,23 @@
0
+On-access scanning for OS X
1
+---------------------------
2
+
3
+The ClamAuth kernel extension enables ClamAV to provide on-access scanning
4
+for Mac OS X 10.5 and later. The current version works in a passive mode
5
+only - ClamAV will log the detection but won't block access to the infected
6
+file. However, it's possible to perform special actions (eg. quarantine
7
+files) with the VirusEvent directive of clamd.
8
+
9
+Usage
10
+-----
11
+
12
+1. Run ClamAuth_load to load the kernel extension (you can edit the
13
+script to change or add more paths that will be monitored).
14
+2. Add "ClamAuth yes" to your clamd.conf
15
+3. Start clamd with root privileges ('sudo /usr/local/sbin/clamd')
16
+
17
+If clamd properly connects to the driver, you should see a line like this
18
+in the log file:
19
+
20
+ClamAuth: Driver version: 0.3, protocol version: 2
21
+
22
+ClamAV is now monitoring the paths specified in ClamAuth_load.
0 23
new file mode 100644
... ...
@@ -0,0 +1,757 @@
0
+/*
1
+ * Copyright (c) 2007 by Apple Computer, Inc., All Rights Reserved.
2
+ * Copyright (c) 2011 Sourcefire, Inc.
3
+ */
4
+
5
+#include <kern/assert.h>
6
+#include <mach/mach_types.h>
7
+#include <libkern/libkern.h>
8
+#include <libkern/OSAtomic.h>
9
+#include <libkern/OSMalloc.h>
10
+#include <sys/sysctl.h>
11
+#include <sys/systm.h>
12
+#include <sys/kauth.h>
13
+#include <sys/vnode.h>
14
+#include <sys/uio.h>
15
+#include <sys/conf.h>
16
+#include <miscfs/devfs/devfs.h>
17
+
18
+#define CLAMAUTH_VERSION            "0.3"
19
+#define CLAMAUTH_PROTOCOL_VERSION    2
20
+
21
+#pragma mark ***** Global Resources
22
+/* These declarations are required to allocate memory and create locks.
23
+ * They're created when we start and destroyed when we stop.
24
+ */
25
+
26
+static OSMallocTag  gMallocTag = NULL;
27
+static lck_grp_t *  gLockGroup = NULL;
28
+
29
+#define CLAMAUTH_EVENTS (KAUTH_VNODE_EXECUTE)
30
+
31
+struct AuthEvent {
32
+    /* don't change the first two fields */
33
+    UInt32 action;
34
+    char path[1024];
35
+    UInt32 pid;
36
+
37
+};
38
+
39
+#define EVENTQSIZE 64
40
+
41
+struct AuthEventQueue {
42
+    struct AuthEvent queue[EVENTQSIZE];
43
+    int cnt, first, last;
44
+};
45
+
46
+void AuthEventInitQueue(struct AuthEventQueue *queue);
47
+void AuthEventEnqueue(struct AuthEventQueue *queue, struct AuthEvent *event);
48
+int AuthEventDequeue(struct AuthEventQueue *queue, struct AuthEvent *event);
49
+
50
+void AuthEventInitQueue(struct AuthEventQueue *queue)
51
+{
52
+    memset(queue, 0, sizeof(struct AuthEventQueue));
53
+    queue->first = queue->cnt = 0;
54
+    queue->last = EVENTQSIZE - 1;
55
+}
56
+
57
+void AuthEventEnqueue(struct AuthEventQueue *queue, struct AuthEvent *event)
58
+{
59
+    queue->last = (queue->last + 1) % EVENTQSIZE;
60
+    memcpy(&queue->queue[queue->last], event, sizeof(struct AuthEvent));
61
+    queue->cnt++;
62
+}
63
+
64
+int AuthEventDequeue(struct AuthEventQueue *queue, struct AuthEvent *event)
65
+{
66
+    if(!queue->cnt)
67
+        return 1;
68
+    memcpy(event, &queue->queue[queue->first], sizeof(struct AuthEvent));
69
+    queue->first = (queue->first + 1) % EVENTQSIZE;
70
+    queue->cnt--;
71
+    return 0;
72
+}
73
+
74
+struct AuthEventQueue gEventQueue;
75
+static lck_mtx_t *gEventQueueLock = NULL;
76
+static SInt32 gEventCount = 0;
77
+
78
+#define MAX_PREFIX_NUM 10
79
+#define MAX_PREFIX_LEN 128
80
+static char gPrefixTable[MAX_PREFIX_NUM][MAX_PREFIX_LEN];
81
+static unsigned int gPrefixCount = 0;
82
+
83
+static int CreateVnodePath(vnode_t vp, char **vpPathPtr)
84
+    /* Creates a full path for a vnode.  vp may be NULL, in which 
85
+     * case the returned path is NULL (that is, no memory is allocated).
86
+     * vpPathPtr is a place to store the allocated path buffer.  
87
+     * The caller is responsible for freeing this memory using OSFree 
88
+     * (the size is always MAXPATHLEN).
89
+     */
90
+{
91
+    int             err;
92
+    int             pathLen;
93
+
94
+    assert( vpPathPtr != NULL);
95
+    assert(*vpPathPtr == NULL);
96
+    
97
+    err = 0;
98
+    if (vp != NULL) {
99
+        *vpPathPtr = OSMalloc(MAXPATHLEN, gMallocTag);
100
+        if (*vpPathPtr == NULL) {
101
+            err = ENOMEM;
102
+        }
103
+        if (err == 0) {
104
+            pathLen = MAXPATHLEN;
105
+            err = vn_getpath(vp, *vpPathPtr, &pathLen);
106
+        }
107
+    }
108
+    
109
+    return err;
110
+}
111
+
112
+/* /dev/clamauth handling */
113
+
114
+static int ca_devidx = -1;
115
+static void *ca_devnode = NULL;
116
+int dev_open = 0, dev_read = 0;
117
+
118
+static int ca_open(dev_t dev, int flag, int devtype, proc_t p)
119
+{
120
+    if(dev_open)
121
+        return EBUSY;
122
+    
123
+    dev_open = 1;
124
+    
125
+    return 0;
126
+}
127
+
128
+static int ca_close(dev_t dev, int flag, int devtype, proc_t p)
129
+{
130
+    dev_open = 0;
131
+    return 0;
132
+}
133
+
134
+static int ca_read(dev_t dev, uio_t uio, int ioflag)
135
+{
136
+    int ret = 0, size, retq = 0;
137
+    struct AuthEvent event;
138
+    struct timespec waittime;
139
+    
140
+    waittime.tv_sec  = 1;
141
+    waittime.tv_nsec = 0;
142
+    while(uio_resid(uio) > 0) {
143
+        lck_mtx_lock(gEventQueueLock);
144
+        retq = AuthEventDequeue(&gEventQueue, &event);
145
+        dev_read = 1;
146
+        lck_mtx_unlock(gEventQueueLock);
147
+        if(retq != 1) {
148
+            /* snprintf(info, sizeof(info), "PATH: %s, PID: %d, ACTION: %d\n", event.path, event.pid, event.action); */
149
+            size = MIN(uio_resid(uio), sizeof(event));
150
+            ret = uiomove((const char *) &event, size, uio);
151
+            if(ret)
152
+                break;
153
+        }  else {
154
+            //(void) msleep(&gEventQueue, NULL, PUSER, "events", &waittime);
155
+            break;
156
+        }
157
+    }
158
+    
159
+    if(ret) {
160
+        printf("ClamAuth: uiomove() failed\n");
161
+    }
162
+    
163
+    return ret;
164
+}
165
+
166
+static int ca_write(dev_t dev, uio_t uio, int ioflag)
167
+{
168
+    return EBADF;
169
+}
170
+
171
+static int ca_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, proc_t p)
172
+{
173
+    return EBADF;
174
+}
175
+
176
+static int ca_select(dev_t dev, int flag, void * wql, proc_t p)
177
+{
178
+    return EBADF;
179
+}
180
+
181
+static struct cdevsw clamauth_cdevsw = {
182
+    ca_open,
183
+    ca_close,
184
+    ca_read,
185
+    ca_write,
186
+    ca_ioctl,
187
+    eno_stop,
188
+    eno_reset,
189
+    NULL,
190
+    ca_select,
191
+    eno_mmap,
192
+    eno_strat,
193
+    eno_getc,
194
+    eno_putc,
195
+    0
196
+};
197
+
198
+static int ca_remove(void)
199
+{
200
+    if(ca_devnode)
201
+        devfs_remove(ca_devnode);
202
+    
203
+    if(ca_devidx != -1) {
204
+        if(cdevsw_remove(ca_devidx, &clamauth_cdevsw) != ca_devidx) {
205
+            printf("ClamAuth: cdevsw_remove() failed\n");
206
+            return KERN_FAILURE;
207
+        }
208
+    }
209
+    
210
+    return KERN_SUCCESS;
211
+}
212
+
213
+
214
+#pragma mark ***** Listener Resources
215
+
216
+/* Some scopes (for example KAUTH_SCOPE_VNODE) are called a /lot/.  Thus, 
217
+ * it's a good idea to avoid taking mutexes in your listener if at all 
218
+ * possible.  Thus, we use non-blocking synchronisation to protect the 
219
+ * global data that's accessed by our listener (gPrefix).  
220
+ * Every time we enter a listener, we increment gActivationCount, and ever 
221
+ * time we leave we decrement it.  When we want to change the listener, we 
222
+ * first remove the listener, then we wait for the activation count to hit, 
223
+ * then we can modify the globals protected by that activation count.
224
+ *
225
+ * IMPORTANT:
226
+ * There is still a race condition here.  See RemoveListener for a description 
227
+ * of the race and why we can't fix it.
228
+ */
229
+
230
+static SInt32 gActivationCount = 0;
231
+
232
+static int VnodeScopeListener(
233
+    kauth_cred_t    credential,
234
+    void *          idata,
235
+    kauth_action_t  action,
236
+    uintptr_t       arg0,
237
+    uintptr_t       arg1,
238
+    uintptr_t       arg2,
239
+    uintptr_t       arg3
240
+)
241
+    /* A Kauth listener that's called to authorize an action in the vnode scope */
242
+{
243
+    #pragma unused(credential)
244
+    #pragma unused(idata)
245
+    #pragma unused(arg3)
246
+    int             err;
247
+    vfs_context_t   context;
248
+    vnode_t         vp;
249
+    vnode_t         dvp;
250
+    char *          vpPath;
251
+    char *          dvpPath;
252
+    struct AuthEvent event;
253
+    unsigned int    i, mpath = 0;
254
+        
255
+    (void) OSIncrementAtomic(&gActivationCount);
256
+
257
+    context = (vfs_context_t) arg0;
258
+    vp      = (vnode_t) arg1;
259
+    dvp     = (vnode_t) arg2;
260
+    
261
+    vpPath = NULL;
262
+    dvpPath = NULL;
263
+    
264
+    /* Convert the vnode, if any, to a path. */
265
+    err = CreateVnodePath(vp, &vpPath);
266
+    
267
+    /* Convert the parent directory vnode, if any, to a path. */
268
+    if (err == 0)
269
+        err = CreateVnodePath(dvp, &dvpPath);
270
+
271
+    /* Tell the user about this request.  Note that we filter requests 
272
+     * based on gPrefix.  If gPrefix is set, only requests where one 
273
+     * of the paths is prefixed by gPrefix will be printed.
274
+     */    
275
+    if (err == 0) {
276
+        for(i = 0; i < gPrefixCount; i++) {
277
+            if(vpPath && strprefix(vpPath, gPrefixTable[i])) {
278
+                mpath = 1;
279
+            } else if(dvpPath && strprefix(dvpPath, gPrefixTable[i])) {
280
+                mpath = 1;
281
+            }
282
+            if(mpath)
283
+                break;
284
+        }
285
+
286
+        if (mpath) {
287
+            if(action & CLAMAUTH_EVENTS)
288
+                   printf(
289
+                "scope=" KAUTH_SCOPE_VNODE ", uid=%ld, vp=%s, dvp=%s\n", 
290
+                (long) kauth_cred_getuid(vfs_context_ucred(context)),
291
+                (vpPath  != NULL) ?  vpPath : "<null>",
292
+                (dvpPath != NULL) ? dvpPath : "<null>"
293
+            );
294
+            
295
+            event.pid = vfs_context_pid(context);    
296
+            event.action = action;
297
+            if(vpPath) {
298
+                strncpy(event.path, vpPath, sizeof(event.path));
299
+                event.path[sizeof(event.path) - 1] = 0;
300
+            } else {
301
+                event.path[0] = 0;
302
+            }
303
+            lck_mtx_lock(gEventQueueLock);
304
+            if(dev_read && (action & CLAMAUTH_EVENTS)) {
305
+                // printf("gPrefix: %s, vpPath: %s, dvpPath: %s, action: %d\n", gPrefix, vpPath ? vpPath : "<null>", dvpPath ? dvpPath : "<null>", action);
306
+                AuthEventEnqueue(&gEventQueue, &event);
307
+            }
308
+            lck_mtx_unlock(gEventQueueLock);
309
+            (void) OSIncrementAtomic(&gEventCount);
310
+        }
311
+    } else {
312
+        printf("ClamAuth.VnodeScopeListener: Error %d.\n", err);
313
+    }
314
+    
315
+    if (vpPath != NULL) {
316
+        OSFree(vpPath, MAXPATHLEN, gMallocTag);
317
+    }
318
+    if (dvpPath != NULL) {
319
+        OSFree(dvpPath, MAXPATHLEN, gMallocTag);
320
+    }
321
+
322
+    (void) OSDecrementAtomic(&gActivationCount);
323
+
324
+    return KAUTH_RESULT_DEFER;
325
+}
326
+
327
+static int FileOpScopeListener(
328
+                               kauth_cred_t    credential,
329
+                               void *          idata,
330
+                               kauth_action_t  action,
331
+                               uintptr_t       arg0,
332
+                               uintptr_t       arg1,
333
+                               uintptr_t       arg2,
334
+                               uintptr_t       arg3
335
+                               )
336
+/* A Kauth listener that's called to authorize an action in the file operation */
337
+{
338
+#pragma unused(credential)
339
+#pragma unused(idata)
340
+#pragma unused(arg2)
341
+#pragma unused(arg3)
342
+    struct AuthEvent event;
343
+    vfs_context_t   context;
344
+    const char *path;
345
+    unsigned int i, mpath = 0;
346
+
347
+    if(!dev_read)
348
+        return KAUTH_RESULT_DEFER;
349
+
350
+    context = (vfs_context_t) arg0;
351
+    path = (const char *) arg1;
352
+
353
+    (void) OSIncrementAtomic(&gActivationCount);
354
+
355
+    switch (action) {
356
+        /* case KAUTH_FILEOP_OPEN: */
357
+        case KAUTH_FILEOP_EXEC:
358
+            for(i = 0; i < gPrefixCount; i++) {
359
+                if(strprefix((const char *) arg1, gPrefixTable[i])) {
360
+                    mpath = 1;
361
+                    break;
362
+                }
363
+            }
364
+            if(mpath) {
365
+                event.pid = vfs_context_pid(context);
366
+                event.action = action;
367
+                strncpy(event.path, path, sizeof(event.path));
368
+                event.path[sizeof(event.path) - 1] = 0;
369
+                lck_mtx_lock(gEventQueueLock);
370
+                AuthEventEnqueue(&gEventQueue, &event);
371
+                lck_mtx_unlock(gEventQueueLock);
372
+            }
373
+            break;
374
+        default:
375
+            break;
376
+    }
377
+    
378
+    (void) OSDecrementAtomic(&gActivationCount);
379
+
380
+    return KAUTH_RESULT_DEFER;
381
+}
382
+
383
+#pragma mark ***** Listener Install/Remove
384
+
385
+/* gConfigurationLock is a mutex that protects us from two threads trying to 
386
+ * simultaneously modify the configuration.  The configuration is protect in 
387
+ * N ways:
388
+ *
389
+ * o During startup, we register our sysctl OID last, so no one can start 
390
+ *   modifying the configuration until everything is set up nicely.
391
+ * 
392
+ * o During normal operations, the sysctl handler (SysctlHandler) takes 
393
+ *   the lock to prevent two threads from reconfiguring the system at the 
394
+ *   same time.
395
+ *
396
+ * o During termination, the stop routine first removes the sysctl OID 
397
+ *   and then takes the lock before it removes the listener.  The first 
398
+ *   act prevents any new sysctl requests coming it, the second blocks 
399
+ *   until current sysctl requests are done.
400
+ *
401
+ * IMPORTANT:
402
+ * There is still a race condition here.  See the stop routine for a description 
403
+ * of the race and why we can't fix it.
404
+ */
405
+
406
+static lck_mtx_t *      gConfigurationLock = NULL;
407
+
408
+/* gListener is our handle to the installed scope listener.  We need to 
409
+ * keep it around so that we can remove the listener when we're done.
410
+ */
411
+
412
+static kauth_listener_t gListener = NULL;
413
+
414
+static void RemoveListener(void)
415
+    /* Removes the installed scope listener, if any.
416
+     *
417
+     * Under almost all circumstances this routine runs under the 
418
+     * gConfigurationLock.  The only time that this might not be the case 
419
+     * is when the KEXT's start routine fails prior to gConfigurationLock 
420
+     * being created.
421
+     */
422
+{
423
+    /* First prevent any more threads entering our listener. */
424
+    if (gListener != NULL) {
425
+        kauth_unlisten_scope(gListener);
426
+        gListener = NULL;
427
+    }
428
+    
429
+    /* Then wait for any threads within out listener to stop.  Note that there 
430
+     * is still a race condition here; there could still be a thread executing 
431
+     * between the OSDecrementAtomic and the return from the listener function 
432
+     * (for example, FileOpScopeListener).  However, there's no way to close 
433
+     * this race because of the weak concurrency guarantee for kauth_unlisten_scope.
434
+     * Moreover, the window is very small and, seeing as this only happens during 
435
+     * reconfiguration, I'm not too worried.  However, I am worried enough 
436
+     * to ensure that this loop runs at least once, so we always delay the teardown  
437
+     * for at least one second waiting for the threads to drain from our 
438
+     * listener.
439
+     */
440
+    
441
+    do {
442
+        struct timespec oneSecond;
443
+
444
+        oneSecond.tv_sec  = 1;
445
+        oneSecond.tv_nsec = 0;
446
+
447
+        (void) msleep(&gActivationCount, NULL, PUSER, "com_apple_dts_kext_ClamAuth.RemoveListener", &oneSecond);
448
+    } while ( gActivationCount > 0 );
449
+}
450
+
451
+static void InstallListener(void)
452
+    /* Installs a listener for the specified scope.  scope and scopeLen specifies 
453
+     * the scope to listen for.  prefix is a parameter for the scope listener. 
454
+     * It may be NULL.
455
+     *
456
+     * prefix points into the gConfiguration global variable, so this routine 
457
+     * doesn't make a copy of it.  However, it has to make a copy of scope 
458
+     * because scope can point to a place in the middle of the gConfiguration 
459
+     * variable, so there's no guarantee it's null terminated (which we need it 
460
+     * to be in order to call kauth_listen_scope.
461
+     *
462
+     * This routine always runs under the gConfigurationLock.
463
+     */
464
+{   
465
+
466
+    assert(gListener == NULL);
467
+    //gListener = kauth_listen_scope(KAUTH_SCOPE_VNODE, VnodeScopeListener, NULL);
468
+    gListener = kauth_listen_scope(KAUTH_SCOPE_FILEOP, FileOpScopeListener, NULL);
469
+    if (gListener == NULL) {
470
+        printf("ClamAuth.InstallListener: Could not create gListener.\n");
471
+        RemoveListener();
472
+    } else {
473
+        printf("ClamAuth: Installed file listener\n");
474
+    }
475
+}
476
+
477
+static void ConfigureKauth(const char *configuration)
478
+    /* This routine is called by the sysctl handler when it notices 
479
+     * that the configuration has changed.  It's responsible for 
480
+     * parsing the new configuration string and updating the listener.
481
+     *
482
+     * See SysctlHandler for a description of how I chose to handle the 
483
+     * failure case.
484
+     *
485
+     * This routine always runs under the gConfigurationLock.
486
+     */
487
+{
488
+    unsigned int i = 0;
489
+    assert(configuration != NULL);
490
+    
491
+    /* Remove the existing listener. */
492
+    RemoveListener();
493
+
494
+    /* Parse the configuration string and install the new listener. */
495
+    if (strcmp(configuration, "remove") == 0) {
496
+        printf("ClamAuth.ConfigureKauth: Removed listener.\n");
497
+    } else if ( strprefix(configuration, "monitor ") ) {
498
+        const char *cursor;
499
+        
500
+        /* Skip the "monitor ". */        
501
+        cursor = configuration + strlen("monitor ");
502
+
503
+        gPrefixCount = 0;
504
+        while(*cursor == ' ')
505
+            cursor++;
506
+
507
+        if (!*cursor) {
508
+            printf("ClamAuth.ConfigureKauth: Bad configuration '%s'.\n", configuration);
509
+            return;
510
+        }
511
+
512
+        while(1) {
513
+            if(i < MAX_PREFIX_LEN - 1) {
514
+                if(*cursor == ' ') {
515
+                    gPrefixTable[gPrefixCount][i] = 0;
516
+                    gPrefixCount++;
517
+                    i = 0;
518
+                    if(gPrefixCount >= MAX_PREFIX_NUM) {
519
+                        printf("ClamAuth.ConfigureKauth: Too many paths (> %u).\n", MAX_PREFIX_NUM);
520
+                        gPrefixCount = 0;
521
+                        return;  
522
+                    }
523
+                } else {
524
+                    gPrefixTable[gPrefixCount][i++] = *cursor;
525
+                }
526
+            } else {
527
+                printf("ClamAuth.ConfigureKauth: Path too long (%u > %u).\n", i, MAX_PREFIX_LEN);
528
+                gPrefixCount = 0;
529
+                return;
530
+            }
531
+            cursor++;
532
+            if(!*cursor) {
533
+                gPrefixTable[gPrefixCount][i] = 0;
534
+                gPrefixCount++;
535
+                break;
536
+            }
537
+        }
538
+        printf("ClamAuth.ConfigureKauth: Monitoring %u path(s)\n", gPrefixCount);
539
+        InstallListener();
540
+    }
541
+}
542
+
543
+/* gConfiguration holds our current configuration string.  It's modified by 
544
+ * SysctlHandler (well, by sysctl_handle_string which is called by SysctlHandler).
545
+ */
546
+
547
+static char gConfiguration[1024];
548
+
549
+
550
+static int SysctlHandler(
551
+    struct sysctl_oid * oidp, 
552
+    void *              arg1, 
553
+    int                 arg2, 
554
+    struct sysctl_req * req
555
+)
556
+    /* This routine is called by the kernel when the user reads or 
557
+     * writes our sysctl variable.  The arguments are standard for 
558
+     * a sysctl handler.
559
+     */
560
+{
561
+    int     result;
562
+    
563
+    /* Prevent two threads trying to change our configuration at the same 
564
+     * time.
565
+     */    
566
+    lck_mtx_lock(gConfigurationLock);
567
+    
568
+    /* Let sysctl_handle_string do all the heavy lifting of getting 
569
+     * and setting the variable.
570
+     */    
571
+    result = sysctl_handle_string(oidp, arg1, arg2, req);
572
+    
573
+    /* On the way out, if we got no error and a new value was set, 
574
+     * do our magic.
575
+     */    
576
+    if ( (result == 0) && (req->newptr != 0) ) {
577
+        ConfigureKauth(gConfiguration);
578
+    }
579
+    
580
+    lck_mtx_unlock(gConfigurationLock);
581
+
582
+    return result;
583
+}
584
+
585
+/* Declare our sysctl OID (that is, a variable that the user can 
586
+ * get and set using sysctl).  Once this OID is registered (which 
587
+ * is done in the start routine, ClamAuth_start, below), the user 
588
+ * user can get and set our configuration variable (gConfiguration) 
589
+ * using the sysctl command line tool.
590
+ *
591
+ * We use OID using SYSCTL_OID rather than SYSCTL_STRING because 
592
+ * we want to override the hander function that's call (we want 
593
+ * SysctlHandler rather than sysctl_handle_string).
594
+ */
595
+
596
+SYSCTL_OID(
597
+    _kern,                                          /* parent OID */
598
+    OID_AUTO,                                       /* sysctl number, OID_AUTO means we're only accessible by name */
599
+    com_apple_dts_kext_ClamAuth,                    /* our name */
600
+    CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_KERN,     /* we're a string, more or less */
601
+    gConfiguration,                                 /* sysctl_handle_string gets/sets this string */
602
+    sizeof(gConfiguration),                         /* and this is its maximum length */
603
+    SysctlHandler,                                  /* our handler */
604
+    "A",                                            /* because that's what SYSCTL_STRING does */
605
+    ""                                              /* just a comment */
606
+);
607
+
608
+/* gRegisteredOID tracks whether we've registered our OID or not. */
609
+
610
+static boolean_t gRegisteredOID = FALSE;
611
+
612
+
613
+
614
+#pragma mark ***** Start/Stop
615
+
616
+/* Prototypes for our entry points */
617
+extern kern_return_t com_apple_dts_kext_ClamAuth_start(kmod_info_t * ki, void * d);
618
+extern kern_return_t com_apple_dts_kext_ClamAuth_stop(kmod_info_t * ki, void * d);
619
+
620
+extern kern_return_t com_apple_dts_kext_ClamAuth_start(kmod_info_t * ki, void * d)
621
+/* Called by the system to start up the kext. */
622
+{
623
+    #pragma unused(ki)
624
+    #pragma unused(d)
625
+    kern_return_t   err;
626
+    struct AuthEvent event;
627
+
628
+    ca_devidx = cdevsw_add(-1, &clamauth_cdevsw);
629
+    if(ca_devidx == -1) {
630
+        printf("ClamAuth: cdevsw_add() failed\n");
631
+        return KERN_FAILURE;
632
+    }
633
+
634
+    ca_devnode = devfs_make_node(makedev(ca_devidx, 0), DEVFS_CHAR, UID_ROOT, GID_WHEEL, 0660, "clamauth");
635
+    if(!ca_devnode) {
636
+        printf("ClamAuth: Can't create /dev/clamauth\n");
637
+        return ca_remove();
638
+    }    
639
+    
640
+    /* Allocate our global resources, needed in order to allocate memory 
641
+     * and locks throughout the rest of the program.
642
+     */
643
+    err = KERN_SUCCESS;
644
+    gMallocTag = OSMalloc_Tagalloc("com.apple.dts.kext.ClamAuth", OSMT_DEFAULT);
645
+    if (gMallocTag == NULL) {
646
+        err = KERN_FAILURE;
647
+    }
648
+    if (err == KERN_SUCCESS) {
649
+        gLockGroup = lck_grp_alloc_init("com.apple.dts.kext.ClamAuth", LCK_GRP_ATTR_NULL);
650
+        if (gLockGroup == NULL) {
651
+            err = KERN_FAILURE;
652
+        }
653
+    }
654
+    
655
+    /* Allocate the lock that protects our configuration. */
656
+    if (err == KERN_SUCCESS) {
657
+        gConfigurationLock = lck_mtx_alloc_init(gLockGroup, LCK_ATTR_NULL);
658
+        if (gConfigurationLock == NULL) {
659
+            err = KERN_FAILURE;
660
+        }
661
+    }
662
+
663
+    /* Event queue lock */
664
+    if (err == KERN_SUCCESS) {
665
+        gEventQueueLock = lck_mtx_alloc_init(gLockGroup, LCK_ATTR_NULL);
666
+        if (gEventQueueLock == NULL) {
667
+            err = KERN_FAILURE;
668
+        }
669
+    }
670
+    AuthEventInitQueue(&gEventQueue);
671
+
672
+    /* Initialize event queue and add version info event */
673
+    event.action = CLAMAUTH_PROTOCOL_VERSION;
674
+    strncpy(event.path, "ClamAuth "CLAMAUTH_VERSION"", sizeof(event.path));
675
+    event.pid = 0xdeadbeef;
676
+    AuthEventEnqueue(&gEventQueue, &event);
677
+
678
+    /* Register our sysctl handler. */    
679
+    if (err == KERN_SUCCESS) {
680
+        sysctl_register_oid(&sysctl__kern_com_apple_dts_kext_ClamAuth);
681
+        gRegisteredOID = TRUE;
682
+    }
683
+    
684
+    /* If we failed, shut everything down. */
685
+    if (err != KERN_SUCCESS) {
686
+        printf("ClamAuth_start: Failed to initialize the driver\n");
687
+        (void) com_apple_dts_kext_ClamAuth_stop(ki, d);
688
+    } else
689
+        printf("ClamAuth_start: ClamAV kernel driver loaded\n");
690
+
691
+    return err;
692
+}
693
+
694
+extern kern_return_t com_apple_dts_kext_ClamAuth_stop(kmod_info_t * ki, void * d)
695
+    /* Called by the system to shut down the kext. */
696
+{
697
+    #pragma unused(ki)
698
+    #pragma unused(d)
699
+    int ret;
700
+
701
+    /* Remove our sysctl handler.  This prevents more threads entering the 
702
+     * handler and trying to change the configuration.  There is still a 
703
+     * race condition here though.  If a thread is already running in our 
704
+     * sysctl handler, there's no way to guarantee that it's done before 
705
+     * we destroy key resources (notably the gConfigurationLock mutex) that 
706
+     * it depends on.  That's because sysctl_unregister_oid makes no attempt 
707
+     * to wait until all threads running inside the OID handler are done 
708
+     * before it returns.  I could do stuff to minimise the risk, but there's 
709
+     * is no 100% way to close this race so I'm going to ignore it.
710
+     */    
711
+    if (gRegisteredOID) {
712
+        sysctl_unregister_oid(&sysctl__kern_com_apple_dts_kext_ClamAuth);
713
+        gRegisteredOID = FALSE;
714
+    }
715
+
716
+    /* remove the character device */
717
+    ret = ca_remove();
718
+
719
+    /* Shut down the scope listen, if any.  Not that we lock gConfigurationLock 
720
+     * because RemoveListener requires it to be locked.  Further note that 
721
+     * we only do this if the lock has actually been allocated.  If the startup 
722
+     * routine fails, we can get called with gConfigurationLock set to NULL.
723
+     */    
724
+    if (gConfigurationLock != NULL) {
725
+        lck_mtx_lock(gConfigurationLock);
726
+    }
727
+    RemoveListener();
728
+    if (gConfigurationLock != NULL) {
729
+        lck_mtx_unlock(gConfigurationLock);
730
+    }
731
+    
732
+    /* Clean up the configuration lock. */    
733
+    if (gConfigurationLock != NULL) {
734
+        lck_mtx_free(gConfigurationLock, gLockGroup);
735
+        gConfigurationLock = NULL;
736
+    }
737
+
738
+    /* Clean up the event queue lock. */    
739
+    if (gEventQueueLock != NULL) {
740
+        lck_mtx_free(gEventQueueLock, gLockGroup);
741
+        gEventQueueLock = NULL;
742
+    }
743
+
744
+    /* Clean up our global resources. */
745
+    if (gLockGroup != NULL) {
746
+        lck_grp_free(gLockGroup);
747
+        gLockGroup = NULL;
748
+    }
749
+    if (gMallocTag != NULL) {
750
+        OSMalloc_Tagfree(gMallocTag);
751
+        gMallocTag = NULL;
752
+    }
753
+    
754
+    printf("ClamAuth_stop: ClamAV kernel driver removed\n");
755
+    return ret;
756
+}
0 757
new file mode 100644
... ...
@@ -0,0 +1,262 @@
0
+// !$*UTF8*$!
1
+{
2
+	archiveVersion = 1;
3
+	classes = {
4
+	};
5
+	objectVersion = 46;
6
+	objects = {
7
+
8
+/* Begin PBXBuildFile section */
9
+		52ADB27A148676E700208F0E /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = 52ADB279148676E700208F0E /* LICENSE */; };
10
+		52ADB28014867AF400208F0E /* ClamAuth.c in Sources */ = {isa = PBXBuildFile; fileRef = 52ADB27F14867AF400208F0E /* ClamAuth.c */; };
11
+/* End PBXBuildFile section */
12
+
13
+/* Begin PBXFileReference section */
14
+		32A4FEC30562C75700D090E7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
15
+		32A4FEC40562C75800D090E7 /* ClamAuth.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ClamAuth.kext; sourceTree = BUILT_PRODUCTS_DIR; };
16
+		52ADB279148676E700208F0E /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
17
+		52ADB27F14867AF400208F0E /* ClamAuth.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ClamAuth.c; sourceTree = "<group>"; };
18
+		E4C7A4390832568C00556BCE /* Kernel.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Kernel.framework; path = /System/Library/Frameworks/Kernel.framework; sourceTree = "<absolute>"; };
19
+/* End PBXFileReference section */
20
+
21
+/* Begin PBXFrameworksBuildPhase section */
22
+		32A4FEBF0562C75700D090E7 /* Frameworks */ = {
23
+			isa = PBXFrameworksBuildPhase;
24
+			buildActionMask = 2147483647;
25
+			files = (
26
+			);
27
+			runOnlyForDeploymentPostprocessing = 0;
28
+		};
29
+/* End PBXFrameworksBuildPhase section */
30
+
31
+/* Begin PBXGroup section */
32
+		089C166AFE841209C02AAC07 /* KauthORama */ = {
33
+			isa = PBXGroup;
34
+			children = (
35
+				52ADB27F14867AF400208F0E /* ClamAuth.c */,
36
+				52ADB279148676E700208F0E /* LICENSE */,
37
+				32A4FEC30562C75700D090E7 /* Info.plist */,
38
+				E4C7A4390832568C00556BCE /* Kernel.framework */,
39
+				19C28FB6FE9D52B211CA2CBB /* Products */,
40
+			);
41
+			name = KauthORama;
42
+			sourceTree = "<group>";
43
+		};
44
+		19C28FB6FE9D52B211CA2CBB /* Products */ = {
45
+			isa = PBXGroup;
46
+			children = (
47
+				32A4FEC40562C75800D090E7 /* ClamAuth.kext */,
48
+			);
49
+			name = Products;
50
+			sourceTree = "<group>";
51
+		};
52
+/* End PBXGroup section */
53
+
54
+/* Begin PBXHeadersBuildPhase section */
55
+		32A4FEBA0562C75700D090E7 /* Headers */ = {
56
+			isa = PBXHeadersBuildPhase;
57
+			buildActionMask = 2147483647;
58
+			files = (
59
+			);
60
+			runOnlyForDeploymentPostprocessing = 0;
61
+		};
62
+/* End PBXHeadersBuildPhase section */
63
+
64
+/* Begin PBXNativeTarget section */
65
+		32A4FEB80562C75700D090E7 /* ClamAuth */ = {
66
+			isa = PBXNativeTarget;
67
+			buildConfigurationList = E40CF0E60890089400F3BED8 /* Build configuration list for PBXNativeTarget "ClamAuth" */;
68
+			buildPhases = (
69
+				32A4FEB90562C75700D090E7 /* ShellScript */,
70
+				32A4FEBA0562C75700D090E7 /* Headers */,
71
+				32A4FEBB0562C75700D090E7 /* Resources */,
72
+				32A4FEBD0562C75700D090E7 /* Sources */,
73
+				32A4FEBF0562C75700D090E7 /* Frameworks */,
74
+				32A4FEC00562C75700D090E7 /* Rez */,
75
+				32A4FEC10562C75700D090E7 /* ShellScript */,
76
+			);
77
+			buildRules = (
78
+			);
79
+			dependencies = (
80
+			);
81
+			name = ClamAuth;
82
+			productInstallPath = "$(SYSTEM_LIBRARY_DIR)/Extensions";
83
+			productName = KauthORama;
84
+			productReference = 32A4FEC40562C75800D090E7 /* ClamAuth.kext */;
85
+			productType = "com.apple.product-type.kernel-extension";
86
+		};
87
+/* End PBXNativeTarget section */
88
+
89
+/* Begin PBXProject section */
90
+		089C1669FE841209C02AAC07 /* Project object */ = {
91
+			isa = PBXProject;
92
+			attributes = {
93
+				LastUpgradeCheck = 0420;
94
+			};
95
+			buildConfigurationList = E40CF0EA0890089400F3BED8 /* Build configuration list for PBXProject "ClamAuth" */;
96
+			compatibilityVersion = "Xcode 3.2";
97
+			developmentRegion = English;
98
+			hasScannedForEncodings = 1;
99
+			knownRegions = (
100
+				en,
101
+			);
102
+			mainGroup = 089C166AFE841209C02AAC07 /* KauthORama */;
103
+			projectDirPath = "";
104
+			projectRoot = "";
105
+			targets = (
106
+				32A4FEB80562C75700D090E7 /* ClamAuth */,
107
+			);
108
+		};
109
+/* End PBXProject section */
110
+
111
+/* Begin PBXResourcesBuildPhase section */
112
+		32A4FEBB0562C75700D090E7 /* Resources */ = {
113
+			isa = PBXResourcesBuildPhase;
114
+			buildActionMask = 2147483647;
115
+			files = (
116
+				52ADB27A148676E700208F0E /* LICENSE in Resources */,
117
+			);
118
+			runOnlyForDeploymentPostprocessing = 0;
119
+		};
120
+/* End PBXResourcesBuildPhase section */
121
+
122
+/* Begin PBXRezBuildPhase section */
123
+		32A4FEC00562C75700D090E7 /* Rez */ = {
124
+			isa = PBXRezBuildPhase;
125
+			buildActionMask = 2147483647;
126
+			files = (
127
+			);
128
+			runOnlyForDeploymentPostprocessing = 0;
129
+		};
130
+/* End PBXRezBuildPhase section */
131
+
132
+/* Begin PBXShellScriptBuildPhase section */
133
+		32A4FEB90562C75700D090E7 /* ShellScript */ = {
134
+			isa = PBXShellScriptBuildPhase;
135
+			buildActionMask = 2147483647;
136
+			files = (
137
+			);
138
+			runOnlyForDeploymentPostprocessing = 0;
139
+			shellPath = /bin/sh;
140
+			shellScript = "script=\"${SYSTEM_DEVELOPER_DIR}/ProjectBuilder Extras/Kernel Extension Support/KEXTPreprocess\";\nif [ -x \"$script\" ]; then\n    . \"$script\"\nfi";
141
+		};
142
+		32A4FEC10562C75700D090E7 /* ShellScript */ = {
143
+			isa = PBXShellScriptBuildPhase;
144
+			buildActionMask = 2147483647;
145
+			files = (
146
+			);
147
+			runOnlyForDeploymentPostprocessing = 0;
148
+			shellPath = /bin/sh;
149
+			shellScript = "script=\"${SYSTEM_DEVELOPER_DIR}/ProjectBuilder Extras/Kernel Extension Support/KEXTPostprocess\";\nif [ -x \"$script\" ]; then\n    . \"$script\"\nfi";
150
+		};
151
+/* End PBXShellScriptBuildPhase section */
152
+
153
+/* Begin PBXSourcesBuildPhase section */
154
+		32A4FEBD0562C75700D090E7 /* Sources */ = {
155
+			isa = PBXSourcesBuildPhase;
156
+			buildActionMask = 2147483647;
157
+			files = (
158
+				52ADB28014867AF400208F0E /* ClamAuth.c in Sources */,
159
+			);
160
+			runOnlyForDeploymentPostprocessing = 0;
161
+		};
162
+/* End PBXSourcesBuildPhase section */
163
+
164
+/* Begin XCBuildConfiguration section */
165
+		E40CF0E70890089400F3BED8 /* Debug */ = {
166
+			isa = XCBuildConfiguration;
167
+			buildSettings = {
168
+				INFOPLIST_FILE = Info.plist;
169
+				MODULE_NAME = com.apple.dts.kext.ClamAuth;
170
+				MODULE_START = com_apple_dts_kext_ClamAuth_start;
171
+				MODULE_STOP = com_apple_dts_kext_ClamAuth_stop;
172
+				MODULE_VERSION = 0.1;
173
+				PRODUCT_NAME = ClamAuth;
174
+				WRAPPER_EXTENSION = kext;
175
+			};
176
+			name = Debug;
177
+		};
178
+		E40CF0E80890089400F3BED8 /* Release */ = {
179
+			isa = XCBuildConfiguration;
180
+			buildSettings = {
181
+				INFOPLIST_FILE = Info.plist;
182
+				MODULE_NAME = com.apple.dts.kext.ClamAuth;
183
+				MODULE_START = com_apple_dts_kext_ClamAuth_start;
184
+				MODULE_STOP = com_apple_dts_kext_ClamAuth_stop;
185
+				MODULE_VERSION = 0.1;
186
+				PRODUCT_NAME = ClamAuth;
187
+				WRAPPER_EXTENSION = kext;
188
+			};
189
+			name = Release;
190
+		};
191
+		E40CF0EB0890089400F3BED8 /* Debug */ = {
192
+			isa = XCBuildConfiguration;
193
+			buildSettings = {
194
+				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
195
+				COPY_PHASE_STRIP = NO;
196
+				GCC_DYNAMIC_NO_PIC = NO;
197
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
198
+				GCC_OPTIMIZATION_LEVEL = 0;
199
+				GCC_TREAT_WARNINGS_AS_ERRORS = NO;
200
+				GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
201
+				GCC_WARN_MISSING_PARENTHESES = YES;
202
+				GCC_WARN_SIGN_COMPARE = YES;
203
+				GCC_WARN_UNUSED_FUNCTION = YES;
204
+				GCC_WARN_UNUSED_LABEL = YES;
205
+				GCC_WARN_UNUSED_PARAMETER = YES;
206
+				GCC_WARN_UNUSED_VALUE = YES;
207
+				GCC_WARN_UNUSED_VARIABLE = YES;
208
+				MACOSX_DEPLOYMENT_TARGET = 10.5;
209
+				SDKROOT = macosx10.7;
210
+				WARNING_CFLAGS = "-Wall";
211
+			};
212
+			name = Debug;
213
+		};
214
+		E40CF0EC0890089400F3BED8 /* Release */ = {
215
+			isa = XCBuildConfiguration;
216
+			buildSettings = {
217
+				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
218
+				COPY_PHASE_STRIP = YES;
219
+				GCC_DYNAMIC_NO_PIC = NO;
220
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
221
+				GCC_OPTIMIZATION_LEVEL = s;
222
+				GCC_TREAT_WARNINGS_AS_ERRORS = NO;
223
+				GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
224
+				GCC_WARN_MISSING_PARENTHESES = YES;
225
+				GCC_WARN_SIGN_COMPARE = YES;
226
+				GCC_WARN_UNUSED_FUNCTION = YES;
227
+				GCC_WARN_UNUSED_LABEL = YES;
228
+				GCC_WARN_UNUSED_PARAMETER = YES;
229
+				GCC_WARN_UNUSED_VALUE = YES;
230
+				GCC_WARN_UNUSED_VARIABLE = YES;
231
+				MACOSX_DEPLOYMENT_TARGET = 10.5;
232
+				SDKROOT = macosx10.7;
233
+				WARNING_CFLAGS = "-Wall";
234
+			};
235
+			name = Release;
236
+		};
237
+/* End XCBuildConfiguration section */
238
+
239
+/* Begin XCConfigurationList section */
240
+		E40CF0E60890089400F3BED8 /* Build configuration list for PBXNativeTarget "ClamAuth" */ = {
241
+			isa = XCConfigurationList;
242
+			buildConfigurations = (
243
+				E40CF0E70890089400F3BED8 /* Debug */,
244
+				E40CF0E80890089400F3BED8 /* Release */,
245
+			);
246
+			defaultConfigurationIsVisible = 0;
247
+			defaultConfigurationName = Debug;
248
+		};
249
+		E40CF0EA0890089400F3BED8 /* Build configuration list for PBXProject "ClamAuth" */ = {
250
+			isa = XCConfigurationList;
251
+			buildConfigurations = (
252
+				E40CF0EB0890089400F3BED8 /* Debug */,
253
+				E40CF0EC0890089400F3BED8 /* Release */,
254
+			);
255
+			defaultConfigurationIsVisible = 0;
256
+			defaultConfigurationName = Debug;
257
+		};
258
+/* End XCConfigurationList section */
259
+	};
260
+	rootObject = 089C1669FE841209C02AAC07 /* Project object */;
261
+}
0 262
new file mode 100644
... ...
@@ -0,0 +1,29 @@
0
+<?xml version="1.0" encoding="UTF-8"?>
1
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
2
+<plist version="1.0">
3
+<dict>
4
+	<key>CFBundleDevelopmentRegion</key>
5
+	<string>English</string>
6
+	<key>CFBundleExecutable</key>
7
+	<string>ClamAuth</string>
8
+	<key>CFBundleIconFile</key>
9
+	<string></string>
10
+	<key>CFBundleIdentifier</key>
11
+	<string>com.apple.dts.kext.ClamAuth</string>
12
+	<key>CFBundleInfoDictionaryVersion</key>
13
+	<string>6.0</string>
14
+	<key>CFBundlePackageType</key>
15
+	<string>KEXT</string>
16
+	<key>CFBundleSignature</key>
17
+	<string>????</string>
18
+	<key>CFBundleVersion</key>
19
+	<string>$(MODULE_VERSION)</string>
20
+	<key>OSBundleLibraries</key>
21
+	<dict>
22
+		<key>com.apple.kpi.bsd</key>
23
+		<string>8.0.0</string>
24
+		<key>com.apple.kpi.libkern</key>
25
+		<string>8.0.0</string>
26
+	</dict>
27
+</dict>
28
+</plist>
0 29
new file mode 100644
... ...
@@ -0,0 +1,40 @@
0
+Copyright (C) 2011 Sourcefire, Inc., All Rights Reserved.
1
+
2
+The KAuth code is based on KauthORama:
3
+       
4
+Copyright (c) 2007 by Apple Computer, Inc., All Rights Reserved.
5
+
6
+Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
7
+                ("Apple") in consideration of your agreement to the following terms, and your
8
+                use, installation, modification or redistribution of this Apple software
9
+                constitutes acceptance of these terms.  If you do not agree with these terms,
10
+                please do not use, install, modify or redistribute this Apple software.
11
+
12
+                In consideration of your agreement to abide by the following terms, and subject
13
+                to these terms, Apple grants you a personal, non-exclusive license, under Apple's
14
+                copyrights in this original Apple software (the "Apple Software"), to use,
15
+                reproduce, modify and redistribute the Apple Software, with or without
16
+                modifications, in source and/or binary forms; provided that if you redistribute
17
+                the Apple Software in its entirety and without modifications, you must retain
18
+                this notice and the following text and disclaimers in all such redistributions of
19
+                the Apple Software.  Neither the name, trademarks, service marks or logos of
20
+                Apple Computer, Inc. may be used to endorse or promote products derived from the
21
+                Apple Software without specific prior written permission from Apple.  Except as
22
+                expressly stated in this notice, no other rights or licenses, express or implied,
23
+                are granted by Apple herein, including but not limited to any patent rights that
24
+                may be infringed by your derivative works or by other works in which the Apple
25
+                Software may be incorporated.
26
+
27
+                The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
28
+                WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
29
+                WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30
+                PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
31
+                COMBINATION WITH YOUR PRODUCTS.
32
+
33
+                IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
34
+                CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
35
+                GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36
+                ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
37
+                OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
38
+                (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
39
+                ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0 40
\ No newline at end of file