/* * Parse one line from the audit_user file into the au_user_ent structure. */ static struct au_user_ent * userfromstr(char *str, struct au_user_ent *u) { char *username, *always, *never; char *last; username = strtok_r(str, user_delim, &last); always = strtok_r(NULL, user_delim, &last); never = strtok_r(NULL, user_delim, &last); if ((username == NULL) || (always == NULL) || (never == NULL)) return (NULL); if (strlen(username) >= AU_USER_NAME_MAX) return (NULL); strlcpy(u->au_name, username, AU_USER_NAME_MAX); if (getauditflagsbin(always, &(u->au_always)) == -1) return (NULL); if (getauditflagsbin(never, &(u->au_never)) == -1) return (NULL); return (u); }
/* * Read the default system wide audit classes from audit_control, combine with * the per-user audit class and update the binary preselection mask. */ int au_user_mask(char *username, au_mask_t *mask_p) { char auditstring[MAX_AUDITSTRING_LEN + 1]; char user_ent_name[AU_USER_NAME_MAX]; struct au_user_ent u, *up; bzero(&u, sizeof(u)); bzero(user_ent_name, sizeof(user_ent_name)); u.au_name = user_ent_name; /* Get user mask. */ if ((up = getauusernam_r(&u, username)) != NULL) { if (-1 == getfauditflags(&up->au_always, &up->au_never, mask_p)) return (-1); return (0); } /* Read the default system mask. */ if (getacflg(auditstring, MAX_AUDITSTRING_LEN) == 0) { if (-1 == getauditflagsbin(auditstring, mask_p)) return (-1); return (0); } /* No masks defined. */ return (-1); }
/* * Check if the specified event is selected (enabled) for auditing. * Returns 1 if the event is selected, 0 if not and -1 on failure. */ static int selected(char *username, uid_t uid, au_event_t event, int sf) { int rc, sorf; char naflags[512]; struct au_mask mask; mask.am_success = mask.am_failure = 0; if (uid < 0) { /* get flags for non-attributable (to a real user) events */ rc = getacna(naflags, sizeof(naflags)); if (rc == 0) (void) getauditflagsbin(naflags, &mask); } else rc = au_user_mask(username, &mask); sorf = (sf == 0) ? AU_PRS_SUCCESS : AU_PRS_FAILURE; return(au_preselect(event, &mask, sorf, AU_PRS_REREAD)); }
/* * update_kcontext() - updates the non-/attributable preselection masks in * the kernel context. Returns B_TRUE on success, B_FALSE otherwise. */ boolean_t update_kcontext(int cmd, char *cmask) { au_mask_t bmask; (void) getauditflagsbin(cmask, &bmask); if (auditon(cmd, (caddr_t)&bmask, sizeof (bmask)) == -1) { (void) printf("Could not update kernel context (%s).\n", cmd == A_SETAMASK ? "A_SETAMASK" : "A_SETKMASK"); return (B_FALSE); } #ifdef DEBUG (void) printf("svc-auditset: %s mask set to %s", cmd == A_SETAMASK ? "Attributable" : "Non-Attributable", cmask); #endif return (B_TRUE); }
/* * Generate the process audit state by combining the audit masks passed as * parameters with the system audit masks. */ int getfauditflags(au_mask_t *usremask, au_mask_t *usrdmask, au_mask_t *lastmask) { char auditstring[MAX_AUDITSTRING_LEN + 1]; if ((usremask == NULL) || (usrdmask == NULL) || (lastmask == NULL)) return (-1); lastmask->am_success = 0; lastmask->am_failure = 0; /* Get the system mask. */ if (getacflg(auditstring, MAX_AUDITSTRING_LEN) == 0) { if (getauditflagsbin(auditstring, lastmask) != 0) return (-1); } ADDMASK(lastmask, usremask); SUBMASK(lastmask, usrdmask); return (0); }
/* * Check if the specified event is selected (enabled) for auditing. * Returns 1 if the event is selected, 0 if not and -1 on failure. */ static int selected(char *username, uid_t uid, au_event_t event, int sf) { int rc, sorf; char naflags[512]; struct au_mask mask; mask.am_success = mask.am_failure = 0; #if __APPLE__ if (uid == (uid_t)-1) { #else if (uid < 0) { #endif /* get flags for non-attributable (to a real user) events */ rc = getacna(naflags, sizeof(naflags)); if (rc == 0) (void) getauditflagsbin(naflags, &mask); } else rc = au_user_mask(username, &mask); sorf = (sf == 0) ? AU_PRS_SUCCESS : AU_PRS_FAILURE; return(au_preselect(event, &mask, sorf, AU_PRS_REREAD)); } static void bsm_audit_record(int typ, char *string, au_event_t event_no) { int ad, rc, sel; uid_t uid = -1; gid_t gid = -1; pid_t pid = getpid(); AuditInfoTermID tid = ssh_bsm_tid; if (the_authctxt == NULL) { error("BSM audit: audit record internal error (NULL ctxt)"); abort(); } if (the_authctxt->valid) { uid = the_authctxt->pw->pw_uid; gid = the_authctxt->pw->pw_gid; } rc = (typ == 0) ? 0 : -1; sel = selected(the_authctxt->user, uid, event_no, rc); debug3("BSM audit: typ %d rc %d \"%s\"", typ, rc, string); if (!sel) return; /* audit event does not match mask, do not write */ debug3("BSM audit: writing audit new record"); ad = au_open(); (void) au_write(ad, AUToSubjectFunc(uid, uid, gid, uid, gid, pid, pid, &tid)); (void) au_write(ad, au_to_text(string)); (void) au_write(ad, AUToReturnFunc(typ, rc)); #ifdef BROKEN_BSM_API /* The last argument is the event modifier flags. For some seemingly undocumented reason it was added in Solaris 11. */ rc = au_close(ad, AU_TO_WRITE, event_no, 0); #else rc = au_close(ad, AU_TO_WRITE, event_no); #endif if (rc < 0) error("BSM audit: %s failed to write \"%s\" record: %s", __func__, string, strerror(errno)); }
int main(int argc, char *argv []) { struct sockaddr_in6 *sin6; struct sockaddr_in *sin; auditinfo_addr_t aia; struct addrinfo *res; struct passwd *pwd; char *r, *prog; int ch, error; prog = argv[0]; bzero(&aia, sizeof(aia)); aia.ai_termid.at_type = AU_IPv4; while ((ch = getopt(argc, argv, "a:m:s:p:")) != -1) switch (ch) { case 'a': aflag = optarg; break; case 'm': mflag = optarg; break; case 's': sflag = optarg; break; case 'p': aia.ai_termid.at_port = htons(atoi(optarg)); break; default: usage(prog); /* NOT REACHED */ } argc -= optind; argv += optind; if (argc == 0) usage(prog); if (aflag) { pwd = getpwnam(aflag); if (pwd == NULL) { aia.ai_auid = strtoul(aflag, &r, 10); if (r != NULL) errx(1, "%s: invalid user", aflag); } else aia.ai_auid = pwd->pw_uid; } if (mflag) { if (getauditflagsbin(mflag, &aia.ai_mask) < 0) err(1, "getauditflagsbin"); } if (sflag) { error = getaddrinfo(sflag, NULL, NULL, &res); if (error) errx(1, "%s", gai_strerror(error)); switch (res->ai_family) { case PF_INET6: sin6 = (struct sockaddr_in6 *) res->ai_addr; bcopy(&sin6->sin6_addr.s6_addr, &aia.ai_termid.at_addr[0], sizeof(struct in6_addr)); aia.ai_termid.at_type = AU_IPv6; break; case PF_INET: sin = (struct sockaddr_in *) res->ai_addr; bcopy(&sin->sin_addr.s_addr, &aia.ai_termid.at_addr[0], sizeof(struct in_addr)); aia.ai_termid.at_type = AU_IPv4; break; } } if (setaudit_addr(&aia, sizeof(aia)) < 0) err(1, "setaudit_addr"); (void) execvp(*argv, argv); err(1, "%s", *argv); }