]>
Commit | Line | Data |
---|---|---|
d8f41ccd A |
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 | ||
28 | namespace Security | |
29 | { | |
30 | ||
31 | namespace CommonCriteria | |
32 | { | |
33 | ||
34 | namespace 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 | // | |
56 | class AuditLogger | |
57 | { | |
58 | public: | |
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 | ||
92 | protected: | |
93 | void logInternalError(const char *fmt, ...); | |
94 | ||
95 | private: | |
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 | // | |
120 | class KeychainAuthLogger : public AuditLogger | |
121 | { | |
122 | static const char *sysKCAuthStr; | |
123 | static const char *unknownKCStr; | |
124 | static const char *unknownItemStr; | |
125 | ||
126 | public: | |
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 | ||
136 | private: | |
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 | // | |
145 | class RightLogger | |
146 | { | |
147 | protected: | |
148 | static const char *unknownRightStr; | |
149 | ||
150 | public: | |
151 | RightLogger() : mRight(unknownRightStr) { } | |
152 | virtual ~RightLogger() { } | |
153 | ||
154 | void setRight(const string &rightName); | |
155 | void setRight(const char *rightName); | |
156 | ||
157 | protected: | |
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 | // | |
172 | class AuthMechLogger : public AuditLogger, public RightLogger | |
173 | { | |
174 | static const char *unknownMechStr; | |
175 | static const char *mechStr; | |
176 | ||
177 | public: | |
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 | ||
192 | private: | |
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 | // | |
220 | class 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 | ||
231 | public: | |
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); } | |
fa7225c8 | 245 | void logAuthenticatorFailure(uid_t authenticator, const char *targetName); |
d8f41ccd A |
246 | }; |
247 | ||
248 | ||
249 | } // namespace Securityd | |
250 | ||
251 | } // namespace CommonCriteria | |
252 | ||
253 | } // namespace Security |