/ securityd / src / credential.cpp
credential.cpp
  1  /*
  2   * Copyright (c) 2000-2004,2006-2007,2009,2012 Apple Inc. All Rights Reserved.
  3   * 
  4   * @APPLE_LICENSE_HEADER_START@
  5   * 
  6   * This file contains Original Code and/or Modifications of Original Code
  7   * as defined in and that are subject to the Apple Public Source License
  8   * Version 2.0 (the 'License'). You may not use this file except in
  9   * compliance with the License. Please obtain a copy of the License at
 10   * http://www.opensource.apple.com/apsl/ and read it before using this
 11   * file.
 12   * 
 13   * The Original Code and all software distributed under the License are
 14   * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 15   * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 16   * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 17   * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 18   * Please see the License for the specific language governing rights and
 19   * limitations under the License.
 20   * 
 21   * @APPLE_LICENSE_HEADER_END@
 22   */
 23  
 24  #include "credential.h"
 25  #include <pwd.h>
 26  #include <syslog.h>
 27  
 28  #include <Security/checkpw.h>
 29  extern "C" int checkpw_internal( const struct passwd *pw, const char* password );
 30  #include "server.h"
 31  
 32  namespace Authorization {
 33  
 34  // default credential: invalid for everything, needed as a default session credential
 35  CredentialImpl::CredentialImpl() : mShared(false), mRight(false), mUid(0), mName(""), mCreationTime(CFAbsoluteTimeGetCurrent()), mValid(false)
 36  {
 37  }
 38  
 39  // only for testing whether this credential is usable
 40  CredentialImpl::CredentialImpl(const uid_t uid, const string &username, const string &realname, bool shared) : mShared(shared), mRight(false), mUid(uid), mName(username), mRealName(realname), mCreationTime(CFAbsoluteTimeGetCurrent()), mValid(true)
 41  {
 42  }
 43  
 44  CredentialImpl::CredentialImpl(const string &username, const string &password, bool shared) : mShared(shared), mRight(false), mName(username), mCreationTime(CFAbsoluteTimeGetCurrent()), mValid(false)
 45  {
 46      Server::active().longTermActivity();
 47      const char *user = username.c_str();
 48      struct passwd *pw = getpwnam(user);
 49  
 50      do {
 51          if (!pw) {
 52  			syslog(LOG_ERR, "getpwnam() failed for user %s, creating invalid credential", user);
 53              break;
 54          }
 55  
 56          mUid = pw->pw_uid;
 57          mName = pw->pw_name;
 58          mRealName = pw->pw_gecos;
 59  
 60          const char *passwd = password.c_str();
 61          int checkpw_status = checkpw_internal(pw, passwd);
 62  
 63          if (checkpw_status != CHECKPW_SUCCESS) {
 64              syslog(LOG_ERR, "checkpw() returned %d; failed to authenticate user %s (uid %u).", checkpw_status, pw->pw_name, pw->pw_uid);
 65              break;
 66          }
 67  
 68  		syslog(LOG_INFO, "checkpw() succeeded, creating%s credential for user %s", mShared ? " shared" : "", user);
 69  
 70          mValid = true;
 71  
 72          endpwent();
 73      } while (0);
 74  }
 75  
 76  // least-privilege
 77      // @@@  arguably we don't care about the UID any more and should not
 78      // require it in this ctor
 79  CredentialImpl::CredentialImpl(const string &right, bool shared) : mShared(shared), mRight(true), mUid(-2), mName(right), mRealName(""), mCreationTime(CFAbsoluteTimeGetCurrent()), mValid(true)
 80  {
 81  }
 82  
 83  CredentialImpl::~CredentialImpl()
 84  {
 85  }
 86  
 87  bool
 88  CredentialImpl::operator < (const CredentialImpl &other) const
 89  {
 90      // all shared creds are placed into mSessionCreds
 91      // all non shared creds are placed into AuthorizationToken
 92      //
 93      // There are 2 types of credentials UID and Right
 94      // UID = Authenticated Identity
 95      // Right = Rights which were previously authenticated by a uid credential
 96      
 97      // Right Credentials are only used during kAuthorizationFlagLeastPrivileged 
 98      // operations and should not have a valid uid set    
 99  
100      // this allows shared and none shared co-exist in the same container
101      // used when processing multiple rights shared vs non-shared during evaluation 
102      if (!mShared && other.mShared)
103          return true;
104      if (!other.mShared && mShared)
105          return false;
106      
107      // this allows uids and rights co-exist in the same container
108      // used when holding onto Rights inside of the AuthorizationToken
109      if (mRight && !other.mRight)
110          return true;
111      if (!mRight && other.mRight)
112          return false;
113      
114      // this is the actual comparision
115      if (mRight) {
116          return mName < other.mName;
117      } else {
118          return mUid < other.mUid;
119      }
120  }
121  
122  // Returns true if this CredentialImpl should be shared.
123  bool
124  CredentialImpl::isShared() const
125  {
126          return mShared;
127  }
128  
129  // Merge with other
130  void
131  CredentialImpl::merge(const CredentialImpl &other)
132  {
133      // try to ensure that the credentials are the same type
134      assert(mRight == other.mRight);
135      if (mRight) {
136          assert(mName == other.mName);
137      } else {
138          assert(mUid == other.mUid);
139      }
140  
141      if (other.mValid && (!mValid || mCreationTime < other.mCreationTime))
142      {
143          mCreationTime = other.mCreationTime;
144          mValid = true;
145      }
146  }
147  
148  // The time at which this credential was obtained.
149  CFAbsoluteTime
150  CredentialImpl::creationTime() const
151  {
152          return mCreationTime;
153  }
154  
155  // Return true iff this credential is valid.
156  bool
157  CredentialImpl::isValid() const
158  {
159          return mValid;
160  }
161  
162  void
163  CredentialImpl::invalidate()
164  {
165          mValid = false;
166  }
167  
168  //
169  // Credential class
170  //
171  Credential::Credential() :
172  RefPointer<CredentialImpl>(new CredentialImpl())
173  {
174  }
175  
176  Credential::Credential(CredentialImpl *impl) :
177  RefPointer<CredentialImpl>(impl)
178  {
179  }
180  
181  Credential::Credential(const uid_t uid, const string &username, const string &realname, bool shared) :
182  RefPointer<CredentialImpl>(new CredentialImpl(uid, username, realname, shared))
183  {
184  }
185  
186  Credential::Credential(const string &username, const string &password, bool shared) : RefPointer<CredentialImpl>(new CredentialImpl(username, password, shared))
187  {
188  }
189  
190  Credential::Credential(const string &right, bool shared) : RefPointer<CredentialImpl>(new CredentialImpl(right, shared))
191  {
192  }
193  
194  Credential::~Credential()
195  {
196  }
197  
198  bool
199  Credential::operator < (const Credential &other) const
200  {
201          if (!*this)
202                  return other;
203  
204          if (!other)
205                  return false;
206  
207          return (**this) < (*other);
208  }
209  
210  } // end namespace Authorization
211  
212