xref: /freebsd/contrib/openbsm/libbsm/bsm_audit.c (revision b626f5a73a48f44a31a200291b141e1da408a2ff)
152267f74SRobert Watson /*-
252267f74SRobert Watson  * Copyright (c) 2004 Apple Inc.
3ca0716f5SRobert Watson  * Copyright (c) 2005 SPARTA, Inc.
4ca0716f5SRobert Watson  * All rights reserved.
5ca0716f5SRobert Watson  *
6ca0716f5SRobert Watson  * This code was developed in part by Robert N. M. Watson, Senior Principal
7ca0716f5SRobert Watson  * Scientist, SPARTA, Inc.
8ca0716f5SRobert Watson  *
9ca0716f5SRobert Watson  * Redistribution and use in source and binary forms, with or without
10ca0716f5SRobert Watson  * modification, are permitted provided that the following conditions
11ca0716f5SRobert Watson  * are met:
12ca0716f5SRobert Watson  * 1.  Redistributions of source code must retain the above copyright
13ca0716f5SRobert Watson  *     notice, this list of conditions and the following disclaimer.
14ca0716f5SRobert Watson  * 2.  Redistributions in binary form must reproduce the above copyright
15ca0716f5SRobert Watson  *     notice, this list of conditions and the following disclaimer in the
16ca0716f5SRobert Watson  *     documentation and/or other materials provided with the distribution.
17*aa772005SRobert Watson  * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
18ca0716f5SRobert Watson  *     its contributors may be used to endorse or promote products derived
19ca0716f5SRobert Watson  *     from this software without specific prior written permission.
20ca0716f5SRobert Watson  *
21ca0716f5SRobert Watson  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
22ca0716f5SRobert Watson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23ca0716f5SRobert Watson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24ca0716f5SRobert Watson  * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
25ca0716f5SRobert Watson  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26ca0716f5SRobert Watson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27ca0716f5SRobert Watson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28ca0716f5SRobert Watson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29ca0716f5SRobert Watson  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30ca0716f5SRobert Watson  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31ca0716f5SRobert Watson  * POSSIBILITY OF SUCH DAMAGE.
32ca0716f5SRobert Watson  */
33ca0716f5SRobert Watson 
34ca0716f5SRobert Watson #include <sys/types.h>
353b97a967SRobert Watson 
363b97a967SRobert Watson #include <config/config.h>
373b97a967SRobert Watson #ifdef HAVE_FULL_QUEUE_H
38ca0716f5SRobert Watson #include <sys/queue.h>
393b97a967SRobert Watson #else
403b97a967SRobert Watson #include <compat/queue.h>
413b97a967SRobert Watson #endif
42ca0716f5SRobert Watson 
43ca0716f5SRobert Watson #include <bsm/audit_internal.h>
44ca0716f5SRobert Watson #include <bsm/libbsm.h>
45ca0716f5SRobert Watson 
4652267f74SRobert Watson #include <netinet/in.h>
4752267f74SRobert Watson 
48ca0716f5SRobert Watson #include <errno.h>
497a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
50ca0716f5SRobert Watson #include <pthread.h>
517a0a89d2SRobert Watson #endif
52ca0716f5SRobert Watson #include <stdlib.h>
53ca0716f5SRobert Watson #include <string.h>
54ca0716f5SRobert Watson 
55ca0716f5SRobert Watson /* array of used descriptors */
56ca0716f5SRobert Watson static au_record_t	*open_desc_table[MAX_AUDIT_RECORDS];
57ca0716f5SRobert Watson 
58ca0716f5SRobert Watson /* The current number of active record descriptors */
5922ccb20dSRobert Watson static int	audit_rec_count = 0;
60ca0716f5SRobert Watson 
61ca0716f5SRobert Watson /*
62ca0716f5SRobert Watson  * Records that can be recycled are maintained in the list given below.  The
63ca0716f5SRobert Watson  * maximum number of elements that can be present in this list is bounded by
64ca0716f5SRobert Watson  * MAX_AUDIT_RECORDS.  Memory allocated for these records are never freed.
65ca0716f5SRobert Watson  */
6622ccb20dSRobert Watson static LIST_HEAD(, au_record)	audit_free_q;
67ca0716f5SRobert Watson 
687a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
69ca0716f5SRobert Watson static pthread_mutex_t	mutex = PTHREAD_MUTEX_INITIALIZER;
707a0a89d2SRobert Watson #endif
71ca0716f5SRobert Watson 
72ca0716f5SRobert Watson /*
73ca0716f5SRobert Watson  * This call frees a token_t and its internal data.
74ca0716f5SRobert Watson  */
75ca0716f5SRobert Watson void
au_free_token(token_t * tok)76ca0716f5SRobert Watson au_free_token(token_t *tok)
77ca0716f5SRobert Watson {
78ca0716f5SRobert Watson 
79ca0716f5SRobert Watson 	if (tok != NULL) {
80ca0716f5SRobert Watson 		if (tok->t_data)
81ca0716f5SRobert Watson 			free(tok->t_data);
82ca0716f5SRobert Watson 		free(tok);
83ca0716f5SRobert Watson 	}
84ca0716f5SRobert Watson }
85ca0716f5SRobert Watson 
86ca0716f5SRobert Watson /*
87ca0716f5SRobert Watson  * This call reserves memory for the audit record.  Memory must be guaranteed
88ca0716f5SRobert Watson  * before any auditable event can be generated.  The au_record_t structure
89ca0716f5SRobert Watson  * maintains a reference to the memory allocated above and also the list of
90ca0716f5SRobert Watson  * tokens associated with this record.  Descriptors are recyled once the
91ca0716f5SRobert Watson  * records are added to the audit trail following au_close().
92ca0716f5SRobert Watson  */
93ca0716f5SRobert Watson int
au_open(void)94ca0716f5SRobert Watson au_open(void)
95ca0716f5SRobert Watson {
96ca0716f5SRobert Watson 	au_record_t *rec = NULL;
97ca0716f5SRobert Watson 
987a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
99ca0716f5SRobert Watson 	pthread_mutex_lock(&mutex);
1007a0a89d2SRobert Watson #endif
101ca0716f5SRobert Watson 
10222ccb20dSRobert Watson 	if (audit_rec_count == 0)
10322ccb20dSRobert Watson 		LIST_INIT(&audit_free_q);
104ca0716f5SRobert Watson 
105ca0716f5SRobert Watson 	/*
106ca0716f5SRobert Watson 	 * Find an unused descriptor, remove it from the free list, mark as
107ca0716f5SRobert Watson 	 * used.
108ca0716f5SRobert Watson 	 */
10922ccb20dSRobert Watson 	if (!LIST_EMPTY(&audit_free_q)) {
11022ccb20dSRobert Watson 		rec = LIST_FIRST(&audit_free_q);
111ca0716f5SRobert Watson 		rec->used = 1;
112ca0716f5SRobert Watson 		LIST_REMOVE(rec, au_rec_q);
113ca0716f5SRobert Watson 	}
114ca0716f5SRobert Watson 
1157a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
116ca0716f5SRobert Watson 	pthread_mutex_unlock(&mutex);
1177a0a89d2SRobert Watson #endif
118ca0716f5SRobert Watson 
119ca0716f5SRobert Watson 	if (rec == NULL) {
120ca0716f5SRobert Watson 		/*
121ca0716f5SRobert Watson 		 * Create a new au_record_t if no descriptors are available.
122ca0716f5SRobert Watson 		 */
123ca0716f5SRobert Watson 		rec = malloc (sizeof(au_record_t));
124ca0716f5SRobert Watson 		if (rec == NULL)
125ca0716f5SRobert Watson 			return (-1);
126ca0716f5SRobert Watson 
127ca0716f5SRobert Watson 		rec->data = malloc (MAX_AUDIT_RECORD_SIZE * sizeof(u_char));
128ca0716f5SRobert Watson 		if (rec->data == NULL) {
129ca0716f5SRobert Watson 			free(rec);
130ca0716f5SRobert Watson 			errno = ENOMEM;
131ca0716f5SRobert Watson 			return (-1);
132ca0716f5SRobert Watson 		}
133ca0716f5SRobert Watson 
1347a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
135ca0716f5SRobert Watson 		pthread_mutex_lock(&mutex);
1367a0a89d2SRobert Watson #endif
137ca0716f5SRobert Watson 
13822ccb20dSRobert Watson 		if (audit_rec_count == MAX_AUDIT_RECORDS) {
1397a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
140ca0716f5SRobert Watson 			pthread_mutex_unlock(&mutex);
1417a0a89d2SRobert Watson #endif
142ca0716f5SRobert Watson 			free(rec->data);
143ca0716f5SRobert Watson 			free(rec);
144ca0716f5SRobert Watson 
145ca0716f5SRobert Watson 			/* XXX We need to increase size of MAX_AUDIT_RECORDS */
146ca0716f5SRobert Watson 			errno = ENOMEM;
147ca0716f5SRobert Watson 			return (-1);
148ca0716f5SRobert Watson 		}
14922ccb20dSRobert Watson 		rec->desc = audit_rec_count;
15022ccb20dSRobert Watson 		open_desc_table[audit_rec_count] = rec;
15122ccb20dSRobert Watson 		audit_rec_count++;
152ca0716f5SRobert Watson 
1537a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
154ca0716f5SRobert Watson 		pthread_mutex_unlock(&mutex);
1557a0a89d2SRobert Watson #endif
156ca0716f5SRobert Watson 
157ca0716f5SRobert Watson 	}
158ca0716f5SRobert Watson 
159ca0716f5SRobert Watson 	memset(rec->data, 0, MAX_AUDIT_RECORD_SIZE);
160ca0716f5SRobert Watson 
161ca0716f5SRobert Watson 	TAILQ_INIT(&rec->token_q);
162ca0716f5SRobert Watson 	rec->len = 0;
163ca0716f5SRobert Watson 	rec->used = 1;
164ca0716f5SRobert Watson 
165ca0716f5SRobert Watson 	return (rec->desc);
166ca0716f5SRobert Watson }
167ca0716f5SRobert Watson 
168ca0716f5SRobert Watson /*
169ca0716f5SRobert Watson  * Store the token with the record descriptor.
170ca0716f5SRobert Watson  *
171ca0716f5SRobert Watson  * Don't permit writing more to the buffer than would let the trailer be
172ca0716f5SRobert Watson  * appended later.
173ca0716f5SRobert Watson  */
174ca0716f5SRobert Watson int
au_write(int d,token_t * tok)175ca0716f5SRobert Watson au_write(int d, token_t *tok)
176ca0716f5SRobert Watson {
177ca0716f5SRobert Watson 	au_record_t *rec;
178ca0716f5SRobert Watson 
179ca0716f5SRobert Watson 	if (tok == NULL) {
180ca0716f5SRobert Watson 		errno = EINVAL;
181ca0716f5SRobert Watson 		return (-1); /* Invalid Token */
182ca0716f5SRobert Watson 	}
183ca0716f5SRobert Watson 
184ca0716f5SRobert Watson 	/* Write the token to the record descriptor */
185ca0716f5SRobert Watson 	rec = open_desc_table[d];
186ca0716f5SRobert Watson 	if ((rec == NULL) || (rec->used == 0)) {
187ca0716f5SRobert Watson 		errno = EINVAL;
188ca0716f5SRobert Watson 		return (-1); /* Invalid descriptor */
189ca0716f5SRobert Watson 	}
190ca0716f5SRobert Watson 
19122ccb20dSRobert Watson 	if (rec->len + tok->len + AUDIT_TRAILER_SIZE > MAX_AUDIT_RECORD_SIZE) {
192ca0716f5SRobert Watson 		errno = ENOMEM;
193ca0716f5SRobert Watson 		return (-1);
194ca0716f5SRobert Watson 	}
195ca0716f5SRobert Watson 
196ca0716f5SRobert Watson 	/* Add the token to the tail */
197ca0716f5SRobert Watson 	/*
198ca0716f5SRobert Watson 	 * XXX Not locking here -- we should not be writing to
199ca0716f5SRobert Watson 	 * XXX the same descriptor from different threads
200ca0716f5SRobert Watson 	 */
201ca0716f5SRobert Watson 	TAILQ_INSERT_TAIL(&rec->token_q, tok, tokens);
202ca0716f5SRobert Watson 
203ca0716f5SRobert Watson 	rec->len += tok->len; /* grow record length by token size bytes */
204ca0716f5SRobert Watson 
205ca0716f5SRobert Watson 	/* Token should not be available after this call */
206ca0716f5SRobert Watson 	tok = NULL;
207ca0716f5SRobert Watson 	return (0); /* Success */
208ca0716f5SRobert Watson }
209ca0716f5SRobert Watson 
210ca0716f5SRobert Watson /*
211ca0716f5SRobert Watson  * Assemble an audit record out of its tokens, including allocating header and
212ca0716f5SRobert Watson  * trailer tokens.  Does not free the token chain, which must be done by the
213ca0716f5SRobert Watson  * caller if desirable.
214ca0716f5SRobert Watson  *
215ca0716f5SRobert Watson  * XXX: Assumes there is sufficient space for the header and trailer.
216ca0716f5SRobert Watson  */
217ca0716f5SRobert Watson static int
au_assemble(au_record_t * rec,short event)218ca0716f5SRobert Watson au_assemble(au_record_t *rec, short event)
219ca0716f5SRobert Watson {
220c74c7b73SRobert Watson #ifdef HAVE_AUDIT_SYSCALLS
22152267f74SRobert Watson 	struct in6_addr *aptr;
22252267f74SRobert Watson 	struct auditinfo_addr aia;
22352267f74SRobert Watson 	struct timeval tm;
224c74c7b73SRobert Watson 	size_t hdrsize;
225c74c7b73SRobert Watson #endif /* HAVE_AUDIT_SYSCALLS */
226c74c7b73SRobert Watson 	token_t *header, *tok, *trailer;
227c74c7b73SRobert Watson 	size_t tot_rec_size;
228c74c7b73SRobert Watson 	u_char *dptr;
229c74c7b73SRobert Watson 	int error;
230ca0716f5SRobert Watson 
23152267f74SRobert Watson #ifdef HAVE_AUDIT_SYSCALLS
23252267f74SRobert Watson 	/*
23352267f74SRobert Watson 	 * Grab the size of the address family stored in the kernel's audit
23452267f74SRobert Watson 	 * state.
23552267f74SRobert Watson 	 */
23652267f74SRobert Watson 	aia.ai_termid.at_type = AU_IPv4;
23752267f74SRobert Watson 	aia.ai_termid.at_addr[0] = INADDR_ANY;
238c0020399SRobert Watson 	if (audit_get_kaudit(&aia, sizeof(aia)) != 0) {
2397a0a89d2SRobert Watson 		if (errno != ENOSYS && errno != EPERM)
24052267f74SRobert Watson 			return (-1);
24152267f74SRobert Watson #endif /* HAVE_AUDIT_SYSCALLS */
24252267f74SRobert Watson 		tot_rec_size = rec->len + AUDIT_HEADER_SIZE +
24352267f74SRobert Watson 		    AUDIT_TRAILER_SIZE;
24452267f74SRobert Watson 		header = au_to_header(tot_rec_size, event, 0);
24552267f74SRobert Watson #ifdef HAVE_AUDIT_SYSCALLS
24652267f74SRobert Watson 	} else {
24752267f74SRobert Watson 		if (gettimeofday(&tm, NULL) < 0)
24852267f74SRobert Watson 			return (-1);
24952267f74SRobert Watson 		switch (aia.ai_termid.at_type) {
25052267f74SRobert Watson 		case AU_IPv4:
25152267f74SRobert Watson 			hdrsize = (aia.ai_termid.at_addr[0] == INADDR_ANY) ?
25252267f74SRobert Watson 			    AUDIT_HEADER_SIZE : AUDIT_HEADER_EX_SIZE(&aia);
25352267f74SRobert Watson 			break;
25452267f74SRobert Watson 		case AU_IPv6:
25552267f74SRobert Watson 			aptr = (struct in6_addr *)&aia.ai_termid.at_addr[0];
25652267f74SRobert Watson 			hdrsize =
25752267f74SRobert Watson 			    (IN6_IS_ADDR_UNSPECIFIED(aptr)) ?
25852267f74SRobert Watson 			    AUDIT_HEADER_SIZE : AUDIT_HEADER_EX_SIZE(&aia);
25952267f74SRobert Watson 			break;
2607a0a89d2SRobert Watson 		default:
2617a0a89d2SRobert Watson 			return (-1);
26252267f74SRobert Watson 		}
26352267f74SRobert Watson 		tot_rec_size = rec->len + hdrsize + AUDIT_TRAILER_SIZE;
26452267f74SRobert Watson 		/*
26552267f74SRobert Watson 		 * A header size greater then AUDIT_HEADER_SIZE means
26652267f74SRobert Watson 		 * that we are using an extended header.
26752267f74SRobert Watson 		 */
26852267f74SRobert Watson 		if (hdrsize > AUDIT_HEADER_SIZE)
26952267f74SRobert Watson 			header = au_to_header32_ex_tm(tot_rec_size, event,
27052267f74SRobert Watson 			    0, tm, &aia);
27152267f74SRobert Watson 		else
27252267f74SRobert Watson 			header = au_to_header(tot_rec_size, event, 0);
27352267f74SRobert Watson 	}
27452267f74SRobert Watson #endif /* HAVE_AUDIT_SYSCALLS */
275ca0716f5SRobert Watson 	if (header == NULL)
276ca0716f5SRobert Watson 		return (-1);
277ca0716f5SRobert Watson 
278ca0716f5SRobert Watson 	trailer = au_to_trailer(tot_rec_size);
279ca0716f5SRobert Watson 	if (trailer == NULL) {
280ca0716f5SRobert Watson 		error = errno;
281ca0716f5SRobert Watson 		au_free_token(header);
282ca0716f5SRobert Watson 		errno = error;
283ca0716f5SRobert Watson 		return (-1);
284ca0716f5SRobert Watson 	}
285ca0716f5SRobert Watson 
286ca0716f5SRobert Watson 	TAILQ_INSERT_HEAD(&rec->token_q, header, tokens);
287ca0716f5SRobert Watson 	TAILQ_INSERT_TAIL(&rec->token_q, trailer, tokens);
288ca0716f5SRobert Watson 
289ca0716f5SRobert Watson 	rec->len = tot_rec_size;
290ca0716f5SRobert Watson 	dptr = rec->data;
291ca0716f5SRobert Watson 
292ca0716f5SRobert Watson 	TAILQ_FOREACH(tok, &rec->token_q, tokens) {
293ca0716f5SRobert Watson 		memcpy(dptr, tok->t_data, tok->len);
294ca0716f5SRobert Watson 		dptr += tok->len;
295ca0716f5SRobert Watson 	}
296ca0716f5SRobert Watson 
297ca0716f5SRobert Watson 	return (0);
298ca0716f5SRobert Watson }
299ca0716f5SRobert Watson 
300ca0716f5SRobert Watson /*
301ca0716f5SRobert Watson  * Given a record that is no longer of interest, tear it down and convert to a
302ca0716f5SRobert Watson  * free record.
303ca0716f5SRobert Watson  */
304ca0716f5SRobert Watson static void
au_teardown(au_record_t * rec)305ca0716f5SRobert Watson au_teardown(au_record_t *rec)
306ca0716f5SRobert Watson {
307ca0716f5SRobert Watson 	token_t *tok;
308ca0716f5SRobert Watson 
309ca0716f5SRobert Watson 	/* Free the token list */
310ca0716f5SRobert Watson 	while ((tok = TAILQ_FIRST(&rec->token_q)) != NULL) {
311ca0716f5SRobert Watson 		TAILQ_REMOVE(&rec->token_q, tok, tokens);
312ca0716f5SRobert Watson 		free(tok->t_data);
313ca0716f5SRobert Watson 		free(tok);
314ca0716f5SRobert Watson 	}
315ca0716f5SRobert Watson 
316ca0716f5SRobert Watson 	rec->used = 0;
317ca0716f5SRobert Watson 	rec->len = 0;
318ca0716f5SRobert Watson 
3197a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
320ca0716f5SRobert Watson 	pthread_mutex_lock(&mutex);
3217a0a89d2SRobert Watson #endif
322ca0716f5SRobert Watson 
323ca0716f5SRobert Watson 	/* Add the record to the freelist tail */
32422ccb20dSRobert Watson 	LIST_INSERT_HEAD(&audit_free_q, rec, au_rec_q);
325ca0716f5SRobert Watson 
3267a0a89d2SRobert Watson #ifdef HAVE_PTHREAD_MUTEX_LOCK
327ca0716f5SRobert Watson 	pthread_mutex_unlock(&mutex);
3287a0a89d2SRobert Watson #endif
329ca0716f5SRobert Watson }
330ca0716f5SRobert Watson 
3313b97a967SRobert Watson #ifdef HAVE_AUDIT_SYSCALLS
332ca0716f5SRobert Watson /*
333ca0716f5SRobert Watson  * Add the header token, identify any missing tokens.  Write out the tokens to
334ca0716f5SRobert Watson  * the record memory and finally, call audit.
335ca0716f5SRobert Watson  */
3363b97a967SRobert Watson int
au_close(int d,int keep,short event)3373b97a967SRobert Watson au_close(int d, int keep, short event)
338ca0716f5SRobert Watson {
339ca0716f5SRobert Watson 	au_record_t *rec;
340ca0716f5SRobert Watson 	size_t tot_rec_size;
341ca0716f5SRobert Watson 	int retval = 0;
342ca0716f5SRobert Watson 
343ca0716f5SRobert Watson 	rec = open_desc_table[d];
344ca0716f5SRobert Watson 	if ((rec == NULL) || (rec->used == 0)) {
345ca0716f5SRobert Watson 		errno = EINVAL;
346ca0716f5SRobert Watson 		return (-1); /* Invalid descriptor */
347ca0716f5SRobert Watson 	}
348ca0716f5SRobert Watson 
349506764c6SRobert Watson 	if (keep == AU_TO_NO_WRITE) {
350ca0716f5SRobert Watson 		retval = 0;
351ca0716f5SRobert Watson 		goto cleanup;
352ca0716f5SRobert Watson 	}
353ca0716f5SRobert Watson 
35452267f74SRobert Watson 	tot_rec_size = rec->len + MAX_AUDIT_HEADER_SIZE + AUDIT_TRAILER_SIZE;
355ca0716f5SRobert Watson 
356ca0716f5SRobert Watson 	if (tot_rec_size > MAX_AUDIT_RECORD_SIZE) {
357ca0716f5SRobert Watson 		/*
358ca0716f5SRobert Watson 		 * XXXRW: Since au_write() is supposed to prevent this, spew
359ca0716f5SRobert Watson 		 * an error here.
360ca0716f5SRobert Watson 		 */
361ca0716f5SRobert Watson 		fprintf(stderr, "au_close failed");
362ca0716f5SRobert Watson 		errno = ENOMEM;
363ca0716f5SRobert Watson 		retval = -1;
364ca0716f5SRobert Watson 		goto cleanup;
365ca0716f5SRobert Watson 	}
366ca0716f5SRobert Watson 
367ca0716f5SRobert Watson 	if (au_assemble(rec, event) < 0) {
368ca0716f5SRobert Watson 		/*
369ca0716f5SRobert Watson 		 * XXXRW: This is also not supposed to happen, but might if we
370ca0716f5SRobert Watson 		 * are unable to allocate header and trailer memory.
371ca0716f5SRobert Watson 		 */
372ca0716f5SRobert Watson 		retval = -1;
373ca0716f5SRobert Watson 		goto cleanup;
374ca0716f5SRobert Watson 	}
375ca0716f5SRobert Watson 
376ca0716f5SRobert Watson 	/* Call the kernel interface to audit */
377ca0716f5SRobert Watson 	retval = audit(rec->data, rec->len);
378ca0716f5SRobert Watson 
379ca0716f5SRobert Watson cleanup:
380ca0716f5SRobert Watson 	/* CLEANUP */
381ca0716f5SRobert Watson 	au_teardown(rec);
382ca0716f5SRobert Watson 	return (retval);
383ca0716f5SRobert Watson }
3843b97a967SRobert Watson #endif /* HAVE_AUDIT_SYSCALLS */
385ca0716f5SRobert Watson 
386ca0716f5SRobert Watson /*
387ca0716f5SRobert Watson  * au_close(), except onto an in-memory buffer.  Buffer size as an argument,
388ca0716f5SRobert Watson  * record size returned via same argument on success.
389ca0716f5SRobert Watson  */
390ca0716f5SRobert Watson int
au_close_buffer(int d,short event,u_char * buffer,size_t * buflen)391ca0716f5SRobert Watson au_close_buffer(int d, short event, u_char *buffer, size_t *buflen)
392ca0716f5SRobert Watson {
393ca0716f5SRobert Watson 	size_t tot_rec_size;
394ca0716f5SRobert Watson 	au_record_t *rec;
395ca0716f5SRobert Watson 	int retval;
396ca0716f5SRobert Watson 
397ca0716f5SRobert Watson 	rec = open_desc_table[d];
398ca0716f5SRobert Watson 	if ((rec == NULL) || (rec->used == 0)) {
399ca0716f5SRobert Watson 		errno = EINVAL;
400ca0716f5SRobert Watson 		return (-1);
401ca0716f5SRobert Watson 	}
402ca0716f5SRobert Watson 
403ca0716f5SRobert Watson 	retval = 0;
40452267f74SRobert Watson 	tot_rec_size = rec->len + MAX_AUDIT_HEADER_SIZE + AUDIT_TRAILER_SIZE;
405ca0716f5SRobert Watson 	if ((tot_rec_size > MAX_AUDIT_RECORD_SIZE) ||
406ca0716f5SRobert Watson 	    (tot_rec_size > *buflen)) {
407ca0716f5SRobert Watson 		/*
408ca0716f5SRobert Watson 		 * XXXRW: See au_close() comment.
409ca0716f5SRobert Watson 		 */
410ca0716f5SRobert Watson 		fprintf(stderr, "au_close_buffer failed %zd", tot_rec_size);
411ca0716f5SRobert Watson 		errno = ENOMEM;
412ca0716f5SRobert Watson 		retval = -1;
413ca0716f5SRobert Watson 		goto cleanup;
414ca0716f5SRobert Watson 	}
415ca0716f5SRobert Watson 
416ca0716f5SRobert Watson 	if (au_assemble(rec, event) < 0) {
417ca0716f5SRobert Watson 		/* XXXRW: See au_close() comment. */
418ca0716f5SRobert Watson 		retval = -1;
419ca0716f5SRobert Watson 		goto cleanup;
420ca0716f5SRobert Watson 	}
421ca0716f5SRobert Watson 
422ca0716f5SRobert Watson 	memcpy(buffer, rec->data, rec->len);
423ca0716f5SRobert Watson 	*buflen = rec->len;
424ca0716f5SRobert Watson 
425ca0716f5SRobert Watson cleanup:
426ca0716f5SRobert Watson 	au_teardown(rec);
427ca0716f5SRobert Watson 	return (retval);
428ca0716f5SRobert Watson }
429506764c6SRobert Watson 
430506764c6SRobert Watson /*
431506764c6SRobert Watson  * au_close_token() returns the byte format of a token_t.  This won't
432506764c6SRobert Watson  * generally be used by applications, but is quite useful for writing test
433506764c6SRobert Watson  * tools.  Will free the token on either success or failure.
434506764c6SRobert Watson  */
435506764c6SRobert Watson int
au_close_token(token_t * tok,u_char * buffer,size_t * buflen)436506764c6SRobert Watson au_close_token(token_t *tok, u_char *buffer, size_t *buflen)
437506764c6SRobert Watson {
438506764c6SRobert Watson 
439506764c6SRobert Watson 	if (tok->len > *buflen) {
440506764c6SRobert Watson 		au_free_token(tok);
441506764c6SRobert Watson 		errno = ENOMEM;
442506764c6SRobert Watson 		return (EINVAL);
443506764c6SRobert Watson 	}
444506764c6SRobert Watson 
445506764c6SRobert Watson 	memcpy(buffer, tok->t_data, tok->len);
446506764c6SRobert Watson 	*buflen = tok->len;
447506764c6SRobert Watson 	au_free_token(tok);
448506764c6SRobert Watson 	return (0);
449506764c6SRobert Watson }
450