1 |
/*- |
2 |
* Copyright (c) 2004-2009 Apple Inc. |
3 |
* All rights reserved. |
4 |
* |
5 |
* Redistribution and use in source and binary forms, with or without |
6 |
* modification, are permitted provided that the following conditions |
7 |
* are met: |
8 |
* 1. Redistributions of source code must retain the above copyright |
9 |
* notice, this list of conditions and the following disclaimer. |
10 |
* 2. Redistributions in binary form must reproduce the above copyright |
11 |
* notice, this list of conditions and the following disclaimer in the |
12 |
* documentation and/or other materials provided with the distribution. |
13 |
* 3. Neither the name of Apple Inc. ("Apple") nor the names of |
14 |
* its contributors may be used to endorse or promote products derived |
15 |
* from this software without specific prior written permission. |
16 |
* |
17 |
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND |
18 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
19 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
20 |
* ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR |
21 |
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
22 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
23 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
24 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
25 |
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
26 |
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
27 |
* POSSIBILITY OF SUCH DAMAGE. |
28 |
*/ |
29 |
|
30 |
#ifdef __APPLE__ |
31 |
#define _SYS_AUDIT_H /* Prevent include of sys/audit.h. */ |
32 |
#endif |
33 |
|
34 |
#include <sys/param.h> |
35 |
#include <sys/stat.h> |
36 |
|
37 |
#ifdef __APPLE__ |
38 |
#include <sys/queue.h> /* Our bsm/audit.h doesn't include queue.h. */ |
39 |
#endif |
40 |
|
41 |
#include <sys/sysctl.h> |
42 |
|
43 |
#include <bsm/libbsm.h> |
44 |
|
45 |
#include <unistd.h> |
46 |
#include <syslog.h> |
47 |
#include <stdarg.h> |
48 |
#include <string.h> |
49 |
#include <errno.h> |
50 |
|
51 |
/* These are not advertised in libbsm.h */ |
52 |
int audit_set_terminal_port(dev_t *p); |
53 |
int audit_set_terminal_host(uint32_t *m); |
54 |
|
55 |
/* |
56 |
* General purpose audit submission mechanism for userspace. |
57 |
*/ |
58 |
int |
59 |
audit_submit(short au_event, au_id_t auid, char status, |
60 |
int reterr, const char *fmt, ...) |
61 |
{ |
62 |
char text[MAX_AUDITSTRING_LEN]; |
63 |
token_t *token; |
64 |
int acond; |
65 |
va_list ap; |
66 |
pid_t pid; |
67 |
int error, afd, subj_ex; |
68 |
struct auditinfo ai; |
69 |
struct auditinfo_addr aia; |
70 |
au_tid_t atid; |
71 |
|
72 |
if (audit_get_cond(&acond) != 0) { |
73 |
/* |
74 |
* If auditon(2) returns ENOSYS, then audit has not been |
75 |
* compiled into the kernel, so just return. |
76 |
*/ |
77 |
if (errno == ENOSYS) |
78 |
return (0); |
79 |
error = errno; |
80 |
syslog(LOG_AUTH | LOG_ERR, "audit: auditon failed: %s", |
81 |
strerror(errno)); |
82 |
errno = error; |
83 |
return (-1); |
84 |
} |
85 |
if (acond == AUC_NOAUDIT) |
86 |
return (0); |
87 |
afd = au_open(); |
88 |
if (afd < 0) { |
89 |
error = errno; |
90 |
syslog(LOG_AUTH | LOG_ERR, "audit: au_open failed: %s", |
91 |
strerror(errno)); |
92 |
errno = error; |
93 |
return (-1); |
94 |
} |
95 |
/* |
96 |
* Try to use getaudit_addr(2) first. If this kernel does not support |
97 |
* it, then fall back on to getaudit(2). |
98 |
*/ |
99 |
subj_ex = 0; |
100 |
error = getaudit_addr(&aia, sizeof(aia)); |
101 |
if (error < 0 && errno == ENOSYS) { |
102 |
error = getaudit(&ai); |
103 |
if (error < 0) { |
104 |
error = errno; |
105 |
syslog(LOG_AUTH | LOG_ERR, "audit: getaudit failed: %s", |
106 |
strerror(errno)); |
107 |
errno = error; |
108 |
return (-1); |
109 |
} |
110 |
/* |
111 |
* Convert this auditinfo_t to an auditinfo_addr_t to make the |
112 |
* following code less complicated wrt to preselection and |
113 |
* subject token generation. |
114 |
*/ |
115 |
aia.ai_auid = ai.ai_auid; |
116 |
aia.ai_mask = ai.ai_mask; |
117 |
aia.ai_asid = ai.ai_asid; |
118 |
aia.ai_termid.at_type = AU_IPv4; |
119 |
aia.ai_termid.at_addr[0] = ai.ai_termid.machine; |
120 |
aia.ai_termid.at_port = ai.ai_termid.port; |
121 |
} else if (error < 0) { |
122 |
error = errno; |
123 |
syslog(LOG_AUTH | LOG_ERR, "audit: getaudit_addr failed: %s", |
124 |
strerror(errno)); |
125 |
errno = error; |
126 |
return (-1); |
127 |
} |
128 |
/* |
129 |
* NB: We should be performing pre-selection here now that we have the |
130 |
* masks for this process. |
131 |
*/ |
132 |
if (aia.ai_termid.at_type == AU_IPv6) |
133 |
subj_ex = 1; |
134 |
pid = getpid(); |
135 |
if (subj_ex == 0) { |
136 |
atid.port = aia.ai_termid.at_port; |
137 |
atid.machine = aia.ai_termid.at_addr[0]; |
138 |
token = au_to_subject32(auid, geteuid(), getegid(), |
139 |
getuid(), getgid(), pid, pid, &atid); |
140 |
} else |
141 |
token = au_to_subject_ex(auid, geteuid(), getegid(), |
142 |
getuid(), getgid(), pid, pid, &aia.ai_termid); |
143 |
if (token == NULL) { |
144 |
syslog(LOG_AUTH | LOG_ERR, |
145 |
"audit: unable to build subject token"); |
146 |
(void) au_close(afd, AU_TO_NO_WRITE, au_event); |
147 |
errno = EPERM; |
148 |
return (-1); |
149 |
} |
150 |
if (au_write(afd, token) < 0) { |
151 |
error = errno; |
152 |
syslog(LOG_AUTH | LOG_ERR, |
153 |
"audit: au_write failed: %s", strerror(errno)); |
154 |
(void) au_close(afd, AU_TO_NO_WRITE, au_event); |
155 |
errno = error; |
156 |
return (-1); |
157 |
} |
158 |
if (fmt != NULL) { |
159 |
va_start(ap, fmt); |
160 |
(void) vsnprintf(text, MAX_AUDITSTRING_LEN, fmt, ap); |
161 |
va_end(ap); |
162 |
token = au_to_text(text); |
163 |
if (token == NULL) { |
164 |
syslog(LOG_AUTH | LOG_ERR, |
165 |
"audit: failed to generate text token"); |
166 |
(void) au_close(afd, AU_TO_NO_WRITE, au_event); |
167 |
errno = EPERM; |
168 |
return (-1); |
169 |
} |
170 |
if (au_write(afd, token) < 0) { |
171 |
error = errno; |
172 |
syslog(LOG_AUTH | LOG_ERR, |
173 |
"audit: au_write failed: %s", strerror(errno)); |
174 |
(void) au_close(afd, AU_TO_NO_WRITE, au_event); |
175 |
errno = error; |
176 |
return (-1); |
177 |
} |
178 |
} |
179 |
token = au_to_return32(au_errno_to_bsm(status), reterr); |
180 |
if (token == NULL) { |
181 |
syslog(LOG_AUTH | LOG_ERR, |
182 |
"audit: unable to build return token"); |
183 |
(void) au_close(afd, AU_TO_NO_WRITE, au_event); |
184 |
errno = EPERM; |
185 |
return (-1); |
186 |
} |
187 |
if (au_write(afd, token) < 0) { |
188 |
error = errno; |
189 |
syslog(LOG_AUTH | LOG_ERR, |
190 |
"audit: au_write failed: %s", strerror(errno)); |
191 |
(void) au_close(afd, AU_TO_NO_WRITE, au_event); |
192 |
errno = error; |
193 |
return (-1); |
194 |
} |
195 |
if (au_close(afd, AU_TO_WRITE, au_event) < 0) { |
196 |
error = errno; |
197 |
syslog(LOG_AUTH | LOG_ERR, "audit: record not committed"); |
198 |
errno = error; |
199 |
return (-1); |
200 |
} |
201 |
return (0); |
202 |
} |
203 |
|
204 |
int |
205 |
audit_set_terminal_port(dev_t *p) |
206 |
{ |
207 |
struct stat st; |
208 |
|
209 |
if (p == NULL) |
210 |
return (kAUBadParamErr); |
211 |
|
212 |
#ifdef NODEV |
213 |
*p = NODEV; |
214 |
#else |
215 |
*p = -1; |
216 |
#endif |
217 |
|
218 |
/* for /usr/bin/login, try fstat() first */ |
219 |
if (fstat(STDIN_FILENO, &st) != 0) { |
220 |
if (errno != EBADF) { |
221 |
syslog(LOG_ERR, "fstat() failed (%s)", |
222 |
strerror(errno)); |
223 |
return (kAUStatErr); |
224 |
} |
225 |
if (stat("/dev/console", &st) != 0) { |
226 |
syslog(LOG_ERR, "stat() failed (%s)", |
227 |
strerror(errno)); |
228 |
return (kAUStatErr); |
229 |
} |
230 |
} |
231 |
*p = st.st_rdev; |
232 |
return (kAUNoErr); |
233 |
} |
234 |
|
235 |
int |
236 |
audit_set_terminal_host(uint32_t *m) |
237 |
{ |
238 |
|
239 |
#ifdef KERN_HOSTID |
240 |
int name[2] = { CTL_KERN, KERN_HOSTID }; |
241 |
size_t len; |
242 |
|
243 |
if (m == NULL) |
244 |
return (kAUBadParamErr); |
245 |
*m = 0; |
246 |
len = sizeof(*m); |
247 |
if (sysctl(name, 2, m, &len, NULL, 0) != 0) { |
248 |
syslog(LOG_ERR, "sysctl() failed (%s)", strerror(errno)); |
249 |
return (kAUSysctlErr); |
250 |
} |
251 |
return (kAUNoErr); |
252 |
#else |
253 |
*m = -1; |
254 |
return (kAUNoErr); |
255 |
#endif |
256 |
} |
257 |
|
258 |
int |
259 |
audit_set_terminal_id(au_tid_t *tid) |
260 |
{ |
261 |
int ret; |
262 |
|
263 |
if (tid == NULL) |
264 |
return (kAUBadParamErr); |
265 |
if ((ret = audit_set_terminal_port(&tid->port)) != kAUNoErr) |
266 |
return (ret); |
267 |
return (audit_set_terminal_host(&tid->machine)); |
268 |
} |
269 |
|
270 |
/* |
271 |
* This is OK for those callers who have only one token to write. If you have |
272 |
* multiple tokens that logically form part of the same audit record, you need |
273 |
* to use the existing au_open()/au_write()/au_close() API: |
274 |
* |
275 |
* aufd = au_open(); |
276 |
* tok = au_to_random_token_1(...); |
277 |
* au_write(aufd, tok); |
278 |
* tok = au_to_random_token_2(...); |
279 |
* au_write(aufd, tok); |
280 |
* ... |
281 |
* au_close(aufd, AU_TO_WRITE, AUE_your_event_type); |
282 |
* |
283 |
* Assumes, like all wrapper calls, that the caller has previously checked |
284 |
* that auditing is enabled via the audit_get_state() call. |
285 |
* |
286 |
* XXX: Should be more robust against bad arguments. |
287 |
*/ |
288 |
int |
289 |
audit_write(short event_code, token_t *subject, token_t *misctok, char retval, |
290 |
int errcode) |
291 |
{ |
292 |
int aufd; |
293 |
char *func = "audit_write()"; |
294 |
token_t *rettok; |
295 |
|
296 |
if ((aufd = au_open()) == -1) { |
297 |
au_free_token(subject); |
298 |
au_free_token(misctok); |
299 |
syslog(LOG_ERR, "%s: au_open() failed", func); |
300 |
return (kAUOpenErr); |
301 |
} |
302 |
|
303 |
/* Save subject. */ |
304 |
if (subject && au_write(aufd, subject) == -1) { |
305 |
au_free_token(subject); |
306 |
au_free_token(misctok); |
307 |
(void)au_close(aufd, AU_TO_NO_WRITE, event_code); |
308 |
syslog(LOG_ERR, "%s: write of subject failed", func); |
309 |
return (kAUWriteSubjectTokErr); |
310 |
} |
311 |
|
312 |
/* Save the event-specific token. */ |
313 |
if (misctok && au_write(aufd, misctok) == -1) { |
314 |
au_free_token(misctok); |
315 |
(void)au_close(aufd, AU_TO_NO_WRITE, event_code); |
316 |
syslog(LOG_ERR, "%s: write of caller token failed", func); |
317 |
return (kAUWriteCallerTokErr); |
318 |
} |
319 |
|
320 |
/* Tokenize and save the return value. */ |
321 |
if ((rettok = au_to_return32(retval, errcode)) == NULL) { |
322 |
(void)au_close(aufd, AU_TO_NO_WRITE, event_code); |
323 |
syslog(LOG_ERR, "%s: au_to_return32() failed", func); |
324 |
return (kAUMakeReturnTokErr); |
325 |
} |
326 |
|
327 |
if (au_write(aufd, rettok) == -1) { |
328 |
au_free_token(rettok); |
329 |
(void)au_close(aufd, AU_TO_NO_WRITE, event_code); |
330 |
syslog(LOG_ERR, "%s: write of return code failed", func); |
331 |
return (kAUWriteReturnTokErr); |
332 |
} |
333 |
|
334 |
/* |
335 |
* We assume the caller wouldn't have bothered with this |
336 |
* function if it hadn't already decided to keep the record. |
337 |
*/ |
338 |
if (au_close(aufd, AU_TO_WRITE, event_code) < 0) { |
339 |
syslog(LOG_ERR, "%s: au_close() failed", func); |
340 |
return (kAUCloseErr); |
341 |
} |
342 |
|
343 |
return (kAUNoErr); |
344 |
} |
345 |
|
346 |
/* |
347 |
* Same caveats as audit_write(). In addition, this function explicitly |
348 |
* assumes success; use audit_write_failure() on error. |
349 |
*/ |
350 |
int |
351 |
audit_write_success(short event_code, token_t *tok, au_id_t auid, uid_t euid, |
352 |
gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, |
353 |
au_tid_t *tid) |
354 |
{ |
355 |
char *func = "audit_write_success()"; |
356 |
token_t *subject = NULL; |
357 |
|
358 |
/* Tokenize and save subject. */ |
359 |
subject = au_to_subject32(auid, euid, egid, ruid, rgid, pid, sid, |
360 |
tid); |
361 |
if (subject == NULL) { |
362 |
syslog(LOG_ERR, "%s: au_to_subject32() failed", func); |
363 |
return kAUMakeSubjectTokErr; |
364 |
} |
365 |
|
366 |
return (audit_write(event_code, subject, tok, 0, 0)); |
367 |
} |
368 |
|
369 |
/* |
370 |
* Same caveats as audit_write(). In addition, this function explicitly |
371 |
* assumes success; use audit_write_failure_self() on error. |
372 |
*/ |
373 |
int |
374 |
audit_write_success_self(short event_code, token_t *tok) |
375 |
{ |
376 |
token_t *subject; |
377 |
char *func = "audit_write_success_self()"; |
378 |
|
379 |
if ((subject = au_to_me()) == NULL) { |
380 |
syslog(LOG_ERR, "%s: au_to_me() failed", func); |
381 |
return (kAUMakeSubjectTokErr); |
382 |
} |
383 |
|
384 |
return (audit_write(event_code, subject, tok, 0, 0)); |
385 |
} |
386 |
|
387 |
/* |
388 |
* Same caveats as audit_write(). In addition, this function explicitly |
389 |
* assumes failure; use audit_write_success() otherwise. |
390 |
* |
391 |
* XXX This should let the caller pass an error return value rather than |
392 |
* hard-coding -1. |
393 |
*/ |
394 |
int |
395 |
audit_write_failure(short event_code, char *errmsg, int errcode, au_id_t auid, |
396 |
uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, |
397 |
au_tid_t *tid) |
398 |
{ |
399 |
char *func = "audit_write_failure()"; |
400 |
token_t *subject, *errtok; |
401 |
|
402 |
subject = au_to_subject32(auid, euid, egid, ruid, rgid, pid, sid, tid); |
403 |
if (subject == NULL) { |
404 |
syslog(LOG_ERR, "%s: au_to_subject32() failed", func); |
405 |
return (kAUMakeSubjectTokErr); |
406 |
} |
407 |
|
408 |
/* tokenize and save the error message */ |
409 |
if ((errtok = au_to_text(errmsg)) == NULL) { |
410 |
au_free_token(subject); |
411 |
syslog(LOG_ERR, "%s: au_to_text() failed", func); |
412 |
return (kAUMakeTextTokErr); |
413 |
} |
414 |
|
415 |
return (audit_write(event_code, subject, errtok, -1, errcode)); |
416 |
} |
417 |
|
418 |
/* |
419 |
* Same caveats as audit_write(). In addition, this function explicitly |
420 |
* assumes failure; use audit_write_success_self() otherwise. |
421 |
* |
422 |
* XXX This should let the caller pass an error return value rather than |
423 |
* hard-coding -1. |
424 |
*/ |
425 |
int |
426 |
audit_write_failure_self(short event_code, char *errmsg, int errret) |
427 |
{ |
428 |
char *func = "audit_write_failure_self()"; |
429 |
token_t *subject, *errtok; |
430 |
|
431 |
if ((subject = au_to_me()) == NULL) { |
432 |
syslog(LOG_ERR, "%s: au_to_me() failed", func); |
433 |
return (kAUMakeSubjectTokErr); |
434 |
} |
435 |
/* tokenize and save the error message */ |
436 |
if ((errtok = au_to_text(errmsg)) == NULL) { |
437 |
au_free_token(subject); |
438 |
syslog(LOG_ERR, "%s: au_to_text() failed", func); |
439 |
return (kAUMakeTextTokErr); |
440 |
} |
441 |
return (audit_write(event_code, subject, errtok, -1, errret)); |
442 |
} |
443 |
|
444 |
/* |
445 |
* For auditing errors during login. Such errors are implicitly |
446 |
* non-attributable (i.e., not ascribable to any user). |
447 |
* |
448 |
* Assumes, like all wrapper calls, that the caller has previously checked |
449 |
* that auditing is enabled via the audit_get_state() call. |
450 |
*/ |
451 |
int |
452 |
audit_write_failure_na(short event_code, char *errmsg, int errret, uid_t euid, |
453 |
uid_t egid, pid_t pid, au_tid_t *tid) |
454 |
{ |
455 |
|
456 |
return (audit_write_failure(event_code, errmsg, errret, -1, euid, |
457 |
egid, -1, -1, pid, -1, tid)); |
458 |
} |
459 |
|
460 |
/* END OF au_write() WRAPPERS */ |
461 |
|
462 |
#ifdef __APPLE__ |
463 |
void |
464 |
audit_token_to_au32(audit_token_t atoken, uid_t *auidp, uid_t *euidp, |
465 |
gid_t *egidp, uid_t *ruidp, gid_t *rgidp, pid_t *pidp, au_asid_t *asidp, |
466 |
au_tid_t *tidp) |
467 |
{ |
468 |
|
469 |
if (auidp != NULL) |
470 |
*auidp = (uid_t)atoken.val[0]; |
471 |
if (euidp != NULL) |
472 |
*euidp = (uid_t)atoken.val[1]; |
473 |
if (egidp != NULL) |
474 |
*egidp = (gid_t)atoken.val[2]; |
475 |
if (ruidp != NULL) |
476 |
*ruidp = (uid_t)atoken.val[3]; |
477 |
if (rgidp != NULL) |
478 |
*rgidp = (gid_t)atoken.val[4]; |
479 |
if (pidp != NULL) |
480 |
*pidp = (pid_t)atoken.val[5]; |
481 |
if (asidp != NULL) |
482 |
*asidp = (au_asid_t)atoken.val[6]; |
483 |
if (tidp != NULL) { |
484 |
audit_set_terminal_host(&tidp->machine); |
485 |
tidp->port = (dev_t)atoken.val[7]; |
486 |
} |
487 |
} |
488 |
#endif /* !__APPLE__ */ |
489 |
|
490 |
int |
491 |
audit_get_cond(int *cond) |
492 |
{ |
493 |
int ret; |
494 |
|
495 |
ret = auditon(A_GETCOND, cond, sizeof(*cond)); |
496 |
#ifdef A_OLDGETCOND |
497 |
if ((0 != ret) && EINVAL == errno) { |
498 |
long lcond = *cond; |
499 |
|
500 |
ret = auditon(A_OLDGETCOND, &lcond, sizeof(lcond)); |
501 |
*cond = (int)lcond; |
502 |
} |
503 |
#endif |
504 |
return (ret); |
505 |
} |
506 |
|
507 |
int |
508 |
audit_set_cond(int *cond) |
509 |
{ |
510 |
int ret; |
511 |
|
512 |
ret = auditon(A_SETCOND, cond, sizeof(*cond)); |
513 |
#ifdef A_OLDSETCOND |
514 |
if ((0 != ret) && (EINVAL == errno)) { |
515 |
long lcond = (long)*cond; |
516 |
|
517 |
ret = auditon(A_OLDSETCOND, &lcond, sizeof(lcond)); |
518 |
*cond = (int)lcond; |
519 |
} |
520 |
#endif |
521 |
return (ret); |
522 |
} |
523 |
|
524 |
int |
525 |
audit_get_policy(int *policy) |
526 |
{ |
527 |
int ret; |
528 |
|
529 |
ret = auditon(A_GETPOLICY, policy, sizeof(*policy)); |
530 |
#ifdef A_OLDGETPOLICY |
531 |
if ((0 != ret) && (EINVAL == errno)){ |
532 |
long lpolicy = (long)*policy; |
533 |
|
534 |
ret = auditon(A_OLDGETPOLICY, &lpolicy, sizeof(lpolicy)); |
535 |
*policy = (int)lpolicy; |
536 |
} |
537 |
#endif |
538 |
return (ret); |
539 |
} |
540 |
|
541 |
int |
542 |
audit_set_policy(int *policy) |
543 |
{ |
544 |
int ret; |
545 |
|
546 |
ret = auditon(A_SETPOLICY, policy, sizeof(*policy)); |
547 |
#ifdef A_OLDSETPOLICY |
548 |
if ((0 != ret) && (EINVAL == errno)){ |
549 |
long lpolicy = (long)*policy; |
550 |
|
551 |
ret = auditon(A_OLDSETPOLICY, &lpolicy, sizeof(lpolicy)); |
552 |
*policy = (int)lpolicy; |
553 |
} |
554 |
#endif |
555 |
return (ret); |
556 |
} |
557 |
|
558 |
int |
559 |
audit_get_qctrl(au_qctrl_t *qctrl, size_t sz) |
560 |
{ |
561 |
int ret; |
562 |
|
563 |
if (sizeof(*qctrl) != sz) { |
564 |
errno = EINVAL; |
565 |
return (-1); |
566 |
} |
567 |
|
568 |
ret = auditon(A_GETQCTRL, qctrl, sizeof(*qctrl)); |
569 |
#ifdef A_OLDGETQCTRL |
570 |
if ((0 != ret) && (EINVAL == errno)){ |
571 |
struct old_qctrl { |
572 |
size_t oq_hiwater; |
573 |
size_t oq_lowater; |
574 |
size_t oq_bufsz; |
575 |
clock_t oq_delay; |
576 |
int oq_minfree; |
577 |
} oq; |
578 |
|
579 |
oq.oq_hiwater = (size_t)qctrl->aq_hiwater; |
580 |
oq.oq_lowater = (size_t)qctrl->aq_lowater; |
581 |
oq.oq_bufsz = (size_t)qctrl->aq_bufsz; |
582 |
oq.oq_delay = (clock_t)qctrl->aq_delay; |
583 |
oq.oq_minfree = qctrl->aq_minfree; |
584 |
|
585 |
ret = auditon(A_OLDGETQCTRL, &oq, sizeof(oq)); |
586 |
|
587 |
qctrl->aq_hiwater = (int)oq.oq_hiwater; |
588 |
qctrl->aq_lowater = (int)oq.oq_lowater; |
589 |
qctrl->aq_bufsz = (int)oq.oq_bufsz; |
590 |
qctrl->aq_delay = (int)oq.oq_delay; |
591 |
qctrl->aq_minfree = oq.oq_minfree; |
592 |
} |
593 |
#endif /* A_OLDGETQCTRL */ |
594 |
return (ret); |
595 |
} |
596 |
|
597 |
int |
598 |
audit_set_qctrl(au_qctrl_t *qctrl, size_t sz) |
599 |
{ |
600 |
int ret; |
601 |
|
602 |
if (sizeof(*qctrl) != sz) { |
603 |
errno = EINVAL; |
604 |
return (-1); |
605 |
} |
606 |
|
607 |
ret = auditon(A_SETQCTRL, qctrl, sz); |
608 |
#ifdef A_OLDSETQCTRL |
609 |
if ((0 != ret) && (EINVAL == errno)) { |
610 |
struct old_qctrl { |
611 |
size_t oq_hiwater; |
612 |
size_t oq_lowater; |
613 |
size_t oq_bufsz; |
614 |
clock_t oq_delay; |
615 |
int oq_minfree; |
616 |
} oq; |
617 |
|
618 |
oq.oq_hiwater = (size_t)qctrl->aq_hiwater; |
619 |
oq.oq_lowater = (size_t)qctrl->aq_lowater; |
620 |
oq.oq_bufsz = (size_t)qctrl->aq_bufsz; |
621 |
oq.oq_delay = (clock_t)qctrl->aq_delay; |
622 |
oq.oq_minfree = qctrl->aq_minfree; |
623 |
|
624 |
ret = auditon(A_OLDSETQCTRL, &oq, sizeof(oq)); |
625 |
|
626 |
qctrl->aq_hiwater = (int)oq.oq_hiwater; |
627 |
qctrl->aq_lowater = (int)oq.oq_lowater; |
628 |
qctrl->aq_bufsz = (int)oq.oq_bufsz; |
629 |
qctrl->aq_delay = (int)oq.oq_delay; |
630 |
qctrl->aq_minfree = oq.oq_minfree; |
631 |
} |
632 |
#endif /* A_OLDSETQCTRL */ |
633 |
return (ret); |
634 |
} |
635 |
|
636 |
int |
637 |
audit_send_trigger(int *trigger) |
638 |
{ |
639 |
|
640 |
return (auditon(A_SENDTRIGGER, trigger, sizeof(*trigger))); |
641 |
} |
642 |
|
643 |
int |
644 |
audit_get_kaudit(auditinfo_addr_t *aia, size_t sz) |
645 |
{ |
646 |
|
647 |
if (sizeof(*aia) != sz) { |
648 |
errno = EINVAL; |
649 |
return (-1); |
650 |
} |
651 |
|
652 |
return (auditon(A_GETKAUDIT, aia, sz)); |
653 |
} |
654 |
|
655 |
int |
656 |
audit_set_kaudit(auditinfo_addr_t *aia, size_t sz) |
657 |
{ |
658 |
|
659 |
if (sizeof(*aia) != sz) { |
660 |
errno = EINVAL; |
661 |
return (-1); |
662 |
} |
663 |
|
664 |
return (auditon(A_SETKAUDIT, aia, sz)); |
665 |
} |
666 |
|
667 |
int |
668 |
audit_get_class(au_evclass_map_t *evc_map, size_t sz) |
669 |
{ |
670 |
|
671 |
if (sizeof(*evc_map) != sz) { |
672 |
errno = EINVAL; |
673 |
return (-1); |
674 |
} |
675 |
|
676 |
return (auditon(A_GETCLASS, evc_map, sz)); |
677 |
} |
678 |
|
679 |
int |
680 |
audit_set_class(au_evclass_map_t *evc_map, size_t sz) |
681 |
{ |
682 |
|
683 |
if (sizeof(*evc_map) != sz) { |
684 |
errno = EINVAL; |
685 |
return (-1); |
686 |
} |
687 |
|
688 |
return (auditon(A_SETCLASS, evc_map, sz)); |
689 |
} |
690 |
|
691 |
int |
692 |
audit_get_kmask(au_mask_t *kmask, size_t sz) |
693 |
{ |
694 |
if (sizeof(*kmask) != sz) { |
695 |
errno = EINVAL; |
696 |
return (-1); |
697 |
} |
698 |
|
699 |
return (auditon(A_GETKMASK, kmask, sz)); |
700 |
} |
701 |
|
702 |
int |
703 |
audit_set_kmask(au_mask_t *kmask, size_t sz) |
704 |
{ |
705 |
if (sizeof(*kmask) != sz) { |
706 |
errno = EINVAL; |
707 |
return (-1); |
708 |
} |
709 |
|
710 |
return (auditon(A_SETKMASK, kmask, sz)); |
711 |
} |
712 |
|
713 |
int |
714 |
audit_get_fsize(au_fstat_t *fstat, size_t sz) |
715 |
{ |
716 |
|
717 |
if (sizeof(*fstat) != sz) { |
718 |
errno = EINVAL; |
719 |
return (-1); |
720 |
} |
721 |
|
722 |
return (auditon(A_GETFSIZE, fstat, sz)); |
723 |
} |
724 |
|
725 |
int |
726 |
audit_set_fsize(au_fstat_t *fstat, size_t sz) |
727 |
{ |
728 |
|
729 |
if (sizeof(*fstat) != sz) { |
730 |
errno = EINVAL; |
731 |
return (-1); |
732 |
} |
733 |
|
734 |
return (auditon(A_SETFSIZE, fstat, sz)); |
735 |
} |
736 |
|
737 |
int |
738 |
audit_set_pmask(auditpinfo_t *api, size_t sz) |
739 |
{ |
740 |
|
741 |
if (sizeof(*api) != sz) { |
742 |
errno = EINVAL; |
743 |
return (-1); |
744 |
} |
745 |
|
746 |
return (auditon(A_SETPMASK, api, sz)); |
747 |
} |
748 |
|
749 |
int |
750 |
audit_get_pinfo(auditpinfo_t *api, size_t sz) |
751 |
{ |
752 |
|
753 |
if (sizeof(*api) != sz) { |
754 |
errno = EINVAL; |
755 |
return (-1); |
756 |
} |
757 |
|
758 |
return (auditon(A_GETPINFO, api, sz)); |
759 |
} |
760 |
|
761 |
int |
762 |
audit_get_pinfo_addr(auditpinfo_addr_t *apia, size_t sz) |
763 |
{ |
764 |
|
765 |
if (sizeof(*apia) != sz) { |
766 |
errno = EINVAL; |
767 |
return (-1); |
768 |
} |
769 |
|
770 |
return (auditon(A_GETPINFO_ADDR, apia, sz)); |
771 |
} |
772 |
|
773 |
int |
774 |
audit_get_sinfo_addr(auditinfo_addr_t *aia, size_t sz) |
775 |
{ |
776 |
|
777 |
if (sizeof(*aia) != sz) { |
778 |
errno = EINVAL; |
779 |
return (-1); |
780 |
} |
781 |
|
782 |
return (auditon(A_GETSINFO_ADDR, aia, sz)); |
783 |
} |
784 |
|
785 |
int |
786 |
audit_get_stat(au_stat_t *stats, size_t sz) |
787 |
{ |
788 |
|
789 |
if (sizeof(*stats) != sz) { |
790 |
errno = EINVAL; |
791 |
return (-1); |
792 |
} |
793 |
|
794 |
return (auditon(A_GETSTAT, stats, sz)); |
795 |
} |
796 |
|
797 |
int |
798 |
audit_set_stat(au_stat_t *stats, size_t sz) |
799 |
{ |
800 |
|
801 |
if (sizeof(*stats) != sz) { |
802 |
errno = EINVAL; |
803 |
return (-1); |
804 |
} |
805 |
|
806 |
return (auditon(A_GETSTAT, stats, sz)); |
807 |
} |
808 |
|
809 |
int |
810 |
audit_get_cwd(char *path, size_t sz) |
811 |
{ |
812 |
|
813 |
return (auditon(A_GETCWD, path, sz)); |
814 |
} |
815 |
|
816 |
int |
817 |
audit_get_car(char *path, size_t sz) |
818 |
{ |
819 |
|
820 |
return (auditon(A_GETCAR, path, sz)); |
821 |
} |