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