xref: /titanic_44/usr/src/cmd/vscan/vscand/vs_svc.c (revision c8dbf746aa55f3a63c8095f8dbae339574156bb8)
1911106dfSjm199354 /*
2911106dfSjm199354  * CDDL HEADER START
3911106dfSjm199354  *
4911106dfSjm199354  * The contents of this file are subject to the terms of the
5911106dfSjm199354  * Common Development and Distribution License (the "License").
6911106dfSjm199354  * You may not use this file except in compliance with the License.
7911106dfSjm199354  *
8911106dfSjm199354  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9911106dfSjm199354  * or http://www.opensolaris.org/os/licensing.
10911106dfSjm199354  * See the License for the specific language governing permissions
11911106dfSjm199354  * and limitations under the License.
12911106dfSjm199354  *
13911106dfSjm199354  * When distributing Covered Code, include this CDDL HEADER in each
14911106dfSjm199354  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15911106dfSjm199354  * If applicable, add the following below this CDDL HEADER, with the
16911106dfSjm199354  * fields enclosed by brackets "[]" replaced with your own identifying
17911106dfSjm199354  * information: Portions Copyright [yyyy] [name of copyright owner]
18911106dfSjm199354  *
19911106dfSjm199354  * CDDL HEADER END
20911106dfSjm199354  */
21911106dfSjm199354 /*
2253c11029Sjm199354  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23911106dfSjm199354  * Use is subject to license terms.
24911106dfSjm199354  */
25911106dfSjm199354 
26911106dfSjm199354 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27911106dfSjm199354 
28911106dfSjm199354 /*
29911106dfSjm199354  * Implementation of the "scan file" interface
30911106dfSjm199354  */
31911106dfSjm199354 
32911106dfSjm199354 #include <stdio.h>
33911106dfSjm199354 #include <stdlib.h>
34911106dfSjm199354 #include <unistd.h>
35911106dfSjm199354 #include <string.h>
36911106dfSjm199354 #include <errno.h>
37911106dfSjm199354 #include <syslog.h>
38911106dfSjm199354 #include <sys/types.h>
39911106dfSjm199354 #include <fcntl.h>
40911106dfSjm199354 #include <bsm/adt.h>
41911106dfSjm199354 #include <bsm/adt_event.h>
42bfc848c6Sjm199354 #include <pthread.h>
43911106dfSjm199354 
44911106dfSjm199354 #include "vs_incl.h"
45911106dfSjm199354 
46bfc848c6Sjm199354 /*
47bfc848c6Sjm199354  * vs_svc_nodes - table of scan requests and their thread id and
48bfc848c6Sjm199354  * scan engine context.
49bfc848c6Sjm199354  * The table is sized by the value passed to vs_svc_init. This
50bfc848c6Sjm199354  * value is obtained from the kernel and represents the maximum
51bfc848c6Sjm199354  * request idx that the kernel will request vscand to process.
52bfc848c6Sjm199354  * The table is indexed by the vsr_idx value passed in
53bfc848c6Sjm199354  * the scan request - always non-zero. This value is also the index
54bfc848c6Sjm199354  * into the kernel scan request table and identifies the instance of
55bfc848c6Sjm199354  * the driver being used to access file data for the scan. Although
56bfc848c6Sjm199354  * this is of no consequence here, it is useful information for debug.
57bfc848c6Sjm199354  *
58bfc848c6Sjm199354  * When a scan request is received a response is sent indicating
59bfc848c6Sjm199354  * one of the following:
60bfc848c6Sjm199354  * VS_STATUS_ERROR - an error occurred
61bfc848c6Sjm199354  * VS_STATUS_NO_SCAN - no scan is required
62bfc848c6Sjm199354  * VS_STATUS_SCANNING - request has been queued for async processing
63bfc848c6Sjm199354  *
64bfc848c6Sjm199354  * If the scan is required (VS_STATUS_SCANNING) a thread is created
65bfc848c6Sjm199354  * to perform the scan. It's tid is saved in vs_svc_nodes.
66bfc848c6Sjm199354  *
67bfc848c6Sjm199354  * In the case of SHUTDOWN, vs_terminate requests that all scan
68bfc848c6Sjm199354  * engine connections be closed, thus termintaing any in-progress
69bfc848c6Sjm199354  * scans, then awaits completion of all scanning threads as identified
70bfc848c6Sjm199354  * in vs_svc_nodes.
71bfc848c6Sjm199354  */
72bfc848c6Sjm199354 
73bfc848c6Sjm199354 typedef struct vs_svc_node {
74bfc848c6Sjm199354 	pthread_t vsn_tid;
75bfc848c6Sjm199354 	vs_scan_req_t vsn_req;
76bfc848c6Sjm199354 	vs_eng_ctx_t vsn_eng;
77bfc848c6Sjm199354 } vs_svc_node_t;
78bfc848c6Sjm199354 
79bfc848c6Sjm199354 static vs_svc_node_t *vs_svc_nodes;
80bfc848c6Sjm199354 static uint32_t vs_svc_max_node; /* max idx into vs_svc_nodes */
81bfc848c6Sjm199354 static pthread_mutex_t vs_svc_mutex = PTHREAD_MUTEX_INITIALIZER;
82bfc848c6Sjm199354 
83bfc848c6Sjm199354 
84911106dfSjm199354 /* local functions */
85bfc848c6Sjm199354 static void *vs_svc_async_scan(void *);
86bfc848c6Sjm199354 static int vs_svc_scan_file(vs_svc_node_t *, vs_scanstamp_t *);
87911106dfSjm199354 static void vs_svc_vlog(char *, vs_result_t *);
88911106dfSjm199354 static void vs_svc_audit(char *, vs_result_t *);
89911106dfSjm199354 
90bfc848c6Sjm199354 
91911106dfSjm199354 /*
92911106dfSjm199354  * vs_svc_init, vs_svc_fini
93911106dfSjm199354  *
94911106dfSjm199354  * Invoked on daemon load and unload
95911106dfSjm199354  */
96bfc848c6Sjm199354 int
vs_svc_init(uint32_t max_req)97bfc848c6Sjm199354 vs_svc_init(uint32_t max_req)
98911106dfSjm199354 {
99bfc848c6Sjm199354 	vs_svc_max_node = max_req;
100bfc848c6Sjm199354 	vs_svc_nodes = (vs_svc_node_t *)
101bfc848c6Sjm199354 	    calloc(max_req + 1, sizeof (vs_svc_node_t));
102bfc848c6Sjm199354 
103bfc848c6Sjm199354 	return (vs_svc_nodes == NULL ? -1 : 0);
104911106dfSjm199354 }
105911106dfSjm199354 
106911106dfSjm199354 void
vs_svc_fini()107911106dfSjm199354 vs_svc_fini()
108911106dfSjm199354 {
109bfc848c6Sjm199354 	if (vs_svc_nodes)
110bfc848c6Sjm199354 		free(vs_svc_nodes);
111bfc848c6Sjm199354 }
112bfc848c6Sjm199354 
113bfc848c6Sjm199354 
114bfc848c6Sjm199354 /*
115bfc848c6Sjm199354  * vs_svc_terminate
116bfc848c6Sjm199354  *
117bfc848c6Sjm199354  * Close all scan engine connections to terminate in-progress scan
118bfc848c6Sjm199354  * requests, and wait for all threads in vs_svc_nodes to complete
119bfc848c6Sjm199354  */
120bfc848c6Sjm199354 void
vs_svc_terminate()121bfc848c6Sjm199354 vs_svc_terminate()
122bfc848c6Sjm199354 {
123bfc848c6Sjm199354 	int i;
124bfc848c6Sjm199354 	pthread_t tid;
125bfc848c6Sjm199354 
126bfc848c6Sjm199354 	/* close connections to abort requests */
127bfc848c6Sjm199354 	vs_eng_close_connections();
128bfc848c6Sjm199354 
129bfc848c6Sjm199354 	/* wait for threads */
130bfc848c6Sjm199354 	for (i = 1; i <= vs_svc_max_node; i++) {
131bfc848c6Sjm199354 
132bfc848c6Sjm199354 		(void) pthread_mutex_lock(&vs_svc_mutex);
133bfc848c6Sjm199354 		tid = vs_svc_nodes[i].vsn_tid;
134bfc848c6Sjm199354 		(void) pthread_mutex_unlock(&vs_svc_mutex);
135bfc848c6Sjm199354 
136bfc848c6Sjm199354 		if (tid != 0)
137bfc848c6Sjm199354 			(void) pthread_join(tid, NULL);
138bfc848c6Sjm199354 	}
139bfc848c6Sjm199354 }
140bfc848c6Sjm199354 
141bfc848c6Sjm199354 
142bfc848c6Sjm199354 /*
143bfc848c6Sjm199354  * vs_svc_queue_scan_req
144bfc848c6Sjm199354  *
145bfc848c6Sjm199354  * Determine if the file needs to be scanned - either it has
146bfc848c6Sjm199354  * been modified or its scanstamp is not current.
147bfc848c6Sjm199354  * Initiate a thread to process the request, saving the tid
148bfc848c6Sjm199354  * in vs_svc_nodes[idx].vsn_tid, where idx is the vsr_idx passed in
149bfc848c6Sjm199354  * the scan request.
150bfc848c6Sjm199354  *
151bfc848c6Sjm199354  * Returns: VS_STATUS_ERROR - error
152bfc848c6Sjm199354  *          VS_STATUS_NO_SCAN - no scan required
153bfc848c6Sjm199354  *          VS_STATUS_SCANNING - async scan initiated
154bfc848c6Sjm199354  */
155bfc848c6Sjm199354 int
vs_svc_queue_scan_req(vs_scan_req_t * req)156bfc848c6Sjm199354 vs_svc_queue_scan_req(vs_scan_req_t *req)
157bfc848c6Sjm199354 {
158bfc848c6Sjm199354 	pthread_t tid;
159bfc848c6Sjm199354 	vs_svc_node_t *node;
160bfc848c6Sjm199354 
161bfc848c6Sjm199354 	/* No scan if file quarantined */
162bfc848c6Sjm199354 	if (req->vsr_quarantined)
163bfc848c6Sjm199354 		return (VS_STATUS_NO_SCAN);
164bfc848c6Sjm199354 
165bfc848c6Sjm199354 	/* No scan if file not modified AND scanstamp is current */
166bfc848c6Sjm199354 	if ((req->vsr_modified == 0) &&
167bfc848c6Sjm199354 	    vs_eng_scanstamp_current(req->vsr_scanstamp)) {
168bfc848c6Sjm199354 		return (VS_STATUS_NO_SCAN);
169bfc848c6Sjm199354 	}
170bfc848c6Sjm199354 
171bfc848c6Sjm199354 	/* scan required */
172bfc848c6Sjm199354 	node = &(vs_svc_nodes[req->vsr_idx]);
173bfc848c6Sjm199354 
174bfc848c6Sjm199354 	(void) pthread_mutex_lock(&vs_svc_mutex);
175bfc848c6Sjm199354 	if ((node->vsn_tid != 0) || (req->vsr_idx > vs_svc_max_node)) {
176bfc848c6Sjm199354 		(void) pthread_mutex_unlock(&vs_svc_mutex);
177bfc848c6Sjm199354 		return (VS_STATUS_ERROR);
178bfc848c6Sjm199354 	}
179bfc848c6Sjm199354 
180bfc848c6Sjm199354 	node->vsn_req = *req;
181bfc848c6Sjm199354 
182bfc848c6Sjm199354 	if (pthread_create(&tid, NULL, vs_svc_async_scan, (void *)node) != 0) {
183bfc848c6Sjm199354 		(void) pthread_mutex_unlock(&vs_svc_mutex);
184bfc848c6Sjm199354 		return (VS_STATUS_ERROR);
185bfc848c6Sjm199354 	}
186bfc848c6Sjm199354 
187bfc848c6Sjm199354 	node->vsn_tid = tid;
188bfc848c6Sjm199354 	(void) pthread_mutex_unlock(&vs_svc_mutex);
189bfc848c6Sjm199354 
190bfc848c6Sjm199354 	return (VS_STATUS_SCANNING);
191bfc848c6Sjm199354 }
192bfc848c6Sjm199354 
193bfc848c6Sjm199354 
194bfc848c6Sjm199354 /*
195bfc848c6Sjm199354  * vs_svc_async_scan
196bfc848c6Sjm199354  *
197bfc848c6Sjm199354  * Initialize response structure, invoke vs_svc_scan_file to
198bfc848c6Sjm199354  * perform the scan, then send the result to the kernel.
199bfc848c6Sjm199354  */
200bfc848c6Sjm199354 static void *
vs_svc_async_scan(void * arg)201bfc848c6Sjm199354 vs_svc_async_scan(void *arg)
202bfc848c6Sjm199354 {
203bfc848c6Sjm199354 	vs_svc_node_t *node = (vs_svc_node_t *)arg;
204bfc848c6Sjm199354 	vs_scan_req_t *scan_req = &(node->vsn_req);
205bfc848c6Sjm199354 	vs_scan_rsp_t scan_rsp;
206bfc848c6Sjm199354 
207bfc848c6Sjm199354 	scan_rsp.vsr_idx = scan_req->vsr_idx;
208bfc848c6Sjm199354 	scan_rsp.vsr_seqnum = scan_req->vsr_seqnum;
209bfc848c6Sjm199354 	scan_rsp.vsr_result = vs_svc_scan_file(node, &scan_rsp.vsr_scanstamp);
210bfc848c6Sjm199354 
211bfc848c6Sjm199354 	/* clear node and send async response to kernel */
212bfc848c6Sjm199354 	(void) pthread_mutex_lock(&vs_svc_mutex);
213bfc848c6Sjm199354 	(void) memset(node, 0, sizeof (vs_svc_node_t));
214bfc848c6Sjm199354 	(void) pthread_mutex_unlock(&vs_svc_mutex);
215bfc848c6Sjm199354 
216bfc848c6Sjm199354 	(void) vscand_kernel_result(&scan_rsp);
217bfc848c6Sjm199354 
218bfc848c6Sjm199354 	return (NULL);
219911106dfSjm199354 }
220911106dfSjm199354 
221911106dfSjm199354 
222911106dfSjm199354 /*
223911106dfSjm199354  * vs_svc_scan_file
224911106dfSjm199354  *
225911106dfSjm199354  * vs_svc_scan_file is responsible for:
226911106dfSjm199354  *  - obtaining & releasing a scan engine connection
227911106dfSjm199354  *  - invoking the scan engine interface code to do the scan
228911106dfSjm199354  *  - retrying a failed scan (up to VS_MAX_RETRY times)
229911106dfSjm199354  *  - updating scan statistics
230911106dfSjm199354  *  - logging virus information
231911106dfSjm199354  *
23253c11029Sjm199354  *
233911106dfSjm199354  * Returns:
234bfc848c6Sjm199354  *  VS_STATUS_NO_SCAN - scan not reqd; daemon shutting down
23553c11029Sjm199354  *  VS_STATUS_CLEAN - scan success. File clean.
23653c11029Sjm199354  *                    new scanstamp returned in scanstamp param.
23753c11029Sjm199354  *  VS_STATUS_INFECTED - scan success. File infected.
23853c11029Sjm199354  *  VS_STATUS_ERROR - scan failure either in vscand or scan engine.
239911106dfSjm199354  */
240bfc848c6Sjm199354 static int
vs_svc_scan_file(vs_svc_node_t * node,vs_scanstamp_t * scanstamp)241bfc848c6Sjm199354 vs_svc_scan_file(vs_svc_node_t *node, vs_scanstamp_t *scanstamp)
242911106dfSjm199354 {
243bfc848c6Sjm199354 	char devname[MAXPATHLEN];
244bfc848c6Sjm199354 	int flags = 0;
24553c11029Sjm199354 	int retries;
246911106dfSjm199354 	vs_result_t result;
247bfc848c6Sjm199354 	vs_scan_req_t *req = &(node->vsn_req);
248bfc848c6Sjm199354 	vs_eng_ctx_t *eng = &(node->vsn_eng);
249bfc848c6Sjm199354 
250bfc848c6Sjm199354 	(void) snprintf(devname, MAXPATHLEN, "%s%d", VS_DRV_PATH, req->vsr_idx);
251911106dfSjm199354 
25253c11029Sjm199354 	/* initialize response scanstamp to current scanstamp value */
253bfc848c6Sjm199354 	(void) strlcpy(*scanstamp, req->vsr_scanstamp, sizeof (vs_scanstamp_t));
254911106dfSjm199354 
255911106dfSjm199354 	(void) memset(&result, 0, sizeof (vs_result_t));
256911106dfSjm199354 	result.vsr_rc = VS_RESULT_UNDEFINED;
257911106dfSjm199354 
258911106dfSjm199354 	for (retries = 0; retries <= VS_MAX_RETRY; retries++) {
259bfc848c6Sjm199354 		/* get engine connection */
260bfc848c6Sjm199354 		if (vs_eng_get(eng, (retries != 0)) != 0) {
26153c11029Sjm199354 			result.vsr_rc = VS_RESULT_ERROR;
262911106dfSjm199354 			continue;
263911106dfSjm199354 		}
264911106dfSjm199354 
265bfc848c6Sjm199354 		/* shutdown could occur while waiting for engine connection */
266911106dfSjm199354 		if (vscand_get_state() == VS_STATE_SHUTDOWN) {
267bfc848c6Sjm199354 			vs_eng_release(eng);
26853c11029Sjm199354 			return (VS_STATUS_NO_SCAN);
269911106dfSjm199354 		}
270911106dfSjm199354 
271bfc848c6Sjm199354 		/* scan file */
272bfc848c6Sjm199354 		(void) vs_icap_scan_file(eng, devname, req->vsr_path,
273bfc848c6Sjm199354 		    req->vsr_size, flags, &result);
274911106dfSjm199354 
275911106dfSjm199354 		/* if no error, clear error state on engine and break */
27653c11029Sjm199354 		if ((result.vsr_rc != VS_RESULT_SE_ERROR) &&
27753c11029Sjm199354 		    (result.vsr_rc != VS_RESULT_ERROR)) {
278bfc848c6Sjm199354 			vs_eng_set_error(eng, 0);
279bfc848c6Sjm199354 			vs_eng_release(eng);
280911106dfSjm199354 			break;
281911106dfSjm199354 		}
282911106dfSjm199354 
28353c11029Sjm199354 		/* treat error on shutdown as scan not required */
284911106dfSjm199354 		if (vscand_get_state() == VS_STATE_SHUTDOWN) {
285bfc848c6Sjm199354 			vs_eng_release(eng);
28653c11029Sjm199354 			return (VS_STATUS_NO_SCAN);
287911106dfSjm199354 		}
288911106dfSjm199354 
289911106dfSjm199354 		/* set engine's error state and update engine stats */
290bfc848c6Sjm199354 		if (result.vsr_rc == VS_RESULT_SE_ERROR)
291bfc848c6Sjm199354 			vs_eng_set_error(eng, 1);
292bfc848c6Sjm199354 
293bfc848c6Sjm199354 		vs_eng_release(eng);
294911106dfSjm199354 	}
295911106dfSjm199354 
29653c11029Sjm199354 	vs_stats_set(result.vsr_rc);
297911106dfSjm199354 
29853c11029Sjm199354 	/*
29953c11029Sjm199354 	 * VS_RESULT_CLEANED - file infected, cleaned data available
30053c11029Sjm199354 	 * VS_RESULT_FORBIDDEN - file infected, no cleaned data
30153c11029Sjm199354 	 * Log virus, write audit record and return INFECTED status
30253c11029Sjm199354 	 */
303911106dfSjm199354 	if (result.vsr_rc == VS_RESULT_CLEANED ||
304911106dfSjm199354 	    result.vsr_rc == VS_RESULT_FORBIDDEN) {
305bfc848c6Sjm199354 		vs_svc_vlog(req->vsr_path, &result);
306bfc848c6Sjm199354 		vs_svc_audit(req->vsr_path, &result);
30753c11029Sjm199354 		return (VS_STATUS_INFECTED);
308911106dfSjm199354 	}
309911106dfSjm199354 
31053c11029Sjm199354 	/* VS_RESULT_CLEAN - Set the scanstamp and return CLEAN status */
31153c11029Sjm199354 	if (result.vsr_rc == VS_RESULT_CLEAN) {
31253c11029Sjm199354 		(void) strlcpy(*scanstamp, result.vsr_scanstamp,
313911106dfSjm199354 		    sizeof (vs_scanstamp_t));
31453c11029Sjm199354 		return (VS_STATUS_CLEAN);
315911106dfSjm199354 	}
316911106dfSjm199354 
31753c11029Sjm199354 	return (VS_STATUS_ERROR);
318911106dfSjm199354 }
319911106dfSjm199354 
320911106dfSjm199354 
321911106dfSjm199354 /*
322911106dfSjm199354  * vs_svc_vlog
323911106dfSjm199354  *
324bfc848c6Sjm199354  * log details of infections detected in syslig
325bfc848c6Sjm199354  * If virus log is configured log details there too
326911106dfSjm199354  */
327911106dfSjm199354 static void
vs_svc_vlog(char * filepath,vs_result_t * result)328911106dfSjm199354 vs_svc_vlog(char *filepath, vs_result_t *result)
329911106dfSjm199354 {
330911106dfSjm199354 	FILE *fp = NULL;
331911106dfSjm199354 	time_t sec;
332911106dfSjm199354 	struct tm *timestamp;
333911106dfSjm199354 	char timebuf[18]; /* MM/DD/YY hh:mm:ss */
334911106dfSjm199354 	int i;
335911106dfSjm199354 	char *log;
336911106dfSjm199354 
337bfc848c6Sjm199354 	/* syslog */
338911106dfSjm199354 	if (result->vsr_nviolations == 0) {
339*c8dbf746Sjm199354 		syslog(LOG_NOTICE, "quarantine %s\n", filepath);
340911106dfSjm199354 	} else {
341911106dfSjm199354 		for (i = 0; i < result->vsr_nviolations; i++) {
342*c8dbf746Sjm199354 			syslog(LOG_NOTICE, "quarantine %s %d - %s\n",
343911106dfSjm199354 			    filepath,
344911106dfSjm199354 			    result->vsr_vrec[i].vr_id,
345911106dfSjm199354 			    result->vsr_vrec[i].vr_desc);
346911106dfSjm199354 		}
347911106dfSjm199354 	}
348bfc848c6Sjm199354 
349bfc848c6Sjm199354 	/* log file */
350bfc848c6Sjm199354 	if (((log = vscand_viruslog()) == NULL) ||
351bfc848c6Sjm199354 	    ((fp = fopen(log, "a")) == NULL)) {
352bfc848c6Sjm199354 		return;
353911106dfSjm199354 	}
354911106dfSjm199354 
355bfc848c6Sjm199354 	(void) time(&sec);
356bfc848c6Sjm199354 	timestamp = localtime(&sec);
357bfc848c6Sjm199354 	(void) strftime(timebuf, sizeof (timebuf), "%D %T", timestamp);
358bfc848c6Sjm199354 
359bfc848c6Sjm199354 	if (result->vsr_nviolations == 0) {
360bfc848c6Sjm199354 		(void) fprintf(fp, "%s quarantine %d[%s]\n",
361bfc848c6Sjm199354 		    timebuf, strlen(filepath), filepath);
362bfc848c6Sjm199354 	} else {
363bfc848c6Sjm199354 		for (i = 0; i < result->vsr_nviolations; i++) {
364bfc848c6Sjm199354 			(void) fprintf(fp, "%s quarantine %d[%s] %d - %d[%s]\n",
365bfc848c6Sjm199354 			    timebuf, strlen(filepath), filepath,
366bfc848c6Sjm199354 			    result->vsr_vrec[i].vr_id,
367bfc848c6Sjm199354 			    strlen(result->vsr_vrec[i].vr_desc),
368bfc848c6Sjm199354 			    result->vsr_vrec[i].vr_desc);
369bfc848c6Sjm199354 		}
370bfc848c6Sjm199354 	}
371bfc848c6Sjm199354 
372911106dfSjm199354 	(void) fclose(fp);
373911106dfSjm199354 }
374911106dfSjm199354 
375911106dfSjm199354 
376911106dfSjm199354 /*
377911106dfSjm199354  * vs_svc_audit
378911106dfSjm199354  *
379911106dfSjm199354  * Generate AUE_vscan_quarantine audit record containing name
380911106dfSjm199354  * of infected file, and violation details if available.
381911106dfSjm199354  */
382911106dfSjm199354 static void
vs_svc_audit(char * filepath,vs_result_t * result)383911106dfSjm199354 vs_svc_audit(char *filepath, vs_result_t *result)
384911106dfSjm199354 {
385911106dfSjm199354 	int i;
386911106dfSjm199354 	char *violations[VS_MAX_VIOLATIONS];
387911106dfSjm199354 	char data[VS_MAX_VIOLATIONS][VS_DESCRIPTION_MAX];
388911106dfSjm199354 	adt_session_data_t *ah;
389911106dfSjm199354 	adt_termid_t *p_tid;
390911106dfSjm199354 	adt_event_data_t *event;
391911106dfSjm199354 
392911106dfSjm199354 	if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA)) {
393911106dfSjm199354 		syslog(LOG_AUTH | LOG_ALERT, "adt_start_session: %m");
394911106dfSjm199354 		return;
395911106dfSjm199354 	}
396911106dfSjm199354 
397911106dfSjm199354 	if (adt_load_ttyname("/dev/console", &p_tid) != 0) {
398911106dfSjm199354 		syslog(LOG_AUTH | LOG_ALERT,
399911106dfSjm199354 		    "adt_load_ttyname(/dev/console): %m");
400911106dfSjm199354 		return;
401911106dfSjm199354 	}
402911106dfSjm199354 
403911106dfSjm199354 	if (adt_set_user(ah, ADT_NO_ATTRIB, ADT_NO_ATTRIB, ADT_NO_ATTRIB,
404911106dfSjm199354 	    ADT_NO_ATTRIB, p_tid, ADT_NEW) != 0) {
405911106dfSjm199354 		syslog(LOG_AUTH | LOG_ALERT, "adt_set_user(ADT_NO_ATTRIB): %m");
406911106dfSjm199354 		(void) adt_end_session(ah);
407911106dfSjm199354 		return;
408911106dfSjm199354 	}
409911106dfSjm199354 
410911106dfSjm199354 	if ((event = adt_alloc_event(ah, ADT_vscan_quarantine)) == NULL) {
411911106dfSjm199354 		syslog(LOG_AUTH | LOG_ALERT,
412911106dfSjm199354 		    "adt_alloc_event(ADT_vscan_quarantine)): %m");
413911106dfSjm199354 		(void) adt_end_session(ah);
414911106dfSjm199354 		return;
415911106dfSjm199354 	}
416911106dfSjm199354 
417911106dfSjm199354 	/* populate vscan audit event */
418911106dfSjm199354 	event->adt_vscan_quarantine.file = filepath;
419911106dfSjm199354 	for (i = 0; i < result->vsr_nviolations; i++) {
420911106dfSjm199354 		(void) snprintf(data[i], VS_DESCRIPTION_MAX, "%d - %s",
421911106dfSjm199354 		    result->vsr_vrec[i].vr_id, result->vsr_vrec[i].vr_desc);
422911106dfSjm199354 		violations[i] = data[i];
423911106dfSjm199354 	}
424911106dfSjm199354 
425911106dfSjm199354 	event->adt_vscan_quarantine.violations = (char **)violations;
426911106dfSjm199354 	event->adt_vscan_quarantine.nviolations = result->vsr_nviolations;
427911106dfSjm199354 
428911106dfSjm199354 	if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS))
429911106dfSjm199354 		syslog(LOG_AUTH | LOG_ALERT, "adt_put_event: %m");
430911106dfSjm199354 
431911106dfSjm199354 	adt_free_event(event);
432911106dfSjm199354 	(void) adt_end_session(ah);
433911106dfSjm199354 }
434