X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5c19dc3ae3bd8e40a9c028b0deddd50ff337692c..refs/heads/master:/securityd/src/transition.cpp?ds=inline diff --git a/securityd/src/transition.cpp b/securityd/src/transition.cpp index 1512fd96..b2bd64d1 100644 --- a/securityd/src/transition.cpp +++ b/securityd/src/transition.cpp @@ -1,15 +1,15 @@ /* - * Copyright (c) 2000-2009,2012-2013 Apple Inc. All Rights Reserved. - * + * Copyright (c) 2000-2009,2012-2013,2016 Apple Inc. All Rights Reserved. + * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -37,16 +37,21 @@ #include "database.h" #include "kcdatabase.h" #include "tokendatabase.h" +#include "acl_keychain.h" #include "kckey.h" #include "child.h" #include #include +#include "SecRandom.h" #include #include #include #include +#include #include #include +#include +#include #include #include @@ -61,12 +66,10 @@ #define BEGIN_IPCN *rcode = CSSM_OK; try { #define BEGIN_IPC(name) BEGIN_IPCN RefPointer connRef(&Server::connection(replyPort, auditToken)); \ Connection &connection __attribute__((unused)) = *connRef; \ - if (SECURITYD_REQUEST_ENTRY_ENABLED()) { \ - const char * volatile s = #name; volatile char __attribute__((unused)) pagein = s[0]; \ - SECURITYD_REQUEST_ENTRY((char *)s, &connection, &connection.process()); \ - } + secinfo("SecServer", "request entry " #name " (pid:%d session:%d)", connection.process().pid(), connection.session().sessionId()); + #define END_IPC(base) END_IPCN(base) Server::requestComplete(*rcode); return KERN_SUCCESS; -#define END_IPCN(base) SECURITYD_REQUEST_RETURN(*rcode); \ +#define END_IPCN(base) secinfo("SecServer", "request return: %d", *(rcode)); \ } \ catch (const CommonError &err) { *rcode = CssmError::cssmError(err, CSSM_ ## base ## _BASE_ERROR); } \ catch (const std::bad_alloc &) { *rcode = CssmError::merge(CSSM_ERRCODE_MEMORY_ERROR, CSSM_ ## base ## _BASE_ERROR); } \ @@ -173,11 +176,11 @@ public: OutputData(void **outP, mach_msg_type_number_t *outLength) : mData(*outP), mLength(*outLength) { } ~OutputData() - { mData = data(); mLength = length(); Server::releaseWhenDone(mData); } - + { mData = data(); mLength = int_cast(length()); Server::releaseWhenDone(mData); } + void operator = (const CssmData &source) { CssmData::operator = (source); } - + private: void * &mData; mach_msg_type_number_t &mLength; @@ -204,62 +207,65 @@ Database *pickDb(Database *db1, Database *db2) // persistent db1 always wins if (db1 && !db1->transient()) return db1; - + // persistent db2 is next choice if (db2 && !db2->transient()) return db2; - + // pick any existing transient database if (db1) return db1; if (db2) return db2; - + // none at all. use the canonical transient store return Server::optionalDatabase(noDb); } +static void checkPathLength(char const *str) { + if (strlen(str) >= PATH_MAX) { + secerror("SecServer: path too long"); + CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); + } +} + // // Setup/Teardown functions. // + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wmissing-prototypes" + kern_return_t ucsp_server_setup(UCSP_ARGS, mach_port_t taskPort, ClientSetupInfo info, const char *identity) { BEGIN_IPCN - SECURITYD_REQUEST_ENTRY((char*)"setup", NULL, NULL); + secinfo("SecServer", "request entry: setup"); Server::active().setupConnection(Server::connectNewProcess, replyPort, taskPort, auditToken, &info); END_IPCN(CSSM) if (*rcode) Syslog::notice("setup(%s) failed rcode=%d", identity ? identity : "", *rcode); + mach_port_deallocate(mach_task_self(), taskPort); return KERN_SUCCESS; } kern_return_t ucsp_server_setupThread(UCSP_ARGS, mach_port_t taskPort) { - SECURITYD_REQUEST_ENTRY((char*)"setupThread", NULL, NULL); + secinfo("SecServer", "request entry: setupThread"); BEGIN_IPCN Server::active().setupConnection(Server::connectNewThread, replyPort, taskPort, auditToken); END_IPCN(CSSM) if (*rcode) Syslog::notice("setupThread failed rcode=%d", *rcode); - return KERN_SUCCESS; -} - - -kern_return_t ucsp_server_teardown(UCSP_ARGS) -{ - BEGIN_IPCN - SECURITYD_REQUEST_ENTRY((char*)"teardown", NULL, NULL); - Server::active().endConnection(replyPort); - END_IPCN(CSSM) + mach_port_deallocate(mach_task_self(), taskPort); return KERN_SUCCESS; } kern_return_t ucsp_server_verifyPrivileged(UCSP_ARGS) { BEGIN_IPCN - SECURITYD_REQUEST_ENTRY((char*)"verifyPrivileged", NULL, NULL); + secinfo("SecServer", "request entry: verifyPrivileged"); // doing nothing (we just want securityd's audit credentials returned) END_IPCN(CSSM) return KERN_SUCCESS; @@ -268,7 +274,8 @@ kern_return_t ucsp_server_verifyPrivileged(UCSP_ARGS) kern_return_t ucsp_server_verifyPrivileged2(UCSP_ARGS, mach_port_t *originPort) { BEGIN_IPCN - SECURITYD_REQUEST_ENTRY((char*)"verifyPrivileged2", NULL, NULL); + + secinfo("SecServer", "request entry: verifyPrivileged2"); // send the port back to the sender to check for a MitM (6986198) *originPort = servicePort; END_IPCN(CSSM) @@ -282,7 +289,7 @@ kern_return_t ucsp_server_authenticateDb(UCSP_ARGS, DbHandle db, CSSM_DB_ACCESS_TYPE accessType, DATA_IN(cred)) { BEGIN_IPC(authenticateDb) - secdebug("dl", "authenticateDb"); + secinfo("dl", "authenticateDb"); CopyOutAccessCredentials creds(cred, credLength); // ignoring accessType Server::database(db)->authenticate(accessType, creds); @@ -301,15 +308,16 @@ kern_return_t ucsp_server_getDbName(UCSP_ARGS, DbHandle db, char name[PATH_MAX]) { BEGIN_IPC(getDbName) string result = Server::database(db)->dbName(); - assert(result.length() < PATH_MAX); - memcpy(name, result.c_str(), result.length() + 1); + checkPathLength(result.c_str()); + memcpy(name, result.c_str(), result.length() + 1); END_IPC(DL) } kern_return_t ucsp_server_setDbName(UCSP_ARGS, DbHandle db, const char *name) { BEGIN_IPC(setDbName) - Server::database(db)->dbName(name); + checkPathLength(name); + Server::database(db)->dbName(name); END_IPC(DL) } @@ -322,13 +330,16 @@ kern_return_t ucsp_server_openToken(UCSP_ARGS, uint32 ssid, FilePath name, { BEGIN_IPC(openToken) CopyOutAccessCredentials creds(accessCredentials, accessCredentialsLength); +// The static analyzer is not a fan of this "create object, send handle to foreign process" model. Tell it not to worry. +#ifndef __clang_analyzer__ *db = (new TokenDatabase(ssid, connection.process(), name, creds))->handle(); +#endif END_IPC(DL) } kern_return_t ucsp_server_findFirst(UCSP_ARGS, DbHandle db, DATA_IN(inQuery), DATA_IN(inAttributes), DATA_OUT(outAttributes), - boolean_t getData, DATA_OUT(data), + boolean_t getData, DATA_OUT(data), KeyHandle *hKey, SearchHandle *hSearch, IPCRecordHandle *hRecord) { BEGIN_IPC(findFirst) @@ -340,10 +351,10 @@ kern_return_t ucsp_server_findFirst(UCSP_ARGS, DbHandle db, RefPointer key; CssmData outData; CssmDbRecordAttributeData *outAttrs = NULL; mach_msg_type_number_t outAttrsLength; - Server::database(db)->findFirst(*query, + Server::database(db)->findFirst(*query, attrs.attribute_data(), attrs.length(), getData ? &outData : NULL, key, search, record, outAttrs, outAttrsLength); - + // handle nothing-found case without exceptions if (!record) { *hRecord = noRecord; @@ -361,7 +372,7 @@ kern_return_t ucsp_server_findFirst(UCSP_ARGS, DbHandle db, CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); Server::releaseWhenDone(*outAttributes); } - + // return data (temporary fix) if (getData) { Server::releaseWhenDone(outData.data()); @@ -393,7 +404,7 @@ kern_return_t ucsp_server_findNext(UCSP_ARGS, SearchHandle hSearch, CssmDbRecordAttributeData *outAttrs = NULL; mach_msg_type_number_t outAttrsLength; search->database().findNext(search, attrs.attribute_data(), attrs.length(), getData ? &outData : NULL, key, record, outAttrs, outAttrsLength); - + // handle nothing-found case without exceptions if (!record) { *hRecord = noRecord; @@ -404,14 +415,14 @@ kern_return_t ucsp_server_findNext(UCSP_ARGS, SearchHandle hSearch, *hKey = key ? key->handle() : noKey; if (outAttrsLength && outAttrs) { - secdebug("attrmem", "Found attrs: %p of length: %d", outAttrs, outAttrsLength); + secinfo("attrmem", "Found attrs: %p of length: %d", outAttrs, outAttrsLength); Server::releaseWhenDone(outAttrs); // exception proof it against next line if (!copyin(outAttrs, reinterpret_cast (xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA), outAttributes, outAttributesLength)) CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); - secdebug("attrmem", "Copied attrs: %p of length: %d", *outAttributes, *outAttributesLength); + secinfo("attrmem", "Copied attrs: %p of length: %d", *outAttributes, *outAttributesLength); Server::releaseWhenDone(*outAttributes); } - + // return data (temporary fix) if (getData) { Server::releaseWhenDone(outData.data()); @@ -439,7 +450,7 @@ kern_return_t ucsp_server_findRecordHandle(UCSP_ARGS, IPCRecordHandle hRecord, CssmDbRecordAttributeData *outAttrs; mach_msg_type_number_t outAttrsLength; record->database().findRecordHandle(record, attrs.attribute_data(), attrs.length(), getData ? &outData : NULL, key, outAttrs, outAttrsLength); - + // return handles *hKey = key ? key->handle() : noKey; @@ -449,7 +460,7 @@ kern_return_t ucsp_server_findRecordHandle(UCSP_ARGS, IPCRecordHandle hRecord, CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); Server::releaseWhenDone(*outAttributes); } - + // return data (temporary fix) if (getData) { /* @@ -533,19 +544,71 @@ kern_return_t ucsp_server_createDb(UCSP_ARGS, DbHandle *db, CopyOutAccessCredentials creds(cred, credLength); CopyOutEntryAcl owneracl(owner, ownerLength); CopyOut flatident(ident, identLength, reinterpret_cast(xdr_DLDbFlatIdentifierRef)); + checkPathLength((*reinterpret_cast(flatident.data())).name); +#ifndef __clang_analyzer__ *db = (new KeychainDatabase(*reinterpret_cast(flatident.data()), params, connection.process(), creds, owneracl))->handle(); +#endif END_IPC(DL) } +kern_return_t ucsp_server_cloneDb(UCSP_ARGS, DbHandle srcDb, DATA_IN(ident), DbHandle *newDb) { + BEGIN_IPC(cloneDb) + + secnotice("integrity", "cloning a db"); + + CopyOut flatident(ident, identLength, reinterpret_cast(xdr_DLDbFlatIdentifierRef)); + + checkPathLength((*reinterpret_cast(flatident.data())).name); + + RefPointer srcKC = Server::keychain(srcDb); + secnotice("integrity", "cloning db %d", srcKC->handle()); + +#ifndef __clang_analyzer__ + KeychainDatabase* newKC = new KeychainDatabase(*reinterpret_cast(flatident.data()), *srcKC, connection.process()); + secnotice("integrity", "returning db %d", newKC->handle()); + *newDb = newKC->handle(); +#endif + + END_IPC(DL) +} + kern_return_t ucsp_server_recodeDbForSync(UCSP_ARGS, DbHandle dbToClone, DbHandle srcDb, DbHandle *newDb) { BEGIN_IPC(recodeDbForSync) RefPointer srcKC = Server::keychain(srcDb); +#ifndef __clang_analyzer__ *newDb = (new KeychainDatabase(*srcKC, connection.process(), dbToClone))->handle(); +#endif END_IPC(DL) } +kern_return_t ucsp_server_recodeDbToVersion(UCSP_ARGS, uint32 newVersion, DbHandle srcDb, DbHandle *newDb) +{ + BEGIN_IPC(recodeDbToVersion) + RefPointer srcKC = Server::keychain(srcDb); + + // You can only recode an unlocked keychain, so let's make sure. + srcKC->unlockDb(false); + + KeychainDatabase* newKC = new KeychainDatabase(newVersion, *srcKC, connection.process()); + if(newKC->blob()->version() != newVersion) { + CssmError::throwMe(CSSM_ERRCODE_INCOMPATIBLE_VERSION); + } + + *newDb = newKC->handle(); + + END_IPC(DL) +} + +kern_return_t ucsp_server_recodeFinished(UCSP_ARGS, DbHandle db) +{ + BEGIN_IPC(recodeDbToVersion) + Server::keychain(db)->recodeFinished(); + END_IPC(DL) +} + + kern_return_t ucsp_server_authenticateDbsForSync(UCSP_ARGS, DATA_IN(dbHandleArray), DATA_IN(agentData), DbHandle* authenticatedDBHandle) { @@ -563,7 +626,7 @@ kern_return_t ucsp_server_authenticateDbsForSync(UCSP_ARGS, DATA_IN(dbHandleArra int index; for (index=0; index < ipcDbHandleArrayCount; index++) { - *currIPCDbHandleArrayPtr = *dbHandleArrayPtr; + *currIPCDbHandleArrayPtr = *dbHandleArrayPtr; Server::keychain(*currIPCDbHandleArrayPtr)->lockDb(); // lock this db if it was unlocked in the past (user could have deleted the kc, resetLogin, etc.) currIPCDbHandleArrayPtr++; dbHandleArrayPtr++; @@ -588,7 +651,7 @@ kern_return_t ucsp_server_commitDbForSync(UCSP_ARGS, DbHandle srcDb, *blob = dbBlob; *blobLength = dbBlob->length(); } else { - secdebug("kcrecode", "No blob can be returned to client"); + secinfo("kcrecode", "No blob can be returned to client"); } END_IPC(DL) } @@ -601,9 +664,13 @@ kern_return_t ucsp_server_decodeDb(UCSP_ARGS, DbHandle *db, CopyOut flatident(ident, identLength, reinterpret_cast(xdr_DLDbFlatIdentifierRef)); DLDbFlatIdentifier* flatID = (DLDbFlatIdentifier*) flatident.data(); DLDbIdentifier id = *flatID; // invokes a casting operator - + + checkPathLength(id.dbName()); + +#ifndef __clang_analyzer__ *db = (new KeychainDatabase(id, SSBLOB(DbBlob, blob), connection.process(), creds))->handle(); +#endif END_IPC(DL) } @@ -649,7 +716,7 @@ kern_return_t ucsp_server_lockAll (UCSP_ARGS, boolean_t) kern_return_t ucsp_server_unlockDb(UCSP_ARGS, DbHandle db) { BEGIN_IPC(unlockDb) - Server::keychain(db)->unlockDb(); + Server::keychain(db)->unlockDb(true); END_IPC(DL) } @@ -660,28 +727,28 @@ static void check_stash_entitlement(Process & proc) CFDictionaryRef entitlements = NULL; CFTypeRef value = NULL; bool entitled = false; - - status = SecCodeCopySigningInformation(proc.processCode(), kSecCSRequirementInformation, &code_info); + + status = proc.copySigningInfo(kSecCSRequirementInformation, &code_info); require_noerr(status, done); - + if (CFDictionaryGetValueIfPresent(code_info, kSecCodeInfoEntitlementsDict, &value)) { if (CFGetTypeID(value) == CFDictionaryGetTypeID()) { entitlements = (CFDictionaryRef)value; } } require(entitlements != NULL, done); - - if (CFDictionaryGetValueIfPresent(entitlements, CFSTR("com.apple.private.securityd.stash"), &value)) { + + if (CFDictionaryGetValueIfPresent(entitlements, kSecEntitlementPrivateStash, &value)) { if (CFGetTypeID(value) && CFBooleanGetTypeID()) { entitled = CFBooleanGetValue((CFBooleanRef)value); } } - + done: if (code_info) { CFRelease(code_info); } - + if (!entitled) { CssmError::throwMe(CSSM_ERRCODE_OS_ACCESS_DENIED); } @@ -690,7 +757,7 @@ done: kern_return_t ucsp_server_unlockDbWithPassphrase(UCSP_ARGS, DbHandle db, DATA_IN(passphrase)) { BEGIN_IPC(unlockDbWithPassphrase) - Server::keychain(db)->unlockDb(DATA(passphrase)); + Server::keychain(db)->unlockDb(DATA(passphrase), true); END_IPC(DL) } @@ -713,6 +780,8 @@ kern_return_t ucsp_server_stashDbCheck(UCSP_ARGS, DbHandle db) kern_return_t ucsp_server_isLocked(UCSP_ARGS, DbHandle db, boolean_t *locked) { BEGIN_IPC(isLocked) + // Must hold the DB's common's lock to safely determine if it's locked. Locking is a mess in there. + StLock _(Server::database(db)->common()); *locked = Server::database(db)->isLocked(); END_IPC(DL) } @@ -775,7 +844,7 @@ kern_return_t ucsp_server_decodeKey(UCSP_ARGS, KeyHandle *keyh, DATA_OUT(keyHead } // keychain synchronization -kern_return_t ucsp_server_recodeKey(UCSP_ARGS, DbHandle oldDb, KeyHandle keyh, +kern_return_t ucsp_server_recodeKey(UCSP_ARGS, DbHandle oldDb, KeyHandle keyh, DbHandle newDb, DATA_OUT(newBlob)) { BEGIN_IPC(recodeKey) @@ -790,7 +859,7 @@ kern_return_t ucsp_server_recodeKey(UCSP_ARGS, DbHandle oldDb, KeyHandle keyh, // @@@ stop leaking blob } else { // not a KeychainKey CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE); - } + } END_IPC(CSP) } @@ -825,7 +894,7 @@ kern_return_t ucsp_server_getKeyDigest(UCSP_ARGS, KeyHandle key, DATA_OUT(digest BEGIN_IPC(getKeyDigest) CssmData digestData = Server::key(key)->canonicalDigest(); *digest = digestData.data(); - *digestLength = digestData.length(); + *digestLength = int_cast(digestData.length()); END_IPC(CSP) } @@ -945,7 +1014,7 @@ kern_return_t ucsp_server_generateKeyPair(UCSP_ARGS, DbHandle db, DATA_IN(contex database->generateKey(*ctx, creds, owneracl, pubUsage, pubAttrs, privUsage, privAttrs, pub, priv); CssmKey::Header tmpPubHeader, tmpPrivHeader; - + pub->returnKey(*pubKey, tmpPubHeader); if (!copyin(&tmpPubHeader, reinterpret_cast (xdr_CSSM_KEYHEADER), pubHeader, pubHeaderLength)) CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); @@ -981,7 +1050,7 @@ kern_return_t ucsp_server_wrapKey(UCSP_ARGS, DATA_IN(context), KeyHandle hWrappi if (!copyin(&wrappedKey, reinterpret_cast (xdr_CSSM_KEY), wrappedKeyData, wrappedKeyDataLength)) CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); - + Server::releaseWhenDone(*wrappedKeyData); END_IPC(CSP) } @@ -1003,7 +1072,7 @@ kern_return_t ucsp_server_unwrapKey(UCSP_ARGS, DbHandle db, DATA_IN(context), pickDb(Server::optionalDatabase(db), wrappingKey)->unwrapKey(*ctx, creds, owneracl, wrappingKey, Server::optionalKey(hPublicKey), usage, attrs, wrappedKey.key(), unwrappedKey, descriptiveDatas); - + CssmKey::Header newHeader; unwrappedKey->returnKey(*newKey, newHeader); if (!copyin(&newHeader, reinterpret_cast (xdr_CSSM_KEYHEADER), keyHeader, keyHeaderLength)) @@ -1033,7 +1102,7 @@ kern_return_t ucsp_server_deriveKey(UCSP_ARGS, DbHandle db, DATA_IN(context), Ke CopyOutDeriveData deriveParam(paramInput, paramInputLength); if (deriveParam.algorithm() != ctx.context().algorithm()) CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); // client layer fault - + RefPointer database = Server::optionalDatabase(db, attrs & CSSM_KEYATTR_PERMANENT); RefPointer key = Server::optionalKey(hKey); @@ -1041,14 +1110,14 @@ kern_return_t ucsp_server_deriveKey(UCSP_ARGS, DbHandle db, DATA_IN(context), Ke RefPointer derivedKey; pickDb(Server::optionalDatabase(db, attrs & CSSM_KEYATTR_PERMANENT), key)->deriveKey(*ctx, key, creds, owneracl, static_cast(¶m), usage, attrs, derivedKey); - + CssmKey::Header newHeader; derivedKey->returnKey(*newKey, newHeader); - + if (!copyin(&newHeader, reinterpret_cast (xdr_CSSM_KEYHEADER), keyHeader, keyHeaderLength)) CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); Server::releaseWhenDone(*keyHeader); - + if (param.Length) { if (!param.Data) // CSP screwed up CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); @@ -1057,30 +1126,6 @@ kern_return_t ucsp_server_deriveKey(UCSP_ARGS, DbHandle db, DATA_IN(context), Ke END_IPC(CSP) } - -// -// Random generation -// -kern_return_t ucsp_server_generateRandom(UCSP_ARGS, uint32 ssid, DATA_IN(context), DATA_OUT(data)) -{ - BEGIN_IPC(generateRandom) - CopyOutContext ctx(context, contextLength); - if (ssid) - CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); - - // default version (use /dev/random) - Allocator &allocator = Allocator::standard(Allocator::sensitive); - if (size_t bytes = ctx.context().getInt(CSSM_ATTRIBUTE_OUTPUT_SIZE)) { - void *buffer = allocator.malloc(bytes); - Server::active().random(buffer, bytes); - *data = buffer; - *dataLength = bytes; - Server::releaseWhenDone(allocator, buffer); - } - END_IPC(CSP) -} - - // // ACL management. // Watch out for the memory-management tap-dance. @@ -1093,7 +1138,7 @@ kern_return_t ucsp_server_getOwner(UCSP_ARGS, AclKind kind, KeyHandle key, Server::aclBearer(kind, key).getOwner(owner); // allocates memory in owner void *owners_data; u_int owners_length; if (!::copyin(&owner, reinterpret_cast(xdr_CSSM_ACL_OWNER_PROTOTYPE), &owners_data, &owners_length)) - CssmError::throwMe(CSSM_ERRCODE_MEMORY_ERROR); + CssmError::throwMe(CSSM_ERRCODE_MEMORY_ERROR); { ChunkFreeWalker free; walk(free, owner); } // release chunked original Server::releaseWhenDone(owners_data); // throw flat copy out when done @@ -1119,23 +1164,26 @@ kern_return_t ucsp_server_getAcl(UCSP_ARGS, AclKind kind, KeyHandle key, BEGIN_IPC(getAcl) uint32 count; AclEntryInfo *aclList; - Server::aclBearer(kind, key).getAcl(haveTag ? tag : NULL, count, aclList); + + AclSource& aclRef = Server::aclBearer(kind, key); + secinfo("SecAccess", "getting the ACL for handle %d [%d] (%p)", key, (uint32_t) kind, &aclRef); + aclRef.getAcl(haveTag ? tag : NULL, count, aclList); CSSM_ACL_ENTRY_INFO_ARRAY aclsArray = { count, aclList }; void *acls_data; u_int acls_length; if (!::copyin(&aclsArray, reinterpret_cast(xdr_CSSM_ACL_ENTRY_INFO_ARRAY), &acls_data, &acls_length)) - CssmError::throwMe(CSSM_ERRCODE_MEMORY_ERROR); - + CssmError::throwMe(CSSM_ERRCODE_MEMORY_ERROR); + { // release the chunked memory originals ChunkFreeWalker free; for (uint32 n = 0; n < count; n++) walk(free, aclList[n]); - + // release the memory allocated for the list itself when we are done Allocator::standard().free (aclList); } - - + + *countp = count; // XXX/cs count becomes part of the blob *aclsLength = acls_length; *acls = acls_data; @@ -1151,7 +1199,10 @@ kern_return_t ucsp_server_changeAcl(UCSP_ARGS, AclKind kind, KeyHandle key, CopyOutAccessCredentials creds(cred, credLength); CopyOutAclEntryInput entryacl(acl, aclLength); - Server::aclBearer(kind, key).changeAcl(AclEdit(mode, handle, entryacl), creds); + AclSource& aclRef = Server::aclBearer(kind, key); + secinfo("SecAccess", "changing the ACL for handle %d [%d] (%p)", key, (uint32_t) kind, &aclRef); + aclRef.changeAcl(AclEdit(mode, handle, entryacl), creds); + END_IPC(CSP) } @@ -1253,167 +1304,6 @@ kern_return_t ucsp_server_extractMasterKey(UCSP_ARGS, DbHandle db, DATA_IN(conte } -// -// Authorization subsystem support -// -kern_return_t ucsp_server_authorizationCreate(UCSP_ARGS, - void *inRights, mach_msg_type_number_t inRightsLength, - uint32 flags, - void *inEnvironment, mach_msg_type_number_t inEnvironmentLength, - AuthorizationBlob *authorization) -{ - BEGIN_IPC(authorizationCreate) - AuthorizationItemSet *authrights = NULL, *authenvironment = NULL; - - if (inRights && !copyout_AuthorizationItemSet(inRights, inRightsLength, &authrights)) - { - Syslog::alert("ucsp_server_authorizationCreate(): error converting 'rights' input"); - CssmError::throwMe(errAuthorizationInternal); // allocation error probably - } - - if (inEnvironment && !copyout_AuthorizationItemSet(inEnvironment, inEnvironmentLength, &authenvironment)) - { - free(authrights); - Syslog::alert("ucsp_server_authorizationCreate(): error converting 'environment' input"); - CssmError::throwMe(errAuthorizationInternal); // allocation error probably - } - - Authorization::AuthItemSet rights(authrights), environment(authenvironment); - - *rcode = connection.process().session().authCreate(rights, environment, - flags, *authorization, auditToken); - - // @@@ safe-guard against code throw()ing in here - - if (authrights) - free(authrights); - - if (authenvironment) - free(authenvironment); - - END_IPC(CSSM) -} - -kern_return_t ucsp_server_authorizationRelease(UCSP_ARGS, - AuthorizationBlob authorization, uint32 flags) -{ - BEGIN_IPC(authorizationRelease) - connection.process().session().authFree(authorization, flags); - END_IPC(CSSM) -} - -kern_return_t ucsp_server_authorizationCopyRights(UCSP_ARGS, - AuthorizationBlob authorization, - void *inRights, mach_msg_type_number_t inRightsLength, - uint32 flags, - void *inEnvironment, mach_msg_type_number_t inEnvironmentLength, - void **result, mach_msg_type_number_t *resultLength) -{ - BEGIN_IPC(authorizationCopyRights) - AuthorizationItemSet *authrights = NULL, *authenvironment = NULL; - - if (inRights && !copyout_AuthorizationItemSet(inRights, inRightsLength, &authrights)) - { - Syslog::alert("ucsp_server_authorizationCopyRights(): error converting 'rights' input"); - CssmError::throwMe(errAuthorizationInternal); // allocation error probably - } - if (inEnvironment && !copyout_AuthorizationItemSet(inEnvironment, inEnvironmentLength, &authenvironment)) - { - free(authrights); - Syslog::alert("ucsp_server_authorizationCopyRights(): error converting 'environment' input"); - CssmError::throwMe(errAuthorizationInternal); // allocation error probably - } - - Authorization::AuthItemSet rights(authrights), environment(authenvironment), grantedRights; - *rcode = Session::authGetRights(authorization, rights, environment, flags, grantedRights); - - // @@@ safe-guard against code throw()ing in here - - if (authrights) - free(authrights); - - if (authenvironment) - free(authenvironment); - - if (result && resultLength) - { - AuthorizationItemSet *copyout = grantedRights.copy(); - if (!copyin_AuthorizationItemSet(copyout, result, resultLength)) - { - free(copyout); - Syslog::alert("ucsp_server_authorizationCopyRights(): error packaging return information"); - CssmError::throwMe(errAuthorizationInternal); - } - free(copyout); - Server::releaseWhenDone(*result); - } - END_IPC(CSSM) -} - -kern_return_t ucsp_server_authorizationCopyInfo(UCSP_ARGS, - AuthorizationBlob authorization, - AuthorizationString tag, - void **info, mach_msg_type_number_t *infoLength) -{ - BEGIN_IPC(authorizationCopyInfo) - Authorization::AuthItemSet infoSet; - *info = NULL; - *infoLength = 0; - *rcode = connection.process().session().authGetInfo(authorization, - tag[0] ? tag : NULL, infoSet); - if (*rcode == noErr) - { - AuthorizationItemSet *copyout = infoSet.copy(); - if (!copyin_AuthorizationItemSet(copyout, info, infoLength)) - { - free(copyout); - Syslog::alert("ucsp_server_authorizationCopyInfo(): error packaging return information"); - CssmError::throwMe(errAuthorizationInternal); - } - free(copyout); - Server::releaseWhenDone(*info); - } - END_IPC(CSSM) -} - -kern_return_t ucsp_server_authorizationExternalize(UCSP_ARGS, - AuthorizationBlob authorization, AuthorizationExternalForm *extForm) -{ - BEGIN_IPC(authorizationExternalize) - *rcode = connection.process().session().authExternalize(authorization, *extForm); - END_IPC(CSSM) -} - -kern_return_t ucsp_server_authorizationInternalize(UCSP_ARGS, - AuthorizationExternalForm extForm, AuthorizationBlob *authorization) -{ - BEGIN_IPC(authorizationInternalize) - *rcode = connection.process().session().authInternalize(extForm, *authorization); - END_IPC(CSSM) -} - - -// -// Session management subsystem -// -kern_return_t ucsp_server_setSessionUserPrefs(UCSP_ARGS, SecuritySessionId sessionId, DATA_IN(userPrefs)) -{ - BEGIN_IPC(setSessionuserPrefs) - CFRef data(CFDataCreate(NULL, (UInt8 *)userPrefs, userPrefsLength)); - - if (!data) - { - *rcode = errSessionValueNotSet; - return 0; - } - - Session::find(sessionId).setUserPrefs(data); - *rcode = 0; - - END_IPC(CSSM) -} - - // // Notification core subsystem // @@ -1422,71 +1312,7 @@ kern_return_t ucsp_server_postNotification(UCSP_ARGS, uint32 domain, uint32 even DATA_IN(data), uint32 sequence) { BEGIN_IPC(postNotification) - Listener::notify(domain, event, sequence, DATA(data)); - END_IPC(CSSM) -} - - -// -// AuthorizationDB modification -// -kern_return_t ucsp_server_authorizationdbGet(UCSP_ARGS, const char *rightname, DATA_OUT(rightDefinition)) -{ - BEGIN_IPC(authorizationdbGet) - CFDictionaryRef rightDict; - - *rcode = connection.process().session().authorizationdbGet(rightname, &rightDict); - - if (!*rcode && rightDict) - { - CFRef data(CFPropertyListCreateXMLData (NULL, rightDict)); - CFRelease(rightDict); - if (!data) - { - Syslog::alert("ucsp_server_authorizationGet(): unable to make XML version of right definition for '%s'", rightname); - return errAuthorizationInternal; - } - - // @@@ copy data to avoid having to do a delayed cfrelease - mach_msg_type_number_t length = CFDataGetLength(data); - void *xmlData = Allocator::standard().malloc(length); - memcpy(xmlData, CFDataGetBytePtr(data), length); - Server::releaseWhenDone(xmlData); - - *rightDefinition = xmlData; - *rightDefinitionLength = length; - } - END_IPC(CSSM) -} - -kern_return_t ucsp_server_authorizationdbSet(UCSP_ARGS, AuthorizationBlob authorization, const char *rightname, DATA_IN(rightDefinition)) -{ - BEGIN_IPC(authorizationdbSet) - CFRef data(CFDataCreate(NULL, (UInt8 *)rightDefinition, rightDefinitionLength)); - - if (!data) - { - Syslog::alert("ucsp_server_authorizationSet(): CFDataCreate() error"); - return errAuthorizationInternal; - } - - CFRef rightDefinition(static_cast(CFPropertyListCreateFromXMLData(NULL, data, kCFPropertyListImmutable, NULL))); - - if (!rightDefinition || (CFGetTypeID(rightDefinition) != CFDictionaryGetTypeID())) - { - Syslog::alert("ucsp_server_authorizationSet(): error converting XML right definition for '%s' to property list", rightname); - return errAuthorizationInternal; - } - - *rcode = connection.process().session().authorizationdbSet(authorization, rightname, rightDefinition); - - END_IPC(CSSM) -} - -kern_return_t ucsp_server_authorizationdbRemove(UCSP_ARGS, AuthorizationBlob authorization, const char *rightname) -{ - BEGIN_IPC(authorizationdbRemove) - *rcode = connection.process().session().authorizationdbRemove(authorization, rightname); + Listener::notify(domain, event, sequence, DATA(data), auditToken); END_IPC(CSSM) } @@ -1495,73 +1321,26 @@ kern_return_t ucsp_server_authorizationdbRemove(UCSP_ARGS, AuthorizationBlob aut // Child check-in service. // Note that this isn't using the standard argument pattern. // -kern_return_t ucsp_server_childCheckIn(mach_port_t serverPort, +kern_return_t ucsp_server_childCheckIn(audit_token_t auditToken, mach_port_t serverPort, mach_port_t servicePort, mach_port_t taskPort) { BEGIN_IPCS - ServerChild::checkIn(servicePort, TaskPort(taskPort).pid()); + ServerChild::checkIn(servicePort, audit_token_to_pid(auditToken)); + // Will be NULL from newer frameworks, but mach_port_deallocate doesn't seem to mind END_IPCS(mach_port_deallocate(mach_task_self(), taskPort)) } // -// Code Signing Hosting registration. -// Note that the Code Signing Proxy facility (implementing the "cshosting" -// IPC protocol) is elsewhere. +// Testing-related RPCs // -kern_return_t ucsp_server_registerHosting(UCSP_ARGS, mach_port_t hostingPort, uint32 flags) +kern_return_t ucsp_server_getUserPromptAttempts(UCSP_ARGS, uint32* attempts) { - BEGIN_IPC(registerHosting) - connection.process().registerCodeSigning(hostingPort, flags); - END_IPC(CSSM) -} - -kern_return_t ucsp_server_hostingPort(UCSP_ARGS, pid_t hostPid, mach_port_t *hostingPort) -{ - BEGIN_IPC(hostingPort) - if (RefPointer process = Server::active().findPid(hostPid)) - *hostingPort = process->hostingPort(); - else - *hostingPort = MACH_PORT_NULL; - secdebug("hosting", "hosting port for for pid=%d is port %d", hostPid, *hostingPort); - END_IPC(CSSM) -} + BEGIN_IPC(keychainPromptAttempts) + *attempts = KeychainPromptAclSubject::getPromptAttempts() + KeychainDatabase::getInteractiveUnlockAttempts(); -kern_return_t ucsp_server_setGuest(UCSP_ARGS, SecGuestRef guest, SecCSFlags flags) -{ - BEGIN_IPC(setGuest) - connection.guestRef(guest, flags); - END_IPC(CSSM) -} - - -kern_return_t ucsp_server_createGuest(UCSP_ARGS, SecGuestRef host, - uint32_t status, const char *path, DATA_IN(cdhash), DATA_IN(attributes), - SecCSFlags flags, SecGuestRef *newGuest) -{ - BEGIN_IPC(createGuest) - *newGuest = connection.process().createGuest(host, status, path, DATA(cdhash), DATA(attributes), flags); - END_IPC(CSSM) -} - -kern_return_t ucsp_server_setGuestStatus(UCSP_ARGS, SecGuestRef guest, - uint32_t status, DATA_IN(attributes)) -{ - BEGIN_IPC(setGuestStatus) - connection.process().setGuestStatus(guest, status, DATA(attributes)); - END_IPC(CSSM) -} - -kern_return_t ucsp_server_removeGuest(UCSP_ARGS, SecGuestRef host, SecGuestRef guest) -{ - BEGIN_IPC(removeGuest) - connection.process().removeGuest(host, guest); - END_IPC(CSSM) + END_IPC(DL) } -kern_return_t ucsp_server_helpCheckLoad(UCSP_ARGS, const char path[PATH_MAX], uint32_t type) -{ - BEGIN_IPC(helpCheckLoad) - END_IPC(CSSM) -} +#pragma clang diagnostic pop