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