void audit_ftpd_logout(void) { int rd; /* audit record descriptor */ uid_t euid; gid_t egid; uid_t uid; gid_t gid; pid_t pid; struct auditinfo_addr info; if (cannot_audit(0)) { return; } (void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_AUDIT, NULL); /* see if terminal id already set */ if (getaudit_addr(&info, sizeof (info)) < 0) { perror("getaudit"); } /* determine if we're preselected */ if (au_preselect(AUE_ftpd_logout, &info.ai_mask, AU_PRS_SUCCESS, AU_PRS_USECACHE) == 0) { (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_AUDIT, NULL); return; } euid = geteuid(); egid = getegid(); uid = getuid(); gid = getgid(); pid = getpid(); rd = au_open(); /* add subject token */ (void) au_write(rd, au_to_subject_ex(info.ai_auid, euid, egid, uid, gid, pid, pid, &info.ai_termid)); if (is_system_labeled()) (void) au_write(rd, au_to_mylabel()); /* add return token */ errno = 0; #ifdef _LP64 (void) au_write(rd, au_to_return64(0, (int64_t)0)); #else (void) au_write(rd, au_to_return32(0, (int32_t)0)); #endif /* write audit record */ if (au_close(rd, 1, AUE_ftpd_logout) < 0) { (void) au_close(rd, 0, 0); } (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_AUDIT, NULL); }
/* * This is OK for those callers who have only one token to write. If you * have multiple tokens that logically form part of the same audit record, * you need to use the existing au_open()/au_write()/au_close() API: * * aufd = au_open(); * tok = au_to_random_token_1(...); * au_write(aufd, tok); * tok = au_to_random_token_2(...); * au_write(aufd, tok); * ... * au_close(aufd, 1, AUE_your_event_type); * * Assumes, like all wrapper calls, that the caller has previously checked * that auditing is enabled via the audit_get_state() call. * * XXX Should be more robust against bad arguments */ int audit_write(short event_code, token_t *subject, token_t *misctok, char retval, int errcode) { int aufd; char *func = "audit_write()"; token_t *rettok; if ((aufd = au_open()) == -1) { au_free_token(subject); au_free_token(misctok); syslog(LOG_ERR, "%s: au_open() failed", func); return kAUOpenErr; } /* save subject */ if (subject && au_write(aufd, subject) == -1) { au_free_token(subject); au_free_token(misctok); (void)au_close(aufd, 0, event_code); syslog(LOG_ERR, "%s: write of subject failed", func); return kAUWriteSubjectTokErr; } /* save the event-specific token */ if (misctok && au_write(aufd, misctok) == -1) { au_free_token(misctok); (void)au_close(aufd, 0, event_code); syslog(LOG_ERR, "%s: write of caller token failed", func); return kAUWriteCallerTokErr; } /* tokenize and save the return value */ if ((rettok = au_to_return32(retval, errcode)) == NULL) { (void)au_close(aufd, 0, event_code); syslog(LOG_ERR, "%s: au_to_return32() failed", func); return kAUMakeReturnTokErr; } if (au_write(aufd, rettok) == -1) { au_free_token(rettok); (void)au_close(aufd, 0, event_code); syslog(LOG_ERR, "%s: write of return code failed", func); return kAUWriteReturnTokErr; } /* * au_close()'s second argument is "keep": if keep == 0, the record is * discarded. We assume the caller wouldn't have bothered with this * function if it hadn't already decided to keep the record. */ if (au_close(aufd, 1, event_code) < 0) { syslog(LOG_ERR, "%s: au_close() failed", func); return kAUCloseErr; } return kAUNoErr; }
/* * The following tokens are included in the audit record for a logout: * header, subject, return. */ void audit_logout(void) { token_t *tok; int aufd; uid_t uid = pwd->pw_uid; gid_t gid = pwd->pw_gid; pid_t pid = getpid(); int au_cond; /* If we are not auditing, don't cut an audit record; just return. */ if (auditon(A_GETCOND, &au_cond, sizeof(int)) < 0) { if (errno == ENOSYS) return; errx(1, "could not determine audit condition"); } if (au_cond == AUC_NOAUDIT) return; if ((aufd = au_open()) == -1) errx(1, "audit error: au_open() failed"); /* The subject that is created (euid, egid of the current process). */ if ((tok = au_to_subject32(uid, geteuid(), getegid(), uid, gid, pid, pid, &tid)) == NULL) errx(1, "audit error: au_to_subject32() failed"); au_write(aufd, tok); if ((tok = au_to_return32(0, 0)) == NULL) errx(1, "audit error: au_to_return32() failed"); au_write(aufd, tok); if (au_close(aufd, 1, AUE_logout) == -1) errx(1, "audit record was not committed."); }
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 && 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)); rc = au_close(ad, AU_TO_WRITE, event_no); if (rc < 0) error("BSM audit: %s failed to write \"%s\" record: %s", __func__, string, strerror(errno)); }
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 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 && 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)); }
/* * The following tokens are included in the audit record for failed * login attempts: header, subject, text, return. */ void au_login_fail(const char *errmsg, int na) { token_t *tok; int aufd; int au_cond; uid_t uid; gid_t gid; pid_t pid = getpid(); /* If we are not auditing, don't cut an audit record; just return. */ if (auditon(A_GETCOND, &au_cond, sizeof(au_cond)) < 0) { if (errno == ENOSYS) return; errx(1, "could not determine audit condition"); } if (au_cond == AUC_NOAUDIT) return; if ((aufd = au_open()) == -1) errx(1, "audit error: au_open() failed"); if (na) { /* * Non attributable event. Assuming that login is not called * within a user's session => auid,asid == -1. */ if ((tok = au_to_subject32(-1, geteuid(), getegid(), -1, -1, pid, -1, &tid)) == NULL) errx(1, "audit error: au_to_subject32() failed"); } else { /* We know the subject -- so use its value instead. */ uid = pwd->pw_uid; gid = pwd->pw_gid; if ((tok = au_to_subject32(uid, geteuid(), getegid(), uid, gid, pid, pid, &tid)) == NULL) errx(1, "audit error: au_to_subject32() failed"); } au_write(aufd, tok); /* Include the error message. */ if ((tok = au_to_text(errmsg)) == NULL) errx(1, "audit error: au_to_text() failed"); au_write(aufd, tok); if ((tok = au_to_return32(1, errno)) == NULL) errx(1, "audit error: au_to_return32() failed"); au_write(aufd, tok); if (au_close(aufd, 1, AUE_login) == -1) errx(1, "audit error: au_close() was not committed"); }
void AuditLogger::close(bool writeLog/* = true*/) { if (-1 != mAuditFd) { int keep = writeLog == true ? AU_TO_WRITE : AU_TO_NO_WRITE; int error = au_close(mAuditFd, keep, mEvent); mAuditFd = -1; if (writeLog == true && error < 0) { logInternalError("au_close() failed; record not committed"); UnixError::throwMe(error); } } }
/* * The following tokens are included in the audit record for a successful * login: header, subject, return. */ void au_login_success(void) { token_t *tok; int aufd; au_mask_t aumask; auditinfo_t auinfo; uid_t uid = pwd->pw_uid; gid_t gid = pwd->pw_gid; pid_t pid = getpid(); int au_cond; /* If we are not auditing, don't cut an audit record; just return. */ if (auditon(A_GETCOND, &au_cond, sizeof(au_cond)) < 0) { if (errno == ENOSYS) return; errx(1, "could not determine audit condition"); } if (au_cond == AUC_NOAUDIT) return; /* Compute and set the user's preselection mask. */ if (au_user_mask(pwd->pw_name, &aumask) == -1) errx(1, "could not set audit mask"); /* Set the audit info for the user. */ auinfo.ai_auid = uid; auinfo.ai_asid = pid; bcopy(&tid, &auinfo.ai_termid, sizeof(auinfo.ai_termid)); bcopy(&aumask, &auinfo.ai_mask, sizeof(auinfo.ai_mask)); if (setaudit(&auinfo) != 0) err(1, "setaudit failed"); if ((aufd = au_open()) == -1) errx(1, "audit error: au_open() failed"); if ((tok = au_to_subject32(uid, geteuid(), getegid(), uid, gid, pid, pid, &tid)) == NULL) errx(1, "audit error: au_to_subject32() failed"); au_write(aufd, tok); if ((tok = au_to_return32(0, 0)) == NULL) errx(1, "audit error: au_to_return32() failed"); au_write(aufd, tok); if (au_close(aufd, 1, AUE_login) == -1) errx(1, "audit record was not committed."); }
static int builtin_close(struct audio_output_struct *ao) { switch(param.outmode) { case DECODE_WAV: wav_close(); break; case DECODE_AU: au_close(); break; case DECODE_CDR: cdr_close(); break; } return 0; }
/* * 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); }
/* * 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)); }
static void generate_record( char *locuser, /* username of local user */ int err, /* error status */ /* (=0 success, >0 error code) */ char *msg) /* error message */ { int rd; /* audit record descriptor */ char buf[256]; /* temporary buffer */ uid_t uid; gid_t gid; uid_t ruid; /* real uid */ gid_t rgid; /* real gid */ pid_t pid; struct passwd *pwd; uid_t ceuid; /* current effective uid */ struct auditinfo_addr info; if (cannot_audit(0)) { return; } pwd = getpwnam(locuser); if (pwd == NULL) { uid = (uid_t)-1; gid = (gid_t)-1; } else { uid = pwd->pw_uid; gid = pwd->pw_gid; } ceuid = geteuid(); /* save current euid */ (void) seteuid(0); /* change to root so you can audit */ /* determine if we're preselected */ if (!selected(uid, locuser, AUE_ftpd, err)) { (void) seteuid(ceuid); return; } ruid = getuid(); /* get real uid */ rgid = getgid(); /* get real gid */ pid = getpid(); /* see if terminal id already set */ if (getaudit_addr(&info, sizeof (info)) < 0) { perror("getaudit"); } rd = au_open(); /* add subject token */ (void) au_write(rd, au_to_subject_ex(uid, uid, gid, ruid, rgid, pid, pid, &info.ai_termid)); if (is_system_labeled()) (void) au_write(rd, au_to_mylabel()); /* add return token */ errno = 0; if (err) { /* add reason for failure */ if (err == UNKNOWN_USER) (void) snprintf(buf, sizeof (buf), "%s %s", msg, locuser); else (void) snprintf(buf, sizeof (buf), "%s", msg); (void) au_write(rd, au_to_text(buf)); #ifdef _LP64 (void) au_write(rd, au_to_return64(-1, (int64_t)err)); #else (void) au_write(rd, au_to_return32(-1, (int32_t)err)); #endif } else { #ifdef _LP64 (void) au_write(rd, au_to_return64(0, (int64_t)0)); #else (void) au_write(rd, au_to_return32(0, (int32_t)0)); #endif } /* write audit record */ if (au_close(rd, 1, AUE_ftpd) < 0) { (void) au_close(rd, 0, 0); } (void) seteuid(ceuid); }
/* * audit_audit: * Cut and audit record if it is selected. * Return 0, if successfully written. * Return 0, if not written, and not expected to write. * Return -1, if not written because of unexpected error. */ int audit_audit(door_data_t *door_dp) { int ad; if (can_audit() == 0) { return (0); } if (door_dp->audit_na) { if (!audit_na_selected(door_dp)) { return (0); } } else if (!audit_selected(door_dp)) { return (0); } if ((ad = au_open()) == -1) { return (-1); } (void) au_write(ad, au_to_subject_ex(door_dp->audit_auid, door_dp->audit_euid, door_dp->audit_egid, door_dp->audit_uid, door_dp->audit_gid, door_dp->audit_pid, door_dp->audit_asid, &door_dp->audit_tid)); if (is_system_labeled()) (void) au_write(ad, au_to_mylabel()); if (door_dp->audit_policy & AUDIT_GROUP) { int ng; int maxgrp = getgroups(0, NULL); gid_t *grplst = alloca(maxgrp * sizeof (gid_t)); if ((ng = getgroups(maxgrp, grplst))) { (void) au_write(ad, au_to_newgroups(ng, grplst)); } } if (strlen(door_dp->audit_text) != 0) { (void) au_write(ad, au_to_text(door_dp->audit_text)); } if (strlen(door_dp->audit_text1) != 0) { (void) au_write(ad, au_to_text(door_dp->audit_text1)); } if (door_dp->audit_path != NULL) { (void) au_write(ad, au_to_path(door_dp->audit_path)); } #ifdef _LP64 (void) au_write(ad, au_to_return64((door_dp->audit_sorf == 0) ? 0 : -1, (int64_t)door_dp->audit_sorf)); #else (void) au_write(ad, au_to_return32((door_dp->audit_sorf == 0) ? 0 : -1, (int32_t)door_dp->audit_sorf)); #endif if (au_close(ad, 1, door_dp->audit_event) < 0) { (void) au_close(ad, 0, 0); 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; }