X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/securityd/src/ccaudit_extensions.h diff --git a/securityd/src/ccaudit_extensions.h b/securityd/src/ccaudit_extensions.h new file mode 100644 index 00000000..8b4150b1 --- /dev/null +++ b/securityd/src/ccaudit_extensions.h @@ -0,0 +1,253 @@ +/* + * ccaudit_extensions.h + * securityd + * + * Created by G H on 3/24/09. + * Copyright (c) 2009 Apple Inc. All Rights Reserved. + * + * Extensions to utility classes in Security::CommonCriteria + * (libsecurity_utilities). Not clear that these are useful enough to be + * added there, so for now, they're here. + */ + +#include +#include +#include +#include // AUE_NULL +#include + +// +// Regarding message formats in comments, below: +// +// <> denotes a string with the indicated information +// '' denotes a literal string +// +// Message info is in text tokens unless otherwise indicated. +// + +namespace Security +{ + +namespace CommonCriteria +{ + +namespace Securityd +{ + +// +// Pure virtual class from which audit log writers should be derived. +// The assumption about logging is that a "success" case logs certain +// data about what succeeded, while a "failure" case logs that same data +// plus some indication as to why the failure occurred. +// +// Subclasses minimally need to provide a writeCommon() method. They may +// override logSuccess(); q.v. +// +// An AuditLogger is intended to live no longer than the audit trailer of a +// securityd IPC. +// +// setClientInfo() must be called before logging, or at best, gibberish +// will be logged. +// +// Nomenclature: +// "write" methods only au_write() +// "log" methods open, write, and close the log +// +class AuditLogger +{ +public: + AuditLogger() : mAuditFd(-1), mEvent(AUE_NULL), mClientInfoSet(false) { } + AuditLogger(const audit_token_t *srcToken, short auEvent = AUE_NULL); + AuditLogger(const AuditToken &srcToken, short auEvent = AUE_NULL); + virtual ~AuditLogger(); + + bool open(); // false if auditing disabled; throws on real errors + void close(bool writeLog = true); // throws if writeLog true but au_close() failed + + void setClientInfo(const audit_token_t *srcToken); + void setClientInfo(const AuditToken &srcToken); + void setEvent(short auEvent) { mEvent = auEvent; } + short event() const { return mEvent; } + + // common log-writing activities + void writeToken(token_t *token, const char *name); + void writeSubject(); + void writeReturn(char status, int reterr); + virtual void writeCommon() = 0; // should not open or close log + + // logSuccess() assumes that all the ancillary information you need is + // written by writeCommon(). If that's not true, you can either + // override logSuccess() in your subclass, or use a different method + // altogether. Do not call AuditLogger::logSuccess() from the subclass + // in eiher case. + virtual void logSuccess(); + + virtual void logFailure(const char *errMsg = NULL, int errcode = errAuthorizationDenied); + virtual void logFailure(string &errMsg, int errcode = errAuthorizationDenied) { logFailure(errMsg.c_str(), errcode); } + + // @@@ Extra credit: let callers add arbitrary tokens. Tokens added + // before a log*() call would be appended to the end of writeCommon()'s + // standard set. + +protected: + void logInternalError(const char *fmt, ...); + +private: + int mAuditFd; + short mEvent; + bool mClientInfoSet; // disallow resetting client info + + uid_t mAuditId; + uid_t mEuid; + gid_t mEgid; + uid_t mRuid; + gid_t mRgid; + pid_t mPid; + au_asid_t mAuditSessionId; + au_tid_t mOldTerminalId; // to cache audit_token_to_au32() result + au_tid_addr_t mTerminalId; // @@@ AuditInfo still uses ai_tid_t +}; + +// +// KeychainAuthLogger format: +// 'System keychain authorization' +// +// +// [optional] +// +// For QueryKeychainAuth audit logging +// +class KeychainAuthLogger : public AuditLogger +{ + static const char *sysKCAuthStr; + static const char *unknownKCStr; + static const char *unknownItemStr; + +public: + KeychainAuthLogger() : AuditLogger(), mDatabase(unknownKCStr), mItem(unknownItemStr) { } + KeychainAuthLogger(const audit_token_t *srcToken, short auEvent); + KeychainAuthLogger(const audit_token_t *srcToken, short auEvent, const char *database, const char *item); + KeychainAuthLogger(const AuditToken &srcToken, short auEvent); + KeychainAuthLogger(const AuditToken &srcToken, short auEvent, const char *database, const char *item); + void setDbName(const char *database); + void setItemName(const char *item); + virtual void writeCommon(); + +private: + string mDatabase; + string mItem; +}; + +// +// RightLogger provides basic common data and behavior for rights-based +// logging classes. @@@ "RightLogger" is a lousy name +// +class RightLogger +{ +protected: + static const char *unknownRightStr; + +public: + RightLogger() : mRight(unknownRightStr) { } + virtual ~RightLogger() { } + + void setRight(const string &rightName); + void setRight(const char *rightName); + +protected: + string mRight; +}; + +// +// Basic (per-mechanism) AuthMechLogger format: +// +// [optional] 'mechanism' +// [optional] +// +// e.g.: +// com.foo.bar +// mechanism FooPlugin:SomeMechanism +// unknown mechanism; ending rule evaluation +// +class AuthMechLogger : public AuditLogger, public RightLogger +{ + static const char *unknownMechStr; + static const char *mechStr; + +public: + AuthMechLogger() : AuditLogger(), RightLogger(), mEvaluatingMechanism(false), mCurrentMechanism(unknownMechStr) { } + AuthMechLogger(const AuditToken &srcToken, short auEvent); + AuthMechLogger(const audit_token_t *srcToken, short auEvent); + + void setCurrentMechanism(const char *mech); // pass NULL if not running mechs. + void setCurrentMechanism(const string &mech) { setCurrentMechanism(mech.c_str()); } + virtual void writeCommon(); + + // Authorization mechanism-evaluation interrupts need to be logged since + // they cause evaluation to restart, possibly at a different point in the + // mechanism chain. + void logInterrupt(const char *msg); // NULL msg okay + void logInterrupt(string &msg) { logInterrupt(msg.c_str()); } + +private: + bool mEvaluatingMechanism; + string mCurrentMechanism; +}; + +// +// Basic RightAuthenticationLogger formats: +// +// Per-credential (newly granted during an evaluation): +// +// UID of user performing the authentication [arg32 token] +// UID and username of the successfully authenticated user [arg32 token] +// or: +// +// UID of user performing the authentication [arg32 token] +// Name of the user as whom the first UID was attempting to authenticate +// +// Final (i.e., after all mechanisms) right-granting decision format: +// +// name of process requesting authorization +// name of process that created the Authorization handle +// +// Least-privilege credential-generating event format: +// +// 'least-privilege' +// +// @@@ each format should be its own class +// +class RightAuthenticationLogger : public AuditLogger, public RightLogger +{ + static const char *unknownUserStr; + static const char *unknownClientStr; + static const char *unknownAuthCreatorStr; + static const char *authenticatorStr; + static const char *clientStr; + static const char *authCreatorStr; + static const char *authenticatedAsStr; + static const char *leastPrivStr; + +public: + RightAuthenticationLogger() : AuditLogger(), RightLogger() { } + RightAuthenticationLogger(const AuditToken &srcToken, short auEvent); + RightAuthenticationLogger(const audit_token_t *srcToken, short auEvent); + virtual ~RightAuthenticationLogger() { } + + virtual void writeCommon(); + + virtual void logSuccess() { } // throw? in any case, don't allow the usual logSuccess() to work + // @@@ clean up, consolidate Success and AuthorizationResult + void logSuccess(uid_t authenticator, uid_t target, const char *targetName); + void logAuthorizationResult(const char *client, const char *authCreator, int errcode); + void logLeastPrivilege(uid_t userId, bool isAuthorizingUser); + virtual void logFailure(const char *errMsg, int errcode) { AuditLogger::logFailure(errMsg, errcode); } + void logFailure(uid_t authenticator, const char *targetName); +}; + + +} // namespace Securityd + +} // namespace CommonCriteria + +} // namespace Security