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