]> git.saurik.com Git - apple/security.git/blobdiff - libsecurity_codesigning/lib/piddiskrep.cpp
Security-55471.tar.gz
[apple/security.git] / libsecurity_codesigning / lib / piddiskrep.cpp
diff --git a/libsecurity_codesigning/lib/piddiskrep.cpp b/libsecurity_codesigning/lib/piddiskrep.cpp
new file mode 100644 (file)
index 0000000..aafba02
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2012 Apple Computer, 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,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * 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@
+ */
+#include "piddiskrep.h"
+#include "sigblob.h"
+#include <sys/param.h>
+#include <sys/utsname.h>
+#include <System/sys/codesign.h>
+#include <libproc.h>
+#include <xpc/xpc.h>
+
+namespace Security {
+namespace CodeSigning {
+                
+using namespace UnixPlusPlus;
+        
+void
+PidDiskRep::fetchData(void)
+{
+       xpc_connection_t conn = xpc_connection_create("com.apple.CodeSigningHelper",
+                                                     dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
+       xpc_connection_set_event_handler(conn, ^(xpc_object_t object){ });
+       xpc_connection_resume(conn);
+       
+       xpc_object_t request = xpc_dictionary_create(NULL, NULL, 0);
+       assert(request != NULL);
+       xpc_dictionary_set_string(request, "command", "fetchData");
+       xpc_dictionary_set_int64(request, "pid", mPid);
+        
+       xpc_object_t reply = xpc_connection_send_message_with_reply_sync(conn, request);
+       if (reply && xpc_get_type(reply) == XPC_TYPE_DICTIONARY) {
+               const void *data;
+               size_t size;
+
+               if (!mInfoPlist) {
+                       data = xpc_dictionary_get_data(reply, "infoPlist", &size);
+                       if (data && size > 0 && size < 50 * 1024)
+                               mInfoPlist.take(CFDataCreate(NULL, (const UInt8 *)data, (CFIndex)size));
+               }
+               if (!mBundleURL) {
+                       data = xpc_dictionary_get_data(reply, "bundleURL", &size);
+                       if (data && size > 0 && size < 50 * 1024)
+                               mBundleURL.take(CFURLCreateWithBytes(NULL, (const UInt8 *)data, (CFIndex)size, kCFStringEncodingUTF8, NULL));
+               }
+       }
+       if (reply)
+               xpc_release(reply);
+
+       xpc_release(request);
+       xpc_release(conn);
+}
+
+
+PidDiskRep::PidDiskRep(pid_t pid, CFDataRef infoPlist)
+{
+        BlobCore header;
+        CODESIGN_DISKREP_CREATE_KERNEL(this);
+        
+        mPid = pid;
+        mInfoPlist = infoPlist;
+
+       fetchData();
+        
+        int rcent = ::csops(pid, CS_OPS_BLOB, &header, sizeof(header));
+        if (rcent == 0)
+                MacOSError::throwMe(errSecCSNoSuchCode);
+        
+        if (errno != ERANGE)
+                UnixError::throwMe(errno);
+
+        if (header.length() > 1024 * 1024)
+                MacOSError::throwMe(errSecCSNoSuchCode);
+        
+        uint32_t bufferLen = (uint32_t)header.length();
+        mBuffer = new uint8_t [bufferLen];
+        
+        UnixError::check(::csops(pid, CS_OPS_BLOB, mBuffer, bufferLen));
+
+        const BlobCore *b = (const BlobCore *)mBuffer;
+               if (b->magic() != kSecCodeMagicEmbeddedSignature)
+                       MacOSError::throwMe(errSecCSSignatureInvalid);
+        if (b->length() < sizeof(*b))
+                MacOSError::throwMe(errSecCSNoSuchCode);
+}
+
+PidDiskRep::~PidDiskRep()
+{
+        if (mBuffer)
+                delete [] mBuffer;
+}
+
+
+bool PidDiskRep::supportInfoPlist()
+{
+        return mInfoPlist;
+}
+
+
+CFDataRef PidDiskRep::component(CodeDirectory::SpecialSlot slot)
+{
+       if (slot == cdInfoSlot)
+                return mInfoPlist.retain();
+
+        EmbeddedSignatureBlob *b = (EmbeddedSignatureBlob *)this->blob();
+        return b->component(slot);
+}
+
+CFDataRef PidDiskRep::identification()
+{
+        return NULL;
+}
+
+
+CFURLRef PidDiskRep::canonicalPath()
+{
+        return mBundleURL.retain();
+}
+
+string PidDiskRep::recommendedIdentifier(const SigningContext &)
+{
+       return string("pid") + to_string(mPid);
+}
+
+size_t PidDiskRep::signingLimit()
+{
+        return 0;
+}
+
+string PidDiskRep::format()
+{
+        return "pid diskrep";
+}
+
+UnixPlusPlus::FileDesc &PidDiskRep::fd()
+{
+        UnixError::throwMe(EINVAL);
+}
+
+string PidDiskRep::mainExecutablePath()
+{
+        char path[MAXPATHLEN * 2];
+        if(::proc_pidpath(mPid, path, sizeof(path)) == 0)
+               UnixError::throwMe(errno);
+
+        return path;
+}
+                
+                
+} // end namespace CodeSigning
+} // end namespace Security