/* * Collects audit information for the current process and creates a subject * token from it. */ token_t * au_to_me(void) { auditinfo_t auinfo; auditinfo_addr_t aia; /* * Try to use getaudit_addr(2) first. If this kernel does not support * it, then fall back on to getaudit(2). */ if (getaudit_addr(&aia, sizeof(aia)) != 0) { if (errno == ENOSYS) { if (getaudit(&auinfo) != 0) return (NULL); return (au_to_subject32(auinfo.ai_auid, geteuid(), getegid(), getuid(), getgid(), getpid(), auinfo.ai_asid, &auinfo.ai_termid)); } else { /* getaudit_addr(2) failed for some other reason. */ return (NULL); } } return (au_to_subject32_ex(aia.ai_auid, geteuid(), getegid(), getuid(), getgid(), getpid(), aia.ai_asid, &aia.ai_termid)); }
void bsm_audit_failure(char **exec_args, char const *const fmt, va_list ap) { auditinfo_addr_t ainfo_addr; auditinfo_t ainfo; char text[256]; token_t *tok; long au_cond; au_id_t auid; pid_t pid; int aufd; debug_decl(bsm_audit_success, SUDO_DEBUG_AUDIT) pid = getpid(); /* * If we are not auditing, don't cut an audit record; just return. */ if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) { if (errno == AUDIT_NOT_CONFIGURED) debug_return; error(1, _("Could not determine audit condition")); } if (au_cond == AUC_NOAUDIT) debug_return; if (!audit_sudo_selected(1)) debug_return; if (getauid(&auid) < 0) error(1, _("getauid: failed")); if ((aufd = au_open()) == -1) error(1, _("au_open: failed")); if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) == 0) { tok = au_to_subject_ex(auid, geteuid(), getegid(), getuid(), getuid(), pid, pid, &ainfo_addr.ai_termid); } else if (errno == ENOSYS) { if (getaudit(&ainfo) < 0) error(1, _("getaudit: failed")); tok = au_to_subject(auid, geteuid(), getegid(), getuid(), getuid(), pid, pid, &ainfo.ai_termid); } else error(1, _("getaudit: failed")); if (tok == NULL) error(1, _("au_to_subject: failed")); au_write(aufd, tok); tok = au_to_exec_args(exec_args); if (tok == NULL) error(1, _("au_to_exec_args: failed")); au_write(aufd, tok); (void) vsnprintf(text, sizeof(text), fmt, ap); tok = au_to_text(text); if (tok == NULL) error(1, _("au_to_text: failed")); au_write(aufd, tok); tok = au_to_return32(EPERM, 1); if (tok == NULL) error(1, _("au_to_return32: failed")); au_write(aufd, tok); if (au_close(aufd, 1, AUE_sudo) == -1) error(1, _("unable to commit audit record")); debug_return; }
static int do_ipv4_address(struct sockaddr_in *peer, struct sockaddr_in *sock) { auditinfo_t ai; /* get audit characteristics of process */ if (getaudit(&ai) < 0) { return (errno); } /* * if terminal ID already set, i.e. non-zero, then just return */ if (ai.ai_termid.port || ai.ai_termid.machine) { return (0); } ai.ai_termid.port = (peer->sin_port<<16 | sock->sin_port); ai.ai_termid.machine = (uint32_t)peer->sin_addr.s_addr; if (setaudit(&ai) < 0) { return (errno); } return (0); }
/*ARGSUSED1*/ int auditsys(struct auditcalls *uap, rval_t *rvp) { int err; int result = 0; if (audit_active == C2AUDIT_DISABLED) return (ENOTSUP); switch (uap->code) { case BSM_GETAUID: result = getauid((caddr_t)uap->a1); break; case BSM_SETAUID: result = setauid((caddr_t)uap->a1); break; case BSM_GETAUDIT: result = getaudit((caddr_t)uap->a1); break; case BSM_GETAUDIT_ADDR: result = getaudit_addr((caddr_t)uap->a1, (int)uap->a2); break; case BSM_SETAUDIT: result = setaudit((caddr_t)uap->a1); break; case BSM_SETAUDIT_ADDR: result = setaudit_addr((caddr_t)uap->a1, (int)uap->a2); break; case BSM_AUDITCTL: result = auditctl((int)uap->a1, (caddr_t)uap->a2, (int)uap->a3); break; case BSM_AUDIT: if (audit_active == C2AUDIT_UNLOADED) return (0); result = audit((caddr_t)uap->a1, (int)uap->a2); break; case BSM_AUDITDOOR: if (audit_active == C2AUDIT_LOADED) { result = auditdoor((int)uap->a1); break; } default: if (audit_active == C2AUDIT_LOADED) { result = EINVAL; break; } /* Return a different error when not privileged */ err = secpolicy_audit_config(CRED()); if (err == 0) return (EINVAL); else return (err); } rvp->r_vals = result; return (result); }
static void common_audit( au_event_t event, /* audit event */ struct in_addr *r_addr, /* remote ipv4 addr */ in_port_t r_port, /* remote port */ in_port_t l_port, /* local port */ char *cname, /* client principal name */ char *sname, /* requested service name */ int sorf) /* flag for success or failure */ { auditinfo_t ai; dev_t port = 0; uint32_t machine; char text_buf[512]; dprintf(("common_audit() start\n")); /* if auditing turned off, then don't do anything */ if (cannot_audit(0)) return; (void) aug_save_namask(); if (getaudit(&ai)) { perror("krb5kdc"); return; } aug_save_auid(ai.ai_auid); /* Audit ID */ aug_save_uid(getuid()); /* User ID */ aug_save_euid(geteuid()); /* Effective User ID */ aug_save_gid(getgid()); /* Group ID */ aug_save_egid(getegid()); /* Effective Group ID */ aug_save_pid(getpid()); /* process ID */ aug_save_asid(getpid()); /* session ID */ aug_save_event(event); aug_save_sorf(sorf); (void) snprintf(text_buf, sizeof (text_buf), "Client: %s", AUD_NULL_STR(cname)); aug_save_text1(text_buf); (void) snprintf(text_buf, sizeof (text_buf), "Service: %s", AUD_NULL_STR(sname)); aug_save_text2(text_buf); dprintf(("audit_krb5kdc: r_port=%d, l_port=%d\n", r_port, l_port)); port = (htons(r_port)<<16 | htons(l_port)); machine = r_addr ? (uint32_t)r_addr->s_addr : 0; aug_save_tid_ex(port, &machine, AU_IPv4); (void) aug_audit(); }
int priv_audit_setaudit_setup(int asroot, int injail, struct test *test) { if (getaudit(&ai) < 0) { warn("priv_audit_setaudit_setup: getaudit"); return (-1); } if (getaudit_addr(&aia, sizeof(aia)) < 0) { warn("priv_audit_setaudit_setup: getaudit_addr"); return (-1); } return (0); }
static void auditid(void) { auditinfo_t auditinfo; auditinfo_addr_t ainfo_addr; int ret, extended; extended = 0; ret = getaudit(&auditinfo); if (ret < 0 && errno == E2BIG) { if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) < 0) err(1, "getaudit_addr"); extended = 1; } else if (ret < 0) err(1, "getaudit"); if (extended != 0) { (void) printf("auid=%d\n" "mask.success=0x%08x\n" "mask.failure=0x%08x\n" "asid=%d\n" "termid_addr.port=0x%08jx\n" "termid_addr.addr[0]=0x%08x\n" "termid_addr.addr[1]=0x%08x\n" "termid_addr.addr[2]=0x%08x\n" "termid_addr.addr[3]=0x%08x\n", ainfo_addr.ai_auid, ainfo_addr.ai_mask.am_success, ainfo_addr.ai_mask.am_failure, ainfo_addr.ai_asid, (uintmax_t)ainfo_addr.ai_termid.at_port, ainfo_addr.ai_termid.at_addr[0], ainfo_addr.ai_termid.at_addr[1], ainfo_addr.ai_termid.at_addr[2], ainfo_addr.ai_termid.at_addr[3]); } else { (void) printf("auid=%d\n" "mask.success=0x%08x\n" "mask.failure=0x%08x\n" "asid=%d\n" "termid.port=0x%08jx\n" "termid.machine=0x%08x\n", auditinfo.ai_auid, auditinfo.ai_mask.am_success, auditinfo.ai_mask.am_failure, auditinfo.ai_asid, (uintmax_t)auditinfo.ai_termid.port, auditinfo.ai_termid.machine); } }
void priv_audit_getaudit(int asroot, int injail, struct test *test) { auditinfo_t ai; int error; error = getaudit(&ai); if (asroot && injail) expect("priv_audit_getaudit(asroot, injail)", error, -1, ENOSYS); if (asroot && !injail) expect("priv_audit_getaudit(asroot, !injail)", error, 0, 0); if (!asroot && injail) expect("priv_audit_getaudit(!asroot, injail)", error, -1, ENOSYS); if (!asroot && !injail) expect("priv_audit_getaudit(!asroot, !injail)", error, -1, EPERM); }
int _auditsys(struct auditcalls *uap, rval_t *rvp) { int result = 0; switch (uap->code) { case BSM_GETAUID: result = getauid((caddr_t)uap->a1); break; case BSM_SETAUID: result = setauid((caddr_t)uap->a1); break; case BSM_GETAUDIT: result = getaudit((caddr_t)uap->a1); break; case BSM_GETAUDIT_ADDR: result = getaudit_addr((caddr_t)uap->a1, (int)uap->a2); break; case BSM_SETAUDIT: result = setaudit((caddr_t)uap->a1); break; case BSM_SETAUDIT_ADDR: result = setaudit_addr((caddr_t)uap->a1, (int)uap->a2); break; case BSM_AUDIT: result = audit((caddr_t)uap->a1, (int)uap->a2); break; case BSM_AUDITDOOR: result = auditdoor((int)uap->a1); break; case BSM_AUDITCTL: result = auditctl((int)uap->a1, (caddr_t)uap->a2, (int)uap->a3); break; default: result = EINVAL; } rvp->r_vals = result; return (result); }
static int audit_sudo_selected(int sf) { auditinfo_addr_t ainfo_addr; struct au_mask *mask; auditinfo_t ainfo; int rc, sorf; debug_decl(audit_sudo_selected, SUDO_DEBUG_AUDIT) if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) < 0) { if (errno == ENOSYS) { if (getaudit(&ainfo) < 0) error(1, _("getaudit: failed")); mask = &ainfo.ai_mask; } else error(1, _("getaudit: failed")); } else mask = &ainfo_addr.ai_mask; sorf = (sf == 0) ? AU_PRS_SUCCESS : AU_PRS_FAILURE; rc = au_preselect(AUE_sudo, mask, sorf, AU_PRS_REREAD); debug_return_int(rc); }
/* * General purpose audit submission mechanism for userspace. */ int audit_submit(short au_event, au_id_t auid, char status, int reterr, const char *fmt, ...) { char text[MAX_AUDITSTRING_LEN]; token_t *token; int acond; va_list ap; pid_t pid; int error, afd, subj_ex; struct auditinfo ai; struct auditinfo_addr aia; au_tid_t atid; if (audit_get_cond(&acond) != 0) { /* * If auditon(2) returns ENOSYS, then audit has not been * compiled into the kernel, so just return. */ if (errno == ENOSYS) return (0); error = errno; syslog(LOG_AUTH | LOG_ERR, "audit: auditon failed: %s", strerror(errno)); errno = error; return (-1); } if (acond == AUC_NOAUDIT) return (0); afd = au_open(); if (afd < 0) { error = errno; syslog(LOG_AUTH | LOG_ERR, "audit: au_open failed: %s", strerror(errno)); errno = error; return (-1); } /* * Try to use getaudit_addr(2) first. If this kernel does not support * it, then fall back on to getaudit(2). */ subj_ex = 0; error = getaudit_addr(&aia, sizeof(aia)); if (error < 0 && errno == ENOSYS) { error = getaudit(&ai); if (error < 0) { error = errno; syslog(LOG_AUTH | LOG_ERR, "audit: getaudit failed: %s", strerror(errno)); errno = error; return (-1); } /* * Convert this auditinfo_t to an auditinfo_addr_t to make the * following code less complicated wrt to preselection and * subject token generation. */ aia.ai_auid = ai.ai_auid; aia.ai_mask = ai.ai_mask; aia.ai_asid = ai.ai_asid; aia.ai_termid.at_type = AU_IPv4; aia.ai_termid.at_addr[0] = ai.ai_termid.machine; aia.ai_termid.at_port = ai.ai_termid.port; } else if (error < 0) { error = errno; syslog(LOG_AUTH | LOG_ERR, "audit: getaudit_addr failed: %s", strerror(errno)); errno = error; return (-1); } /* * NB: We should be performing pre-selection here now that we have the * masks for this process. */ if (aia.ai_termid.at_type == AU_IPv6) subj_ex = 1; pid = getpid(); if (subj_ex == 0) { atid.port = aia.ai_termid.at_port; atid.machine = aia.ai_termid.at_addr[0]; token = au_to_subject32(auid, geteuid(), getegid(), getuid(), getgid(), pid, pid, &atid); } else token = au_to_subject_ex(auid, geteuid(), getegid(), getuid(), getgid(), pid, pid, &aia.ai_termid); if (token == NULL) { syslog(LOG_AUTH | LOG_ERR, "audit: unable to build subject token"); (void) au_close(afd, AU_TO_NO_WRITE, au_event); errno = EPERM; return (-1); } if (au_write(afd, token) < 0) { error = errno; syslog(LOG_AUTH | LOG_ERR, "audit: au_write failed: %s", strerror(errno)); (void) au_close(afd, AU_TO_NO_WRITE, au_event); errno = error; return (-1); } if (fmt != NULL) { va_start(ap, fmt); (void) vsnprintf(text, MAX_AUDITSTRING_LEN, fmt, ap); va_end(ap); token = au_to_text(text); if (token == NULL) { syslog(LOG_AUTH | LOG_ERR, "audit: failed to generate text token"); (void) au_close(afd, AU_TO_NO_WRITE, au_event); errno = EPERM; return (-1); } if (au_write(afd, token) < 0) { error = errno; syslog(LOG_AUTH | LOG_ERR, "audit: au_write failed: %s", strerror(errno)); (void) au_close(afd, AU_TO_NO_WRITE, au_event); errno = error; return (-1); } } token = au_to_return32(au_errno_to_bsm(status), reterr); if (token == NULL) { syslog(LOG_AUTH | LOG_ERR, "audit: unable to build return token"); (void) au_close(afd, AU_TO_NO_WRITE, au_event); errno = EPERM; return (-1); } if (au_write(afd, token) < 0) { error = errno; syslog(LOG_AUTH | LOG_ERR, "audit: au_write failed: %s", strerror(errno)); (void) au_close(afd, AU_TO_NO_WRITE, au_event); errno = error; return (-1); } if (au_close(afd, AU_TO_WRITE, au_event) < 0) { error = errno; syslog(LOG_AUTH | LOG_ERR, "audit: record not committed"); errno = error; return (-1); } return (0); }
void bsm_audit_success(char **exec_args) { auditinfo_addr_t ainfo_addr; auditinfo_t ainfo; token_t *tok; au_id_t auid; long au_cond; int aufd; pid_t pid; debug_decl(bsm_audit_success, SUDO_DEBUG_AUDIT) pid = getpid(); /* * If we are not auditing, don't cut an audit record; just return. */ if (auditon(A_GETCOND, (caddr_t)&au_cond, sizeof(long)) < 0) { if (errno == AUDIT_NOT_CONFIGURED) return; error(1, _("Could not determine audit condition")); } if (au_cond == AUC_NOAUDIT) debug_return; /* * Check to see if the preselection masks are interested in seeing * this event. */ if (!audit_sudo_selected(0)) debug_return; if (getauid(&auid) < 0) error(1, _("getauid failed")); if ((aufd = au_open()) == -1) error(1, _("au_open: failed")); if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) == 0) { tok = au_to_subject_ex(auid, geteuid(), getegid(), getuid(), getuid(), pid, pid, &ainfo_addr.ai_termid); } else if (errno == ENOSYS) { /* * NB: We should probably watch out for ERANGE here. */ if (getaudit(&ainfo) < 0) error(1, _("getaudit: failed")); tok = au_to_subject(auid, geteuid(), getegid(), getuid(), getuid(), pid, pid, &ainfo.ai_termid); } else error(1, _("getaudit: failed")); if (tok == NULL) error(1, _("au_to_subject: failed")); au_write(aufd, tok); tok = au_to_exec_args(exec_args); if (tok == NULL) error(1, _("au_to_exec_args: failed")); au_write(aufd, tok); tok = au_to_return32(0, 0); if (tok == NULL) error(1, _("au_to_return32: failed")); au_write(aufd, tok); if (au_close(aufd, 1, AUE_sudo) == -1) error(1, _("unable to commit audit record")); debug_return; }