#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"
#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 *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;
if (isDebugSetInBootargs()) {
return;
}
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)) {
char scratchPath[PATH_MAX];
if (CFStringGetCString(kextPath, scratchPath,
sizeof(scratchPath),
kCFStringEncodingUTF8) == 0) {
OSKextLogMemError();
goto finish;
}
char *pathPtr = &scratchPath[0];
for (size_t i = 0; i < strlen(&scratchPath[0]); i++) {
if (scratchPath[i] == '/' && scratchPath[i + 1] == '/') {
pathPtr++;
continue;
}
break;
}
if (strncmp(pathPtr,
_kOSKextSystemLibraryExtensionsFolder,
strlen(_kOSKextSystemLibraryExtensionsFolder)) == 0) {
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));
}
}
amsg = asl_new(ASL_TYPE_MSG);
if (!amsg) {
OSKextLogMemError();
goto finish;
}
asl_set(amsg, kMessageTracerDomainKey, kMTKextLoadingDomain);
asl_set(amsg, kMessageTracerBundleIDKey,
bundleIDCString ? bundleIDCString : "");
asl_set(amsg, kMessageTracerVersionKey,
versionCString ? versionCString : "");
asl_set(amsg, kMessageTracerKextNameKey,
filenameCString ? filenameCString : "");
asl_set(amsg, kMessageTracerHashKey,
tempBufPtr ? tempBufPtr : "");
asl_log(NULL, amsg, ASL_LEVEL_NOTICE, "");
finish:
SAFE_FREE(versionCString);
SAFE_FREE(bundleIDCString);
SAFE_FREE(filenameCString);
SAFE_FREE(tempBufPtr);
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);
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);
}