1/*
2 *  ccaudit_extensions.h
3 *  securityd
4 *
5 *  Created by G H on 3/24/09.
6 *  Copyright (c) 2009 Apple Inc. All Rights Reserved.
7 *
8 *  Extensions to utility classes in Security::CommonCriteria
9 *  (libsecurity_utilities).  Not clear that these are useful enough to be
10 *  added there, so for now, they're here.
11 */
12
13#include <string>
14#include <stdint.h>
15#include <Security/Authorization.h>
16#include <bsm/audit_kevents.h>      // AUE_NULL
17#include <bsm/libbsm.h>
18
19//
20// Regarding message formats in comments, below:
21//
22//     <> denotes a string with the indicated information
23//     '' denotes a literal string
24//
25// Message info is in text tokens unless otherwise indicated.
26//
27
28namespace Security
29{
30
31namespace CommonCriteria
32{
33
34namespace Securityd
35{
36
37//
38// Pure virtual class from which audit log writers should be derived.
39// The assumption about logging is that a "success" case logs certain
40// data about what succeeded, while a "failure" case logs that same data
41// plus some indication as to why the failure occurred.
42//
43// Subclasses minimally need to provide a writeCommon() method.  They may
44// override logSuccess(); q.v.
45//
46// An AuditLogger is intended to live no longer than the audit trailer of a
47// securityd IPC.
48//
49// setClientInfo() must be called before logging, or at best, gibberish
50// will be logged.
51//
52// Nomenclature:
53//     "write" methods only au_write()
54//     "log" methods open, write, and close the log
55//
56class AuditLogger
57{
58public:
59    AuditLogger() : mAuditFd(-1), mEvent(AUE_NULL), mClientInfoSet(false)  { }
60    AuditLogger(const audit_token_t *srcToken, short auEvent = AUE_NULL);
61    AuditLogger(const AuditToken &srcToken, short auEvent = AUE_NULL);
62    virtual ~AuditLogger();
63
64    bool open();    // false if auditing disabled; throws on real errors
65    void close(bool writeLog = true);   // throws if writeLog true but au_close() failed
66
67    void setClientInfo(const audit_token_t *srcToken);
68    void setClientInfo(const AuditToken &srcToken);
69    void setEvent(short auEvent)  { mEvent = auEvent; }
70    short event() const  { return mEvent; }
71
72    // common log-writing activities
73    void writeToken(token_t *token, const char *name);
74    void writeSubject();
75    void writeReturn(char status, int reterr);
76    virtual void writeCommon() = 0; // should not open or close log
77
78    // logSuccess() assumes that all the ancillary information you need is
79    // written by writeCommon().  If that's not true, you can either
80    // override logSuccess() in your subclass, or use a different method
81    // altogether.  Do not call AuditLogger::logSuccess() from the subclass
82    // in eiher case.
83    virtual void logSuccess();
84
85    virtual void logFailure(const char *errMsg = NULL, int errcode = errAuthorizationDenied);
86    virtual void logFailure(string &errMsg, int errcode = errAuthorizationDenied)  { logFailure(errMsg.c_str(), errcode); }
87
88    // @@@  Extra credit: let callers add arbitrary tokens.  Tokens added
89    // before a log*() call would be appended to the end of writeCommon()'s
90    // standard set.
91
92protected:
93    void logInternalError(const char *fmt, ...);
94
95private:
96    int mAuditFd;
97    short mEvent;
98    bool mClientInfoSet;    // disallow resetting client info
99
100    uid_t mAuditId;
101    uid_t mEuid;
102    gid_t mEgid;
103    uid_t mRuid;
104    gid_t mRgid;
105    pid_t mPid;
106    au_asid_t mAuditSessionId;
107    au_tid_t mOldTerminalId;    // to cache audit_token_to_au32() result
108    au_tid_addr_t mTerminalId;  // @@@  AuditInfo still uses ai_tid_t
109};
110
111//
112// KeychainAuthLogger format:
113//     'System keychain authorization'
114//     <keychain name>
115//     <keychain item name>
116//     [optional] <more failure info>
117//
118// For QueryKeychainAuth audit logging
119//
120class KeychainAuthLogger : public AuditLogger
121{
122    static const char *sysKCAuthStr;
123    static const char *unknownKCStr;
124    static const char *unknownItemStr;
125
126public:
127    KeychainAuthLogger() : AuditLogger(), mDatabase(unknownKCStr), mItem(unknownItemStr)  { }
128    KeychainAuthLogger(const audit_token_t *srcToken, short auEvent);
129    KeychainAuthLogger(const audit_token_t *srcToken, short auEvent, const char *database, const char *item);
130    KeychainAuthLogger(const AuditToken &srcToken, short auEvent);
131    KeychainAuthLogger(const AuditToken &srcToken, short auEvent, const char *database, const char *item);
132    void setDbName(const char *database);
133    void setItemName(const char *item);
134    virtual void writeCommon();
135
136private:
137    string mDatabase;
138    string mItem;
139};
140
141//
142// RightLogger provides basic common data and behavior for rights-based
143// logging classes.  @@@  "RightLogger" is a lousy name
144//
145class RightLogger
146{
147protected:
148    static const char *unknownRightStr;
149
150public:
151    RightLogger() : mRight(unknownRightStr)  { }
152    virtual ~RightLogger()  { }
153
154    void setRight(const string &rightName);
155    void setRight(const char *rightName);
156
157protected:
158    string mRight;
159};
160
161//
162// Basic (per-mechanism) AuthMechLogger format:
163//     <right name>
164//     [optional] 'mechanism' <mechanism name>
165//     [optional] <more info>
166//
167// e.g.:
168//     com.foo.bar
169//     mechanism FooPlugin:SomeMechanism
170//     unknown mechanism; ending rule evaluation
171//
172class AuthMechLogger : public AuditLogger, public RightLogger
173{
174    static const char *unknownMechStr;
175    static const char *mechStr;
176
177public:
178    AuthMechLogger() : AuditLogger(), RightLogger(), mEvaluatingMechanism(false), mCurrentMechanism(unknownMechStr)  { }
179    AuthMechLogger(const AuditToken &srcToken, short auEvent);
180    AuthMechLogger(const audit_token_t *srcToken, short auEvent);
181
182    void setCurrentMechanism(const char *mech);    // pass NULL if not running mechs.
183    void setCurrentMechanism(const string &mech)  { setCurrentMechanism(mech.c_str()); }
184    virtual void writeCommon();
185
186    // Authorization mechanism-evaluation interrupts need to be logged since
187    // they cause evaluation to restart, possibly at a different point in the
188    // mechanism chain.
189    void logInterrupt(const char *msg);     // NULL msg okay
190    void logInterrupt(string &msg)  { logInterrupt(msg.c_str()); }
191
192private:
193    bool mEvaluatingMechanism;
194    string mCurrentMechanism;
195};
196
197//
198// Basic RightAuthenticationLogger formats:
199//
200// Per-credential (newly granted during an evaluation):
201//     <right name>
202//     UID of user performing the authentication [arg32 token]
203//     UID and username of the successfully authenticated user [arg32 token]
204// or:
205//     <right name>
206//     UID of user performing the authentication [arg32 token]
207//     Name of the user as whom the first UID was attempting to authenticate
208//
209// Final (i.e., after all mechanisms) right-granting decision format:
210//     <right name>
211//     name of process requesting authorization
212//     name of process that created the Authorization handle
213//
214// Least-privilege credential-generating event format:
215//     <right name>
216//     'least-privilege'
217//
218// @@@  each format should be its own class
219//
220class RightAuthenticationLogger : public AuditLogger, public RightLogger
221{
222    static const char *unknownUserStr;
223    static const char *unknownClientStr;
224    static const char *unknownAuthCreatorStr;
225    static const char *authenticatorStr;
226    static const char *clientStr;
227    static const char *authCreatorStr;
228    static const char *authenticatedAsStr;
229    static const char *leastPrivStr;
230
231public:
232    RightAuthenticationLogger() : AuditLogger(), RightLogger()  { }
233    RightAuthenticationLogger(const AuditToken &srcToken, short auEvent);
234    RightAuthenticationLogger(const audit_token_t *srcToken, short auEvent);
235    virtual ~RightAuthenticationLogger()  { }
236
237    virtual void writeCommon();
238
239    virtual void logSuccess()  { }  // throw?  in any case, don't allow the usual logSuccess() to work
240    // @@@  clean up, consolidate Success and AuthorizationResult
241    void logSuccess(uid_t authenticator, uid_t target, const char *targetName);
242    void logAuthorizationResult(const char *client, const char *authCreator, int errcode);
243    void logLeastPrivilege(uid_t userId, bool isAuthorizingUser);
244    virtual void logFailure(const char *errMsg, int errcode)  { AuditLogger::logFailure(errMsg, errcode); }
245    void logFailure(uid_t authenticator, const char *targetName);
246};
247
248
249}   // namespace Securityd
250
251}   // namespace CommonCriteria
252
253}   // namespace Security
254