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
);
97 PidDiskRep::PidDiskRep(pid_t pid
, audit_token_t
*audit
, CFDataRef infoPlist
)
103 mInfoPlist
= infoPlist
;
106 mAudit
.reset(new audit_token_t
);
107 memcpy(mAudit
.get(), audit
, sizeof(audit_token_t
));
115 rcent
= ::csops_audittoken(pid
, CS_OPS_BLOB
, &header
, sizeof(header
), mAudit
.get());
117 rcent
= ::csops(pid
, CS_OPS_BLOB
, &header
, sizeof(header
));
120 MacOSError::throwMe(errSecCSNoSuchCode
);
123 UnixError::throwMe(errno
);
125 if (header
.length() > 1024 * 1024)
126 MacOSError::throwMe(errSecCSNoSuchCode
);
128 uint32_t bufferLen
= (uint32_t)header
.length();
129 mBuffer
= new uint8_t [bufferLen
];
132 UnixError::check(::csops_audittoken(pid
, CS_OPS_BLOB
, mBuffer
, bufferLen
, mAudit
.get()));
134 UnixError::check(::csops(pid
, CS_OPS_BLOB
, mBuffer
, bufferLen
));
137 const EmbeddedSignatureBlob
*b
= (const EmbeddedSignatureBlob
*)mBuffer
;
138 if (!b
->validateBlob(bufferLen
))
139 MacOSError::throwMe(errSecCSSignatureInvalid
);
142 PidDiskRep::~PidDiskRep()
149 bool PidDiskRep::supportInfoPlist()
156 CFDataRef
PidDiskRep::component(CodeDirectory::SpecialSlot slot
)
158 if (slot
== cdInfoSlot
) {
160 return mInfoPlist
.retain();
163 EmbeddedSignatureBlob
*b
= (EmbeddedSignatureBlob
*)this->blob();
164 return b
->component(slot
);
167 CFDataRef
PidDiskRep::identification()
173 CFURLRef
PidDiskRep::copyCanonicalPath()
176 return mBundleURL
.retain();
179 string
PidDiskRep::recommendedIdentifier(const SigningContext
&)
181 return string("pid") + to_string(mPid
);
184 size_t PidDiskRep::signingLimit()
189 size_t PidDiskRep::execSegLimit(const Architecture
*)
194 string
PidDiskRep::format()
196 return "pid diskrep";
199 UnixPlusPlus::FileDesc
&PidDiskRep::fd()
201 UnixError::throwMe(EINVAL
);
204 string
PidDiskRep::mainExecutablePath()
206 char path
[MAXPATHLEN
* 2];
207 // This is unsafe by pid only, but so is using that path in general.
208 if(::proc_pidpath(mPid
, path
, sizeof(path
)) == 0)
209 UnixError::throwMe(errno
);
214 bool PidDiskRep::appleInternalForcePlatform() const
219 if (mAudit
!= NULL
) {
220 rcent
= ::csops_audittoken(mPid
, CS_OPS_STATUS
, &flags
, sizeof(flags
),
223 rcent
= ::csops(mPid
, CS_OPS_STATUS
, &flags
, sizeof(flags
));
227 MacOSError::throwMe(errSecCSNoSuchCode
);
230 return (flags
& CS_PLATFORM_BINARY
) == CS_PLATFORM_BINARY
;
233 } // end namespace CodeSigning
234 } // end namespace Security