/ securityd / src / ccaudit_extensions.h
ccaudit_extensions.h
  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); }
245      void logAuthenticatorFailure(uid_t authenticator, const char *targetName);
246  };
247  
248  
249  }   // namespace Securityd
250  
251  }   // namespace CommonCriteria
252      
253  }   // namespace Security