Home | History | Annotate | Download | only in common
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 
     28 #include <sys/param.h>
     29 #include <sys/time.h>
     30 #include <sys/types.h>
     31 #include <stdlib.h>
     32 #include <string.h>
     33 #include <bsm/audit.h>
     34 #include <bsm/libbsm.h>
     35 #include <bsm/audit_record.h>
     36 #include <synch.h>
     37 
     38 
     39 /*
     40  * Open an audit record = find a free descriptor and pass it back.
     41  * The descriptors are in a "fixed" length array which is extended
     42  * whenever it gets full.
     43  *
     44  *  Since the expected frequency of copies is expected to be low,
     45  *  and since realloc loses data if it fails to expand the buffer,
     46  *  calloc() is used rather than realloc().
     47  */
     48 
     49 /*
     50  * AU_TABLE_MAX must be a integer multiple of AU_TABLE_LENGTH
     51  */
     52 #define	AU_TABLE_LENGTH	16
     53 #define	AU_TABLE_MAX	256
     54 
     55 static token_t	**au_d;
     56 static int	au_d_length = 0;	/* current table length */
     57 static int	au_d_required_length = AU_TABLE_LENGTH; /* new table length */
     58 static mutex_t  mutex_au_d = DEFAULTMUTEX;
     59 
     60 int
     61 au_open(void)
     62 {
     63 	int d;			/* descriptor */
     64 	token_t	**au_d_new;
     65 
     66 	(void) mutex_lock(&mutex_au_d);
     67 
     68 	if (au_d_required_length > au_d_length) {
     69 		au_d_new = (token_t **)calloc(au_d_required_length,
     70 		    sizeof (au_d));
     71 
     72 		if (au_d_new == NULL) {
     73 			au_d_required_length = au_d_length;
     74 			(void) mutex_unlock(&mutex_au_d);
     75 			return (-1);
     76 		}
     77 		if (au_d_length > 0) {
     78 			(void) memcpy(au_d_new, au_d, au_d_length *
     79 			    sizeof (au_d));
     80 			free(au_d);
     81 		}
     82 		au_d = au_d_new;
     83 		au_d_length = au_d_required_length;
     84 	}
     85 	for (d = 0; d < au_d_length; d++) {
     86 		if (au_d[d] == (token_t *)0) {
     87 			au_d[d] = (token_t *)&au_d;
     88 			(void) mutex_unlock(&mutex_au_d);
     89 			return (d);
     90 		}
     91 	}
     92 	/*
     93 	 * table full; make more room.
     94 	 * AU_TABLE_MAX limits recursion.
     95 	 * Logic here expects AU_TABLE_MAX to be multiple of AU_TABLE_LENGTH
     96 	 */
     97 	if (au_d_length >= AU_TABLE_MAX) {
     98 		(void) mutex_unlock(&mutex_au_d);
     99 		return (-1);
    100 	}
    101 	au_d_required_length += AU_TABLE_LENGTH;
    102 	(void) mutex_unlock(&mutex_au_d);
    103 
    104 	return (au_open());
    105 }
    106 
    107 /*
    108  * Write to an audit descriptor.
    109  * Add the mbuf to the descriptor chain and free the chain passed in.
    110  */
    111 
    112 int
    113 au_write(int d, token_t *m)
    114 {
    115 	token_t *mp;
    116 
    117 	if (d < 0)
    118 		return (-1);
    119 	if (m == (token_t *)0)
    120 		return (-1);
    121 	(void) mutex_lock(&mutex_au_d);
    122 	if ((d >= au_d_length) || (au_d[d] == (token_t *)0)) {
    123 		(void) mutex_unlock(&mutex_au_d);
    124 		return (-1);
    125 	} else if (au_d[d] == (token_t *)&au_d) {
    126 		au_d[d] = m;
    127 		(void) mutex_unlock(&mutex_au_d);
    128 		return (0);
    129 	}
    130 	for (mp = au_d[d]; mp->tt_next != (token_t *)0; mp = mp->tt_next)
    131 		;
    132 	mp->tt_next = m;
    133 	(void) mutex_unlock(&mutex_au_d);
    134 	return (0);
    135 }
    136 
    137 /*
    138  * Close an audit descriptor.
    139  * Use the second parameter to indicate if it should be written or not.
    140  */
    141 int
    142 au_close(int d, int right, au_event_t e_type)
    143 {
    144 	au_emod_t e_mod;
    145 	struct timeval now;	/* current time */
    146 	adr_t adr;		/* adr header */
    147 	auditinfo_addr_t	audit_info;
    148 	au_tid_addr_t	*host_info = &audit_info.ai_termid;
    149 	token_t *dchain;	/* mbuf chain which is the tokens */
    150 	token_t *record;	/* mbuf chain which is the record */
    151 	char data_header;	/* token type */
    152 	char version;		/* token version */
    153 	char *buffer;		/* to build record into */
    154 	int  byte_count;	/* bytes in the record */
    155 	int   v;
    156 
    157 	(void) mutex_lock(&mutex_au_d);
    158 	if (d < 0 || d >= au_d_length ||
    159 	    ((dchain = au_d[d]) == (token_t *)0)) {
    160 		(void) mutex_unlock(&mutex_au_d);
    161 		return (-1);
    162 	}
    163 
    164 	au_d[d] = (token_t *)0;
    165 
    166 	if (dchain == (token_t *)&au_d) {
    167 		(void) mutex_unlock(&mutex_au_d);
    168 		return (0);
    169 	}
    170 	/*
    171 	 * If not to be written toss the record
    172 	 */
    173 	if (!right) {
    174 		while (dchain != (token_t *)0) {
    175 			record = dchain;
    176 			dchain = dchain->tt_next;
    177 			free(record->tt_data);
    178 			free(record);
    179 		}
    180 		(void) mutex_unlock(&mutex_au_d);
    181 		return (0);
    182 	}
    183 
    184 	/*
    185 	 * Count up the bytes used in the record.
    186 	 */
    187 	byte_count = sizeof (char) * 2 + sizeof (short) * 2 +
    188 			sizeof (int32_t) + sizeof (struct timeval);
    189 
    190 	for (record = dchain; record != (token_t *)0;
    191 		record = record->tt_next) {
    192 			byte_count += record->tt_size;
    193 	}
    194 
    195 #ifdef _LP64
    196 #define	HEADER_ID	AUT_HEADER64
    197 #define	HEADER_ID_EX	AUT_HEADER64_EX
    198 #else
    199 #define	HEADER_ID	AUT_HEADER32
    200 #define	HEADER_ID_EX	AUT_HEADER32_EX
    201 #endif
    202 
    203 	/* Use the extended headed if our host address can be determined. */
    204 
    205 	data_header = HEADER_ID;		/* Assume the worst */
    206 	if (auditon(A_GETKAUDIT, (caddr_t)&audit_info,
    207 	    sizeof (audit_info)) == 0) {
    208 		int	have_valid_addr;
    209 
    210 		if (host_info->at_type == AU_IPv6)
    211 			have_valid_addr = IN6_IS_ADDR_UNSPECIFIED(
    212 			    (in6_addr_t *)host_info->at_addr) ? 0 : 1;
    213 		else
    214 			have_valid_addr = (host_info->at_addr[0] ==
    215 			    htonl(INADDR_ANY)) ? 0 : 1;
    216 
    217 		if (have_valid_addr) {
    218 			data_header = HEADER_ID_EX;
    219 			byte_count += sizeof (int32_t) + host_info->at_type;
    220 		}
    221 	}
    222 
    223 	/*
    224 	 * Build the header
    225 	 */
    226 	buffer = malloc((size_t)byte_count);
    227 	(void) gettimeofday(&now, NULL);
    228 	version = TOKEN_VERSION;
    229 	e_mod = 0;
    230 	adr_start(&adr, buffer);
    231 	adr_char(&adr, &data_header, 1);
    232 	adr_int32(&adr, (int32_t *)&byte_count, 1);
    233 	adr_char(&adr, &version, 1);
    234 	adr_ushort(&adr, &e_type, 1);
    235 	adr_ushort(&adr, &e_mod, 1);
    236 	if (data_header == HEADER_ID_EX) {
    237 		adr_int32(&adr, (int32_t *)&host_info->at_type, 1);
    238 		adr_char(&adr, (char *)&host_info->at_addr[0],
    239 		    (int)host_info->at_type);
    240 	}
    241 #ifdef _LP64
    242 	adr_int64(&adr, (int64_t *)&now, 2);
    243 #else
    244 	adr_int32(&adr, (int32_t *)&now, 2);
    245 #endif
    246 	/*
    247 	 * Tack on the data, and free the tokens.
    248 	 * We're not supposed to know how adr works, but ...
    249 	 */
    250 	while (dchain != (token_t *)0) {
    251 		(void) memcpy(adr.adr_now, dchain->tt_data, dchain->tt_size);
    252 		adr.adr_now += dchain->tt_size;
    253 		record = dchain;
    254 		dchain = dchain->tt_next;
    255 		free(record->tt_data);
    256 		free(record);
    257 	}
    258 	/*
    259 	 * Send it down to the system
    260 	 */
    261 	v = audit((caddr_t)buffer, byte_count);
    262 	free(buffer);
    263 	(void) mutex_unlock(&mutex_au_d);
    264 	return (v);
    265 }
    266