/*- * Copyright (c) 2008 Christian S.J. Peron * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include static int audit_sudo_selected(int sf) { auditinfo_addr_t ainfo_addr; struct au_mask *mask; auditinfo_t ainfo; int rc, sorf; if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) < 0) { if (errno == ENOSYS) { if (getaudit(&ainfo) < 0) log_error(0, "getaudit: failed"); mask = &ainfo.ai_mask; } else log_error(0, "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); return (rc); } void 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; 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 == ENOSYS) return; log_error(0, "Could not determine audit condition"); } if (au_cond == AUC_NOAUDIT) return; /* * Check to see if the preselection masks are interested in seeing * this event. */ if (!audit_sudo_selected(0)) return; if (getauid(&auid) < 0) log_error(0, "getauid failed"); if ((aufd = au_open()) == -1) log_error(0, "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) log_error(0, "getaudit: failed"); tok = au_to_subject(auid, geteuid(), getegid(), getuid(), getuid(), pid, pid, &ainfo.ai_termid); } else log_error(0, "getaudit: failed"); if (tok == NULL) log_error(0, "au_to_subject: failed"); au_write(aufd, tok); tok = au_to_exec_args(exec_args); if (tok == NULL) log_error(0, "au_to_exec_args: failed"); au_write(aufd, tok); tok = au_to_return32(0, 0); if (tok == NULL) log_error(0, "au_to_return32: failed"); au_write(aufd, tok); if (au_close(aufd, 1, AUE_sudo) == -1) log_error(0, "unable to commit audit record"); } void audit_failure(char **exec_args, char const *const fmt, ...) { auditinfo_addr_t ainfo_addr; auditinfo_t ainfo; char text[256]; token_t *tok; long au_cond; au_id_t auid; va_list ap; pid_t pid; int aufd; 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 == ENOSYS) return; log_error(0, "Could not determine audit condition"); } if (au_cond == AUC_NOAUDIT) return; if (!audit_sudo_selected(1)) return; if (getauid(&auid) < 0) log_error(0, "getauid: failed"); if ((aufd = au_open()) == -1) log_error(0, "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) log_error(0, "getaudit: failed"); tok = au_to_subject(auid, geteuid(), getegid(), getuid(), getuid(), pid, pid, &ainfo.ai_termid); } else log_error(0, "getaudit: failed"); if (tok == NULL) log_error(0, "au_to_subject: failed"); au_write(aufd, tok); tok = au_to_exec_args(exec_args); if (tok == NULL) log_error(0, "au_to_exec_args: failed"); au_write(aufd, tok); va_start(ap, fmt); (void) vsnprintf(text, sizeof(text), fmt, ap); va_end(ap); tok = au_to_text(text); if (tok == NULL) log_error(0, "au_to_text: failed"); au_write(aufd, tok); tok = au_to_return32(EPERM, 1); if (tok == NULL) log_error(0, "au_to_return32: failed"); au_write(aufd, tok); if (au_close(aufd, 1, AUE_sudo) == -1) log_error(0, "unable to commit audit record"); }