Home | History | Annotate | Download | only in common
      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 2009 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 int		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
     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
    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
    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
    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
    199 aug_save_auid(au_id_t id)
    200 {
    201 	aug_auid = id;
    202 }
    203 
    204 void
    205 aug_save_uid(uid_t id)
    206 {
    207 	aug_uid = id;
    208 }
    209 
    210 void
    211 aug_save_euid(uid_t id)
    212 {
    213 	aug_euid = id;
    214 }
    215 
    216 void
    217 aug_save_gid(gid_t id)
    218 {
    219 	aug_gid = id;
    220 }
    221 
    222 void
    223 aug_save_egid(gid_t id)
    224 {
    225 	aug_egid = id;
    226 }
    227 
    228 void
    229 aug_save_pid(pid_t id)
    230 {
    231 	aug_pid = id;
    232 }
    233 
    234 void
    235 aug_save_asid(au_asid_t id)
    236 {
    237 	aug_asid = id;
    238 }
    239 
    240 void
    241 aug_save_afunc(int (*afunc)())
    242 {
    243 	aug_afunc = afunc;
    244 }
    245 
    246 void
    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
    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
    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
    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
    317 aug_save_event(au_event_t id)
    318 {
    319 	aug_event = id;
    320 }
    321 
    322 void
    323 aug_save_sorf(int sorf)
    324 {
    325 	aug_sorf = sorf;
    326 }
    327 
    328 void
    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
    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
    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
    362 aug_save_na(int flag)
    363 {
    364 	aug_na = flag;
    365 }
    366 
    367 void
    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
    378 aug_save_policy()
    379 {
    380 	int 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
    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
    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
    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
    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