#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;
}
} }