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