1/*
2 * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19#include <strings.h>	// bcopy()
20#include <errno.h>
21#include <bsm/libbsm.h>
22#include <security_utilities/utilities.h>
23#include <security_utilities/debugging.h>
24#include <security_utilities/logging.h>
25#include <security_utilities/errors.h>
26#include <security_utilities/ccaudit.h>
27
28namespace Security
29{
30namespace CommonCriteria
31{
32
33TerminalId::TerminalId()
34{
35	if (audit_set_terminal_id(this) != kAUNoErr)
36	{
37		Syslog::warning("setting terminal ID info failed; using defaults");
38		port = 0;
39		machine = 0;
40	}
41}
42
43AuditToken::AuditToken(const audit_token_t &token)
44    : mAuditToken(token)
45{
46    ::audit_token_to_au32(token, &mAuditId, &mEuid, &mEgid, &mRuid, &mRgid, &mPid, &mSessionId, &mTerminalId);
47}
48
49
50//
51// AuditInfo
52//
53void AuditInfo::get()
54{
55	this->clearPod();
56	UnixError::check(::getaudit_addr(this, sizeof(*this)));
57}
58
59void AuditInfo::get(au_asid_t session)
60{
61	this->get();
62	if (session != this->ai_asid) {
63		// need to use higher-privileged call to get info about a session that is not our own
64		this->ai_asid = session;
65		UnixError::check(::auditon(A_GETSINFO_ADDR, this, sizeof(*this)));
66	}
67}
68
69void AuditInfo::getPid(pid_t pid)
70{
71	auditpinfo_addr_t pinfo;
72	memset(&pinfo, 0, sizeof(pinfo));
73	pinfo.ap_pid = pid;
74	UnixError::check(::auditon(A_GETPINFO_ADDR, &pinfo, sizeof(pinfo)));
75	get(pinfo.ap_asid);
76}
77
78void AuditInfo::set()
79{
80	UnixError::check(::setaudit_addr(this, sizeof(*this)));
81}
82
83void AuditInfo::create(uint64_t flags, uid_t auid /* = AU_DEFAUDITID */)
84{
85	this->clearPod();
86	ai_auid = auid;
87	ai_asid = AU_ASSIGN_ASID;
88	ai_termid.at_type = AU_IPv4;
89	ai_flags = flags;
90	UnixError::check(::setaudit_addr(this, sizeof(*this)));
91}
92
93
94void AuditSession::registerSession(void)
95{
96    auditinfo_t auinfo;
97
98    auinfo.ai_auid = mAuditId;
99    auinfo.ai_asid = mSessionId;
100    bcopy(&mTerminalId, &(auinfo.ai_termid), sizeof(auinfo.ai_termid));
101    bcopy(&mEventMask.get(), &(auinfo.ai_mask), sizeof(auinfo.ai_mask));
102
103    if (setaudit(&auinfo) != 0)
104	{
105		if (errno == ENOTSUP)
106			Syslog::notice("Attempted to initialize auditing, but this kernel does not support auditing");
107		else
108			Syslog::warning("Could not initialize auditing (%m); continuing");
109	}
110}
111
112void AuditRecord::submit(const short event_code, const int returnCode,
113			 const char *msg)
114{
115    // If we're not auditing, do nothing
116    if (!(au_get_state() == AUC_AUDITING))
117		return;
118
119    secdebug("ccaudit", "Submitting authorization audit record");
120
121    int ret = kAUNoErr;
122
123    // XXX/gh  3574731: Fix BSM SPI so the const_cast<>s aren't necessary
124    if (returnCode == 0)
125    {
126		token_t *tok = NULL;
127
128		if (msg)
129			tok = au_to_text(const_cast<char *>(msg));
130		ret = audit_write_success(event_code, const_cast<token_t *>(tok),
131								  mAuditToken.auditId(), mAuditToken.euid(),
132								  mAuditToken.egid(), mAuditToken.ruid(),
133								  mAuditToken.rgid(), mAuditToken.pid(),
134								  mAuditToken.sessionId(),
135								  const_cast<au_tid_t *>(&(mAuditToken.terminalId())));
136    }
137    else
138    {
139		ret = audit_write_failure(event_code, const_cast<char *>(msg),
140								  returnCode, mAuditToken.auditId(),
141								  mAuditToken.euid(), mAuditToken.egid(),
142								  mAuditToken.ruid(), mAuditToken.rgid(),
143								  mAuditToken.pid(), mAuditToken.sessionId(),
144								  const_cast<au_tid_t *>(&(mAuditToken.terminalId())));
145    }
146    if (ret != kAUNoErr)
147		MacOSError::throwMe(ret);
148}
149
150
151}	// end namespace CommonCriteria
152}	// end namespace Security
153