xref: /onnv-gate/usr/src/lib/libbsm/common/au_open.c (revision 12071:1af7bbe2d937)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
56812Sraf  * Common Development and Distribution License (the "License").
66812Sraf  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
216812Sraf 
220Sstevel@tonic-gate /*
23*12071Sgww@eng.sun.com  * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <sys/param.h>
270Sstevel@tonic-gate #include <sys/time.h>
280Sstevel@tonic-gate #include <sys/types.h>
290Sstevel@tonic-gate #include <stdlib.h>
300Sstevel@tonic-gate #include <string.h>
310Sstevel@tonic-gate #include <bsm/audit.h>
320Sstevel@tonic-gate #include <bsm/libbsm.h>
330Sstevel@tonic-gate #include <bsm/audit_record.h>
340Sstevel@tonic-gate #include <synch.h>
350Sstevel@tonic-gate 
360Sstevel@tonic-gate 
370Sstevel@tonic-gate /*
380Sstevel@tonic-gate  * Open an audit record = find a free descriptor and pass it back.
390Sstevel@tonic-gate  * The descriptors are in a "fixed" length array which is extended
400Sstevel@tonic-gate  * whenever it gets full.
410Sstevel@tonic-gate  *
420Sstevel@tonic-gate  *  Since the expected frequency of copies is expected to be low,
430Sstevel@tonic-gate  *  and since realloc loses data if it fails to expand the buffer,
440Sstevel@tonic-gate  *  calloc() is used rather than realloc().
450Sstevel@tonic-gate  */
460Sstevel@tonic-gate 
470Sstevel@tonic-gate /*
480Sstevel@tonic-gate  * AU_TABLE_MAX must be a integer multiple of AU_TABLE_LENGTH
490Sstevel@tonic-gate  */
500Sstevel@tonic-gate #define	AU_TABLE_LENGTH	16
510Sstevel@tonic-gate #define	AU_TABLE_MAX	256
520Sstevel@tonic-gate 
530Sstevel@tonic-gate static token_t	**au_d;
540Sstevel@tonic-gate static int	au_d_length = 0;	/* current table length */
550Sstevel@tonic-gate static int	au_d_required_length = AU_TABLE_LENGTH; /* new table length */
560Sstevel@tonic-gate static mutex_t  mutex_au_d = DEFAULTMUTEX;
570Sstevel@tonic-gate 
580Sstevel@tonic-gate int
au_open(void)590Sstevel@tonic-gate au_open(void)
600Sstevel@tonic-gate {
610Sstevel@tonic-gate 	int d;			/* descriptor */
620Sstevel@tonic-gate 	token_t	**au_d_new;
630Sstevel@tonic-gate 
646812Sraf 	(void) mutex_lock(&mutex_au_d);
650Sstevel@tonic-gate 
660Sstevel@tonic-gate 	if (au_d_required_length > au_d_length) {
670Sstevel@tonic-gate 		au_d_new = (token_t **)calloc(au_d_required_length,
680Sstevel@tonic-gate 		    sizeof (au_d));
690Sstevel@tonic-gate 
700Sstevel@tonic-gate 		if (au_d_new == NULL) {
710Sstevel@tonic-gate 			au_d_required_length = au_d_length;
726812Sraf 			(void) mutex_unlock(&mutex_au_d);
730Sstevel@tonic-gate 			return (-1);
740Sstevel@tonic-gate 		}
750Sstevel@tonic-gate 		if (au_d_length > 0) {
760Sstevel@tonic-gate 			(void) memcpy(au_d_new, au_d, au_d_length *
770Sstevel@tonic-gate 			    sizeof (au_d));
780Sstevel@tonic-gate 			free(au_d);
790Sstevel@tonic-gate 		}
800Sstevel@tonic-gate 		au_d = au_d_new;
810Sstevel@tonic-gate 		au_d_length = au_d_required_length;
820Sstevel@tonic-gate 	}
830Sstevel@tonic-gate 	for (d = 0; d < au_d_length; d++) {
840Sstevel@tonic-gate 		if (au_d[d] == (token_t *)0) {
850Sstevel@tonic-gate 			au_d[d] = (token_t *)&au_d;
866812Sraf 			(void) mutex_unlock(&mutex_au_d);
870Sstevel@tonic-gate 			return (d);
880Sstevel@tonic-gate 		}
890Sstevel@tonic-gate 	}
900Sstevel@tonic-gate 	/*
910Sstevel@tonic-gate 	 * table full; make more room.
920Sstevel@tonic-gate 	 * AU_TABLE_MAX limits recursion.
930Sstevel@tonic-gate 	 * Logic here expects AU_TABLE_MAX to be multiple of AU_TABLE_LENGTH
940Sstevel@tonic-gate 	 */
950Sstevel@tonic-gate 	if (au_d_length >= AU_TABLE_MAX) {
966812Sraf 		(void) mutex_unlock(&mutex_au_d);
970Sstevel@tonic-gate 		return (-1);
980Sstevel@tonic-gate 	}
990Sstevel@tonic-gate 	au_d_required_length += AU_TABLE_LENGTH;
1006812Sraf 	(void) mutex_unlock(&mutex_au_d);
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate 	return (au_open());
1030Sstevel@tonic-gate }
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate /*
1060Sstevel@tonic-gate  * Write to an audit descriptor.
1070Sstevel@tonic-gate  * Add the mbuf to the descriptor chain and free the chain passed in.
1080Sstevel@tonic-gate  */
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate int
au_write(int d,token_t * m)1110Sstevel@tonic-gate au_write(int d, token_t *m)
1120Sstevel@tonic-gate {
1130Sstevel@tonic-gate 	token_t *mp;
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate 	if (d < 0)
1160Sstevel@tonic-gate 		return (-1);
1170Sstevel@tonic-gate 	if (m == (token_t *)0)
1180Sstevel@tonic-gate 		return (-1);
1196812Sraf 	(void) mutex_lock(&mutex_au_d);
1200Sstevel@tonic-gate 	if ((d >= au_d_length) || (au_d[d] == (token_t *)0)) {
1216812Sraf 		(void) mutex_unlock(&mutex_au_d);
1220Sstevel@tonic-gate 		return (-1);
1230Sstevel@tonic-gate 	} else if (au_d[d] == (token_t *)&au_d) {
1240Sstevel@tonic-gate 		au_d[d] = m;
1256812Sraf 		(void) mutex_unlock(&mutex_au_d);
1260Sstevel@tonic-gate 		return (0);
1270Sstevel@tonic-gate 	}
1280Sstevel@tonic-gate 	for (mp = au_d[d]; mp->tt_next != (token_t *)0; mp = mp->tt_next)
1290Sstevel@tonic-gate 		;
1300Sstevel@tonic-gate 	mp->tt_next = m;
1316812Sraf 	(void) mutex_unlock(&mutex_au_d);
1320Sstevel@tonic-gate 	return (0);
1330Sstevel@tonic-gate }
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate /*
1360Sstevel@tonic-gate  * Close an audit descriptor.
1370Sstevel@tonic-gate  * Use the second parameter to indicate if it should be written or not.
1380Sstevel@tonic-gate  */
1390Sstevel@tonic-gate int
au_close(int d,int right,au_event_t e_type)1407753STon.Nguyen@Sun.COM au_close(int d, int right, au_event_t e_type)
1410Sstevel@tonic-gate {
1427753STon.Nguyen@Sun.COM 	au_emod_t e_mod;
1430Sstevel@tonic-gate 	struct timeval now;	/* current time */
1440Sstevel@tonic-gate 	adr_t adr;		/* adr header */
1450Sstevel@tonic-gate 	auditinfo_addr_t	audit_info;
1460Sstevel@tonic-gate 	au_tid_addr_t	*host_info = &audit_info.ai_termid;
1470Sstevel@tonic-gate 	token_t *dchain;	/* mbuf chain which is the tokens */
1480Sstevel@tonic-gate 	token_t *record;	/* mbuf chain which is the record */
1490Sstevel@tonic-gate 	char data_header;	/* token type */
1500Sstevel@tonic-gate 	char version;		/* token version */
1510Sstevel@tonic-gate 	char *buffer;		/* to build record into */
1520Sstevel@tonic-gate 	int  byte_count;	/* bytes in the record */
1530Sstevel@tonic-gate 	int   v;
1540Sstevel@tonic-gate 
1556812Sraf 	(void) mutex_lock(&mutex_au_d);
1560Sstevel@tonic-gate 	if (d < 0 || d >= au_d_length ||
1570Sstevel@tonic-gate 	    ((dchain = au_d[d]) == (token_t *)0)) {
1586812Sraf 		(void) mutex_unlock(&mutex_au_d);
1590Sstevel@tonic-gate 		return (-1);
1600Sstevel@tonic-gate 	}
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate 	au_d[d] = (token_t *)0;
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate 	if (dchain == (token_t *)&au_d) {
1656812Sraf 		(void) mutex_unlock(&mutex_au_d);
1660Sstevel@tonic-gate 		return (0);
1670Sstevel@tonic-gate 	}
1680Sstevel@tonic-gate 	/*
1690Sstevel@tonic-gate 	 * If not to be written toss the record
1700Sstevel@tonic-gate 	 */
1710Sstevel@tonic-gate 	if (!right) {
1720Sstevel@tonic-gate 		while (dchain != (token_t *)0) {
1730Sstevel@tonic-gate 			record = dchain;
1740Sstevel@tonic-gate 			dchain = dchain->tt_next;
1750Sstevel@tonic-gate 			free(record->tt_data);
1760Sstevel@tonic-gate 			free(record);
1770Sstevel@tonic-gate 		}
1786812Sraf 		(void) mutex_unlock(&mutex_au_d);
1790Sstevel@tonic-gate 		return (0);
1800Sstevel@tonic-gate 	}
1810Sstevel@tonic-gate 
1820Sstevel@tonic-gate 	/*
1830Sstevel@tonic-gate 	 * Count up the bytes used in the record.
1840Sstevel@tonic-gate 	 */
1850Sstevel@tonic-gate 	byte_count = sizeof (char) * 2 + sizeof (short) * 2 +
186*12071Sgww@eng.sun.com 	    sizeof (int32_t) + sizeof (struct timeval);
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate 	for (record = dchain; record != (token_t *)0;
189*12071Sgww@eng.sun.com 	    record = record->tt_next) {
190*12071Sgww@eng.sun.com 		byte_count += record->tt_size;
1910Sstevel@tonic-gate 	}
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate #ifdef _LP64
1940Sstevel@tonic-gate #define	HEADER_ID	AUT_HEADER64
1950Sstevel@tonic-gate #define	HEADER_ID_EX	AUT_HEADER64_EX
1960Sstevel@tonic-gate #else
1970Sstevel@tonic-gate #define	HEADER_ID	AUT_HEADER32
1980Sstevel@tonic-gate #define	HEADER_ID_EX	AUT_HEADER32_EX
1990Sstevel@tonic-gate #endif
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate 	/* Use the extended headed if our host address can be determined. */
2020Sstevel@tonic-gate 
2030Sstevel@tonic-gate 	data_header = HEADER_ID;		/* Assume the worst */
2040Sstevel@tonic-gate 	if (auditon(A_GETKAUDIT, (caddr_t)&audit_info,
2050Sstevel@tonic-gate 	    sizeof (audit_info)) == 0) {
2060Sstevel@tonic-gate 		int	have_valid_addr;
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate 		if (host_info->at_type == AU_IPv6)
2090Sstevel@tonic-gate 			have_valid_addr = IN6_IS_ADDR_UNSPECIFIED(
2100Sstevel@tonic-gate 			    (in6_addr_t *)host_info->at_addr) ? 0 : 1;
2110Sstevel@tonic-gate 		else
2120Sstevel@tonic-gate 			have_valid_addr = (host_info->at_addr[0] ==
2130Sstevel@tonic-gate 			    htonl(INADDR_ANY)) ? 0 : 1;
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate 		if (have_valid_addr) {
2160Sstevel@tonic-gate 			data_header = HEADER_ID_EX;
2170Sstevel@tonic-gate 			byte_count += sizeof (int32_t) + host_info->at_type;
2180Sstevel@tonic-gate 		}
2190Sstevel@tonic-gate 	}
2200Sstevel@tonic-gate 
2210Sstevel@tonic-gate 	/*
2220Sstevel@tonic-gate 	 * Build the header
2230Sstevel@tonic-gate 	 */
224*12071Sgww@eng.sun.com 	if ((buffer = malloc((size_t)byte_count)) == NULL) {
225*12071Sgww@eng.sun.com 		/* free the token chain */
226*12071Sgww@eng.sun.com 		while (dchain != (token_t *)0) {
227*12071Sgww@eng.sun.com 			record = dchain;
228*12071Sgww@eng.sun.com 			dchain = dchain->tt_next;
229*12071Sgww@eng.sun.com 			free(record->tt_data);
230*12071Sgww@eng.sun.com 			free(record);
231*12071Sgww@eng.sun.com 		}
232*12071Sgww@eng.sun.com 		(void) mutex_unlock(&mutex_au_d);
233*12071Sgww@eng.sun.com 		return (-1);
234*12071Sgww@eng.sun.com 	}
2350Sstevel@tonic-gate 	(void) gettimeofday(&now, NULL);
2360Sstevel@tonic-gate 	version = TOKEN_VERSION;
2370Sstevel@tonic-gate 	e_mod = 0;
2380Sstevel@tonic-gate 	adr_start(&adr, buffer);
2390Sstevel@tonic-gate 	adr_char(&adr, &data_header, 1);
2400Sstevel@tonic-gate 	adr_int32(&adr, (int32_t *)&byte_count, 1);
2410Sstevel@tonic-gate 	adr_char(&adr, &version, 1);
2427753STon.Nguyen@Sun.COM 	adr_ushort(&adr, &e_type, 1);
2437753STon.Nguyen@Sun.COM 	adr_ushort(&adr, &e_mod, 1);
2440Sstevel@tonic-gate 	if (data_header == HEADER_ID_EX) {
2450Sstevel@tonic-gate 		adr_int32(&adr, (int32_t *)&host_info->at_type, 1);
2460Sstevel@tonic-gate 		adr_char(&adr, (char *)&host_info->at_addr[0],
2470Sstevel@tonic-gate 		    (int)host_info->at_type);
2480Sstevel@tonic-gate 	}
2490Sstevel@tonic-gate #ifdef _LP64
2500Sstevel@tonic-gate 	adr_int64(&adr, (int64_t *)&now, 2);
2510Sstevel@tonic-gate #else
2520Sstevel@tonic-gate 	adr_int32(&adr, (int32_t *)&now, 2);
2530Sstevel@tonic-gate #endif
2540Sstevel@tonic-gate 	/*
2550Sstevel@tonic-gate 	 * Tack on the data, and free the tokens.
2560Sstevel@tonic-gate 	 * We're not supposed to know how adr works, but ...
2570Sstevel@tonic-gate 	 */
2580Sstevel@tonic-gate 	while (dchain != (token_t *)0) {
2590Sstevel@tonic-gate 		(void) memcpy(adr.adr_now, dchain->tt_data, dchain->tt_size);
2600Sstevel@tonic-gate 		adr.adr_now += dchain->tt_size;
2610Sstevel@tonic-gate 		record = dchain;
2620Sstevel@tonic-gate 		dchain = dchain->tt_next;
2630Sstevel@tonic-gate 		free(record->tt_data);
2640Sstevel@tonic-gate 		free(record);
2650Sstevel@tonic-gate 	}
2660Sstevel@tonic-gate 	/*
2670Sstevel@tonic-gate 	 * Send it down to the system
2680Sstevel@tonic-gate 	 */
2690Sstevel@tonic-gate 	v = audit((caddr_t)buffer, byte_count);
2700Sstevel@tonic-gate 	free(buffer);
2716812Sraf 	(void) mutex_unlock(&mutex_au_d);
2720Sstevel@tonic-gate 	return (v);
2730Sstevel@tonic-gate }
274