1 /*
2 * CDDL HEADER START
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
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>
44
45 #define AUC_NEVER -2 /* audit module not loaded */
46
47 /* Private Functions */
48 static int selected(au_event_t, au_mask_t *, int);
49
50 int aug_selected();
51 int aug_na_selected();
52
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 */
72
73 /*
74 * cannot_audit:
75 * Return 1 if audit module not loaded.
76 * Return 0 otherwise.
77 *
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.
80 */
81 int
cannot_audit(force)82 cannot_audit(force)
83 int force;
84 {
85 static int auc = AUC_UNSET;
86 int cond = 0;
87
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;
93 }
94 }
95 return (auc == AUC_NEVER);
96 }
97
98 /*
99 * aug_init():
100 * Initialize global variables.
101 */
102 void
aug_init()103 aug_init()
104 {
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;
128 }
129
130 /*
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.
135 */
136 dev_t
aug_get_port()137 aug_get_port()
138 {
139 int rc;
140 char *ttyn;
141 struct stat sb;
142
143 ttyn = ttyname(0);
144 if (ttyn == 0 || *ttyn == '\0') {
145 return (0);
146 }
147
148 rc = stat(ttyn, &sb);
149 if (rc < 0) {
150 perror("stat");
151 return (0);
152 }
153
154 return ((dev_t)sb.st_rdev);
155 }
156
157 /*
158 * aug_get_machine:
159 * Return internet address of host hostname,
160 * or 0 if can't do lookup.
161 */
162
163 int
aug_get_machine(const char * hostname,uint32_t * buf,uint32_t * type)164 aug_get_machine(const char *hostname, uint32_t *buf, uint32_t *type)
165 {
166 struct addrinfo *ai;
167 int err;
168 void *p;
169
170 err = getaddrinfo(hostname, NULL, NULL, &ai);
171 if (err != 0)
172 return (0);
173
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);
191 }
192
193 freeaddrinfo(ai);
194
195 return (1);
196 }
197
198 void
aug_save_auid(au_id_t id)199 aug_save_auid(au_id_t id)
200 {
201 aug_auid = id;
202 }
203
204 void
aug_save_uid(uid_t id)205 aug_save_uid(uid_t id)
206 {
207 aug_uid = id;
208 }
209
210 void
aug_save_euid(uid_t id)211 aug_save_euid(uid_t id)
212 {
213 aug_euid = id;
214 }
215
216 void
aug_save_gid(gid_t id)217 aug_save_gid(gid_t id)
218 {
219 aug_gid = id;
220 }
221
222 void
aug_save_egid(gid_t id)223 aug_save_egid(gid_t id)
224 {
225 aug_egid = id;
226 }
227
228 void
aug_save_pid(pid_t id)229 aug_save_pid(pid_t id)
230 {
231 aug_pid = id;
232 }
233
234 void
aug_save_asid(au_asid_t id)235 aug_save_asid(au_asid_t id)
236 {
237 aug_asid = id;
238 }
239
240 void
aug_save_afunc(int (* afunc)())241 aug_save_afunc(int (*afunc)())
242 {
243 aug_afunc = afunc;
244 }
245
246 void
aug_save_tid(dev_t port,int machine)247 aug_save_tid(dev_t port, int machine)
248 {
249 aug_tid.at_port = port;
250 aug_tid.at_type = AU_IPv4;
251 aug_tid.at_addr[0] = machine;
252 }
253
254 void
aug_save_tid_ex(dev_t port,uint32_t * machine,uint32_t type)255 aug_save_tid_ex(dev_t port, uint32_t *machine, uint32_t type)
256 {
257 int i;
258
259 aug_tid.at_port = port;
260 if ((type != AU_IPv4) && (type != AU_IPv6))
261 type = AU_IPv4;
262
263 aug_tid.at_type = type;
264 for (i = 0; i < (type/4); i++)
265 aug_tid.at_addr[i] = machine[i];
266 }
267
268 int
aug_save_me(void)269 aug_save_me(void)
270 {
271 auditinfo_addr_t ai;
272
273 if (getaudit_addr(&ai, sizeof (ai)))
274 return (-1);
275
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);
287 }
288
289 /*
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.
295 */
296 int
aug_save_namask()297 aug_save_namask()
298 {
299 au_mask_t mask;
300
301 aug_na = -1;
302
303 /*
304 * get non-attributable system event mask from kernel.
305 */
306 if (auditon(A_GETKMASK, (caddr_t)&mask, sizeof (mask)) != 0) {
307 return (-1);
308 }
309
310 aug_namask.am_success = mask.am_success;
311 aug_namask.am_failure = mask.am_failure;
312 aug_na = 1;
313 return (0);
314 }
315
316 void
aug_save_event(au_event_t id)317 aug_save_event(au_event_t id)
318 {
319 aug_event = id;
320 }
321
322 void
aug_save_sorf(int sorf)323 aug_save_sorf(int sorf)
324 {
325 aug_sorf = sorf;
326 }
327
328 void
aug_save_text(char * s)329 aug_save_text(char *s)
330 {
331 if (aug_text != NULL)
332 free(aug_text);
333 if (s == NULL)
334 aug_text = NULL;
335 else
336 aug_text = strdup(s);
337 }
338
339 void
aug_save_text1(char * s)340 aug_save_text1(char *s)
341 {
342 if (aug_text1 != NULL)
343 free(aug_text1);
344 if (s == NULL)
345 aug_text1 = NULL;
346 else
347 aug_text1 = strdup(s);
348 }
349
350 void
aug_save_text2(char * s)351 aug_save_text2(char *s)
352 {
353 if (aug_text2 != NULL)
354 free(aug_text2);
355 if (s == NULL)
356 aug_text2 = NULL;
357 else
358 aug_text2 = strdup(s);
359 }
360
361 void
aug_save_na(int flag)362 aug_save_na(int flag)
363 {
364 aug_na = flag;
365 }
366
367 void
aug_save_path(char * s)368 aug_save_path(char *s)
369 {
370 if (aug_path != NULL)
371 free(aug_path);
372 if (s == NULL)
373 aug_path = NULL;
374 aug_path = strdup(s);
375 }
376
377 int
aug_save_policy()378 aug_save_policy()
379 {
380 uint32_t policy;
381
382 if (auditon(A_GETPOLICY, (caddr_t)&policy, sizeof (policy))) {
383 return (-1);
384 }
385 aug_policy = policy;
386 return (0);
387 }
388
389 /*
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.
395 */
396 int
aug_audit(void)397 aug_audit(void)
398 {
399 int ad;
400
401 if (cannot_audit(0)) {
402 return (0);
403 }
404
405 if (aug_na) {
406 if (!aug_na_selected()) {
407 return (0);
408 }
409 } else if (!aug_selected()) {
410 return (0);
411 }
412
413 if ((ad = au_open()) == -1) {
414 return (-1);
415 }
416
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));
425
426 if ((ng = getgroups(maxgrp, grplst)) > 0) {
427 (void) au_write(ad, au_to_newgroups(ng, grplst));
428 }
429 }
430 if (aug_text != NULL) {
431 (void) au_write(ad, au_to_text(aug_text));
432 }
433 if (aug_text1 != NULL) {
434 (void) au_write(ad, au_to_text(aug_text1));
435 }
436 if (aug_text2 != NULL) {
437 (void) au_write(ad, au_to_text(aug_text2));
438 }
439 if (aug_path != NULL) {
440 (void) au_write(ad, au_to_path(aug_path));
441 }
442 if (aug_afunc != NULL) {
443 (*aug_afunc)(ad);
444 }
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);
455 }
456
457 return (0);
458 }
459
460 int
aug_na_selected()461 aug_na_selected()
462 {
463 if (aug_na == -1) {
464 return (-1);
465 }
466
467 return (selected(aug_event, &aug_namask, aug_sorf));
468 }
469
470 int
aug_selected()471 aug_selected()
472 {
473 auditinfo_addr_t mask;
474
475 if (aug_uid > MAXEPHUID) {
476 (void) aug_save_namask();
477 return (aug_na_selected());
478 }
479 if (getaudit_addr(&mask, sizeof (mask))) {
480 return (-1);
481 }
482
483 return (selected(aug_event, &mask.ai_mask, aug_sorf));
484 }
485
486 static int
selected(au_event_t e,au_mask_t * m,int sorf)487 selected(au_event_t e, au_mask_t *m, int sorf)
488 {
489 int prs_sorf;
490
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;
497 }
498
499 return (au_preselect(e, m, prs_sorf, AU_PRS_REREAD));
500 }
501