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
au_open(void)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
au_write(int d,token_t * m)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
au_close(int d,int right,au_event_t e_type)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