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