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.
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.
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]
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 #include <netinet/in.h>
29 #include <sys/errno.h>
30 #include <sys/mutex.h>
31 #include <sys/param.h>
32 #include <sys/socket.h>
34 #include <sys/types.h>
39 #include <bsm/audit.h>
40 #include <bsm/libbsm.h>
41 #include <bsm/audit_uevents.h>
42 #include <bsm/audit_record.h>
44 #define AUC_NEVER -2 /* audit module not loaded */
46 /* Private Functions */
47 static int selected(au_event_t
, au_mask_t
*, int);
50 int aug_na_selected();
52 /* Global Variables */
53 static au_id_t aug_auid
; /* auid of user writing audit record */
54 static uid_t aug_uid
; /* uid of user writing audit record */
55 static uid_t aug_euid
; /* euid of user writing audit record */
56 static gid_t aug_gid
; /* gid of user writing audit record */
57 static gid_t aug_egid
; /* euid of user writing audit record */
58 static pid_t aug_pid
; /* pid of user writing audit record */
59 static au_tid_addr_t aug_tid
; /* tid of user writing audit record */
60 static int aug_na
; /* 0 if event is attributable */
61 static au_mask_t aug_namask
; /* not attributable flags */
62 static au_event_t aug_event
; /* id of event being audited */
63 static int aug_sorf
; /* success or failure of aug_event */
64 static char *aug_text
; /* misc text to be written to trail */
65 static char *aug_text1
; /* misc text to be written to trail */
66 static char *aug_text2
; /* misc text to be written to trail */
67 static au_asid_t aug_asid
; /* asid of process writing record */
68 static int (*aug_afunc
)(); /* write additional tokens if needed */
69 static char *aug_path
; /* path token */
70 static uint32_t aug_policy
; /* kernel audit policy */
74 * Return 1 if audit module not loaded.
77 * The argument, force, should be set to 1 for long-lived processes
78 * like some daemons. Force should be set to 0 for most programs.
84 static int auc
= AUC_UNSET
;
87 if (auc
== AUC_UNSET
|| force
) {
88 if (auditon(A_GETCOND
, (caddr_t
)&cond
, sizeof (cond
))) {
94 return (auc
== AUC_NEVER
);
99 * Initialize global variables.
104 aug_auid
= (uid_t
)-1;
106 aug_euid
= (uid_t
)-1;
108 aug_egid
= (gid_t
)-1;
111 aug_tid
.at_type
= AU_IPv4
;
112 aug_tid
.at_addr
[0] = 0;
113 aug_tid
.at_addr
[1] = 0;
114 aug_tid
.at_addr
[2] = 0;
115 aug_tid
.at_addr
[3] = 0;
116 aug_namask
.am_success
= AU_MASK_ALL
;
117 aug_namask
.am_failure
= AU_MASK_ALL
;
124 aug_asid
= (au_asid_t
)(-1);
131 * Return the raw device number of the port to which the
132 * current process is attached (assumed to be attached
133 * through file descriptor 0) or 0 if can't stat the port.
143 if (ttyn
== 0 || *ttyn
== '\0') {
147 rc
= stat(ttyn
, &sb
);
153 return ((dev_t
)sb
.st_rdev
);
158 * Return internet address of host hostname,
159 * or 0 if can't do lookup.
163 aug_get_machine(const char *hostname
, uint32_t *buf
, uint32_t *type
)
169 err
= getaddrinfo(hostname
, NULL
, NULL
, &ai
);
173 switch (ai
->ai_family
) {
176 p
= &((struct sockaddr_in
*)ai
->ai_addr
)->sin_addr
,
177 (void) memcpy(buf
, p
,
178 sizeof (((struct sockaddr_in
*)0)->sin_addr
));
183 p
= &((struct sockaddr_in6
*)ai
->ai_addr
)->sin6_addr
,
184 (void) memcpy(buf
, p
,
185 sizeof (((struct sockaddr_in6
*)0)->sin6_addr
));
198 aug_save_auid(au_id_t id
)
204 aug_save_uid(uid_t id
)
210 aug_save_euid(uid_t id
)
216 aug_save_gid(gid_t id
)
222 aug_save_egid(gid_t id
)
228 aug_save_pid(pid_t id
)
234 aug_save_asid(au_asid_t id
)
240 aug_save_afunc(int (*afunc
)())
246 aug_save_tid(dev_t port
, int machine
)
248 aug_tid
.at_port
= port
;
249 aug_tid
.at_type
= AU_IPv4
;
250 aug_tid
.at_addr
[0] = machine
;
254 aug_save_tid_ex(dev_t port
, uint32_t *machine
, uint32_t type
)
258 aug_tid
.at_port
= port
;
259 if ((type
!= AU_IPv4
) && (type
!= AU_IPv6
))
262 aug_tid
.at_type
= type
;
263 for (i
= 0; i
< (type
/4); i
++)
264 aug_tid
.at_addr
[i
] = machine
[i
];
272 if (getaudit_addr(&ai
, sizeof (ai
)))
275 aug_save_auid(ai
.ai_auid
);
276 aug_save_euid(geteuid());
277 aug_save_egid(getegid());
278 aug_save_uid(getuid());
279 aug_save_gid(getgid());
280 aug_save_pid(getpid());
281 aug_save_asid(ai
.ai_asid
);
282 aug_save_tid_ex(ai
.ai_termid
.at_port
,
283 ai
.ai_termid
.at_addr
,
284 ai
.ai_termid
.at_type
);
290 * Save the namask using the naflags entry in the audit_control file.
291 * Return 0 if successful.
292 * Return -1, and don't change the namask, if failed.
293 * Side Effect: Sets aug_na to -1 if error, 1 if successful.
303 * get non-attributable system event mask from kernel.
305 if (auditon(A_GETKMASK
, (caddr_t
)&mask
, sizeof (mask
)) != 0) {
309 aug_namask
.am_success
= mask
.am_success
;
310 aug_namask
.am_failure
= mask
.am_failure
;
316 aug_save_event(au_event_t id
)
322 aug_save_sorf(int sorf
)
328 aug_save_text(char *s
)
334 aug_text
= strdup(s
);
338 aug_save_text1(char *s
)
344 aug_text1
= strdup(s
);
348 aug_save_text2(char *s
)
354 aug_text2
= strdup(s
);
358 aug_save_na(int flag
)
364 aug_save_path(char *s
)
369 aug_path
= strdup(s
);
377 if (auditon(A_GETPOLICY
, (caddr_t
)&policy
, sizeof (policy
))) {
386 * Cut and audit record if it is selected.
387 * Return 0, if successfully written.
388 * Return 0, if not written, and not expected to write.
389 * Return -1, if not written because of unexpected error.
396 if (cannot_audit(0)) {
401 if (!aug_na_selected()) {
404 } else if (!aug_selected()) {
408 if ((ad
= au_open()) == -1) {
412 (void) au_write(ad
, au_to_subject_ex(aug_auid
, aug_euid
, aug_egid
,
413 aug_uid
, aug_gid
, aug_pid
, aug_asid
, &aug_tid
));
414 if (aug_policy
& AUDIT_GROUP
) {
416 int maxgrp
= getgroups(0, NULL
);
417 gid_t
*grplst
= alloca(maxgrp
* sizeof (gid_t
));
419 if ((ng
= getgroups(maxgrp
, grplst
)) > 0) {
420 (void) au_write(ad
, au_to_newgroups(ng
, grplst
));
423 if (aug_text
!= NULL
) {
424 (void) au_write(ad
, au_to_text(aug_text
));
426 if (aug_text1
!= NULL
) {
427 (void) au_write(ad
, au_to_text(aug_text1
));
429 if (aug_text2
!= NULL
) {
430 (void) au_write(ad
, au_to_text(aug_text2
));
432 if (aug_path
!= NULL
) {
433 (void) au_write(ad
, au_to_path(aug_path
));
435 if (aug_afunc
!= NULL
) {
439 (void) au_write(ad
, au_to_return64((aug_sorf
== 0) ? 0 : -1,
442 (void) au_write(ad
, au_to_return32((aug_sorf
== 0) ? 0 : -1,
445 if (au_close(ad
, 1, aug_event
) < 0) {
446 (void) au_close(ad
, 0, 0);
460 return (selected(aug_event
, &aug_namask
, aug_sorf
));
466 auditinfo_addr_t mask
;
468 if (aug_uid
> MAXEPHUID
) {
469 (void) aug_save_namask();
470 return (aug_na_selected());
472 if (getaudit_addr(&mask
, sizeof (mask
))) {
476 return (selected(aug_event
, &mask
.ai_mask
, aug_sorf
));
480 selected(au_event_t e
, au_mask_t
*m
, int sorf
)
485 prs_sorf
= AU_PRS_SUCCESS
;
486 } else if (sorf
== -1) {
487 prs_sorf
= AU_PRS_FAILURE
;
489 prs_sorf
= AU_PRS_BOTH
;
492 return (au_preselect(e
, m
, prs_sorf
, AU_PRS_REREAD
));