dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libbsm / common / generic.c
blob3d8a74db45d2930debf5147062d7f37ffb0f062a
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <netdb.h>
27 #include <netinet/in.h>
28 #include <pwd.h>
29 #include <sys/errno.h>
30 #include <sys/mutex.h>
31 #include <sys/param.h>
32 #include <sys/socket.h>
33 #include <sys/stat.h>
34 #include <sys/types.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <alloca.h>
38 #include <stdlib.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);
49 int aug_selected();
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 */
73 * cannot_audit:
74 * Return 1 if audit module not loaded.
75 * Return 0 otherwise.
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.
80 int
81 cannot_audit(force)
82 int force;
84 static int auc = AUC_UNSET;
85 int cond = 0;
87 if (auc == AUC_UNSET || force) {
88 if (auditon(A_GETCOND, (caddr_t)&cond, sizeof (cond))) {
89 auc = AUC_NEVER;
90 } else {
91 auc = cond;
94 return (auc == AUC_NEVER);
98 * aug_init():
99 * Initialize global variables.
101 void
102 aug_init()
104 aug_auid = (uid_t)-1;
105 aug_uid = (uid_t)-1;
106 aug_euid = (uid_t)-1;
107 aug_gid = (gid_t)-1;
108 aug_egid = (gid_t)-1;
109 aug_pid = -1;
110 aug_tid.at_port = 0;
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;
118 aug_event = 0;
119 aug_sorf = -2;
120 aug_text = NULL;
121 aug_text1 = NULL;
122 aug_text2 = NULL;
123 aug_na = 0;
124 aug_asid = (au_asid_t)(-1);
125 aug_afunc = NULL;
126 aug_path = NULL;
130 * aug_get_port:
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.
135 dev_t
136 aug_get_port()
138 int rc;
139 char *ttyn;
140 struct stat sb;
142 ttyn = ttyname(0);
143 if (ttyn == 0 || *ttyn == '\0') {
144 return (0);
147 rc = stat(ttyn, &sb);
148 if (rc < 0) {
149 perror("stat");
150 return (0);
153 return ((dev_t)sb.st_rdev);
157 * aug_get_machine:
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)
165 struct addrinfo *ai;
166 int err;
167 void *p;
169 err = getaddrinfo(hostname, NULL, NULL, &ai);
170 if (err != 0)
171 return (0);
173 switch (ai->ai_family) {
174 case AF_INET:
175 /* LINTED */
176 p = &((struct sockaddr_in *)ai->ai_addr)->sin_addr,
177 (void) memcpy(buf, p,
178 sizeof (((struct sockaddr_in *)0)->sin_addr));
179 *type = AU_IPv4;
180 break;
181 case AF_INET6:
182 /* LINTED */
183 p = &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr,
184 (void) memcpy(buf, p,
185 sizeof (((struct sockaddr_in6 *)0)->sin6_addr));
186 *type = AU_IPv6;
187 break;
188 default:
189 return (0);
192 freeaddrinfo(ai);
194 return (1);
197 void
198 aug_save_auid(au_id_t id)
200 aug_auid = id;
203 void
204 aug_save_uid(uid_t id)
206 aug_uid = id;
209 void
210 aug_save_euid(uid_t id)
212 aug_euid = id;
215 void
216 aug_save_gid(gid_t id)
218 aug_gid = id;
221 void
222 aug_save_egid(gid_t id)
224 aug_egid = id;
227 void
228 aug_save_pid(pid_t id)
230 aug_pid = id;
233 void
234 aug_save_asid(au_asid_t id)
236 aug_asid = id;
239 void
240 aug_save_afunc(int (*afunc)())
242 aug_afunc = afunc;
245 void
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;
253 void
254 aug_save_tid_ex(dev_t port, uint32_t *machine, uint32_t type)
256 int i;
258 aug_tid.at_port = port;
259 if ((type != AU_IPv4) && (type != AU_IPv6))
260 type = AU_IPv4;
262 aug_tid.at_type = type;
263 for (i = 0; i < (type/4); i++)
264 aug_tid.at_addr[i] = machine[i];
268 aug_save_me(void)
270 auditinfo_addr_t ai;
272 if (getaudit_addr(&ai, sizeof (ai)))
273 return (-1);
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);
285 return (0);
289 * aug_save_namask():
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.
296 aug_save_namask()
298 au_mask_t mask;
300 aug_na = -1;
303 * get non-attributable system event mask from kernel.
305 if (auditon(A_GETKMASK, (caddr_t)&mask, sizeof (mask)) != 0) {
306 return (-1);
309 aug_namask.am_success = mask.am_success;
310 aug_namask.am_failure = mask.am_failure;
311 aug_na = 1;
312 return (0);
315 void
316 aug_save_event(au_event_t id)
318 aug_event = id;
321 void
322 aug_save_sorf(int sorf)
324 aug_sorf = sorf;
327 void
328 aug_save_text(char *s)
330 free(aug_text);
331 if (s == NULL)
332 aug_text = NULL;
333 else
334 aug_text = strdup(s);
337 void
338 aug_save_text1(char *s)
340 free(aug_text1);
341 if (s == NULL)
342 aug_text1 = NULL;
343 else
344 aug_text1 = strdup(s);
347 void
348 aug_save_text2(char *s)
350 free(aug_text2);
351 if (s == NULL)
352 aug_text2 = NULL;
353 else
354 aug_text2 = strdup(s);
357 void
358 aug_save_na(int flag)
360 aug_na = flag;
363 void
364 aug_save_path(char *s)
366 free(aug_path);
367 if (s == NULL)
368 aug_path = NULL;
369 aug_path = strdup(s);
373 aug_save_policy()
375 uint32_t policy;
377 if (auditon(A_GETPOLICY, (caddr_t)&policy, sizeof (policy))) {
378 return (-1);
380 aug_policy = policy;
381 return (0);
385 * aug_audit:
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.
392 aug_audit(void)
394 int ad;
396 if (cannot_audit(0)) {
397 return (0);
400 if (aug_na) {
401 if (!aug_na_selected()) {
402 return (0);
404 } else if (!aug_selected()) {
405 return (0);
408 if ((ad = au_open()) == -1) {
409 return (-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) {
415 int ng;
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) {
436 (*aug_afunc)(ad);
438 #ifdef _LP64
439 (void) au_write(ad, au_to_return64((aug_sorf == 0) ? 0 : -1,
440 (int64_t)aug_sorf));
441 #else
442 (void) au_write(ad, au_to_return32((aug_sorf == 0) ? 0 : -1,
443 (int32_t)aug_sorf));
444 #endif
445 if (au_close(ad, 1, aug_event) < 0) {
446 (void) au_close(ad, 0, 0);
447 return (-1);
450 return (0);
454 aug_na_selected()
456 if (aug_na == -1) {
457 return (-1);
460 return (selected(aug_event, &aug_namask, aug_sorf));
464 aug_selected()
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))) {
473 return (-1);
476 return (selected(aug_event, &mask.ai_mask, aug_sorf));
479 static int
480 selected(au_event_t e, au_mask_t *m, int sorf)
482 int prs_sorf;
484 if (sorf == 0) {
485 prs_sorf = AU_PRS_SUCCESS;
486 } else if (sorf == -1) {
487 prs_sorf = AU_PRS_FAILURE;
488 } else {
489 prs_sorf = AU_PRS_BOTH;
492 return (au_preselect(e, m, prs_sorf, AU_PRS_REREAD));