#include <asl.h>
#include <IOKit/kext/OSKext.h>
#include <IOKit/kext/OSKextPrivate.h>
#include <IOKit/IOKitLib.h>
#include "security.h"
#include "kext_tools_util.h"
CFStringRef createArchitectureList(OSKextRef aKext, CFBooleanRef *isFat)
{
if (aKext == NULL || isFat == NULL) {
return NULL;
}
*isFat = kCFBooleanFalse;
const NXArchInfo ** archList = NULL; CFMutableArrayRef archNamesList = NULL; CFStringRef archNames = NULL; const char * archNameCString = NULL; int index = 0;
archList = OSKextCopyArchitectures(aKext);
if (!archList) {
goto finish;
}
archNamesList = CFArrayCreateMutable(kCFAllocatorDefault,
0,
&kCFTypeArrayCallBacks);
if (!archNamesList) {
goto finish;
}
for (index=0; archList[index]; index++) {
archNameCString = archList[index]->name;
if (archNameCString) {
CFStringRef archName = NULL;
archName = CFStringCreateWithCString(kCFAllocatorDefault,
archNameCString,
kCFStringEncodingUTF8);
if (archName) {
CFArrayAppendValue(archNamesList, archName);
SAFE_RELEASE_NULL(archName);
}
}
}
if (CFArrayGetCount(archNamesList)>1) {
*isFat = kCFBooleanTrue;
}
archNames = CFStringCreateByCombiningStrings(kCFAllocatorDefault,
archNamesList,
CFSTR(" "));
if (!archNames) {
goto finish;
}
finish:
SAFE_RELEASE(archNamesList);
SAFE_FREE(archList);
return archNames;
}
#define __kOSKextApplePrefix CFSTR("com.apple.")
void logMTMessage(OSKextRef aKext)
{
CFStringRef versionString; CFStringRef bundleIDString; CFURLRef kextURL = NULL; CFStringRef kextPath = NULL; CFStringRef filename = NULL; aslmsg amsg = NULL; char *versionCString = NULL; char *bundleIDCString = NULL; char *filenameCString = NULL; char *archCString = NULL; char *tempBufPtr = NULL; CFMutableDictionaryRef signdict = NULL; SecCodeSignerRef signerRef = NULL; SecStaticCodeRef staticCodeRef = NULL; CFDataRef signature = NULL; CFDictionaryRef signingDict = NULL; CFDataRef cdhash = NULL; CFMutableDictionaryRef resourceRules = NULL; CFMutableDictionaryRef rules = NULL; CFMutableDictionaryRef omitPlugins = NULL; CFStringRef archString = NULL; CFBooleanRef isFat = kCFBooleanFalse;
unsigned int perThousands = 200;
if (isDebugSetInBootargs()) {
return;
}
if (arc4random_uniform(1000) > perThousands) {
goto finish;
}
if (!OSKextGetURL(aKext)) {
OSKextLogMemError();
goto finish;
}
kextURL = CFURLCopyAbsoluteURL(OSKextGetURL(aKext));
if (!kextURL) {
OSKextLogMemError();
goto finish;
}
kextPath = CFURLCopyFileSystemPath(kextURL, kCFURLPOSIXPathStyle);
if (!kextPath) {
OSKextLogMemError();
goto finish;
}
bundleIDString = OSKextGetIdentifier(aKext);
if (CFStringHasPrefix(bundleIDString, __kOSKextApplePrefix)) {
goto finish;
}
#if 0
OSKextLogCFString( NULL,
kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
CFSTR("%s - logging kext %@"),
__func__,
aKext);
#endif
versionString = OSKextGetValueForInfoDictionaryKey(aKext,
kCFBundleVersionKey);
if (versionString) {
versionCString = createUTF8CStringForCFString(versionString);
}
bundleIDString = OSKextGetValueForInfoDictionaryKey(aKext,
kCFBundleIdentifierKey);
if (bundleIDString) {
bundleIDCString = createUTF8CStringForCFString(bundleIDString);
}
filename = CFURLCopyLastPathComponent(kextURL);
if (filename) {
filenameCString = createUTF8CStringForCFString(filename);
}
SAFE_RELEASE(filename);
if (SecStaticCodeCreateWithPath(kextURL,
kSecCSDefaultFlags,
&staticCodeRef) != 0 ||
(staticCodeRef == NULL)) {
OSKextLogMemError();
goto finish;
}
signature = CFDataCreateMutable(NULL, 0);
if (signature == NULL) {
OSKextLogMemError();
goto finish;
}
signdict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (signdict == NULL) {
OSKextLogMemError();
goto finish;
}
CFDictionarySetValue(signdict, kSecCodeSignerIdentity, kCFNull);
CFDictionarySetValue(signdict, kSecCodeSignerDetached, signature);
resourceRules = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (resourceRules == NULL) {
OSKextLogMemError();
goto finish;
}
rules = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (rules == NULL) {
OSKextLogMemError();
goto finish;
}
omitPlugins = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (omitPlugins == NULL) {
OSKextLogMemError();
goto finish;
}
CFNumberRef myNumValue;
int myNum = 100;
myNumValue = CFNumberCreate(kCFAllocatorDefault,
kCFNumberIntType, &myNum);
if (myNumValue == NULL) {
OSKextLogMemError();
goto finish;
}
CFDictionarySetValue(omitPlugins, CFSTR("omit"), kCFBooleanTrue);
CFDictionarySetValue(omitPlugins, CFSTR("weight"), myNumValue);
CFRelease( myNumValue );
CFDictionarySetValue(rules, CFSTR("^.*"), kCFBooleanTrue);
CFDictionarySetValue(rules, CFSTR("^PlugIns/"), omitPlugins);
CFDictionarySetValue(resourceRules, CFSTR("rules"), rules);
CFDictionarySetValue(signdict, kSecCodeSignerResourceRules, resourceRules);
if (SecCodeSignerCreate(signdict, kSecCSDefaultFlags, &signerRef) != 0) {
OSKextLog(NULL, kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
"%s - SecCodeSignerCreate failed", __func__);
goto finish;
}
if (SecCodeSignerAddSignature(signerRef, staticCodeRef, kSecCSDefaultFlags) != 0) {
OSKextLog(NULL, kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
"%s - SecCodeSignerAddSignature failed", __func__);
goto finish;
}
if (SecCodeSetDetachedSignature(staticCodeRef, signature, kSecCSDefaultFlags) != 0) {
OSKextLog(NULL, kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
"%s - SecCodeSetDetachedSignature failed", __func__);
goto finish;
}
if (SecCodeCopySigningInformation(staticCodeRef, kSecCSDefaultFlags, &signingDict) != 0) {
OSKextLog(NULL, kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
"%s - SecCodeCopySigningInformation failed", __func__);
goto finish;
}
cdhash = CFRetain(CFDictionaryGetValue(signingDict, kSecCodeInfoUnique));
if (cdhash) {
const UInt8 * hashDataPtr = NULL; CFIndex hashDataLen = 0;
hashDataPtr = CFDataGetBytePtr(cdhash);
hashDataLen = CFDataGetLength(cdhash);
tempBufPtr = (char *) malloc((hashDataLen + 1) * 2);
if (tempBufPtr == NULL) {
OSKextLogMemError();
goto finish;
}
#if 0
OSKextLogCFString( NULL,
kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
CFSTR("%s - cdhash %@"),
__func__,
cdhash);
#endif
bzero(tempBufPtr, ((hashDataLen + 1) * 2));
for (int i = 0; i < hashDataLen; i++) {
sprintf(tempBufPtr + (i * 2), "%02.2x", *(hashDataPtr + i));
}
}
archString = createArchitectureList(aKext, &isFat);
if (archString){
archCString = createUTF8CStringForCFString(archString);
}
amsg = asl_new(ASL_TYPE_MSG);
if (!amsg) {
OSKextLogMemError();
goto finish;
}
asl_set(amsg, kMessageTracerDomainKey, kMTKextLoadingDomain);
asl_set(amsg, "com.apple.message.signature",
bundleIDCString ? bundleIDCString : "");
asl_set(amsg, "com.apple.message.signature1",
tempBufPtr ? tempBufPtr : "");
asl_set(amsg, "com.apple.message.signature2",
versionCString ? versionCString : "");
asl_set(amsg, "com.apple.message.signature3",
filenameCString ? filenameCString : "");
asl_set(amsg, "com.apple.message.signature5",
isFat==kCFBooleanTrue ? "true" : "false");
asl_set(amsg, "com.apple.message.signature6",
archCString ? archCString : "");
asl_log(NULL, amsg, ASL_LEVEL_NOTICE, "");
finish:
SAFE_FREE(versionCString);
SAFE_FREE(bundleIDCString);
SAFE_FREE(filenameCString);
SAFE_FREE(tempBufPtr);
SAFE_FREE(archCString);
SAFE_RELEASE(kextURL);
SAFE_RELEASE(kextPath);
SAFE_RELEASE(signdict);
SAFE_RELEASE(signerRef);
SAFE_RELEASE(staticCodeRef);
SAFE_RELEASE(signature);
SAFE_RELEASE(signingDict);
SAFE_RELEASE(cdhash);
SAFE_RELEASE(resourceRules);
SAFE_RELEASE(rules);
SAFE_RELEASE(omitPlugins);
SAFE_RELEASE(archString);
if (amsg) {
asl_free(amsg);
}
return;
}
Boolean isDebugSetInBootargs(void)
{
static int didOnce = 0;
static Boolean result = false;
io_registry_entry_t optionsNode = MACH_PORT_NULL; CFStringRef bootargsEntry = NULL;
if (didOnce) {
return(result);
}
optionsNode = IORegistryEntryFromPath(kIOMasterPortDefault,
"IODeviceTree:/options");
if (optionsNode) {
bootargsEntry = (CFStringRef)
IORegistryEntryCreateCFProperty(optionsNode,
CFSTR("boot-args"),
kCFAllocatorDefault, 0);
if (bootargsEntry) {
CFRange findRange;
findRange = CFStringFind(bootargsEntry, CFSTR("debug"), 0);
if (findRange.length != 0) {
result = true;
}
}
}
didOnce++;
if (optionsNode) IOObjectRelease(optionsNode);
SAFE_RELEASE(bootargsEntry);
return(result);
}