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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <netdb.h> 29 #include <netinet/in.h> 30 #include <pwd.h> 31 #include <sys/errno.h> 32 #include <sys/mutex.h> 33 #include <sys/param.h> 34 #include <sys/socket.h> 35 #include <sys/stat.h> 36 #include <sys/types.h> 37 #include <string.h> 38 #include <unistd.h> 39 #include <stdlib.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 = -1; 106 aug_uid = -1; 107 aug_euid = -1; 108 aug_gid = -1; 109 aug_egid = -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 = -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 (aug_policy & AUDIT_GROUP) { 420 421 int ng; 422 gid_t grplst[NGROUPS_MAX]; 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 < 0) { 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