Initial vendor import of the TrustedBSD OpenBSM distribution, version
1.0 alpha 1, an implementation of the documented Sun Basic Security
Module (BSM) Audit API and file format, as well as local extensions to
support the Mac OS X and FreeBSD operating systems. Also included are
command line tools for audit trail reduction and conversion to text,
as well as documentation of the commands, file format, and APIs. This
distribution is the foundation for the TrustedBSD Audit implementation,
and is a pre-release.
This is the first in a series of commits to introduce support for
Common Criteria CAPP security event audit support.
This software has been made possible through the generous
contributions of Apple Computer, Inc., SPARTA, Inc., as well as
members of the TrustedBSD Project, including Wayne Salamon <wsalamon>
and Tom Rhodes <trhodes>. The original OpenBSM implementation was
created by McAfee Research under contract to Apple Computer, Inc., as
part of their CC CAPP security evaluation.
Many thanks to: wsalamon, trhodes
Obtained from: TrustedBSD Project
2006-01-31 19:40:12 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2004 Apple Computer, Inc.
|
|
|
|
* 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.
|
|
|
|
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
|
|
|
|
* its contributors may be used to endorse or promote products derived
|
|
|
|
* from this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS 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 APPLE OR ITS 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.
|
|
|
|
*
|
2006-02-11 00:39:23 +00:00
|
|
|
* $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_wrappers.c#16 $
|
Initial vendor import of the TrustedBSD OpenBSM distribution, version
1.0 alpha 1, an implementation of the documented Sun Basic Security
Module (BSM) Audit API and file format, as well as local extensions to
support the Mac OS X and FreeBSD operating systems. Also included are
command line tools for audit trail reduction and conversion to text,
as well as documentation of the commands, file format, and APIs. This
distribution is the foundation for the TrustedBSD Audit implementation,
and is a pre-release.
This is the first in a series of commits to introduce support for
Common Criteria CAPP security event audit support.
This software has been made possible through the generous
contributions of Apple Computer, Inc., SPARTA, Inc., as well as
members of the TrustedBSD Project, including Wayne Salamon <wsalamon>
and Tom Rhodes <trhodes>. The original OpenBSM implementation was
created by McAfee Research under contract to Apple Computer, Inc., as
part of their CC CAPP security evaluation.
Many thanks to: wsalamon, trhodes
Obtained from: TrustedBSD Project
2006-01-31 19:40:12 +00:00
|
|
|
*/
|
|
|
|
|
2006-02-11 00:39:23 +00:00
|
|
|
#ifdef __APPLE__
|
|
|
|
#define _SYS_AUDIT_H /* Prevent include of sys/audit.h. */
|
|
|
|
#endif
|
|
|
|
|
Initial vendor import of the TrustedBSD OpenBSM distribution, version
1.0 alpha 1, an implementation of the documented Sun Basic Security
Module (BSM) Audit API and file format, as well as local extensions to
support the Mac OS X and FreeBSD operating systems. Also included are
command line tools for audit trail reduction and conversion to text,
as well as documentation of the commands, file format, and APIs. This
distribution is the foundation for the TrustedBSD Audit implementation,
and is a pre-release.
This is the first in a series of commits to introduce support for
Common Criteria CAPP security event audit support.
This software has been made possible through the generous
contributions of Apple Computer, Inc., SPARTA, Inc., as well as
members of the TrustedBSD Project, including Wayne Salamon <wsalamon>
and Tom Rhodes <trhodes>. The original OpenBSM implementation was
created by McAfee Research under contract to Apple Computer, Inc., as
part of their CC CAPP security evaluation.
Many thanks to: wsalamon, trhodes
Obtained from: TrustedBSD Project
2006-01-31 19:40:12 +00:00
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/sysctl.h>
|
|
|
|
|
|
|
|
#include <bsm/libbsm.h>
|
|
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <syslog.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
/* These are not advertised in libbsm.h */
|
|
|
|
int audit_set_terminal_port(dev_t *p);
|
|
|
|
int audit_set_terminal_host(uint32_t *m);
|
|
|
|
|
|
|
|
int
|
|
|
|
audit_set_terminal_port(dev_t *p)
|
|
|
|
{
|
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
if (p == NULL)
|
|
|
|
return (kAUBadParamErr);
|
|
|
|
|
|
|
|
*p = NODEV;
|
|
|
|
|
|
|
|
/* for /usr/bin/login, try fstat() first */
|
|
|
|
if (fstat(STDIN_FILENO, &st) != 0) {
|
|
|
|
if (errno != EBADF) {
|
|
|
|
syslog(LOG_ERR, "fstat() failed (%s)",
|
|
|
|
strerror(errno));
|
|
|
|
return (kAUStatErr);
|
|
|
|
}
|
|
|
|
if (stat("/dev/console", &st) != 0) {
|
|
|
|
syslog(LOG_ERR, "stat() failed (%s)",
|
|
|
|
strerror(errno));
|
|
|
|
return (kAUStatErr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*p = st.st_rdev;
|
|
|
|
return (kAUNoErr);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
audit_set_terminal_host(uint32_t *m)
|
|
|
|
{
|
|
|
|
int name[2] = { CTL_KERN, KERN_HOSTID };
|
|
|
|
size_t len;
|
|
|
|
|
|
|
|
if (m == NULL)
|
|
|
|
return (kAUBadParamErr);
|
|
|
|
*m = 0;
|
|
|
|
len = sizeof(*m);
|
|
|
|
if (sysctl(name, 2, m, &len, NULL, 0) != 0) {
|
|
|
|
syslog(LOG_ERR, "sysctl() failed (%s)", strerror(errno));
|
|
|
|
return (kAUSysctlErr);
|
|
|
|
}
|
|
|
|
return (kAUNoErr);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
audit_set_terminal_id(au_tid_t *tid)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (tid == NULL)
|
|
|
|
return (kAUBadParamErr);
|
|
|
|
if ((ret = audit_set_terminal_port(&tid->port)) != kAUNoErr)
|
|
|
|
return (ret);
|
|
|
|
return (audit_set_terminal_host(&tid->machine));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Same caveats as audit_write(). In addition, this function explicitly
|
|
|
|
* assumes success; use audit_write_failure() on error.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
audit_write_success(short event_code, token_t *tok, au_id_t auid, uid_t euid,
|
|
|
|
gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid,
|
|
|
|
au_tid_t *tid)
|
|
|
|
{
|
|
|
|
char *func = "audit_write_success()";
|
|
|
|
token_t *subject = NULL;
|
|
|
|
|
|
|
|
/* Tokenize and save subject. */
|
|
|
|
subject = au_to_subject32(auid, euid, egid, ruid, rgid, pid, sid,
|
|
|
|
tid);
|
|
|
|
if (subject == NULL) {
|
|
|
|
syslog(LOG_ERR, "%s: au_to_subject32() failed", func);
|
|
|
|
return kAUMakeSubjectTokErr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (audit_write(event_code, subject, tok, 0, 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Same caveats as audit_write(). In addition, this function explicitly
|
|
|
|
* assumes success; use audit_write_failure_self() on error.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
audit_write_success_self(short event_code, token_t *tok)
|
|
|
|
{
|
|
|
|
token_t *subject;
|
|
|
|
char *func = "audit_write_success_self()";
|
|
|
|
|
|
|
|
if ((subject = au_to_me()) == NULL) {
|
|
|
|
syslog(LOG_ERR, "%s: au_to_me() failed", func);
|
|
|
|
return (kAUMakeSubjectTokErr);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (audit_write(event_code, subject, tok, 0, 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Same caveats as audit_write(). In addition, this function explicitly
|
|
|
|
* assumes failure; use audit_write_success() otherwise.
|
|
|
|
*
|
|
|
|
* XXX This should let the caller pass an error return value rather than
|
|
|
|
* hard-coding -1.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
audit_write_failure(short event_code, char *errmsg, int errcode, au_id_t auid,
|
|
|
|
uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid,
|
|
|
|
au_tid_t *tid)
|
|
|
|
{
|
|
|
|
char *func = "audit_write_failure()";
|
|
|
|
token_t *subject, *errtok;
|
|
|
|
|
|
|
|
subject = au_to_subject32(auid, euid, egid, ruid, rgid, pid, sid, tid);
|
|
|
|
if (subject == NULL) {
|
|
|
|
syslog(LOG_ERR, "%s: au_to_subject32() failed", func);
|
|
|
|
return (kAUMakeSubjectTokErr);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* tokenize and save the error message */
|
|
|
|
if ((errtok = au_to_text(errmsg)) == NULL) {
|
|
|
|
au_free_token(subject);
|
|
|
|
syslog(LOG_ERR, "%s: au_to_text() failed", func);
|
|
|
|
return (kAUMakeTextTokErr);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (audit_write(event_code, subject, errtok, -1, errcode));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Same caveats as audit_write(). In addition, this function explicitly
|
|
|
|
* assumes failure; use audit_write_success_self() otherwise.
|
|
|
|
*
|
|
|
|
* XXX This should let the caller pass an error return value rather than
|
|
|
|
* hard-coding -1.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
audit_write_failure_self(short event_code, char *errmsg, int errret)
|
|
|
|
{
|
|
|
|
char *func = "audit_write_failure_self()";
|
|
|
|
token_t *subject, *errtok;
|
|
|
|
|
|
|
|
if ((subject = au_to_me()) == NULL) {
|
|
|
|
syslog(LOG_ERR, "%s: au_to_me() failed", func);
|
|
|
|
return (kAUMakeSubjectTokErr);
|
|
|
|
}
|
|
|
|
/* tokenize and save the error message */
|
|
|
|
if ((errtok = au_to_text(errmsg)) == NULL) {
|
|
|
|
au_free_token(subject);
|
|
|
|
syslog(LOG_ERR, "%s: au_to_text() failed", func);
|
|
|
|
return (kAUMakeTextTokErr);
|
|
|
|
}
|
|
|
|
return (audit_write(event_code, subject, errtok, -1, errret));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* For auditing errors during login. Such errors are implicitly
|
|
|
|
* non-attributable (i.e., not ascribable to any user).
|
|
|
|
*
|
|
|
|
* Assumes, like all wrapper calls, that the caller has previously checked
|
|
|
|
* that auditing is enabled via the audit_get_state() call.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
audit_write_failure_na(short event_code, char *errmsg, int errret, uid_t euid,
|
|
|
|
uid_t egid, pid_t pid, au_tid_t *tid)
|
|
|
|
{
|
|
|
|
|
|
|
|
return (audit_write_failure(event_code, errmsg, errret, -1, euid,
|
|
|
|
egid, -1, -1, pid, -1, tid));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* END OF au_write() WRAPPERS */
|
|
|
|
|
|
|
|
#ifdef __APPLE__
|
|
|
|
void
|
|
|
|
audit_token_to_au32(audit_token_t atoken, uid_t *auidp, uid_t *euidp,
|
|
|
|
gid_t *egidp, uid_t *ruidp, gid_t *rgidp, pid_t *pidp, au_asid_t *asidp,
|
|
|
|
au_tid_t *tidp)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (auidp != NULL)
|
|
|
|
*auidp = (uid_t)atoken.val[0];
|
|
|
|
if (euidp != NULL)
|
|
|
|
*euidp = (uid_t)atoken.val[1];
|
|
|
|
if (egidp != NULL)
|
|
|
|
*egidp = (gid_t)atoken.val[2];
|
|
|
|
if (ruidp != NULL)
|
|
|
|
*ruidp = (uid_t)atoken.val[3];
|
|
|
|
if (rgidp != NULL)
|
|
|
|
*rgidp = (gid_t)atoken.val[4];
|
|
|
|
if (pidp != NULL)
|
|
|
|
*pidp = (pid_t)atoken.val[5];
|
|
|
|
if (asidp != NULL)
|
|
|
|
*asidp = (au_asid_t)atoken.val[6];
|
|
|
|
if (tidp != NULL) {
|
|
|
|
audit_set_terminal_host(&tidp->machine);
|
|
|
|
tidp->port = (dev_t)atoken.val[7];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* !__APPLE__ */
|