bool 
AuditLogger::open()
{
    if (-1 != mAuditFd)
        return true;
    
    // @@@  use audit_get_cond() when it's available
    int acond = au_get_state();
    switch (acond)
    {
        case AUC_NOAUDIT:
            return false;
        case AUC_AUDITING:
            break;
        default:
            logInternalError("error checking auditing status (%d)", acond);
            UnixError::throwMe(acond);  // assume it's a Unix error
    }
    if ((mAuditFd = au_open()) < 0)
    {
        logInternalError("au_open() failed (%s)", strerror(errno));
        UnixError::throwMe(errno);
    }
    return true;
}
Beispiel #2
0
/*
 * 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));
}
Beispiel #4
0
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;
}
Beispiel #5
0
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);
}
Beispiel #6
0
/*
 * 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;
}
Beispiel #7
0
/*
 * 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");
}
Beispiel #8
0
/*
 * 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.");
}
Beispiel #9
0
au_open()
#endif
{
	int d;			/* descriptor */
	token_t	**au_d_new;

	_mutex_lock(&mutex_au_d);

	if (au_d_required_length > au_d_length) {
		au_d_new = (token_t **)calloc(au_d_required_length,
		    sizeof (au_d));

		if (au_d_new == NULL) {
			au_d_required_length = au_d_length;
			_mutex_unlock(&mutex_au_d);
			return (-1);
		}
		if (au_d_length > 0) {
			(void) memcpy(au_d_new, au_d, au_d_length *
			    sizeof (au_d));
			free(au_d);
		}
		au_d = au_d_new;
		au_d_length = au_d_required_length;
	}
	for (d = 0; d < au_d_length; d++) {
		if (au_d[d] == (token_t *)0) {
			au_d[d] = (token_t *)&au_d;
			_mutex_unlock(&mutex_au_d);
			return (d);
		}
	}
	/*
	 * table full; make more room.
	 * AU_TABLE_MAX limits recursion.
	 * Logic here expects AU_TABLE_MAX to be multiple of AU_TABLE_LENGTH
	 */
	if (au_d_length >= AU_TABLE_MAX) {
		_mutex_unlock(&mutex_au_d);
		return (-1);
	}
	au_d_required_length += AU_TABLE_LENGTH;
	_mutex_unlock(&mutex_au_d);

	return (au_open());
}
Beispiel #10
0
/*
 * Write a token to a file, wrapped in audit record header and trailer.
 */
static void
write_record(const char *directory, const char *filename, token_t *tok,
    short event)
{
	u_char buffer[MAX_AUDIT_RECORD_SIZE];
	size_t buflen;
	int au, fd;

	au = au_open();
	if (au < 0)
		err(EX_UNAVAILABLE, "au_open");
	if (au_write(au, tok) < 0)
		err(EX_UNAVAILABLE, "au_write");
	buflen = MAX_AUDIT_RECORD_SIZE;
	if (au_close_buffer(au, event, buffer, &buflen) < 0)
		err(EX_UNAVAILABLE, "au_close_buffer");
	fd = open_file(directory, filename);
	write_file(fd, buffer, buflen, filename);
	close(fd);
}
Beispiel #11
0
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));
}
Beispiel #12
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);
}
Beispiel #13
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));
}
Beispiel #14
0
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);
}
Beispiel #15
0
/*
 * 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);
}
Beispiel #16
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;
}