]> git.saurik.com Git - apple/security.git/blame - securityd/src/ccaudit_extensions.cpp
Security-59306.101.1.tar.gz
[apple/security.git] / securityd / src / ccaudit_extensions.cpp
CommitLineData
d8f41ccd
A
1/*
2 * ccaudit_extensions.cpp
3 * securityd
4 *
5 * Created by G H on 3/24/09.
6 * Copyright (c) 2009 Apple Inc. All Rights Reserved.
7 *
8 */
9
10#include <errno.h>
11#include <assert.h>
12#include <stdio.h> // vsnprintf()
13#include <stdarg.h> // va_start(), et al.
14#include <syslog.h>
15#include <string.h> // memcpy()
16#include <bsm/audit_uevents.h> // AUE_ssauth*
17#include <bsm/libbsm.h>
18#include <security_utilities/errors.h>
19#include <security_utilities/ccaudit.h>
20#include "ccaudit_extensions.h"
21
22namespace Security
23{
24
25namespace CommonCriteria
26{
27
28namespace Securityd
29{
30
31//
32// AuditLogger
33//
34AuditLogger::AuditLogger(const audit_token_t *srcToken, short auEvent)
35 : mAuditFd(-1), mEvent(auEvent), mClientInfoSet(false)
36{
37 setClientInfo(srcToken);
38}
39
40AuditLogger::AuditLogger(const AuditToken &srcToken, short auEvent)
41 : mAuditFd(-1), mEvent(auEvent), mClientInfoSet(false)
42{
43 setClientInfo(srcToken);
44}
45
46AuditLogger::~AuditLogger()
47{
48 close();
49}
50
51bool
52AuditLogger::open()
53{
54 if (-1 != mAuditFd)
55 return true;
56
57 // @@@ use audit_get_cond() when it's available
58 int acond = au_get_state();
59 switch (acond)
60 {
61 case AUC_NOAUDIT:
62 return false;
63 case AUC_AUDITING:
64 break;
65 default:
66 logInternalError("error checking auditing status (%d)", acond);
67 UnixError::throwMe(acond); // assume it's a Unix error
68 }
69 if ((mAuditFd = au_open()) < 0)
70 {
71 logInternalError("au_open() failed (%s)", strerror(errno));
72 UnixError::throwMe(errno);
73 }
74 return true;
75}
76
77void
78AuditLogger::close(bool writeLog/* = true*/)
79{
80 if (-1 != mAuditFd)
81 {
82 int keep = writeLog == true ? AU_TO_WRITE : AU_TO_NO_WRITE;
83 int error = au_close(mAuditFd, keep, mEvent);
84 mAuditFd = -1;
85 if (writeLog == true && error < 0)
86 {
87 logInternalError("au_close() failed; record not committed");
88 UnixError::throwMe(error);
89 }
90 }
91}
92
93void
94AuditLogger::setClientInfo(const audit_token_t *srcToken)
95{
96 assert(srcToken);
97 audit_token_to_au32(*srcToken, &mAuditId, &mEuid, &mEgid, &mRuid, &mRgid, &mPid, &mAuditSessionId, &mOldTerminalId);
98
99 mTerminalId.at_type = AU_IPv4;
100 mTerminalId.at_addr[0] = mOldTerminalId.machine;
101 mTerminalId.at_port = mOldTerminalId.port;
102
103 mClientInfoSet = true;
104}
105
106void
107AuditLogger::setClientInfo(const AuditToken &srcToken)
108{
109 mAuditId = srcToken.auditId();
110 mEuid = srcToken.euid();
111 mEgid = srcToken.egid();
112 mRuid = srcToken.ruid();
113 mRgid = srcToken.rgid();
114 mPid = srcToken.pid();
115 mAuditSessionId = srcToken.sessionId();
116 memcpy(&mOldTerminalId, &(srcToken.terminalId()), sizeof(mOldTerminalId));
117
118 mTerminalId.at_type = AU_IPv4;
119 mTerminalId.at_addr[0] = mOldTerminalId.machine;
120 mTerminalId.at_port = mOldTerminalId.port;
121
122 mClientInfoSet = true;
123}
124
125void
126AuditLogger::writeToken(token_t *token, const char *name)
127{
128 const char *tokenName = name ? name : "<unidentified>";
129 if (NULL == token)
130 {
131 logInternalError("Invalid '%s' token", tokenName);
132 close();
133 UnixError::throwMe(EPERM); // per audit_submit()
134 }
135 if (au_write(mAuditFd, token) < 0)
136 {
137 logInternalError("Error writing '%s' token (%s)", tokenName, strerror(errno));
138 close();
139 UnixError::throwMe(errno);
140 }
141}
142
143void
144AuditLogger::writeSubject()
145{
146 assert(mClientInfoSet);
147
148 token_t *token;
149
150 // @@@ terminal ID is not carried in the audit trailer nowadays, but
151 // this code should be harmless: it replicates the current logic in
152 // audit_submit()
153 if (AU_IPv4 == mTerminalId.at_type)
154 token = au_to_subject32(mAuditId, mEuid, mEgid, mRuid, mRgid, mPid, mAuditSessionId, &mOldTerminalId);
155 else
156 token = au_to_subject_ex(mAuditId, mEuid, mEgid, mRuid, mRgid, mPid, mAuditSessionId, &mTerminalId);
157 writeToken(token, "subject");
158}
159
160void
161AuditLogger::writeReturn(char status, int reterr)
162{
163 writeToken(au_to_return32(status, reterr), "return");
164}
165
166void
167AuditLogger::logSuccess()
168{
169 if (false == open())
170 return;
171 writeCommon();
172 writeReturn(0, 0);
173 close();
174}
175
176void
177AuditLogger::logFailure(const char *errMsg, int errcode)
178{
179 if (false == open())
180 return;
181 writeCommon();
182 if (errMsg)
183 writeToken(au_to_text(errMsg), "evaluation error");
184 writeReturn(EPERM, errcode);
185 close();
186}
187
188// cribbed from audit_submit()
189void
190AuditLogger::logInternalError(const char *fmt, ...)
191{
192 va_list ap;
193 char text[MAX_AUDITSTRING_LEN];
194
195 if (fmt != NULL)
196 {
197 int error = errno;
198 va_start(ap, fmt);
199 (void)vsnprintf(text, MAX_AUDITSTRING_LEN, fmt, ap);
200 va_end(ap);
201 syslog(LOG_AUTH | LOG_ERR, "%s", text);
202 errno = error;
203 }
204}
205
206//
207// KeychainAuthLogger
208//
209const char *KeychainAuthLogger::sysKCAuthStr = "System keychain authorization";
210const char *KeychainAuthLogger::unknownKCStr = "<unknown keychain>";
211const char *KeychainAuthLogger::unknownItemStr = "<unknown item>";
212
213KeychainAuthLogger::KeychainAuthLogger(const audit_token_t *srcToken, short auEvent)
214 : AuditLogger(srcToken, auEvent), mDatabase(unknownKCStr),
215 mItem(unknownItemStr)
216{
217}
218
219KeychainAuthLogger::KeychainAuthLogger(const AuditToken &srcToken, short auEvent)
220 : AuditLogger(srcToken, auEvent), mDatabase(unknownKCStr),
221 mItem(unknownItemStr)
222{
223}
224
225KeychainAuthLogger::KeychainAuthLogger(const audit_token_t *srcToken, short auEvent, const char *database, const char *item)
226 : AuditLogger(srcToken, auEvent)
227{
228 setDbName(database);
229 setItemName(item);
230}
231
232KeychainAuthLogger::KeychainAuthLogger(const AuditToken &srcToken, short auEvent, const char *database, const char *item)
233 : AuditLogger(srcToken, auEvent)
234{
235 setDbName(database);
236 setItemName(item);
237}
238
239void
240KeychainAuthLogger::setDbName(const char *database)
241{
242 mDatabase = database ? database : unknownKCStr;
243}
244
245void
246KeychainAuthLogger::setItemName(const char *item)
247{
248 mItem = item ? item : unknownItemStr;
249}
250
251void
252KeychainAuthLogger::writeCommon()
253{
254 writeSubject();
255 writeToken(au_to_text(sysKCAuthStr), sysKCAuthStr);
256 writeToken(au_to_text(mDatabase.c_str()), "keychain");
257 writeToken(au_to_text(mItem.c_str()), "keychain item");
258}
259
260
261//
262// RightLogger
263//
264const char *RightLogger::unknownRightStr = "<unknown right>";
265
266void
267RightLogger::setRight(const string &rightName)
268{
269 mRight.clear();
270 mRight = rightName;
271}
272
273void
274RightLogger::setRight(const char *rightName)
275{
276 if (rightName) // NULL bad for string class and au_to_text()
277 {
278 string tmpStr(rightName); // setRight() takes a string&
279 setRight(tmpStr);
280 }
281}
282
283
284//
285// AuthMechLogger
286//
287const char *AuthMechLogger::unknownMechStr = "<unknown mechanism>";
288const char *AuthMechLogger::mechStr = "mechanism ";
289
290AuthMechLogger::AuthMechLogger(const AuditToken &srcToken, short auEvent)
291 : AuditLogger(srcToken, auEvent), RightLogger(),
292 mEvaluatingMechanism(false), mCurrentMechanism(unknownMechStr)
293{
294}
295
296AuthMechLogger::AuthMechLogger(const audit_token_t *srcToken, short auEvent)
297 : AuditLogger(srcToken, auEvent), RightLogger(),
298 mEvaluatingMechanism(false), mCurrentMechanism(unknownMechStr)
299{
300}
301
302void
303AuthMechLogger::setCurrentMechanism(const char *mech)
304{
305 mCurrentMechanism.clear();
306 if (NULL == mech)
307 {
308 mEvaluatingMechanism = false;
309 }
310 else
311 {
312 mCurrentMechanism = mech;
313 mEvaluatingMechanism = true;
314 }
315}
316
317void
318AuthMechLogger::writeCommon()
319{
320 writeSubject();
321 writeToken(au_to_text(mRight.c_str()), "right");
322 if (true == mEvaluatingMechanism)
323 {
324 string tmpStr = mechStr; // mechStr includes a trailing space
325 tmpStr += mCurrentMechanism;
326 writeToken(au_to_text(tmpStr.c_str()), "mechanism");
327 }
328}
329
330void
331AuthMechLogger::logInterrupt(const char *msg)
332{
333 if (false == open())
334 return;
335 writeCommon();
336 if (msg)
337 writeToken(au_to_text(msg), "interrupt");
338 writeReturn(0, 0);
339 close();
340}
341
342//
343// RightAuthenticationLogger
344//
345const char *RightAuthenticationLogger::unknownUserStr = "<unknown user>";
346const char *RightAuthenticationLogger::unknownClientStr = "<unknown client>";
347const char *RightAuthenticationLogger::unknownAuthCreatorStr = "<unknown creator>";
348const char *RightAuthenticationLogger::authenticatorStr = "known UID ";
349const char *RightAuthenticationLogger::clientStr = "client ";
350const char *RightAuthenticationLogger::authCreatorStr = "creator ";
351const char *RightAuthenticationLogger::authenticatedAsStr = "authenticated as ";
352const char *RightAuthenticationLogger::leastPrivStr = "least-privilege";
353
354RightAuthenticationLogger::RightAuthenticationLogger(const AuditToken &srcToken, short auEvent)
355 : AuditLogger(srcToken, auEvent), RightLogger()
356{
357}
358
359RightAuthenticationLogger::RightAuthenticationLogger(const audit_token_t *srcToken, short auEvent)
360 : AuditLogger(srcToken, auEvent), RightLogger()
361{
362}
363
364void
365RightAuthenticationLogger::writeCommon()
366{
367 writeSubject();
368 writeToken(au_to_text(mRight.c_str()), "right");
369}
370
371void
372RightAuthenticationLogger::logSuccess(uid_t authenticator, uid_t target, const char *targetName)
373{
374 if (false == open())
375 return;
376 writeCommon();
377
378 // au_to_arg32() is really meant for auditing syscall arguments;
379 // we're slightly abusing it to get descriptive strings for free.
380 writeToken(au_to_arg32(1, authenticatorStr, authenticator), "authenticator");
381 string tmpStr(authenticatedAsStr);
382 // targetName shouldn't be NULL on a successful authentication, but allow
383 // for programmer screwups
384 tmpStr += targetName ? targetName : unknownUserStr;
385 writeToken(au_to_arg32(2, tmpStr.c_str(), target), "target");
386 writeReturn(0, 0);
387 close();
388}
389
390void
391RightAuthenticationLogger::logAuthorizationResult(const char *client, const char *authCreator, int errcode)
392{
393 if (false == open())
394 return;
395 writeCommon();
396 string tmpStr(clientStr);
397 tmpStr += client ? client : unknownClientStr;
398 writeToken(au_to_text(tmpStr.c_str()), "Authorization client");
399 tmpStr.clear();
400 tmpStr = authCreatorStr;
401 tmpStr += authCreator ? authCreator : unknownAuthCreatorStr;
402 writeToken(au_to_text(tmpStr.c_str()), "Authorization creator");
403 if (errAuthorizationSuccess == errcode)
404 writeReturn(0, 0);
405 else
406 writeReturn(EPERM, errcode);
407 close();
408}
409
410void
411RightAuthenticationLogger::logLeastPrivilege(uid_t userId, bool isAuthorizingUser)
412{
413 if (false == open())
414 return;
415 writeCommon();
416 writeToken(au_to_text(leastPrivStr), leastPrivStr);
417 writeReturn(0, 0);
418 close();
419}
420
421void
fa7225c8 422RightAuthenticationLogger::logAuthenticatorFailure(uid_t authenticator, const char *targetName)
d8f41ccd
A
423{
424 if (false == open())
425 return;
426 writeCommon();
427 writeToken(au_to_arg32(1, authenticatorStr, authenticator), "authenticator");
428 if (NULL == targetName)
429 writeToken(au_to_text(unknownUserStr), "target username");
430 else
431 writeToken(au_to_text(targetName), "target username");
432 // @@@ EAUTH more appropriate, but !defined for _POSIX_C_SOURCE
433 writeReturn(EPERM, errAuthorizationDenied);
434 close();
435}
436
437} // namespace Securityd
438
439} // namespace CommonCriteria
440
441} // namespace Security