xref: /onnv-gate/usr/src/cmd/vscan/vscand/vs_svc.c (revision 7228:a154d351c6f8)
15440Sjm199354 /*
25440Sjm199354  * CDDL HEADER START
35440Sjm199354  *
45440Sjm199354  * The contents of this file are subject to the terms of the
55440Sjm199354  * Common Development and Distribution License (the "License").
65440Sjm199354  * You may not use this file except in compliance with the License.
75440Sjm199354  *
85440Sjm199354  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95440Sjm199354  * or http://www.opensolaris.org/os/licensing.
105440Sjm199354  * See the License for the specific language governing permissions
115440Sjm199354  * and limitations under the License.
125440Sjm199354  *
135440Sjm199354  * When distributing Covered Code, include this CDDL HEADER in each
145440Sjm199354  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155440Sjm199354  * If applicable, add the following below this CDDL HEADER, with the
165440Sjm199354  * fields enclosed by brackets "[]" replaced with your own identifying
175440Sjm199354  * information: Portions Copyright [yyyy] [name of copyright owner]
185440Sjm199354  *
195440Sjm199354  * CDDL HEADER END
205440Sjm199354  */
215440Sjm199354 /*
225931Sjm199354  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
235440Sjm199354  * Use is subject to license terms.
245440Sjm199354  */
255440Sjm199354 
265440Sjm199354 #pragma ident	"%Z%%M%	%I%	%E% SMI"
275440Sjm199354 
285440Sjm199354 /*
295440Sjm199354  * Implementation of the "scan file" interface
305440Sjm199354  */
315440Sjm199354 
325440Sjm199354 #include <stdio.h>
335440Sjm199354 #include <stdlib.h>
345440Sjm199354 #include <unistd.h>
355440Sjm199354 #include <string.h>
365440Sjm199354 #include <errno.h>
375440Sjm199354 #include <syslog.h>
385440Sjm199354 #include <sys/types.h>
395440Sjm199354 #include <fcntl.h>
405440Sjm199354 #include <bsm/adt.h>
415440Sjm199354 #include <bsm/adt_event.h>
426407Sjm199354 #include <pthread.h>
435440Sjm199354 
445440Sjm199354 #include "vs_incl.h"
455440Sjm199354 
466407Sjm199354 /*
476407Sjm199354  * vs_svc_nodes - table of scan requests and their thread id and
486407Sjm199354  * scan engine context.
496407Sjm199354  * The table is sized by the value passed to vs_svc_init. This
506407Sjm199354  * value is obtained from the kernel and represents the maximum
516407Sjm199354  * request idx that the kernel will request vscand to process.
526407Sjm199354  * The table is indexed by the vsr_idx value passed in
536407Sjm199354  * the scan request - always non-zero. This value is also the index
546407Sjm199354  * into the kernel scan request table and identifies the instance of
556407Sjm199354  * the driver being used to access file data for the scan. Although
566407Sjm199354  * this is of no consequence here, it is useful information for debug.
576407Sjm199354  *
586407Sjm199354  * When a scan request is received a response is sent indicating
596407Sjm199354  * one of the following:
606407Sjm199354  * VS_STATUS_ERROR - an error occurred
616407Sjm199354  * VS_STATUS_NO_SCAN - no scan is required
626407Sjm199354  * VS_STATUS_SCANNING - request has been queued for async processing
636407Sjm199354  *
646407Sjm199354  * If the scan is required (VS_STATUS_SCANNING) a thread is created
656407Sjm199354  * to perform the scan. It's tid is saved in vs_svc_nodes.
666407Sjm199354  *
676407Sjm199354  * In the case of SHUTDOWN, vs_terminate requests that all scan
686407Sjm199354  * engine connections be closed, thus termintaing any in-progress
696407Sjm199354  * scans, then awaits completion of all scanning threads as identified
706407Sjm199354  * in vs_svc_nodes.
716407Sjm199354  */
726407Sjm199354 
736407Sjm199354 typedef struct vs_svc_node {
746407Sjm199354 	pthread_t vsn_tid;
756407Sjm199354 	vs_scan_req_t vsn_req;
766407Sjm199354 	vs_eng_ctx_t vsn_eng;
776407Sjm199354 } vs_svc_node_t;
786407Sjm199354 
796407Sjm199354 static vs_svc_node_t *vs_svc_nodes;
806407Sjm199354 static uint32_t vs_svc_max_node; /* max idx into vs_svc_nodes */
816407Sjm199354 static pthread_mutex_t vs_svc_mutex = PTHREAD_MUTEX_INITIALIZER;
826407Sjm199354 
836407Sjm199354 
845440Sjm199354 /* local functions */
856407Sjm199354 static void *vs_svc_async_scan(void *);
866407Sjm199354 static int vs_svc_scan_file(vs_svc_node_t *, vs_scanstamp_t *);
875440Sjm199354 static void vs_svc_vlog(char *, vs_result_t *);
885440Sjm199354 static void vs_svc_audit(char *, vs_result_t *);
895440Sjm199354 
906407Sjm199354 
915440Sjm199354 /*
925440Sjm199354  * vs_svc_init, vs_svc_fini
935440Sjm199354  *
945440Sjm199354  * Invoked on daemon load and unload
955440Sjm199354  */
966407Sjm199354 int
vs_svc_init(uint32_t max_req)976407Sjm199354 vs_svc_init(uint32_t max_req)
985440Sjm199354 {
996407Sjm199354 	vs_svc_max_node = max_req;
1006407Sjm199354 	vs_svc_nodes = (vs_svc_node_t *)
1016407Sjm199354 	    calloc(max_req + 1, sizeof (vs_svc_node_t));
1026407Sjm199354 
1036407Sjm199354 	return (vs_svc_nodes == NULL ? -1 : 0);
1045440Sjm199354 }
1055440Sjm199354 
1065440Sjm199354 void
vs_svc_fini()1075440Sjm199354 vs_svc_fini()
1085440Sjm199354 {
1096407Sjm199354 	if (vs_svc_nodes)
1106407Sjm199354 		free(vs_svc_nodes);
1116407Sjm199354 }
1126407Sjm199354 
1136407Sjm199354 
1146407Sjm199354 /*
1156407Sjm199354  * vs_svc_terminate
1166407Sjm199354  *
1176407Sjm199354  * Close all scan engine connections to terminate in-progress scan
1186407Sjm199354  * requests, and wait for all threads in vs_svc_nodes to complete
1196407Sjm199354  */
1206407Sjm199354 void
vs_svc_terminate()1216407Sjm199354 vs_svc_terminate()
1226407Sjm199354 {
1236407Sjm199354 	int i;
1246407Sjm199354 	pthread_t tid;
1256407Sjm199354 
1266407Sjm199354 	/* close connections to abort requests */
1276407Sjm199354 	vs_eng_close_connections();
1286407Sjm199354 
1296407Sjm199354 	/* wait for threads */
1306407Sjm199354 	for (i = 1; i <= vs_svc_max_node; i++) {
1316407Sjm199354 
1326407Sjm199354 		(void) pthread_mutex_lock(&vs_svc_mutex);
1336407Sjm199354 		tid = vs_svc_nodes[i].vsn_tid;
1346407Sjm199354 		(void) pthread_mutex_unlock(&vs_svc_mutex);
1356407Sjm199354 
1366407Sjm199354 		if (tid != 0)
1376407Sjm199354 			(void) pthread_join(tid, NULL);
1386407Sjm199354 	}
1396407Sjm199354 }
1406407Sjm199354 
1416407Sjm199354 
1426407Sjm199354 /*
1436407Sjm199354  * vs_svc_queue_scan_req
1446407Sjm199354  *
1456407Sjm199354  * Determine if the file needs to be scanned - either it has
1466407Sjm199354  * been modified or its scanstamp is not current.
1476407Sjm199354  * Initiate a thread to process the request, saving the tid
1486407Sjm199354  * in vs_svc_nodes[idx].vsn_tid, where idx is the vsr_idx passed in
1496407Sjm199354  * the scan request.
1506407Sjm199354  *
1516407Sjm199354  * Returns: VS_STATUS_ERROR - error
1526407Sjm199354  *          VS_STATUS_NO_SCAN - no scan required
1536407Sjm199354  *          VS_STATUS_SCANNING - async scan initiated
1546407Sjm199354  */
1556407Sjm199354 int
vs_svc_queue_scan_req(vs_scan_req_t * req)1566407Sjm199354 vs_svc_queue_scan_req(vs_scan_req_t *req)
1576407Sjm199354 {
1586407Sjm199354 	pthread_t tid;
1596407Sjm199354 	vs_svc_node_t *node;
1606407Sjm199354 
1616407Sjm199354 	/* No scan if file quarantined */
1626407Sjm199354 	if (req->vsr_quarantined)
1636407Sjm199354 		return (VS_STATUS_NO_SCAN);
1646407Sjm199354 
1656407Sjm199354 	/* No scan if file not modified AND scanstamp is current */
1666407Sjm199354 	if ((req->vsr_modified == 0) &&
1676407Sjm199354 	    vs_eng_scanstamp_current(req->vsr_scanstamp)) {
1686407Sjm199354 		return (VS_STATUS_NO_SCAN);
1696407Sjm199354 	}
1706407Sjm199354 
1716407Sjm199354 	/* scan required */
1726407Sjm199354 	node = &(vs_svc_nodes[req->vsr_idx]);
1736407Sjm199354 
1746407Sjm199354 	(void) pthread_mutex_lock(&vs_svc_mutex);
1756407Sjm199354 	if ((node->vsn_tid != 0) || (req->vsr_idx > vs_svc_max_node)) {
1766407Sjm199354 		(void) pthread_mutex_unlock(&vs_svc_mutex);
1776407Sjm199354 		return (VS_STATUS_ERROR);
1786407Sjm199354 	}
1796407Sjm199354 
1806407Sjm199354 	node->vsn_req = *req;
1816407Sjm199354 
1826407Sjm199354 	if (pthread_create(&tid, NULL, vs_svc_async_scan, (void *)node) != 0) {
1836407Sjm199354 		(void) pthread_mutex_unlock(&vs_svc_mutex);
1846407Sjm199354 		return (VS_STATUS_ERROR);
1856407Sjm199354 	}
1866407Sjm199354 
1876407Sjm199354 	node->vsn_tid = tid;
1886407Sjm199354 	(void) pthread_mutex_unlock(&vs_svc_mutex);
1896407Sjm199354 
1906407Sjm199354 	return (VS_STATUS_SCANNING);
1916407Sjm199354 }
1926407Sjm199354 
1936407Sjm199354 
1946407Sjm199354 /*
1956407Sjm199354  * vs_svc_async_scan
1966407Sjm199354  *
1976407Sjm199354  * Initialize response structure, invoke vs_svc_scan_file to
1986407Sjm199354  * perform the scan, then send the result to the kernel.
1996407Sjm199354  */
2006407Sjm199354 static void *
vs_svc_async_scan(void * arg)2016407Sjm199354 vs_svc_async_scan(void *arg)
2026407Sjm199354 {
2036407Sjm199354 	vs_svc_node_t *node = (vs_svc_node_t *)arg;
2046407Sjm199354 	vs_scan_req_t *scan_req = &(node->vsn_req);
2056407Sjm199354 	vs_scan_rsp_t scan_rsp;
2066407Sjm199354 
2076407Sjm199354 	scan_rsp.vsr_idx = scan_req->vsr_idx;
2086407Sjm199354 	scan_rsp.vsr_seqnum = scan_req->vsr_seqnum;
2096407Sjm199354 	scan_rsp.vsr_result = vs_svc_scan_file(node, &scan_rsp.vsr_scanstamp);
2106407Sjm199354 
2116407Sjm199354 	/* clear node and send async response to kernel */
2126407Sjm199354 	(void) pthread_mutex_lock(&vs_svc_mutex);
2136407Sjm199354 	(void) memset(node, 0, sizeof (vs_svc_node_t));
2146407Sjm199354 	(void) pthread_mutex_unlock(&vs_svc_mutex);
2156407Sjm199354 
2166407Sjm199354 	(void) vscand_kernel_result(&scan_rsp);
2176407Sjm199354 
2186407Sjm199354 	return (NULL);
2195440Sjm199354 }
2205440Sjm199354 
2215440Sjm199354 
2225440Sjm199354 /*
2235440Sjm199354  * vs_svc_scan_file
2245440Sjm199354  *
2255440Sjm199354  * vs_svc_scan_file is responsible for:
2265440Sjm199354  *  - obtaining & releasing a scan engine connection
2275440Sjm199354  *  - invoking the scan engine interface code to do the scan
2285440Sjm199354  *  - retrying a failed scan (up to VS_MAX_RETRY times)
2295440Sjm199354  *  - updating scan statistics
2305440Sjm199354  *  - logging virus information
2315440Sjm199354  *
2325931Sjm199354  *
2335440Sjm199354  * Returns:
2346407Sjm199354  *  VS_STATUS_NO_SCAN - scan not reqd; daemon shutting down
2355931Sjm199354  *  VS_STATUS_CLEAN - scan success. File clean.
2365931Sjm199354  *                    new scanstamp returned in scanstamp param.
2375931Sjm199354  *  VS_STATUS_INFECTED - scan success. File infected.
2385931Sjm199354  *  VS_STATUS_ERROR - scan failure either in vscand or scan engine.
2395440Sjm199354  */
2406407Sjm199354 static int
vs_svc_scan_file(vs_svc_node_t * node,vs_scanstamp_t * scanstamp)2416407Sjm199354 vs_svc_scan_file(vs_svc_node_t *node, vs_scanstamp_t *scanstamp)
2425440Sjm199354 {
2436407Sjm199354 	char devname[MAXPATHLEN];
2446407Sjm199354 	int flags = 0;
2455931Sjm199354 	int retries;
2465440Sjm199354 	vs_result_t result;
2476407Sjm199354 	vs_scan_req_t *req = &(node->vsn_req);
2486407Sjm199354 	vs_eng_ctx_t *eng = &(node->vsn_eng);
2496407Sjm199354 
2506407Sjm199354 	(void) snprintf(devname, MAXPATHLEN, "%s%d", VS_DRV_PATH, req->vsr_idx);
2515440Sjm199354 
2525931Sjm199354 	/* initialize response scanstamp to current scanstamp value */
2536407Sjm199354 	(void) strlcpy(*scanstamp, req->vsr_scanstamp, sizeof (vs_scanstamp_t));
2545440Sjm199354 
2555440Sjm199354 	(void) memset(&result, 0, sizeof (vs_result_t));
2565440Sjm199354 	result.vsr_rc = VS_RESULT_UNDEFINED;
2575440Sjm199354 
2585440Sjm199354 	for (retries = 0; retries <= VS_MAX_RETRY; retries++) {
2596407Sjm199354 		/* get engine connection */
2606407Sjm199354 		if (vs_eng_get(eng, (retries != 0)) != 0) {
2615931Sjm199354 			result.vsr_rc = VS_RESULT_ERROR;
2625440Sjm199354 			continue;
2635440Sjm199354 		}
2645440Sjm199354 
2656407Sjm199354 		/* shutdown could occur while waiting for engine connection */
2666407Sjm199354 		if (vscand_get_state() == VS_STATE_SHUTDOWN) {
2676407Sjm199354 			vs_eng_release(eng);
2686407Sjm199354 			return (VS_STATUS_NO_SCAN);
2696407Sjm199354 		}
2705440Sjm199354 
2716407Sjm199354 		/* scan file */
2726407Sjm199354 		(void) vs_icap_scan_file(eng, devname, req->vsr_path,
2736407Sjm199354 		    req->vsr_size, flags, &result);
2745440Sjm199354 
2755440Sjm199354 		/* if no error, clear error state on engine and break */
2765931Sjm199354 		if ((result.vsr_rc != VS_RESULT_SE_ERROR) &&
2775931Sjm199354 		    (result.vsr_rc != VS_RESULT_ERROR)) {
2786407Sjm199354 			vs_eng_set_error(eng, 0);
2796407Sjm199354 			vs_eng_release(eng);
2805440Sjm199354 			break;
2815440Sjm199354 		}
2825440Sjm199354 
2835931Sjm199354 		/* treat error on shutdown as scan not required */
2845440Sjm199354 		if (vscand_get_state() == VS_STATE_SHUTDOWN) {
2856407Sjm199354 			vs_eng_release(eng);
2865931Sjm199354 			return (VS_STATUS_NO_SCAN);
2875440Sjm199354 		}
2885440Sjm199354 
2895440Sjm199354 		/* set engine's error state and update engine stats */
2906407Sjm199354 		if (result.vsr_rc == VS_RESULT_SE_ERROR)
2916407Sjm199354 			vs_eng_set_error(eng, 1);
2926407Sjm199354 
2936407Sjm199354 		vs_eng_release(eng);
2945440Sjm199354 	}
2955440Sjm199354 
2965931Sjm199354 	vs_stats_set(result.vsr_rc);
2975440Sjm199354 
2985931Sjm199354 	/*
2995931Sjm199354 	 * VS_RESULT_CLEANED - file infected, cleaned data available
3005931Sjm199354 	 * VS_RESULT_FORBIDDEN - file infected, no cleaned data
3015931Sjm199354 	 * Log virus, write audit record and return INFECTED status
3025931Sjm199354 	 */
3035440Sjm199354 	if (result.vsr_rc == VS_RESULT_CLEANED ||
3045440Sjm199354 	    result.vsr_rc == VS_RESULT_FORBIDDEN) {
3056407Sjm199354 		vs_svc_vlog(req->vsr_path, &result);
3066407Sjm199354 		vs_svc_audit(req->vsr_path, &result);
3075931Sjm199354 		return (VS_STATUS_INFECTED);
3085440Sjm199354 	}
3095440Sjm199354 
3105931Sjm199354 	/* VS_RESULT_CLEAN - Set the scanstamp and return CLEAN status */
3115931Sjm199354 	if (result.vsr_rc == VS_RESULT_CLEAN) {
3125931Sjm199354 		(void) strlcpy(*scanstamp, result.vsr_scanstamp,
3135440Sjm199354 		    sizeof (vs_scanstamp_t));
3145931Sjm199354 		return (VS_STATUS_CLEAN);
3155440Sjm199354 	}
3165440Sjm199354 
3175931Sjm199354 	return (VS_STATUS_ERROR);
3185440Sjm199354 }
3195440Sjm199354 
3205440Sjm199354 
3215440Sjm199354 /*
3225440Sjm199354  * vs_svc_vlog
3235440Sjm199354  *
3246407Sjm199354  * log details of infections detected in syslig
3256407Sjm199354  * If virus log is configured log details there too
3265440Sjm199354  */
3275440Sjm199354 static void
vs_svc_vlog(char * filepath,vs_result_t * result)3285440Sjm199354 vs_svc_vlog(char *filepath, vs_result_t *result)
3295440Sjm199354 {
3305440Sjm199354 	FILE *fp = NULL;
3315440Sjm199354 	time_t sec;
3325440Sjm199354 	struct tm *timestamp;
3335440Sjm199354 	char timebuf[18]; /* MM/DD/YY hh:mm:ss */
3345440Sjm199354 	int i;
3355440Sjm199354 	char *log;
3365440Sjm199354 
3376407Sjm199354 	/* syslog */
3385440Sjm199354 	if (result->vsr_nviolations == 0) {
339*7228Sjm199354 		syslog(LOG_NOTICE, "quarantine %s\n", filepath);
3405440Sjm199354 	} else {
3415440Sjm199354 		for (i = 0; i < result->vsr_nviolations; i++) {
342*7228Sjm199354 			syslog(LOG_NOTICE, "quarantine %s %d - %s\n",
3436407Sjm199354 			    filepath,
3446407Sjm199354 			    result->vsr_vrec[i].vr_id,
3456407Sjm199354 			    result->vsr_vrec[i].vr_desc);
3465440Sjm199354 		}
3475440Sjm199354 	}
3485440Sjm199354 
3496407Sjm199354 	/* log file */
3506407Sjm199354 	if (((log = vscand_viruslog()) == NULL) ||
3516407Sjm199354 	    ((fp = fopen(log, "a")) == NULL)) {
3526407Sjm199354 		return;
3536407Sjm199354 	}
3546407Sjm199354 
3556407Sjm199354 	(void) time(&sec);
3566407Sjm199354 	timestamp = localtime(&sec);
3576407Sjm199354 	(void) strftime(timebuf, sizeof (timebuf), "%D %T", timestamp);
3586407Sjm199354 
3596407Sjm199354 	if (result->vsr_nviolations == 0) {
3606407Sjm199354 		(void) fprintf(fp, "%s quarantine %d[%s]\n",
3616407Sjm199354 		    timebuf, strlen(filepath), filepath);
3626407Sjm199354 	} else {
3636407Sjm199354 		for (i = 0; i < result->vsr_nviolations; i++) {
3646407Sjm199354 			(void) fprintf(fp, "%s quarantine %d[%s] %d - %d[%s]\n",
3656407Sjm199354 			    timebuf, strlen(filepath), filepath,
3666407Sjm199354 			    result->vsr_vrec[i].vr_id,
3676407Sjm199354 			    strlen(result->vsr_vrec[i].vr_desc),
3686407Sjm199354 			    result->vsr_vrec[i].vr_desc);
3696407Sjm199354 		}
3706407Sjm199354 	}
3716407Sjm199354 
3726407Sjm199354 	(void) fclose(fp);
3735440Sjm199354 }
3745440Sjm199354 
3755440Sjm199354 
3765440Sjm199354 /*
3775440Sjm199354  * vs_svc_audit
3785440Sjm199354  *
3795440Sjm199354  * Generate AUE_vscan_quarantine audit record containing name
3805440Sjm199354  * of infected file, and violation details if available.
3815440Sjm199354  */
3825440Sjm199354 static void
vs_svc_audit(char * filepath,vs_result_t * result)3835440Sjm199354 vs_svc_audit(char *filepath, vs_result_t *result)
3845440Sjm199354 {
3855440Sjm199354 	int i;
3865440Sjm199354 	char *violations[VS_MAX_VIOLATIONS];
3875440Sjm199354 	char data[VS_MAX_VIOLATIONS][VS_DESCRIPTION_MAX];
3885440Sjm199354 	adt_session_data_t *ah;
3895440Sjm199354 	adt_termid_t *p_tid;
3905440Sjm199354 	adt_event_data_t *event;
3915440Sjm199354 
3925440Sjm199354 	if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA)) {
3935440Sjm199354 		syslog(LOG_AUTH | LOG_ALERT, "adt_start_session: %m");
3945440Sjm199354 		return;
3955440Sjm199354 	}
3965440Sjm199354 
3975440Sjm199354 	if (adt_load_ttyname("/dev/console", &p_tid) != 0) {
3985440Sjm199354 		syslog(LOG_AUTH | LOG_ALERT,
3995440Sjm199354 		    "adt_load_ttyname(/dev/console): %m");
4005440Sjm199354 		return;
4015440Sjm199354 	}
4025440Sjm199354 
4035440Sjm199354 	if (adt_set_user(ah, ADT_NO_ATTRIB, ADT_NO_ATTRIB, ADT_NO_ATTRIB,
4045440Sjm199354 	    ADT_NO_ATTRIB, p_tid, ADT_NEW) != 0) {
4055440Sjm199354 		syslog(LOG_AUTH | LOG_ALERT, "adt_set_user(ADT_NO_ATTRIB): %m");
4065440Sjm199354 		(void) adt_end_session(ah);
4075440Sjm199354 		return;
4085440Sjm199354 	}
4095440Sjm199354 
4105440Sjm199354 	if ((event = adt_alloc_event(ah, ADT_vscan_quarantine)) == NULL) {
4115440Sjm199354 		syslog(LOG_AUTH | LOG_ALERT,
4125440Sjm199354 		    "adt_alloc_event(ADT_vscan_quarantine)): %m");
4135440Sjm199354 		(void) adt_end_session(ah);
4145440Sjm199354 		return;
4155440Sjm199354 	}
4165440Sjm199354 
4175440Sjm199354 	/* populate vscan audit event */
4185440Sjm199354 	event->adt_vscan_quarantine.file = filepath;
4195440Sjm199354 	for (i = 0; i < result->vsr_nviolations; i++) {
4205440Sjm199354 		(void) snprintf(data[i], VS_DESCRIPTION_MAX, "%d - %s",
4215440Sjm199354 		    result->vsr_vrec[i].vr_id, result->vsr_vrec[i].vr_desc);
4225440Sjm199354 		violations[i] = data[i];
4235440Sjm199354 	}
4245440Sjm199354 
4255440Sjm199354 	event->adt_vscan_quarantine.violations = (char **)violations;
4265440Sjm199354 	event->adt_vscan_quarantine.nviolations = result->vsr_nviolations;
4275440Sjm199354 
4285440Sjm199354 	if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS))
4295440Sjm199354 		syslog(LOG_AUTH | LOG_ALERT, "adt_put_event: %m");
4305440Sjm199354 
4315440Sjm199354 	adt_free_event(event);
4325440Sjm199354 	(void) adt_end_session(ah);
4335440Sjm199354 }
434