8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / libbsm / common / generic.c
blob199076c193122c9fbf148278772f2c5615e55ada
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 <tsol/label.h>
40 #include <bsm/audit.h>
41 #include <bsm/libbsm.h>
42 #include <bsm/audit_uevents.h>
43 #include <bsm/audit_record.h>
45 #define AUC_NEVER -2 /* audit module not loaded */
47 /* Private Functions */
48 static int selected(au_event_t, au_mask_t *, int);
50 int aug_selected();
51 int aug_na_selected();
53 /* Global Variables */
54 static au_id_t aug_auid; /* auid of user writing audit record */
55 static uid_t aug_uid; /* uid of user writing audit record */
56 static uid_t aug_euid; /* euid of user writing audit record */
57 static gid_t aug_gid; /* gid of user writing audit record */
58 static gid_t aug_egid; /* euid of user writing audit record */
59 static pid_t aug_pid; /* pid of user writing audit record */
60 static au_tid_addr_t aug_tid; /* tid of user writing audit record */
61 static int aug_na; /* 0 if event is attributable */
62 static au_mask_t aug_namask; /* not attributable flags */
63 static au_event_t aug_event; /* id of event being audited */
64 static int aug_sorf; /* success or failure of aug_event */
65 static char *aug_text; /* misc text to be written to trail */
66 static char *aug_text1; /* misc text to be written to trail */
67 static char *aug_text2; /* misc text to be written to trail */
68 static au_asid_t aug_asid; /* asid of process writing record */
69 static int (*aug_afunc)(); /* write additional tokens if needed */
70 static char *aug_path; /* path token */
71 static uint32_t aug_policy; /* kernel audit policy */
74 * cannot_audit:
75 * Return 1 if audit module not loaded.
76 * Return 0 otherwise.
78 * The argument, force, should be set to 1 for long-lived processes
79 * like some daemons. Force should be set to 0 for most programs.
81 int
82 cannot_audit(force)
83 int force;
85 static int auc = AUC_UNSET;
86 int cond = 0;
88 if (auc == AUC_UNSET || force) {
89 if (auditon(A_GETCOND, (caddr_t)&cond, sizeof (cond))) {
90 auc = AUC_NEVER;
91 } else {
92 auc = cond;
95 return (auc == AUC_NEVER);
99 * aug_init():
100 * Initialize global variables.
102 void
103 aug_init()
105 aug_auid = (uid_t)-1;
106 aug_uid = (uid_t)-1;
107 aug_euid = (uid_t)-1;
108 aug_gid = (gid_t)-1;
109 aug_egid = (gid_t)-1;
110 aug_pid = -1;
111 aug_tid.at_port = 0;
112 aug_tid.at_type = AU_IPv4;
113 aug_tid.at_addr[0] = 0;
114 aug_tid.at_addr[1] = 0;
115 aug_tid.at_addr[2] = 0;
116 aug_tid.at_addr[3] = 0;
117 aug_namask.am_success = AU_MASK_ALL;
118 aug_namask.am_failure = AU_MASK_ALL;
119 aug_event = 0;
120 aug_sorf = -2;
121 aug_text = NULL;
122 aug_text1 = NULL;
123 aug_text2 = NULL;
124 aug_na = 0;
125 aug_asid = (au_asid_t)(-1);
126 aug_afunc = NULL;
127 aug_path = NULL;
131 * aug_get_port:
132 * Return the raw device number of the port to which the
133 * current process is attached (assumed to be attached
134 * through file descriptor 0) or 0 if can't stat the port.
136 dev_t
137 aug_get_port()
139 int rc;
140 char *ttyn;
141 struct stat sb;
143 ttyn = ttyname(0);
144 if (ttyn == 0 || *ttyn == '\0') {
145 return (0);
148 rc = stat(ttyn, &sb);
149 if (rc < 0) {
150 perror("stat");
151 return (0);
154 return ((dev_t)sb.st_rdev);
158 * aug_get_machine:
159 * Return internet address of host hostname,
160 * or 0 if can't do lookup.
164 aug_get_machine(const char *hostname, uint32_t *buf, uint32_t *type)
166 struct addrinfo *ai;
167 int err;
168 void *p;
170 err = getaddrinfo(hostname, NULL, NULL, &ai);
171 if (err != 0)
172 return (0);
174 switch (ai->ai_family) {
175 case AF_INET:
176 /* LINTED */
177 p = &((struct sockaddr_in *)ai->ai_addr)->sin_addr,
178 (void) memcpy(buf, p,
179 sizeof (((struct sockaddr_in *)0)->sin_addr));
180 *type = AU_IPv4;
181 break;
182 case AF_INET6:
183 /* LINTED */
184 p = &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr,
185 (void) memcpy(buf, p,
186 sizeof (((struct sockaddr_in6 *)0)->sin6_addr));
187 *type = AU_IPv6;
188 break;
189 default:
190 return (0);
193 freeaddrinfo(ai);
195 return (1);
198 void
199 aug_save_auid(au_id_t id)
201 aug_auid = id;
204 void
205 aug_save_uid(uid_t id)
207 aug_uid = id;
210 void
211 aug_save_euid(uid_t id)
213 aug_euid = id;
216 void
217 aug_save_gid(gid_t id)
219 aug_gid = id;
222 void
223 aug_save_egid(gid_t id)
225 aug_egid = id;
228 void
229 aug_save_pid(pid_t id)
231 aug_pid = id;
234 void
235 aug_save_asid(au_asid_t id)
237 aug_asid = id;
240 void
241 aug_save_afunc(int (*afunc)())
243 aug_afunc = afunc;
246 void
247 aug_save_tid(dev_t port, int machine)
249 aug_tid.at_port = port;
250 aug_tid.at_type = AU_IPv4;
251 aug_tid.at_addr[0] = machine;
254 void
255 aug_save_tid_ex(dev_t port, uint32_t *machine, uint32_t type)
257 int i;
259 aug_tid.at_port = port;
260 if ((type != AU_IPv4) && (type != AU_IPv6))
261 type = AU_IPv4;
263 aug_tid.at_type = type;
264 for (i = 0; i < (type/4); i++)
265 aug_tid.at_addr[i] = machine[i];
269 aug_save_me(void)
271 auditinfo_addr_t ai;
273 if (getaudit_addr(&ai, sizeof (ai)))
274 return (-1);
276 aug_save_auid(ai.ai_auid);
277 aug_save_euid(geteuid());
278 aug_save_egid(getegid());
279 aug_save_uid(getuid());
280 aug_save_gid(getgid());
281 aug_save_pid(getpid());
282 aug_save_asid(ai.ai_asid);
283 aug_save_tid_ex(ai.ai_termid.at_port,
284 ai.ai_termid.at_addr,
285 ai.ai_termid.at_type);
286 return (0);
290 * aug_save_namask():
291 * Save the namask using the naflags entry in the audit_control file.
292 * Return 0 if successful.
293 * Return -1, and don't change the namask, if failed.
294 * Side Effect: Sets aug_na to -1 if error, 1 if successful.
297 aug_save_namask()
299 au_mask_t mask;
301 aug_na = -1;
304 * get non-attributable system event mask from kernel.
306 if (auditon(A_GETKMASK, (caddr_t)&mask, sizeof (mask)) != 0) {
307 return (-1);
310 aug_namask.am_success = mask.am_success;
311 aug_namask.am_failure = mask.am_failure;
312 aug_na = 1;
313 return (0);
316 void
317 aug_save_event(au_event_t id)
319 aug_event = id;
322 void
323 aug_save_sorf(int sorf)
325 aug_sorf = sorf;
328 void
329 aug_save_text(char *s)
331 if (aug_text != NULL)
332 free(aug_text);
333 if (s == NULL)
334 aug_text = NULL;
335 else
336 aug_text = strdup(s);
339 void
340 aug_save_text1(char *s)
342 if (aug_text1 != NULL)
343 free(aug_text1);
344 if (s == NULL)
345 aug_text1 = NULL;
346 else
347 aug_text1 = strdup(s);
350 void
351 aug_save_text2(char *s)
353 if (aug_text2 != NULL)
354 free(aug_text2);
355 if (s == NULL)
356 aug_text2 = NULL;
357 else
358 aug_text2 = strdup(s);
361 void
362 aug_save_na(int flag)
364 aug_na = flag;
367 void
368 aug_save_path(char *s)
370 if (aug_path != NULL)
371 free(aug_path);
372 if (s == NULL)
373 aug_path = NULL;
374 aug_path = strdup(s);
378 aug_save_policy()
380 uint32_t policy;
382 if (auditon(A_GETPOLICY, (caddr_t)&policy, sizeof (policy))) {
383 return (-1);
385 aug_policy = policy;
386 return (0);
390 * aug_audit:
391 * Cut and audit record if it is selected.
392 * Return 0, if successfully written.
393 * Return 0, if not written, and not expected to write.
394 * Return -1, if not written because of unexpected error.
397 aug_audit(void)
399 int ad;
401 if (cannot_audit(0)) {
402 return (0);
405 if (aug_na) {
406 if (!aug_na_selected()) {
407 return (0);
409 } else if (!aug_selected()) {
410 return (0);
413 if ((ad = au_open()) == -1) {
414 return (-1);
417 (void) au_write(ad, au_to_subject_ex(aug_auid, aug_euid, aug_egid,
418 aug_uid, aug_gid, aug_pid, aug_asid, &aug_tid));
419 if (is_system_labeled())
420 (void) au_write(ad, au_to_mylabel());
421 if (aug_policy & AUDIT_GROUP) {
422 int ng;
423 int maxgrp = getgroups(0, NULL);
424 gid_t *grplst = alloca(maxgrp * sizeof (gid_t));
426 if ((ng = getgroups(maxgrp, grplst)) > 0) {
427 (void) au_write(ad, au_to_newgroups(ng, grplst));
430 if (aug_text != NULL) {
431 (void) au_write(ad, au_to_text(aug_text));
433 if (aug_text1 != NULL) {
434 (void) au_write(ad, au_to_text(aug_text1));
436 if (aug_text2 != NULL) {
437 (void) au_write(ad, au_to_text(aug_text2));
439 if (aug_path != NULL) {
440 (void) au_write(ad, au_to_path(aug_path));
442 if (aug_afunc != NULL) {
443 (*aug_afunc)(ad);
445 #ifdef _LP64
446 (void) au_write(ad, au_to_return64((aug_sorf == 0) ? 0 : -1,
447 (int64_t)aug_sorf));
448 #else
449 (void) au_write(ad, au_to_return32((aug_sorf == 0) ? 0 : -1,
450 (int32_t)aug_sorf));
451 #endif
452 if (au_close(ad, 1, aug_event) < 0) {
453 (void) au_close(ad, 0, 0);
454 return (-1);
457 return (0);
461 aug_na_selected()
463 if (aug_na == -1) {
464 return (-1);
467 return (selected(aug_event, &aug_namask, aug_sorf));
471 aug_selected()
473 auditinfo_addr_t mask;
475 if (aug_uid > MAXEPHUID) {
476 (void) aug_save_namask();
477 return (aug_na_selected());
479 if (getaudit_addr(&mask, sizeof (mask))) {
480 return (-1);
483 return (selected(aug_event, &mask.ai_mask, aug_sorf));
486 static int
487 selected(au_event_t e, au_mask_t *m, int sorf)
489 int prs_sorf;
491 if (sorf == 0) {
492 prs_sorf = AU_PRS_SUCCESS;
493 } else if (sorf == -1) {
494 prs_sorf = AU_PRS_FAILURE;
495 } else {
496 prs_sorf = AU_PRS_BOTH;
499 return (au_preselect(e, m, prs_sorf, AU_PRS_REREAD));