Deleted Added
sdiff udiff text old ( 187214 ) new ( 189279 )
full compact
1/*-
2 * Copyright (c) 2008 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

--- 10 unchanged lines hidden (view full) ---

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 * $P4: //depot/projects/trustedbsd/openbsm/libauditd/auditd_lib.c#2 $
30 */
31
32#include <sys/param.h>
33
34#include <config/config.h>
35
36#include <sys/dirent.h>
37#include <sys/mount.h>

--- 9 unchanged lines hidden (view full) ---

47
48#include <netinet/in.h>
49
50#include <bsm/audit.h>
51#include <bsm/audit_uevents.h>
52#include <bsm/auditd_lib.h>
53#include <bsm/libbsm.h>
54
55#include <err.h>
56#include <errno.h>
57#include <fcntl.h>
58#include <stdio.h>
59#include <string.h>
60#include <stdlib.h>
61#include <time.h>
62#include <unistd.h>

--- 9 unchanged lines hidden (view full) ---

72/*
73 * XXX This is temporary until this is moved to <bsm/audit.h> and shared with
74 * the kernel.
75 */
76#ifndef AUDIT_HARD_LIMIT_FREE_BLOCKS
77#define AUDIT_HARD_LIMIT_FREE_BLOCKS 4
78#endif
79
80struct dir_ent {
81 char *dirname;
82 uint8_t softlim;
83 uint8_t hardlim;
84 TAILQ_ENTRY(dir_ent) dirs;
85};
86
87static TAILQ_HEAD(, dir_ent) dir_q;
88static int minval = -1;
89
90static char *auditd_errmsg[] = {
91 "no error", /* ADE_NOERR ( 0) */
92 "could not parse audit_control(5) file", /* ADE_PARSE ( 1) */
93 "auditon(2) failed", /* ADE_AUDITON ( 2) */
94 "malloc(3) failed", /* ADE_NOMEM ( 3) */
95 "all audit log directories over soft limit", /* ADE_SOFTLIM ( 4) */
96 "all audit log directories over hard limit", /* ADE_HARDLIM ( 5) */
97 "could not create file name string", /* ADE_STRERR ( 6) */

--- 4 unchanged lines hidden (view full) ---

102 "auditctl(2) failed (trail not swapped)", /* ADE_ACTLERR (11) */
103 "could not swap audit trail file", /* ADE_SWAPERR (12) */
104 "could not rename crash recovery file", /* ADE_RENAME (13) */
105 "could not read 'current' link file", /* ADE_READLINK (14) */
106 "could not create 'current' link file", /* ADE_SYMLINK (15) */
107 "invalid argument", /* ADE_INVAL (16) */
108 "could not resolve hostname to address", /* ADE_GETADDR (17) */
109 "address family not supported", /* ADE_ADDRFAM (18) */
110};
111
112#define MAXERRCODE (sizeof(auditd_errmsg) / sizeof(auditd_errmsg[0]))
113
114#define NA_EVENT_STR_SIZE 25
115#define POL_STR_SIZE 128
116
117

--- 42 unchanged lines hidden (view full) ---

160 /*
161 * Sanity check on file name.
162 */
163 if (strlen(name) != (FILENAME_LEN - 1)) {
164 errno = EINVAL;
165 return (NULL);
166 }
167
168 asprintf(&fn, "%s/%s", dirent->dirname, name);
169 return (fn);
170}
171
172/*
173 * Insert the directory entry in the list by the way they are ordered in
174 * audit_control(5). Move the entries that are over the soft and hard limits
175 * toward the tail.
176 */

--- 22 unchanged lines hidden (view full) ---

199 * ADE_PARSE error parsing audit_control(5).
200 * ADE_AUDITON error getting/setting auditon(2) value.
201 * ADE_GETADDR error getting address info for host.
202 * ADE_ADDRFAM un-supported address family.
203 */
204int
205auditd_set_host(void)
206{
207 char hoststr[MAXHOSTNAMELEN];
208 struct sockaddr_in6 *sin6;
209 struct sockaddr_in *sin;
210 struct addrinfo *res;
211 struct auditinfo_addr aia;
212 int error, ret = ADE_NOERR;
213
214 if (getachost(hoststr, MAXHOSTNAMELEN) != 0) {
215
216 ret = ADE_PARSE;
217
218 /*
219 * To maintain reverse compatability with older audit_control
220 * files, simply drop a warning if the host parameter has not
221 * been set. However, we will explicitly disable the
222 * generation of extended audit header by passing in a zeroed
223 * termid structure.
224 */
225 bzero(&aia, sizeof(aia));
226 aia.ai_termid.at_type = AU_IPv4;
227 error = auditon(A_SETKAUDIT, &aia, sizeof(aia));
228 if (error < 0 && errno != ENOSYS)
229 ret = ADE_AUDITON;
230 return (ret);
231 }
232 error = getaddrinfo(hoststr, NULL, NULL, &res);
233 if (error)
234 return (ADE_GETADDR);
235 switch (res->ai_family) {
236 case PF_INET6:
237 sin6 = (struct sockaddr_in6 *) res->ai_addr;
238 bcopy(&sin6->sin6_addr.s6_addr,
239 &aia.ai_termid.at_addr[0], sizeof(struct in6_addr));
240 aia.ai_termid.at_type = AU_IPv6;

--- 25 unchanged lines hidden (view full) ---

266 * ADE_PARSE error parsing audit_control(5),
267 * ADE_AUDITON error getting/setting auditon(2) value.
268 */
269int
270auditd_set_minfree(void)
271{
272 au_qctrl_t qctrl;
273
274 if (getacmin(&minval) != 0)
275 return (ADE_PARSE);
276
277 if (auditon(A_GETQCTRL, &qctrl, sizeof(qctrl)) != 0)
278 return (ADE_AUDITON);
279
280 if (qctrl.aq_minfree != minval) {
281 qctrl.aq_minfree = minval;
282 if (auditon(A_SETQCTRL, &qctrl, sizeof(qctrl)) != 0)
283 return (ADE_AUDITON);
284 }
285
286 return (0);
287}
288
289/*
290 * Parses the "dir" entry in audit_control(5) into an ordered list. Also, will
291 * set the minfree value if not already set. Arguments include function
292 * pointers to audit_warn functions for soft and hard limits. Returns:
293 * ADE_NOERR on success,
294 * ADE_PARSE error parsing audit_control(5),
295 * ADE_AUDITON error getting/setting auditon(2) value,
296 * ADE_NOMEM error allocating memory,
297 * ADE_SOFTLIM if all the directories are over the soft limit,
298 * ADE_HARDLIM if all the directories are over the hard limit,
299 */
300int
301auditd_read_dirs(int (*warn_soft)(char *), int (*warn_hard)(char *))
302{
303 char cur_dir[MAXNAMLEN];
304 struct dir_ent *dirent;
305 struct statfs sfs;
306 int err;
307 char soft, hard;
308 int tcnt = 0;
309 int scnt = 0;
310 int hcnt = 0;
311
312 if (minval == -1 && (err = auditd_set_minfree()) != 0)
313 return (err);
314
315 /*
316 * Init directory q. Force a re-read of the file the next time.
317 */
318 free_dir_q();
319 endac();
320
321 /*
322 * Read the list of directories into an ordered linked list
323 * admin's preference, then those over soft limit and, finally,
324 * those over the hard limit.
325 *
326 * XXX We should use the reentrant interfaces once they are
327 * available.
328 */
329 while (getacdir(cur_dir, MAXNAMLEN) >= 0) {
330 if (statfs(cur_dir, &sfs) < 0)
331 continue; /* XXX should warn */
332 soft = (sfs.f_bfree < (sfs.f_blocks / (100 / minval))) ? 1 : 0;
333 hard = (sfs.f_bfree < AUDIT_HARD_LIMIT_FREE_BLOCKS) ? 1 : 0;
334 if (soft) {
335 if (warn_soft)
336 (*warn_soft)(cur_dir);
337 scnt++;
338 }
339 if (hard) {
340 if (warn_hard)

--- 21 unchanged lines hidden (view full) ---

362 return (ADE_SOFTLIM);
363 return (0);
364}
365
366void
367auditd_close_dirs(void)
368{
369 free_dir_q();
370 minval = -1;
371}
372
373
374/*
375 * Process the audit event file, obtaining a class mapping for each event, and
376 * set that mapping into the kernel. Return:
377 * n number of event mappings that were successfully processed,
378 * ADE_NOMEM if there was an error allocating memory.

--- 165 unchanged lines hidden (view full) ---

544
545 if (strlen(TS) != (TIMESTAMP_LEN - 1) ||
546 snprintf(timestr, FILENAME_LEN, "%s.%s", TS, NOT_TERMINATED) < 0) {
547 errno = EINVAL;
548 return (ADE_STRERR);
549 }
550
551 /* Try until we succeed. */
552 while ((dirent = TAILQ_FIRST(&dir_q))) {
553 if (dirent->hardlim)
554 continue;
555 if ((fn = affixdir(timestr, dirent)) == NULL)
556 return (ADE_STRERR);
557
558 /*
559 * Create and open the file; then close and pass to the
560 * kernel if all went well.

--- 40 unchanged lines hidden (view full) ---

601 return (ADE_SWAPERR);
602}
603
604/*
605 * Mask calling process from being audited. Returns:
606 * ADE_NOERR on success,
607 * ADE_SETAUDIT if setaudit(2) fails.
608 */
609int
610auditd_prevent_audit(void)
611{
612 auditinfo_t ai;
613
614 /*
615 * To prevent event feedback cycles and avoid audit becoming stalled if
616 * auditing is suspended we mask this processes events from being
617 * audited. We allow the uid, tid, and mask fields to be implicitly
618 * set to zero, but do set the audit session ID to the PID.
619 *
620 * XXXRW: Is there more to it than this?
621 */
622 bzero(&ai, sizeof(ai));
623 ai.ai_asid = getpid();
624 if (setaudit(&ai) != 0)
625 return (ADE_SETAUDIT);
626 return (ADE_NOERR);
627}
628
629/*
630 * Generate and submit audit record for audit startup or shutdown. The event
631 * argument can be AUE_audit_recovery, AUE_audit_startup or
632 * AUE_audit_shutdown. The path argument will add a path token, if not NULL.
633 * Returns:
634 * AUE_NOERR on success,
635 * ADE_NOMEM if memory allocation fails,

--- 72 unchanged lines hidden (view full) ---

708 if (len > 0) {
709 /* 'current' exist but is it pointing at a valid file? */
710 recoveredname[len++] = '\0';
711 if (stat(recoveredname, &sb) == 0) {
712 /* Yes, rename it to a crash recovery file. */
713 strlcpy(newname, recoveredname, MAXPATHLEN);
714
715 if ((ptr = strstr(newname, NOT_TERMINATED)) != NULL) {
716 strlcpy(ptr, CRASH_RECOVERY, TIMESTAMP_LEN);
717 if (rename(recoveredname, newname) != 0)
718 return (ADE_RENAME);
719 } else
720 return (ADE_STRERR);
721
722 path = newname;
723 }
724

--- 20 unchanged lines hidden (view full) ---

745 * notify. Return:
746 * 0 on success,
747 * -1 on failure.
748 */
749int
750audit_quick_start(void)
751{
752 int err;
753 char *newfile;
754 time_t tt;
755 char TS[TIMESTAMP_LEN];
756
757 /*
758 * Mask auditing of this process.
759 */
760 if (auditd_prevent_audit() != 0)
761 return (-1);
762
763 /*

--- 4 unchanged lines hidden (view full) ---

768 return (-1);
769
770 /*
771 * Create a new audit trail log.
772 */
773 if (getTSstr(tt, TS, TIMESTAMP_LEN) != 0)
774 return (-1);
775 err = auditd_swap_trail(TS, &newfile, getgid(), NULL);
776 if (err != ADE_NOERR && err != ADE_ACTL)
777 return (-1);
778
779 /*
780 * Add the current symlink and recover from crash, if needed.
781 */
782 if (auditd_new_curlink(newfile) != 0)
783 return(-1);
784
785 /*
786 * At this point auditing has started so generate audit start-up record.
787 */
788 if (auditd_gen_record(AUE_audit_startup, NULL) != 0)
789 return (-1);
790
791 /*
792 * Configure the audit controls.
793 */
794 (void) auditd_set_evcmap();
795 (void) auditd_set_namask();
796 (void) auditd_set_policy();
797 (void) auditd_set_fsize();
798 (void) auditd_set_minfree();
799 (void) auditd_set_host();
800
801 return (0);
802}
803
804/*
805 * Shut down auditing quickly. Assumes that is only called on system shutdown.
806 * Returns:
807 * 0 on success,
808 * -1 on failure.
809 */

--- 40 unchanged lines hidden (view full) ---

850 oldname[len++] = '\0';
851
852 if (getTSstr(tt, TS, TIMESTAMP_LEN) != 0)
853 return (-1);
854
855 strlcpy(newname, oldname, len);
856
857 if ((ptr = strstr(newname, NOT_TERMINATED)) != NULL) {
858 strlcpy(ptr, TS, TIMESTAMP_LEN);
859 if (rename(oldname, newname) != 0)
860 return (-1);
861 } else
862 return (-1);
863
864 (void) unlink(AUDIT_CURRENT_LINK);
865
866 return (0);
867}