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