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