X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/fa7225c82381bac4432a6edf16f53b5370238d85..refs/heads/master:/securityd/src/transition.cpp diff --git a/securityd/src/transition.cpp b/securityd/src/transition.cpp index 11dcc365..b2bd64d1 100644 --- a/securityd/src/transition.cpp +++ b/securityd/src/transition.cpp @@ -42,6 +42,7 @@ #include "child.h" #include #include +#include "SecRandom.h" #include #include #include @@ -49,6 +50,8 @@ #include #include #include +#include +#include #include #include @@ -63,10 +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; \ - secinfo("SS", "request entry " #name " (pid:%d ession:%d)", connection.process().pid(), connection.session().sessionId()); + 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) secinfo("SS", "request return: %d", *(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); } \ @@ -219,6 +222,13 @@ Database *pickDb(Database *db1, Database *db2) 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. // @@ -229,41 +239,33 @@ Database *pickDb(Database *db1, Database *db2) kern_return_t ucsp_server_setup(UCSP_ARGS, mach_port_t taskPort, ClientSetupInfo info, const char *identity) { BEGIN_IPCN - secinfo("SS", "request entry: setup"); + 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) { - secinfo("SS", "request entry: setupThread"); + 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 - secinfo("SS", "request entry: teardown"); - 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 - secinfo("SS", "request entry: verifyPrivileged"); + secinfo("SecServer", "request entry: verifyPrivileged"); // doing nothing (we just want securityd's audit credentials returned) END_IPCN(CSSM) return KERN_SUCCESS; @@ -273,7 +275,7 @@ kern_return_t ucsp_server_verifyPrivileged2(UCSP_ARGS, mach_port_t *originPort) { BEGIN_IPCN - secinfo("SS", "request entry: verifyPrivileged2"); + secinfo("SecServer", "request entry: verifyPrivileged2"); // send the port back to the sender to check for a MitM (6986198) *originPort = servicePort; END_IPCN(CSSM) @@ -306,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) } @@ -327,7 +330,10 @@ 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) } @@ -538,7 +544,10 @@ 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) } @@ -549,12 +558,16 @@ kern_return_t ucsp_server_cloneDb(UCSP_ARGS, DbHandle srcDb, DATA_IN(ident), DbH 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) } @@ -564,7 +577,9 @@ kern_return_t ucsp_server_recodeDbForSync(UCSP_ARGS, DbHandle dbToClone, { BEGIN_IPC(recodeDbForSync) RefPointer srcKC = Server::keychain(srcDb); +#ifndef __clang_analyzer__ *newDb = (new KeychainDatabase(*srcKC, connection.process(), dbToClone))->handle(); +#endif END_IPC(DL) } @@ -650,8 +665,12 @@ kern_return_t ucsp_server_decodeDb(UCSP_ARGS, DbHandle *db, 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) } @@ -719,7 +738,7 @@ static void check_stash_entitlement(Process & proc) } 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); } @@ -761,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) } @@ -1105,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 = int_cast(bytes); - Server::releaseWhenDone(allocator, buffer); - } - END_IPC(CSP) -} - - // // ACL management. // Watch out for the memory-management tap-dance. @@ -1315,7 +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)); + Listener::notify(domain, event, sequence, DATA(data), auditToken); END_IPC(CSSM) } @@ -1324,77 +1321,16 @@ kern_return_t ucsp_server_postNotification(UCSP_ARGS, uint32 domain, uint32 even // 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. -// -kern_return_t ucsp_server_registerHosting(UCSP_ARGS, mach_port_t hostingPort, uint32 flags) -{ - 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; - secinfo("hosting", "hosting port for for pid=%d is port %d", hostPid, *hostingPort); - END_IPC(CSSM) -} - - -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) -} - -kern_return_t ucsp_server_helpCheckLoad(UCSP_ARGS, const char path[PATH_MAX], uint32_t type) -{ - BEGIN_IPC(helpCheckLoad) - END_IPC(CSSM) -} - // // Testing-related RPCs //