2 * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
23 #include "piddiskrep.h"
25 #include <sys/param.h>
26 #include <sys/utsname.h>
27 #include <System/sys/codesign.h>
32 namespace CodeSigning
{
34 using namespace UnixPlusPlus
;
38 PidDiskRep::setCredentials(const Security::CodeSigning::CodeDirectory
*cd
)
40 // save the Info.plist slot
41 if (cd
->slotIsPresent(cdInfoSlot
)) {
42 mInfoPlistHash
.take(makeCFData(cd
->getSlot(cdInfoSlot
, false), cd
->hashSize
));
47 PidDiskRep::fetchData(void)
49 if (mDataFetched
) // once
52 xpc_connection_t conn
= xpc_connection_create("com.apple.CodeSigningHelper",
53 dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0));
54 xpc_connection_set_event_handler(conn
, ^(xpc_object_t object
){ });
55 xpc_connection_resume(conn
);
57 xpc_object_t request
= xpc_dictionary_create(NULL
, NULL
, 0);
58 assert(request
!= NULL
);
59 xpc_dictionary_set_string(request
, "command", "fetchData");
60 xpc_dictionary_set_int64(request
, "pid", mPid
);
63 xpc_dictionary_set_data(request
, "audit", mAudit
.get(), sizeof(audit_token_t
));
65 xpc_dictionary_set_data(request
, "infohash", CFDataGetBytePtr(mInfoPlistHash
), CFDataGetLength(mInfoPlistHash
));
67 xpc_object_t reply
= xpc_connection_send_message_with_reply_sync(conn
, request
);
68 if (reply
&& xpc_get_type(reply
) == XPC_TYPE_DICTIONARY
) {
73 data
= xpc_dictionary_get_data(reply
, "infoPlist", &size
);
74 if (data
&& size
> 0 && size
< 50 * 1024)
75 mInfoPlist
.take(CFDataCreate(NULL
, (const UInt8
*)data
, (CFIndex
)size
));
78 data
= xpc_dictionary_get_data(reply
, "bundleURL", &size
);
79 if (data
&& size
> 0 && size
< 50 * 1024)
80 mBundleURL
.take(CFURLCreateWithBytes(NULL
, (const UInt8
*)data
, (CFIndex
)size
, kCFStringEncodingUTF8
, NULL
));
90 MacOSError::throwMe(errSecCSNoSuchCode
);
96 PidDiskRep::PidDiskRep(pid_t pid
, audit_token_t
*audit
, CFDataRef infoPlist
)
102 mInfoPlist
= infoPlist
;
105 mAudit
.reset(new audit_token_t
);
106 memcpy(mAudit
.get(), audit
, sizeof(audit_token_t
));
114 rcent
= ::csops_audittoken(pid
, CS_OPS_BLOB
, &header
, sizeof(header
), mAudit
.get());
116 rcent
= ::csops(pid
, CS_OPS_BLOB
, &header
, sizeof(header
));
119 MacOSError::throwMe(errSecCSNoSuchCode
);
122 UnixError::throwMe(errno
);
124 if (header
.length() > 1024 * 1024)
125 MacOSError::throwMe(errSecCSNoSuchCode
);
127 uint32_t bufferLen
= (uint32_t)header
.length();
128 mBuffer
= new uint8_t [bufferLen
];
131 UnixError::check(::csops_audittoken(pid
, CS_OPS_BLOB
, mBuffer
, bufferLen
, mAudit
.get()));
133 UnixError::check(::csops(pid
, CS_OPS_BLOB
, mBuffer
, bufferLen
));
136 const EmbeddedSignatureBlob
*b
= (const EmbeddedSignatureBlob
*)mBuffer
;
137 if (!b
->validateBlob(bufferLen
))
138 MacOSError::throwMe(errSecCSSignatureInvalid
);
141 PidDiskRep::~PidDiskRep()
148 bool PidDiskRep::supportInfoPlist()
155 CFDataRef
PidDiskRep::component(CodeDirectory::SpecialSlot slot
)
157 if (slot
== cdInfoSlot
) {
159 return mInfoPlist
.retain();
162 EmbeddedSignatureBlob
*b
= (EmbeddedSignatureBlob
*)this->blob();
163 return b
->component(slot
);
166 CFDataRef
PidDiskRep::identification()
172 CFURLRef
PidDiskRep::copyCanonicalPath()
175 return mBundleURL
.retain();
178 string
PidDiskRep::recommendedIdentifier(const SigningContext
&)
180 return string("pid") + to_string(mPid
);
183 size_t PidDiskRep::signingLimit()
188 size_t PidDiskRep::execSegLimit(const Architecture
*)
193 string
PidDiskRep::format()
195 return "pid diskrep";
198 UnixPlusPlus::FileDesc
&PidDiskRep::fd()
200 UnixError::throwMe(EINVAL
);
203 string
PidDiskRep::mainExecutablePath()
205 char path
[MAXPATHLEN
* 2];
206 // This is unsafe by pid only, but so is using that path in general.
207 if(::proc_pidpath(mPid
, path
, sizeof(path
)) == 0)
208 UnixError::throwMe(errno
);
213 bool PidDiskRep::appleInternalForcePlatform() const
218 if (mAudit
!= NULL
) {
219 rcent
= ::csops_audittoken(mPid
, CS_OPS_STATUS
, &flags
, sizeof(flags
),
222 rcent
= ::csops(mPid
, CS_OPS_STATUS
, &flags
, sizeof(flags
));
226 MacOSError::throwMe(errSecCSNoSuchCode
);
229 return (flags
& CS_PLATFORM_BINARY
) == CS_PLATFORM_BINARY
;
232 } // end namespace CodeSigning
233 } // end namespace Security