kextd_usernotification.c [plain text]
#include <IOKit/kext/kextmanager_types.h>
#include <IOKit/kext/OSKextPrivate.h>
#include "kextd_usernotification.h"
#include "security.h"
#ifdef NO_CFUserNotification
void kextd_raise_notification(
CFStringRef alertHeader,
CFArrayRef alertMessageArray)
{
return;
}
#else
SCDynamicStoreRef sSysConfigDynamicStore = NULL;
uid_t sConsoleUser = (uid_t)-1;
CFRunLoopSourceRef sNotificationQueueRunLoopSource = NULL;
CFMutableArrayRef sPendedNonsecureKextPaths = NULL; CFUserNotificationRef sNonSecureNotification = NULL; CFRunLoopSourceRef sNonSecureNotificationRunLoopSource = NULL; CFMutableDictionaryRef sNotifiedNonsecureKextPaths = NULL;
CFMutableArrayRef sPendedRevokedCertKextPaths = NULL; CFUserNotificationRef sRevokedCertNotification = NULL; CFRunLoopSourceRef sRevokedCertNotificationRunLoopSource = NULL;
#if 0 // not yet
CFMutableArrayRef sPendedUnsignedKextPaths = NULL; CFUserNotificationRef sUnsignedKextNotification = NULL; CFRunLoopSourceRef sUnsignedKextNotificationRunLoopSource = NULL; #endif
CFMutableArrayRef sPendedNoLoadKextPaths = NULL; CFUserNotificationRef sNoLoadKextNotification = NULL; CFRunLoopSourceRef sNoLoadKextNotificationRunLoopSource = NULL;
CFMutableArrayRef sPendedInvalidSignedKextPaths = NULL; CFUserNotificationRef sInvalidSigNotification = NULL; CFRunLoopSourceRef sInvalidSigNotificationRunLoopSource = NULL;
CFMutableArrayRef sPendedExcludedKextPaths = NULL; CFUserNotificationRef sExcludedKextNotification = NULL; CFRunLoopSourceRef sExcludedKextNotificationRunLoopSource = NULL;
CFDictionaryRef sKextTranslationsPlist = NULL;
static void _sessionDidChange(
SCDynamicStoreRef store,
CFArrayRef changedKeys,
void * info);
void _checkNotificationQueue(void * info);
void _notificationDismissed(
CFUserNotificationRef userNotification,
CFOptionFlags responseFlags);
static CFStringRef createBundleMappingKey( CFStringRef theBundleID );
static Boolean isInAlertsSentArray(
CFArrayRef theSentArray,
CFDictionaryRef theDict,
CFStringRef theMappingKey );
static CFStringRef getKextAlertMessage(
CFDictionaryRef theDict,
CFStringRef theMappingKey );
static Boolean sendKextAlertNotifications(
CFMutableArrayRef * theSentAlertsArrayPtr,
CFArrayRef theKextsArray,
int theAlertType );
static CFStringRef createPathFromAlertType(
CFStringRef theVolRoot,
int theAlertType );
static Boolean doingSystemInstall(void);
static void kextd_raise_nonsecure_notification(
CFStringRef alertHeader,
CFArrayRef alertMessageArray );
static void kextd_raise_noload_notification(
CFStringRef alertHeader,
CFArrayRef alertMessageArray );
static void kextd_raise_invalidsig_notification(
CFStringRef alertHeader,
CFArrayRef alertMessageArray );
static void kextd_raise_revokedcert_notification(
CFStringRef alertHeader,
CFArrayRef alertMessageArray );
static void revealInFinder( CFArrayRef theArray );
#if 0 // not yet
static void kextd_raise_unsignedkext_notification(
CFStringRef alertHeader,
CFArrayRef alertMessageArray );
#endif
static void kextd_raise_excludedkext_notification(
CFStringRef alertHeader,
CFArrayRef alertMessageArray );
static int validateKextsAlertDict( CFDictionaryRef theDict );
ExitStatus startMonitoringConsoleUser(
KextdArgs * toolArgs,
unsigned int * sourcePriority)
{
ExitStatus result = EX_OSERR;
CFStringRef consoleUserName = NULL; CFStringRef consoleUserKey = NULL; CFMutableArrayRef keys = NULL; CFRunLoopSourceRef sysConfigRunLoopSource = NULL; CFRunLoopSourceContext sourceContext;
sSysConfigDynamicStore = SCDynamicStoreCreate(
kCFAllocatorDefault, CFSTR(KEXTD_SERVER_NAME),
_sessionDidChange, NULL);
if (!sSysConfigDynamicStore) {
OSKextLogMemError();
goto finish;
}
consoleUserName = SCDynamicStoreCopyConsoleUser(sSysConfigDynamicStore,
&sConsoleUser, NULL);
if (!consoleUserName) {
sConsoleUser = (uid_t)-1;
OSKextLog( NULL,
kOSKextLogDebugLevel | kOSKextLogGeneralFlag,
"No user logged in at kextd startup.");
} else {
OSKextLog( NULL,
kOSKextLogDebugLevel | kOSKextLogGeneralFlag,
"User %d logged in at kextd startup.", sConsoleUser);
}
consoleUserKey = SCDynamicStoreKeyCreateConsoleUser(kCFAllocatorDefault);
if (!consoleUserKey) {
OSKextLogMemError();
goto finish;
}
keys = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
if (!keys) {
OSKextLogMemError();
goto finish;
}
CFArrayAppendValue(keys, consoleUserKey);
SCDynamicStoreSetNotificationKeys(sSysConfigDynamicStore, keys,
NULL);
sysConfigRunLoopSource = SCDynamicStoreCreateRunLoopSource(
kCFAllocatorDefault, sSysConfigDynamicStore, 0);
if (!sysConfigRunLoopSource) {
OSKextLogMemError();
goto finish;
}
CFRunLoopAddSource(CFRunLoopGetCurrent(), sysConfigRunLoopSource,
kCFRunLoopCommonModes);
bzero(&sourceContext, sizeof(CFRunLoopSourceContext));
sourceContext.version = 0;
sourceContext.perform = _checkNotificationQueue;
sNotificationQueueRunLoopSource = CFRunLoopSourceCreate(kCFAllocatorDefault,
(*sourcePriority)++, &sourceContext);
if (!sNotificationQueueRunLoopSource) {
OSKextLog( NULL, kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
"Failed to create alert run loop source.");
goto finish;
}
CFRunLoopAddSource(CFRunLoopGetCurrent(), sNotificationQueueRunLoopSource,
kCFRunLoopDefaultMode);
if (!createCFMutableArray(&sPendedNonsecureKextPaths,
&kCFTypeArrayCallBacks)) {
OSKextLogMemError();
goto finish;
}
if (!createCFMutableArray(&sPendedNoLoadKextPaths,
&kCFTypeArrayCallBacks)) {
OSKextLogMemError();
goto finish;
}
if (!createCFMutableArray(&sPendedRevokedCertKextPaths,
&kCFTypeArrayCallBacks)) {
OSKextLogMemError();
goto finish;
}
#if 0 // not yet
if (!createCFMutableArray(&sPendedUnsignedKextPaths,
&kCFTypeArrayCallBacks)) {
OSKextLogMemError();
goto finish;
}
#endif
if (!createCFMutableArray(&sPendedInvalidSignedKextPaths,
&kCFTypeArrayCallBacks)) {
OSKextLogMemError();
goto finish;
}
if (!createCFMutableArray(&sPendedExcludedKextPaths,
&kCFTypeArrayCallBacks)) {
OSKextLogMemError();
goto finish;
}
if (!createCFMutableDictionary(&sNotifiedNonsecureKextPaths)) {
OSKextLogMemError();
goto finish;
}
result = EX_OK;
finish:
SAFE_RELEASE(consoleUserName);
SAFE_RELEASE(consoleUserKey);
SAFE_RELEASE(keys);
SAFE_RELEASE(sysConfigRunLoopSource);
return result;
}
void stopMonitoringConsoleUser(void)
{
SAFE_RELEASE(sSysConfigDynamicStore);
SAFE_RELEASE(sNotificationQueueRunLoopSource);
SAFE_RELEASE(sPendedNonsecureKextPaths);
SAFE_RELEASE(sPendedNoLoadKextPaths);
SAFE_RELEASE(sPendedRevokedCertKextPaths);
SAFE_RELEASE(sPendedInvalidSignedKextPaths);
SAFE_RELEASE(sPendedExcludedKextPaths);
SAFE_RELEASE(sNotifiedNonsecureKextPaths);
return;
}
static void _sessionDidChange(
SCDynamicStoreRef store,
CFArrayRef changedKeys,
void * info)
{
CFStringRef consoleUserName = NULL; uid_t oldUser = sConsoleUser;
consoleUserName = SCDynamicStoreCopyConsoleUser(sSysConfigDynamicStore,
&sConsoleUser, NULL);
if (!consoleUserName) {
if (oldUser != (uid_t)-1) {
OSKextLog( NULL,
kOSKextLogDebugLevel | kOSKextLogGeneralFlag,
"User %d logged out.", oldUser);
}
sConsoleUser = (uid_t)-1;
resetUserNotifications( true);
goto finish;
}
if (sConsoleUser != (uid_t)-1 && oldUser != sConsoleUser) {
OSKextLog( NULL,
kOSKextLogDebugLevel | kOSKextLogGeneralFlag,
"User %d logged in.", sConsoleUser);
CFRunLoopSourceSignal(sNotificationQueueRunLoopSource);
CFRunLoopWakeUp(CFRunLoopGetCurrent());
}
finish:
SAFE_RELEASE(consoleUserName);
return;
}
void resetUserNotifications(Boolean dismissAlert)
{
OSKextLog( NULL,
kOSKextLogDebugLevel | kOSKextLogGeneralFlag,
"Resetting user notifications.");
if (dismissAlert) {
if (sNonSecureNotification) {
CFUserNotificationCancel(sNonSecureNotification);
CFRelease(sNonSecureNotification);
sNonSecureNotification = NULL;
}
if (sNonSecureNotificationRunLoopSource) {
CFRunLoopRemoveSource(CFRunLoopGetCurrent(),
sNonSecureNotificationRunLoopSource,
kCFRunLoopDefaultMode);
CFRelease(sNonSecureNotificationRunLoopSource);
sNonSecureNotificationRunLoopSource = NULL;
}
if (sNoLoadKextNotification) {
CFUserNotificationCancel(sNoLoadKextNotification);
CFRelease(sNoLoadKextNotification);
sNoLoadKextNotification = NULL;
}
if (sNoLoadKextNotificationRunLoopSource) {
CFRunLoopRemoveSource(CFRunLoopGetCurrent(),
sNoLoadKextNotificationRunLoopSource,
kCFRunLoopDefaultMode);
CFRelease(sNoLoadKextNotificationRunLoopSource);
sNoLoadKextNotificationRunLoopSource = NULL;
}
if (sRevokedCertNotification) {
CFUserNotificationCancel(sRevokedCertNotification);
CFRelease(sRevokedCertNotification);
sRevokedCertNotification = NULL;
}
if (sRevokedCertNotificationRunLoopSource) {
CFRunLoopRemoveSource(CFRunLoopGetCurrent(),
sRevokedCertNotificationRunLoopSource,
kCFRunLoopDefaultMode);
CFRelease(sRevokedCertNotificationRunLoopSource);
sRevokedCertNotificationRunLoopSource = NULL;
}
#if 0 // not yet
if (sUnsignedKextNotification) {
CFUserNotificationCancel(sUnsignedKextNotification);
CFRelease(sUnsignedKextNotification);
sUnsignedKextNotification = NULL;
}
if (sUnsignedKextNotificationRunLoopSource) {
CFRunLoopRemoveSource(CFRunLoopGetCurrent(),
sUnsignedKextNotificationRunLoopSource,
kCFRunLoopDefaultMode);
CFRelease(sUnsignedKextNotificationRunLoopSource);
sUnsignedKextNotificationRunLoopSource = NULL;
}
#endif
if (sInvalidSigNotification) {
CFUserNotificationCancel(sInvalidSigNotification);
CFRelease(sInvalidSigNotification);
sInvalidSigNotification = NULL;
}
if (sInvalidSigNotificationRunLoopSource) {
CFRunLoopRemoveSource(CFRunLoopGetCurrent(),
sInvalidSigNotificationRunLoopSource,
kCFRunLoopDefaultMode);
CFRelease(sInvalidSigNotificationRunLoopSource);
sInvalidSigNotificationRunLoopSource = NULL;
}
if (sExcludedKextNotification) {
CFUserNotificationCancel(sExcludedKextNotification);
CFRelease(sExcludedKextNotification);
sExcludedKextNotification = NULL;
}
if (sExcludedKextNotificationRunLoopSource) {
CFRunLoopRemoveSource(CFRunLoopGetCurrent(),
sExcludedKextNotificationRunLoopSource,
kCFRunLoopDefaultMode);
CFRelease(sExcludedKextNotificationRunLoopSource);
sExcludedKextNotificationRunLoopSource = NULL;
}
}
CFArrayRemoveAllValues(sPendedNonsecureKextPaths);
CFDictionaryRemoveAllValues(sNotifiedNonsecureKextPaths);
CFArrayRemoveAllValues(sPendedRevokedCertKextPaths);
CFArrayRemoveAllValues(sPendedNoLoadKextPaths);
CFArrayRemoveAllValues(sPendedInvalidSignedKextPaths);
CFArrayRemoveAllValues(sPendedExcludedKextPaths);
return;
}
void _checkNotificationQueue(void * info __unused)
{
CFStringRef kextPath = NULL; CFMutableArrayRef nonsecureAlertMessageArray = NULL; CFMutableArrayRef noLoadAlertMessageArray = NULL; CFMutableArrayRef revokedCertAlertMessageArray = NULL; CFMutableArrayRef invalidSigAlertMessageArray = NULL; CFMutableArrayRef unsignedKextAlertMessageArray = NULL; CFMutableArrayRef excludedAlertMessageArray = NULL; CFMutableStringRef excludedAlertHeader = NULL; CFIndex count, i;
if (sConsoleUser == (uid_t)-1) {
goto finish;
}
if (CFArrayGetCount(sPendedNonsecureKextPaths) &&
sNonSecureNotificationRunLoopSource == NULL) {
nonsecureAlertMessageArray = CFArrayCreateMutable(kCFAllocatorDefault,
0,
&kCFTypeArrayCallBacks);
if (nonsecureAlertMessageArray == NULL) {
goto finish;
}
kextPath = (CFStringRef) CFArrayGetValueAtIndex(
sPendedNonsecureKextPaths, 0);
if (!kextPath) {
goto finish;
}
CFArrayAppendValue(nonsecureAlertMessageArray,
CFSTR("The system extension \""));
CFArrayAppendValue(nonsecureAlertMessageArray, kextPath);
CFArrayAppendValue(nonsecureAlertMessageArray,
CFSTR("\" was installed improperly and cannot be used. "
"Please try reinstalling it, or contact the product's vendor "
"for an update."));
CFArrayRemoveValueAtIndex(sPendedNonsecureKextPaths, 0);
kextd_raise_nonsecure_notification(CFSTR("System extension cannot be used"),
nonsecureAlertMessageArray);
}
count = CFArrayGetCount(sPendedNoLoadKextPaths);
if (count > 0 && sNoLoadKextNotificationRunLoopSource == NULL) {
noLoadAlertMessageArray = CFArrayCreateMutable(
kCFAllocatorDefault,
0,
&kCFTypeArrayCallBacks );
if (noLoadAlertMessageArray == NULL) {
goto finish;
}
CFArrayAppendValue(
noLoadAlertMessageArray,
(count > 1 ? CFSTR("The following kernel extensions can't "
"be loaded because they are from "
"unidentified developers. Extensions "
"loaded from /Library/Extensions must be "
"signed by identified developers. \r")
: CFSTR("The kernel extension at \"")) );
for (i = 0; i < count; i ++) {
kextPath = (CFStringRef)
CFArrayGetValueAtIndex( sPendedNoLoadKextPaths, i );
if (kextPath) {
if (count > 1) {
CFArrayAppendValue(noLoadAlertMessageArray, CFSTR("\r"));
}
CFArrayAppendValue(noLoadAlertMessageArray, kextPath);
}
}
if (count == 1) {
CFArrayAppendValue(noLoadAlertMessageArray,
CFSTR("\" can't be loaded because it is from an "
"unidentified developer. Extensions "
"loaded from /Library/Extensions must be "
"signed by identified developers."));
}
CFArrayAppendValue(noLoadAlertMessageArray,
CFSTR("\r\rPlease contact the kernel extension "
"vendor for updated software."));
CFArrayRemoveAllValues(sPendedNoLoadKextPaths);
kextd_raise_noload_notification(
(count > 1 ? CFSTR("Kernel extensions could not be loaded")
: CFSTR("Kernel extension could not be loaded")),
noLoadAlertMessageArray);
}
count = CFArrayGetCount(sPendedRevokedCertKextPaths);
if (count > 0 && sRevokedCertNotificationRunLoopSource == NULL) {
revokedCertAlertMessageArray = CFArrayCreateMutable(
kCFAllocatorDefault,
0,
&kCFTypeArrayCallBacks );
if (revokedCertAlertMessageArray == NULL) {
goto finish;
}
CFArrayAppendValue(
revokedCertAlertMessageArray,
(count > 1 ? CFSTR("The following kernel extensions "
"are damaged and can't be "
"loaded. \r")
: CFSTR("The kernel extension at \"")) );
for (i = 0; i < count; i ++) {
kextPath = (CFStringRef) CFArrayGetValueAtIndex(
sPendedRevokedCertKextPaths, i );
if (kextPath) {
if (count > 1) {
CFArrayAppendValue(revokedCertAlertMessageArray, CFSTR("\r"));
}
CFArrayAppendValue(revokedCertAlertMessageArray,
kextPath);
}
}
if (count == 1) {
CFArrayAppendValue(revokedCertAlertMessageArray,
CFSTR("\" is damaged and can't be loaded."));
}
CFArrayAppendValue(revokedCertAlertMessageArray,
(count > 1
? CFSTR("\r\rYou should move them to the Trash.")
: CFSTR("\r\rYou should move it to the Trash."))
);
kextd_raise_revokedcert_notification(
(count > 1 ? CFSTR("Kernel extensions could not be loaded")
: CFSTR("Kernel extension could not be loaded")),
revokedCertAlertMessageArray);
}
#if 0 // not yet
count = CFArrayGetCount(sPendedUnsignedKextPaths);
if (count > 0 && sUnsignedKextNotificationRunLoopSource == NULL) {
unsignedKextAlertMessageArray = CFArrayCreateMutable(kCFAllocatorDefault,
0,
&kCFTypeArrayCallBacks);
if (unsignedKextAlertMessageArray == NULL) {
goto finish;
}
CFArrayAppendValue(unsignedKextAlertMessageArray,
CFSTR("The following kernel extensions are not "
"signed.\r"));
for (i = 0; i < count; i ++) {
kextPath = (CFStringRef) CFArrayGetValueAtIndex(
sPendedUnsignedKextPaths, i);
if (kextPath) {
CFArrayAppendValue(unsignedKextAlertMessageArray,
CFSTR("\r"));
CFArrayAppendValue(unsignedKextAlertMessageArray,
kextPath);
}
}
CFArrayAppendValue(unsignedKextAlertMessageArray,
CFSTR("\r\rPlease contact the vendor for each "
"kernel extension for updated software."));
CFArrayRemoveAllValues(sPendedUnsignedKextPaths);
kextd_raise_unsignedkext_notification(CFSTR("Kernel extensions are not signed"),
unsignedKextAlertMessageArray);
}
#endif
count = CFArrayGetCount(sPendedInvalidSignedKextPaths);
if (count > 0 && sInvalidSigNotificationRunLoopSource == NULL) {
invalidSigAlertMessageArray = CFArrayCreateMutable(kCFAllocatorDefault,
0,
&kCFTypeArrayCallBacks);
if (invalidSigAlertMessageArray == NULL) {
goto finish;
}
CFArrayAppendValue(invalidSigAlertMessageArray,
(count > 1 ? CFSTR("The following kernel extensions are not "
"from identified developers but will "
"still be loaded. \r")
: CFSTR("The kernel extension at \"")) );
for (i = 0; i < count; i ++) {
kextPath = (CFStringRef) CFArrayGetValueAtIndex(
sPendedInvalidSignedKextPaths, i);
if (kextPath) {
if (count > 1) {
CFArrayAppendValue(invalidSigAlertMessageArray, CFSTR("\r"));
}
CFArrayAppendValue(invalidSigAlertMessageArray, kextPath);
}
}
if (count == 1) {
CFArrayAppendValue(invalidSigAlertMessageArray,
CFSTR("\" is not from an identified developer "
"but will still be loaded."));
}
CFArrayAppendValue(invalidSigAlertMessageArray,
CFSTR("\r\rPlease contact the kernel extension "
"vendor for updated software."));
CFArrayRemoveAllValues(sPendedInvalidSignedKextPaths);
kextd_raise_invalidsig_notification(
(count > 1 ? CFSTR("Kernel extensions are not from identified "
"developers")
: CFSTR("Kernel extension is not from an identified "
"developer")),
invalidSigAlertMessageArray);
}
#if 1 // <rdar://problem/12811081> warn user about excluded kexts
count = CFArrayGetCount(sPendedExcludedKextPaths);
if (count > 0 && sExcludedKextNotificationRunLoopSource == NULL) {
excludedAlertMessageArray =
CFArrayCreateMutable(kCFAllocatorDefault,
0,
&kCFTypeArrayCallBacks);
if (excludedAlertMessageArray == NULL) {
goto finish;
}
excludedAlertHeader = CFStringCreateMutable(kCFAllocatorDefault, 0);
if (excludedAlertHeader == NULL) {
goto finish;
}
if (count > 1) {
CFStringAppend(excludedAlertHeader,
CFSTR("Some system extensions are not compatible with this version of OS X and can’t be used:"));
for (i = 0; i < count; i ++) {
kextPath = (CFStringRef) CFArrayGetValueAtIndex(
sPendedExcludedKextPaths, i);
if (kextPath) {
CFRange myRange;
myRange = CFStringFind(kextPath, CFSTR("/"), kCFCompareBackwards);
if (myRange.length != 0 && myRange.location++ < CFStringGetLength(kextPath)) {
CFStringRef myString;
myRange.length = CFStringGetLength(kextPath) - myRange.location;
myString = CFStringCreateWithSubstring(kCFAllocatorDefault,
kextPath,
myRange);
if (myString) {
CFArrayAppendValue(excludedAlertMessageArray,
myString);
SAFE_RELEASE(myString);
}
else {
CFArrayAppendValue(excludedAlertMessageArray,
kextPath);
}
}
else {
CFArrayAppendValue(excludedAlertMessageArray,
kextPath);
}
CFArrayAppendValue(excludedAlertMessageArray,
CFSTR("\r"));
}
}
CFArrayAppendValue(excludedAlertMessageArray,
CFSTR("\r"));
}
else {
kextPath = (CFStringRef) CFArrayGetValueAtIndex(
sPendedExcludedKextPaths, 0 );
if (kextPath == NULL) {
goto finish;
}
CFStringAppend(excludedAlertHeader,
CFSTR("The system extension \""));
CFRange myRange;
myRange = CFStringFind(kextPath, CFSTR("/"), kCFCompareBackwards);
if (myRange.length != 0 && myRange.location++ < CFStringGetLength(kextPath)) {
CFStringRef myString;
myRange.length = CFStringGetLength(kextPath) - myRange.location;
myString = CFStringCreateWithSubstring(kCFAllocatorDefault,
kextPath,
myRange);
if (myString) {
CFStringAppend(excludedAlertHeader,
myString);
SAFE_RELEASE(myString);
}
else {
CFStringAppend(excludedAlertHeader,
kextPath);
}
}
else {
CFStringAppend(excludedAlertHeader,
kextPath);
}
CFStringAppend(excludedAlertHeader,
CFSTR("\" is not compatible with this version of OS X and can’t be used."));
}
CFArrayAppendValue(excludedAlertMessageArray,
CFSTR("Please contact the developer for updated software."));
CFArrayRemoveAllValues(sPendedExcludedKextPaths);
kextd_raise_excludedkext_notification(excludedAlertHeader,
excludedAlertMessageArray);
}
#endif // <rdar://problem/12811081>
finish:
SAFE_RELEASE(nonsecureAlertMessageArray);
SAFE_RELEASE(noLoadAlertMessageArray);
SAFE_RELEASE(excludedAlertMessageArray);
SAFE_RELEASE(revokedCertAlertMessageArray);
SAFE_RELEASE(invalidSigAlertMessageArray);
SAFE_RELEASE(unsignedKextAlertMessageArray);
SAFE_RELEASE(excludedAlertHeader);
return;
}
Boolean recordNonsecureKexts(CFArrayRef kextList)
{
Boolean result = false;
CFStringRef nonsecureKextPath = NULL; CFIndex count, i;
if (kextList && (count = CFArrayGetCount(kextList))) {
for (i = 0; i < count; i ++) {
OSKextRef checkKext = (OSKextRef)CFArrayGetValueAtIndex(kextList, i);
SAFE_RELEASE_NULL(nonsecureKextPath);
if (OSKextIsAuthentic(checkKext)) {
continue;
}
nonsecureKextPath = copyKextPath(checkKext);
if (!nonsecureKextPath) {
OSKextLogMemError();
goto finish;
}
if (!CFDictionaryGetValue(sNotifiedNonsecureKextPaths,
nonsecureKextPath)) {
CFArrayAppendValue(sPendedNonsecureKextPaths,
nonsecureKextPath);
CFDictionarySetValue(sNotifiedNonsecureKextPaths,
nonsecureKextPath, kCFBooleanTrue);
result = true;
}
}
}
finish:
SAFE_RELEASE(nonsecureKextPath);
if (result) {
CFRunLoopSourceSignal(sNotificationQueueRunLoopSource);
CFRunLoopWakeUp(CFRunLoopGetCurrent());
}
return result;
}
Boolean recordNoLoadKextPath(CFStringRef theKextPath)
{
Boolean result = false;
if (theKextPath == NULL) {
goto finish;
}
CFArrayAppendValue(sPendedNoLoadKextPaths, theKextPath);
result = true;
finish:
return result;
}
void sendNoLoadKextNotification(void)
{
if (CFArrayGetCount(sPendedNoLoadKextPaths)) {
CFRunLoopSourceSignal(sNotificationQueueRunLoopSource);
CFRunLoopWakeUp(CFRunLoopGetCurrent());
}
return;
}
void recordRevokedCertKextPath(CFStringRef theKextPath)
{
if (theKextPath == NULL) {
goto finish;
}
CFArrayAppendValue(sPendedRevokedCertKextPaths, theKextPath);
finish:
return;
}
void sendRevokedCertKextPath(void)
{
if (CFArrayGetCount(sPendedRevokedCertKextPaths)) {
CFRunLoopSourceSignal(sNotificationQueueRunLoopSource);
CFRunLoopWakeUp(CFRunLoopGetCurrent());
}
return;
}
Boolean recordInvalidSignedKextPath(CFStringRef theKextPath)
{
Boolean result = false;
if (theKextPath == NULL) {
goto finish;
}
CFArrayAppendValue(sPendedInvalidSignedKextPaths, theKextPath);
result = true;
finish:
return result;
}
void sendInvalidSignedKextNotification(void)
{
if (CFArrayGetCount(sPendedInvalidSignedKextPaths)) {
CFRunLoopSourceSignal(sNotificationQueueRunLoopSource);
CFRunLoopWakeUp(CFRunLoopGetCurrent());
}
return;
}
#if 0 // not yet
Boolean recordUnsignedKextPath(CFStringRef theKextPath)
{
Boolean result = false;
if (theKextPath == NULL) {
goto finish;
}
CFArrayAppendValue(sPendedUnsignedKextPaths, theKextPath);
result = true;
finish:
return result;
}
void sendUnsignedKextNotification(void)
{
if (CFArrayGetCount(sPendedUnsignedKextPaths)) {
CFRunLoopSourceSignal(sNotificationQueueRunLoopSource);
CFRunLoopWakeUp(CFRunLoopGetCurrent());
}
return;
}
#endif
Boolean recordExcludedKextPath(CFStringRef theKextPath)
{
Boolean result = false;
if (theKextPath == NULL) {
goto finish;
}
CFArrayAppendValue(sPendedExcludedKextPaths, theKextPath);
result = true;
finish:
return result;
}
void sendExcludedKextNotification(void)
{
if (CFArrayGetCount(sPendedExcludedKextPaths)) {
CFRunLoopSourceSignal(sNotificationQueueRunLoopSource);
CFRunLoopWakeUp(CFRunLoopGetCurrent());
}
return;
}
static CFMutableDictionaryRef createAlertDict(
CFStringRef alertHeader,
CFArrayRef alertMessageArray )
{
CFMutableDictionaryRef alertDict = NULL; CFURLRef iokitFrameworkBundleURL = NULL;
if ( doingSystemInstall() ) {
goto finish;
}
OSKextLog( NULL,
kOSKextLogDebugLevel | kOSKextLogGeneralFlag,
"Raising user notification.");
if (sConsoleUser == (uid_t)-1) {
OSKextLog( NULL,
kOSKextLogDebugLevel | kOSKextLogGeneralFlag,
"No logged in user.");
goto finish;
}
iokitFrameworkBundleURL = CFURLCreateWithFileSystemPath(
kCFAllocatorDefault,
CFSTR("/System/Library/Frameworks/IOKit.framework"),
kCFURLPOSIXPathStyle, true);
if (!iokitFrameworkBundleURL) {
goto finish;
}
alertDict = CFDictionaryCreateMutable(
kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (!alertDict) {
goto finish;
}
CFDictionarySetValue(alertDict, kCFUserNotificationLocalizationURLKey,
iokitFrameworkBundleURL);
CFDictionarySetValue(alertDict, kCFUserNotificationAlertHeaderKey,
alertHeader);
CFDictionarySetValue(alertDict, kCFUserNotificationDefaultButtonTitleKey,
CFSTR("OK"));
CFDictionarySetValue(alertDict, kCFUserNotificationAlertMessageKey,
alertMessageArray);
finish:
SAFE_RELEASE(iokitFrameworkBundleURL);
return(alertDict);
}
static void kextd_raise_nonsecure_notification(
CFStringRef alertHeader,
CFArrayRef alertMessageArray )
{
CFMutableDictionaryRef alertDict = NULL; SInt32 userNotificationError = 0;
alertDict = createAlertDict(alertHeader, alertMessageArray);
if (alertDict == NULL) {
goto finish;
}
sNonSecureNotification = CFUserNotificationCreate(kCFAllocatorDefault,
0 , kCFUserNotificationCautionAlertLevel,
&userNotificationError, alertDict);
if (!sNonSecureNotification) {
OSKextLog( NULL,
kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
"Can't create user notification - %d",
(int)userNotificationError);
goto finish;
}
sNonSecureNotificationRunLoopSource = CFUserNotificationCreateRunLoopSource(
kCFAllocatorDefault,
sNonSecureNotification,
&_notificationDismissed,
5 );
if (!sNonSecureNotificationRunLoopSource) {
CFRelease(sNonSecureNotification);
sNonSecureNotification = NULL;
}
CFRunLoopAddSource(CFRunLoopGetCurrent(),
sNonSecureNotificationRunLoopSource,
kCFRunLoopDefaultMode);
finish:
SAFE_RELEASE(alertDict);
return;
}
static void kextd_raise_noload_notification(
CFStringRef alertHeader,
CFArrayRef alertMessageArray )
{
CFMutableDictionaryRef alertDict = NULL; SInt32 userNotificationError = 0;
alertDict = createAlertDict(alertHeader, alertMessageArray);
if (alertDict == NULL) {
goto finish;
}
sNoLoadKextNotification =
CFUserNotificationCreate(
kCFAllocatorDefault,
0 ,
kCFUserNotificationCautionAlertLevel,
&userNotificationError,
alertDict );
if (!sNoLoadKextNotification) {
OSKextLog( NULL,
kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
"Can't create user notification - %d",
(int)userNotificationError);
goto finish;
}
sNoLoadKextNotificationRunLoopSource =
CFUserNotificationCreateRunLoopSource(
kCFAllocatorDefault,
sNoLoadKextNotification,
&_notificationDismissed,
5 );
if (!sNoLoadKextNotificationRunLoopSource) {
CFRelease(sNoLoadKextNotification);
sNoLoadKextNotification = NULL;
}
CFRunLoopAddSource(CFRunLoopGetCurrent(),
sNoLoadKextNotificationRunLoopSource,
kCFRunLoopDefaultMode);
finish:
SAFE_RELEASE(alertDict);
return;
}
static void kextd_raise_revokedcert_notification(
CFStringRef alertHeader,
CFArrayRef alertMessageArray )
{
CFMutableDictionaryRef alertDict = NULL; SInt32 userNotificationError = 0;
alertDict = createAlertDict(alertHeader, alertMessageArray);
if (alertDict == NULL) {
goto finish;
}
CFDictionarySetValue(alertDict, kCFUserNotificationDefaultButtonTitleKey,
CFSTR("Reveal in Finder"));
sRevokedCertNotification =
CFUserNotificationCreate(
kCFAllocatorDefault,
0 ,
kCFUserNotificationCautionAlertLevel,
&userNotificationError,
alertDict );
if (!sRevokedCertNotification) {
OSKextLog( NULL,
kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
"Can't create user notification - %d",
(int)userNotificationError);
goto finish;
}
sRevokedCertNotificationRunLoopSource =
CFUserNotificationCreateRunLoopSource(
kCFAllocatorDefault,
sRevokedCertNotification,
&_notificationDismissed,
5 );
if (!sRevokedCertNotificationRunLoopSource) {
CFRelease(sRevokedCertNotification);
sRevokedCertNotification = NULL;
}
CFRunLoopAddSource(CFRunLoopGetCurrent(),
sRevokedCertNotificationRunLoopSource,
kCFRunLoopDefaultMode);
finish:
SAFE_RELEASE(alertDict);
return;
}
static void kextd_raise_invalidsig_notification(
CFStringRef alertHeader,
CFArrayRef alertMessageArray )
{
CFMutableDictionaryRef alertDict = NULL; SInt32 userNotificationError = 0;
alertDict = createAlertDict(alertHeader, alertMessageArray);
if (alertDict == NULL) {
goto finish;
}
sInvalidSigNotification =
CFUserNotificationCreate(
kCFAllocatorDefault,
0 ,
kCFUserNotificationCautionAlertLevel,
&userNotificationError,
alertDict );
if (!sInvalidSigNotification) {
OSKextLog( NULL,
kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
"Can't create user notification - %d",
(int)userNotificationError);
goto finish;
}
sInvalidSigNotificationRunLoopSource =
CFUserNotificationCreateRunLoopSource(
kCFAllocatorDefault,
sInvalidSigNotification,
&_notificationDismissed,
5 );
if (!sInvalidSigNotificationRunLoopSource) {
CFRelease(sInvalidSigNotification);
sInvalidSigNotification = NULL;
}
CFRunLoopAddSource(CFRunLoopGetCurrent(),
sInvalidSigNotificationRunLoopSource,
kCFRunLoopDefaultMode);
finish:
SAFE_RELEASE(alertDict);
return;
}
#if 0 // not yet
static void kextd_raise_unsignedkext_notification(
CFStringRef alertHeader,
CFArrayRef alertMessageArray )
{
CFMutableDictionaryRef alertDict = NULL; SInt32 userNotificationError = 0;
alertDict = createAlertDict(alertHeader, alertMessageArray);
if (alertDict == NULL) {
goto finish;
}
sUnsignedKextNotification =
CFUserNotificationCreate(
kCFAllocatorDefault,
0 ,
kCFUserNotificationCautionAlertLevel,
&userNotificationError,
alertDict );
if (!sUnsignedKextNotification) {
OSKextLog( NULL,
kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
"Can't create user notification - %d",
(int)userNotificationError);
goto finish;
}
sUnsignedKextNotificationRunLoopSource =
CFUserNotificationCreateRunLoopSource(
kCFAllocatorDefault,
sUnsignedKextNotification,
&_notificationDismissed,
5 );
if (!sUnsignedKextNotificationRunLoopSource) {
CFRelease(sUnsignedKextNotification);
sUnsignedKextNotification = NULL;
}
CFRunLoopAddSource(CFRunLoopGetCurrent(),
sUnsignedKextNotificationRunLoopSource,
kCFRunLoopDefaultMode);
finish:
SAFE_RELEASE(alertDict);
return;
}
#endif
static void kextd_raise_excludedkext_notification(
CFStringRef alertHeader,
CFArrayRef alertMessageArray )
{
CFMutableDictionaryRef alertDict = NULL; SInt32 userNotificationError = 0;
alertDict = createAlertDict(alertHeader, alertMessageArray);
if (alertDict == NULL) {
goto finish;
}
sExcludedKextNotification =
CFUserNotificationCreate(
kCFAllocatorDefault,
0 ,
kCFUserNotificationCautionAlertLevel,
&userNotificationError,
alertDict );
if (!sExcludedKextNotification) {
OSKextLog( NULL,
kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
"Can't create user notification - %d",
(int)userNotificationError);
goto finish;
}
sExcludedKextNotificationRunLoopSource =
CFUserNotificationCreateRunLoopSource(
kCFAllocatorDefault,
sExcludedKextNotification,
&_notificationDismissed,
5 );
if (!sExcludedKextNotificationRunLoopSource) {
CFRelease(sExcludedKextNotification);
sExcludedKextNotification = NULL;
}
CFRunLoopAddSource(CFRunLoopGetCurrent(),
sExcludedKextNotificationRunLoopSource,
kCFRunLoopDefaultMode);
finish:
SAFE_RELEASE(alertDict);
return;
}
void _notificationDismissed(
CFUserNotificationRef userNotification,
CFOptionFlags responseFlags)
{
if (sNonSecureNotification && sNonSecureNotification == userNotification) {
CFRelease(sNonSecureNotification);
sNonSecureNotification = NULL;
if (sNonSecureNotificationRunLoopSource) {
CFRunLoopRemoveSource(CFRunLoopGetCurrent(),
sNonSecureNotificationRunLoopSource,
kCFRunLoopDefaultMode);
CFRelease(sNonSecureNotificationRunLoopSource);
sNonSecureNotificationRunLoopSource = NULL;
}
}
else if (sNoLoadKextNotification && sNoLoadKextNotification == userNotification) {
CFRelease(sNoLoadKextNotification);
sNoLoadKextNotification = NULL;
if (sNoLoadKextNotificationRunLoopSource) {
CFRunLoopRemoveSource(CFRunLoopGetCurrent(),
sNoLoadKextNotificationRunLoopSource,
kCFRunLoopDefaultMode);
CFRelease(sNoLoadKextNotificationRunLoopSource);
sNoLoadKextNotificationRunLoopSource = NULL;
}
}
else if (sRevokedCertNotification && sRevokedCertNotification == userNotification) {
CFRelease(sRevokedCertNotification);
sRevokedCertNotification = NULL;
if (sRevokedCertNotificationRunLoopSource) {
CFRunLoopRemoveSource(CFRunLoopGetCurrent(),
sRevokedCertNotificationRunLoopSource,
kCFRunLoopDefaultMode);
CFRelease(sRevokedCertNotificationRunLoopSource);
sRevokedCertNotificationRunLoopSource = NULL;
}
if (sPendedRevokedCertKextPaths) {
revealInFinder(sPendedRevokedCertKextPaths);
CFArrayRemoveAllValues(sPendedRevokedCertKextPaths);
} }
else if (sInvalidSigNotification && sInvalidSigNotification == userNotification) {
CFRelease(sInvalidSigNotification);
sInvalidSigNotification = NULL;
if (sInvalidSigNotificationRunLoopSource) {
CFRunLoopRemoveSource(CFRunLoopGetCurrent(),
sInvalidSigNotificationRunLoopSource,
kCFRunLoopDefaultMode);
CFRelease(sInvalidSigNotificationRunLoopSource);
sInvalidSigNotificationRunLoopSource = NULL;
}
}
#if 0 // not yet
else if (sUnsignedKextNotification && sUnsignedKextNotification == userNotification) {
CFRelease(sUnsignedKextNotification);
sUnsignedKextNotification = NULL;
if (sUnsignedKextNotificationRunLoopSource) {
CFRunLoopRemoveSource(CFRunLoopGetCurrent(),
sUnsignedKextNotificationRunLoopSource,
kCFRunLoopDefaultMode);
CFRelease(sUnsignedKextNotificationRunLoopSource);
sUnsignedKextNotificationRunLoopSource = NULL;
}
}
#endif
else if (sExcludedKextNotification && sExcludedKextNotification == userNotification) {
CFRelease(sExcludedKextNotification);
sExcludedKextNotification = NULL;
if (sExcludedKextNotificationRunLoopSource) {
CFRunLoopRemoveSource(CFRunLoopGetCurrent(),
sExcludedKextNotificationRunLoopSource,
kCFRunLoopDefaultMode);
CFRelease(sExcludedKextNotificationRunLoopSource);
sExcludedKextNotificationRunLoopSource = NULL;
}
}
CFRunLoopSourceSignal(sNotificationQueueRunLoopSource);
CFRunLoopWakeUp(CFRunLoopGetCurrent());
return;
}
#include <ApplicationServices/ApplicationServices.h>
static const char kFinderBundleID[] = { "com.apple.finder" };
static void revealInFinder(CFArrayRef theArray)
{
CFIndex myCount, i;
if (theArray == NULL) return;
myCount = CFArrayGetCount(theArray);
for (i = 0; i < myCount; i ++) {
CFStringRef myKextPath = NULL; CFURLRef myURL = NULL; OSErr myResult;
AEDesc myTargetDesc = { typeNull, NULL };
AEDesc myFileDesc = { typeNull, NULL };
AEDescList myParmList = { typeNull, NULL };
AppleEvent myRevealEvent = { typeNull, NULL };
AppleEvent myActivateEvent = { typeNull, NULL };
char myPathString[2 * PATH_MAX];
myKextPath = (CFStringRef) CFArrayGetValueAtIndex(theArray, i);
if (myKextPath == NULL) continue;
myURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
myKextPath,
kCFURLPOSIXPathStyle,
true );
if (myURL == NULL) continue;
myKextPath = CFURLGetString(myURL);
if (myKextPath == NULL ||
CFStringGetCString(myKextPath,
myPathString,
sizeof(myPathString),
kCFStringEncodingUTF8) == false) {
SAFE_RELEASE_NULL(myURL);
continue;
}
SAFE_RELEASE_NULL(myURL);
myResult = AECreateDesc(typeApplicationBundleID,
&kFinderBundleID,
sizeof(kFinderBundleID),
&myTargetDesc);
if (myResult == noErr) {
myResult = AECreateDesc(typeFileURL,
myPathString,
strlen(myPathString),
&myFileDesc);
}
if (myResult == noErr) {
myResult = AECreateList(NULL, 0, false, &myParmList);
}
if (myResult == noErr) {
AEPutDesc(&myParmList, 1, &myFileDesc);
}
if (myResult == noErr) {
myResult = AECreateAppleEvent(kAEMiscStandards,
kAESelect,
&myTargetDesc,
kAutoGenerateReturnID,
kAnyTransactionID,
&myRevealEvent);
}
if (myResult == noErr) {
myResult = AEPutParamDesc(&myRevealEvent,
keyDirectObject,
&myParmList);
}
if (myResult == noErr) {
myResult = AECreateAppleEvent(kAEMiscStandards,
kAEActivate,
&myTargetDesc,
kAutoGenerateReturnID,
kAnyTransactionID,
&myActivateEvent);
}
if (myResult == noErr) {
AESendMessage(&myActivateEvent, NULL, kAENoReply, 0);
AESendMessage(&myRevealEvent, NULL, kAENoReply, 0);
}
AEDisposeDesc(&myTargetDesc);
AEDisposeDesc(&myFileDesc);
AEDisposeDesc(&myParmList);
AEDisposeDesc(&myRevealEvent);
AEDisposeDesc(&myActivateEvent);
}
return;
}
void writeKextAlertPlist( CFDictionaryRef theDict, int theAlertType )
{
CFArrayRef myKextArray; CFURLRef myURL = NULL; CFStringRef myPath = NULL; CFReadStreamRef readStream = NULL; CFWriteStreamRef writeStream = NULL; CFDictionaryRef alertPlist = NULL; CFMutableDictionaryRef alertDict = NULL; Boolean fileExists;
Boolean closeReadStream = false;
Boolean closeWriteStream = false;
if (validateKextsAlertDict(theDict) != 0) {
goto finish;
}
myKextArray = (CFArrayRef) CFDictionaryGetValue(theDict, CFSTR("KextInfoArrayKey"));
myPath = createPathFromAlertType(NULL, theAlertType);
if (myPath == NULL) {
OSKextLogMemError();
goto finish;
}
myURL = CFURLCreateWithFileSystemPath( kCFAllocatorDefault,
myPath,
kCFURLPOSIXPathStyle,
false );
if (myURL == NULL) {
OSKextLogMemError();
goto finish;
}
fileExists = CFURLResourceIsReachable(myURL, NULL);
if (fileExists) {
readStream = CFReadStreamCreateWithFile(kCFAllocatorDefault, myURL);
if (readStream == NULL) {
OSKextLogMemError();
goto finish;
}
closeReadStream = CFReadStreamOpen(readStream);
if (closeReadStream == false) {
OSKextLogMemError();
goto finish;
}
alertPlist = CFPropertyListCreateWithStream(
kCFAllocatorDefault,
readStream,
0,
kCFPropertyListMutableContainersAndLeaves,
NULL, NULL);
if (alertPlist == NULL) {
OSKextLogMemError();
goto finish;
}
CFMutableArrayRef sentArray = NULL; sentArray = (CFMutableArrayRef)
CFDictionaryGetValue(alertPlist, CFSTR("Alerts sent"));
if (sentArray == NULL) {
OSKextLogMemError();
goto finish;
}
Boolean didAppend = false;
didAppend = sendKextAlertNotifications(&sentArray, myKextArray, theAlertType);
if (didAppend) {
writeStream = CFWriteStreamCreateWithFile(kCFAllocatorDefault, myURL);
if (writeStream == NULL) {
OSKextLogMemError();
goto finish;
}
closeWriteStream = CFWriteStreamOpen(writeStream);
if (closeWriteStream == false) {
OSKextLogMemError();
goto finish;
}
CFPropertyListWrite(alertPlist,
writeStream,
kCFPropertyListXMLFormat_v1_0,
0,
NULL);
}
}
else {
alertDict = CFDictionaryCreateMutable(
kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (alertDict == NULL) {
OSKextLogMemError();
goto finish;
}
CFDictionarySetValue(alertDict, CFSTR("Alerts sent"), myKextArray);
alertPlist = CFPropertyListCreateDeepCopy(
kCFAllocatorDefault,
alertDict,
kCFPropertyListMutableContainersAndLeaves );
if (alertPlist == NULL) {
OSKextLogMemError();
goto finish;
}
writeStream = CFWriteStreamCreateWithFile(kCFAllocatorDefault, myURL);
if (writeStream == NULL) {
OSKextLogMemError();
goto finish;
}
closeWriteStream = CFWriteStreamOpen(writeStream);
if (closeWriteStream == false) {
OSKextLogMemError();
goto finish;
}
CFPropertyListWrite(alertPlist,
writeStream,
kCFPropertyListXMLFormat_v1_0,
0,
NULL);
sendKextAlertNotifications(NULL, myKextArray, theAlertType);
}
finish:
#if 0
if (alertPlist) {
OSKextLogCFString(NULL,
kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
CFSTR("%s: alertPlist %@"),
__func__, alertPlist);
}
#endif
if (closeReadStream) CFReadStreamClose(readStream);
if (closeWriteStream) CFWriteStreamClose(writeStream);
SAFE_RELEASE(myURL);
SAFE_RELEASE(readStream);
SAFE_RELEASE(writeStream);
SAFE_RELEASE(alertPlist);
SAFE_RELEASE(alertDict);
SAFE_RELEASE(myPath);
SAFE_RELEASE(theDict);
return;
}
void sendRevokedCertAlert( CFDictionaryRef theDict )
{
CFArrayRef myKextArray; CFIndex count, i;
if (validateKextsAlertDict(theDict) != 0) {
goto finish;
}
myKextArray = (CFArrayRef)
CFDictionaryGetValue(theDict, CFSTR("KextInfoArrayKey"));
if (myKextArray == NULL ||
CFGetTypeID(myKextArray) != CFArrayGetTypeID() ) {
goto finish;
}
count = CFArrayGetCount(myKextArray);
for (i = 0; i < count; i++) {
CFDictionaryRef myDict; CFStringRef myKextPath;
myDict = (CFDictionaryRef)
CFArrayGetValueAtIndex(myKextArray, i);
if (myDict == NULL ||
CFGetTypeID(myDict) != CFDictionaryGetTypeID()) {
continue;
}
myKextPath = CFDictionaryGetValue(myDict, CFSTR("KextPathKey"));
recordRevokedCertKextPath(myKextPath);
}
sendRevokedCertKextPath();
finish:
SAFE_RELEASE(theDict);
return;
}
static Boolean sendKextAlertNotifications(CFMutableArrayRef *theSentAlertsArrayPtr,
CFArrayRef theKextsArray,
int theAlertType)
{
Boolean didAppend = false;
CFIndex count, i;
count = CFArrayGetCount(theKextsArray);
for (i = 0; i < count; i++) {
CFDictionaryRef myDict; CFStringRef myKextMessage; CFStringRef myBundleID; CFStringRef myMappingKey = NULL;
myDict = (CFDictionaryRef) CFArrayGetValueAtIndex(theKextsArray, i);
if (myDict == NULL) continue;
myBundleID = (CFStringRef) CFDictionaryGetValue(myDict, kCFBundleIdentifierKey);
myMappingKey = createBundleMappingKey(myBundleID);
if (theSentAlertsArrayPtr) {
if ( isInAlertsSentArray(*theSentAlertsArrayPtr, myDict, myMappingKey) ) {
SAFE_RELEASE_NULL(myMappingKey);
continue;
}
didAppend = true;
CFArrayAppendValue(*theSentAlertsArrayPtr, myDict);
}
myKextMessage = getKextAlertMessage(myDict, myMappingKey);
if (theAlertType == INVALID_SIGNATURE_KEXT_ALERT) {
recordInvalidSignedKextPath(myKextMessage);
}
else if (theAlertType == NO_LOAD_KEXT_ALERT) {
recordNoLoadKextPath(myKextMessage);
}
else if (theAlertType == EXCLUDED_KEXT_ALERT) {
recordExcludedKextPath(myKextMessage);
}
#if 0 // not yet
else if (theAlertType == UNSIGNED_KEXT_ALERT) {
recordUnsignedKextPath(myKextMessage);
}
#endif
SAFE_RELEASE_NULL(myMappingKey);
}
if (theAlertType == INVALID_SIGNATURE_KEXT_ALERT) {
sendInvalidSignedKextNotification();
}
else if (theAlertType == NO_LOAD_KEXT_ALERT) {
sendNoLoadKextNotification();
}
else if (theAlertType == EXCLUDED_KEXT_ALERT) {
sendExcludedKextNotification();
}
#if 0 // not yet
else if (theAlertType == UNSIGNED_KEXT_ALERT) {
sendUnsignedKextNotification();
}
#endif
return(didAppend);
}
static CFStringRef getKextAlertMessage(
CFDictionaryRef theDict,
CFStringRef theMappingKey )
{
CFStringRef myKextMessage = NULL;
if (theMappingKey && sKextTranslationsPlist) {
CFDictionaryRef myMappingDict = NULL;
myMappingDict = (CFDictionaryRef)
CFDictionaryGetValue(sKextTranslationsPlist,
CFSTR("BundleMappings"));
if (myMappingDict) {
myKextMessage = (CFStringRef)
CFDictionaryGetValue(myMappingDict,
theMappingKey);
}
}
if (myKextMessage == NULL) {
myKextMessage = CFDictionaryGetValue(theDict,
CFSTR("KextPathKey"));
}
return(myKextMessage);
}
#define LOADED_KEXT_MT_ALERT_FULL_PATH \
_kOSKextCachesRootFolder "/" \
_kOSKextStartupCachesSubfolder "/" \
"loadedkextmt.plist"
void writeKextLoadPlist( CFArrayRef theArray )
{
CFURLRef myURL = NULL; CFReadStreamRef readStream = NULL; CFWriteStreamRef writeStream = NULL; CFDictionaryRef alertPlist = NULL; CFMutableDictionaryRef alertDict = NULL; Boolean fileExists;
Boolean closeReadStream = false;
Boolean closeWriteStream = false;
if (theArray == NULL || CFArrayGetCount(theArray) < 1) {
goto finish;
}
myURL = CFURLCreateFromFileSystemRepresentation(
kCFAllocatorDefault,
(UInt8 *) LOADED_KEXT_MT_ALERT_FULL_PATH,
strlen(LOADED_KEXT_MT_ALERT_FULL_PATH),
false );
if (myURL == NULL) {
OSKextLogMemError();
goto finish;
}
fileExists = CFURLResourceIsReachable(myURL, NULL);
if (fileExists) {
readStream = CFReadStreamCreateWithFile(kCFAllocatorDefault, myURL);
if (readStream == NULL) {
OSKextLogMemError();
goto finish;
}
closeReadStream = CFReadStreamOpen(readStream);
if (closeReadStream == false) {
OSKextLogMemError();
goto finish;
}
alertPlist = CFPropertyListCreateWithStream(
kCFAllocatorDefault,
readStream,
0,
kCFPropertyListMutableContainersAndLeaves,
NULL, NULL);
if (alertPlist == NULL) {
OSKextLogMemError();
goto finish;
}
CFMutableArrayRef sentArray = NULL; sentArray = (CFMutableArrayRef)
CFDictionaryGetValue(alertPlist, CFSTR("Alerts sent"));
if (sentArray == NULL) {
OSKextLogMemError();
goto finish;
}
CFIndex count, i;
Boolean didAppend = false;
count = CFArrayGetCount(theArray);
for (i = 0; i < count; i++) {
CFDictionaryRef kextDict = CFArrayGetValueAtIndex(theArray, i);
if (!CFArrayContainsValue(sentArray, RANGE_ALL(sentArray), kextDict)) {
didAppend = true;
CFArrayAppendValue(sentArray, kextDict);
}
}
if (didAppend) {
writeStream = CFWriteStreamCreateWithFile(kCFAllocatorDefault, myURL);
if (writeStream == NULL) {
OSKextLogMemError();
goto finish;
}
closeWriteStream = CFWriteStreamOpen(writeStream);
if (closeWriteStream == false) {
OSKextLogMemError();
goto finish;
}
CFPropertyListWrite(alertPlist,
writeStream,
kCFPropertyListXMLFormat_v1_0,
0,
NULL);
}
}
else {
alertDict = CFDictionaryCreateMutable(
kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (alertDict == NULL) {
OSKextLogMemError();
goto finish;
}
CFDictionarySetValue(alertDict, CFSTR("Alerts sent"), theArray);
alertPlist = CFPropertyListCreateDeepCopy(
kCFAllocatorDefault,
alertDict,
kCFPropertyListMutableContainersAndLeaves );
if (alertPlist == NULL) {
OSKextLogMemError();
goto finish;
}
writeStream = CFWriteStreamCreateWithFile(kCFAllocatorDefault, myURL);
if (writeStream == NULL) {
OSKextLogMemError();
goto finish;
}
closeWriteStream = CFWriteStreamOpen(writeStream);
if (closeWriteStream == false) {
OSKextLogMemError();
goto finish;
}
CFPropertyListWrite(alertPlist,
writeStream,
kCFPropertyListXMLFormat_v1_0,
0,
NULL);
}
finish:
if (closeReadStream) CFReadStreamClose(readStream);
if (closeWriteStream) CFWriteStreamClose(writeStream);
SAFE_RELEASE(myURL);
SAFE_RELEASE(readStream);
SAFE_RELEASE(writeStream);
SAFE_RELEASE(alertPlist);
SAFE_RELEASE(alertDict);
SAFE_RELEASE(theArray);
return;
}
static CFStringRef createBundleMappingKey( CFStringRef theBundleID )
{
CFDictionaryRef myMappingDict = NULL; CFMutableStringRef myMatchKey = NULL;
if (theBundleID == NULL || sKextTranslationsPlist == NULL) {
goto finish;
};
myMappingDict = (CFDictionaryRef)
CFDictionaryGetValue(sKextTranslationsPlist,
CFSTR("BundleMappings"));
if (myMappingDict == NULL) {
goto finish;
}
myMatchKey = CFStringCreateMutableCopy(kCFAllocatorDefault,
0, theBundleID);
while (myMatchKey) {
CFStringRef myProductString = NULL; CFRange myRange;
myProductString = CFDictionaryGetValue(myMappingDict,
myMatchKey);
if (myProductString) {
break;
}
myRange = CFStringFind(myMatchKey, CFSTR("."), kCFCompareBackwards);
if (myRange.length != 0) {
myRange.length = CFStringGetLength(myMatchKey) - myRange.location;
CFStringDelete(myMatchKey, myRange);
myRange = CFStringFind(myMatchKey, CFSTR("."), 0);
if (myRange.length == 0) {
SAFE_RELEASE_NULL(myMatchKey);
}
}
}
finish:
return(myMatchKey);
}
static Boolean isInAlertsSentArray(CFArrayRef theSentArray,
CFDictionaryRef theDict,
CFStringRef theMappingKey)
{
Boolean myResult = false;
CFIndex myCount, i;
if (theSentArray == NULL || theDict == NULL) return(false);
if (CFArrayContainsValue(theSentArray, RANGE_ALL(theSentArray), theDict)) {
return(true);
}
myCount = CFArrayGetCount(theSentArray);
if (theMappingKey && myCount > 0) {
for (i = 0; i < myCount; i++) {
CFDictionaryRef myKextAlertedDict;
CFStringRef myAlertedBundleID;
myKextAlertedDict = (CFDictionaryRef)
CFArrayGetValueAtIndex(theSentArray, i);
if (myKextAlertedDict == NULL ||
CFGetTypeID(myKextAlertedDict) != CFDictionaryGetTypeID()) {
continue;
}
myAlertedBundleID = (CFStringRef)
CFDictionaryGetValue(myKextAlertedDict, kCFBundleIdentifierKey);
if (myAlertedBundleID &&
CFGetTypeID(myAlertedBundleID) == CFStringGetTypeID()) {
CFRange myRange;
myRange = CFStringFind(myAlertedBundleID, theMappingKey, 0);
if (myRange.length > 0) {
myResult = true;
break;
}
}
} }
return( myResult);
}
#define INVALIDSIGNED_KEXT_ALERT_FULL_PATH \
_kOSKextCachesRootFolder "/" \
_kOSKextStartupCachesSubfolder "/" \
"invalidsignedkextalert.plist"
#if 0 // not yet
#define UNSIGNED_KEXT_ALERT_FULL_PATH \
_kOSKextCachesRootFolder "/" \
_kOSKextStartupCachesSubfolder "/" \
"unsignedkextalert.plist"
#endif
#define NO_LOAD_KEXT_ALERT_FULL_PATH \
_kOSKextCachesRootFolder "/" \
_kOSKextStartupCachesSubfolder "/" \
"noloadkextalert.plist"
#define EXCLUDED_KEXT_ALERT_FULL_PATH \
_kOSKextCachesRootFolder "/" \
_kOSKextStartupCachesSubfolder "/" \
"excludedkextalert.plist"
#define TRANSLATIONS_FULL_PATH \
_kOSKextCachesRootFolder "/" \
_kOSKextStartupCachesSubfolder "/" \
"kexttranslation.plist"
static CFStringRef createPathFromAlertType( CFStringRef theVolRoot,
int theAlertType )
{
CFStringRef myPath = NULL;
if (theVolRoot) {
if (theAlertType == INVALID_SIGNATURE_KEXT_ALERT) {
myPath = CFStringCreateWithFormat(
kCFAllocatorDefault,
NULL,
CFSTR("%@%s"),
theVolRoot,
INVALIDSIGNED_KEXT_ALERT_FULL_PATH);
}
#if 0 // not yet
else if (theAlertType == UNSIGNED_KEXT_ALERT) {
myPath = CFStringCreateWithFormat(
kCFAllocatorDefault,
NULL,
CFSTR("%@%s"),
theVolRoot,
UNSIGNED_KEXT_ALERT_FULL_PATH);
}
#endif
else if (theAlertType == NO_LOAD_KEXT_ALERT) {
myPath = CFStringCreateWithFormat(
kCFAllocatorDefault,
NULL,
CFSTR("%@%s"),
theVolRoot,
NO_LOAD_KEXT_ALERT_FULL_PATH);
}
else if (theAlertType == EXCLUDED_KEXT_ALERT) {
myPath = CFStringCreateWithFormat(
kCFAllocatorDefault,
NULL,
CFSTR("%@%s"),
theVolRoot,
EXCLUDED_KEXT_ALERT_FULL_PATH);
}
else {
goto finish;
}
#if 0 // disable this for now. We will go with kext file name or path.
if (sKextTranslationsPlist == NULL) {
myTranslatePath = CFStringCreateWithFormat(
kCFAllocatorDefault,
NULL,
CFSTR("%@%s"),
theVolRoot,
TRANSLATIONS_FULL_PATH);
}
#endif
}
else {
if (theAlertType == INVALID_SIGNATURE_KEXT_ALERT) {
myPath = CFStringCreateWithCString(
kCFAllocatorDefault,
INVALIDSIGNED_KEXT_ALERT_FULL_PATH,
kCFStringEncodingUTF8 );
}
#if 0 // not yet
else if (theAlertType == UNSIGNED_KEXT_ALERT) {
myPath = CFStringCreateWithCString(
kCFAllocatorDefault,
UNSIGNED_KEXT_ALERT_FULL_PATH,
kCFStringEncodingUTF8 );
}
#endif
else if (theAlertType == NO_LOAD_KEXT_ALERT) {
myPath = CFStringCreateWithCString(
kCFAllocatorDefault,
NO_LOAD_KEXT_ALERT_FULL_PATH,
kCFStringEncodingUTF8 );
}
else if (theAlertType == EXCLUDED_KEXT_ALERT) {
myPath = CFStringCreateWithCString(
kCFAllocatorDefault,
EXCLUDED_KEXT_ALERT_FULL_PATH,
kCFStringEncodingUTF8 );
}
else {
goto finish;
}
#if 0 // disable this for now. We will go with kext file name or path.
if (sKextTranslationsPlist == NULL) {
myTranslatePath = CFStringCreateWithCString(
kCFAllocatorDefault,
TRANSLATIONS_FULL_PATH,
kCFStringEncodingUTF8 );
}
#endif
}
#if 0 // disable this for now. We will go with kext file name or path.
if (myTranslatePath) {
CFURLRef myURL = NULL;
myURL = CFURLCreateWithFileSystemPath( kCFAllocatorDefault,
myTranslatePath,
kCFURLPOSIXPathStyle,
false );
if (myURL && CFURLResourceIsReachable(myURL, NULL)) {
CFReadStreamRef readStream = NULL;
readStream = CFReadStreamCreateWithFile(kCFAllocatorDefault, myURL);
if (readStream) {
if (CFReadStreamOpen(readStream)) {
sKextTranslationsPlist = CFPropertyListCreateWithStream(
kCFAllocatorDefault,
readStream,
0,
kCFPropertyListMutableContainersAndLeaves,
NULL, NULL);
CFReadStreamClose(readStream);
}
SAFE_RELEASE(readStream);
}
}
SAFE_RELEASE(myURL);
}
#endif
finish:
return( myPath );
}
static int validateKextsAlertDict( CFDictionaryRef theDict )
{
CFArrayRef myKextArray; CFIndex count, i;
int result = -1;
if (theDict == NULL || CFGetTypeID(theDict) != CFDictionaryGetTypeID()) {
OSKextLogCFString( NULL,
kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
CFSTR("%s invalid dictionary type \n"),
__func__);
goto finish;
}
myKextArray = (CFArrayRef) CFDictionaryGetValue(theDict, CFSTR("KextInfoArrayKey"));
if (myKextArray == NULL) {
OSKextLogCFString( NULL,
kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
CFSTR("%s null array \n"),
__func__);
goto finish;
}
if ( CFGetTypeID(myKextArray) != CFArrayGetTypeID() ) {
OSKextLogCFString( NULL,
kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
CFSTR("%s invalid array type \n"),
__func__);
goto finish;
}
if (CFArrayGetCount(myKextArray) < 1 || CFArrayGetCount(myKextArray) > 10) {
OSKextLogCFString( NULL,
kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
CFSTR("%s invalid array count %lu \n"),
__func__, CFArrayGetCount(myKextArray));
goto finish;
}
count = CFArrayGetCount(myKextArray);
for (i = 0; i < count; i++) {
CFDictionaryRef myDict; CFStringRef myString;
myDict = (CFDictionaryRef) CFArrayGetValueAtIndex(myKextArray, i);
if (myDict == NULL || CFGetTypeID(myDict) != CFDictionaryGetTypeID()) {
OSKextLogCFString( NULL,
kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
CFSTR("%s invalid kext array dictionary \n"),
__func__);
goto finish;
}
if (CFDictionaryGetCount(myDict) > 3) {
OSKextLogCFString( NULL,
kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
CFSTR("%s invalid dictionary count %lu \n"),
__func__, CFDictionaryGetCount(myDict));
goto finish;
}
myString = CFDictionaryGetValue(myDict, CFSTR("KextPathKey"));
if (myString == NULL ||
CFGetTypeID(myString) != CFStringGetTypeID() ||
CFStringGetLength(myString) > 1024) {
OSKextLogCFString( NULL,
kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
CFSTR("%s invalid kext path value \n"),
__func__);
goto finish;
}
myString = CFDictionaryGetValue(myDict, kCFBundleIdentifierKey);
if (myString == NULL ||
CFGetTypeID(myString) != CFStringGetTypeID() ||
CFStringGetLength(myString) > 256) {
OSKextLogCFString( NULL,
kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
CFSTR("%s invalid kext bundle ID value \n"),
__func__);
goto finish;
}
myString = CFDictionaryGetValue(myDict, kCFBundleVersionKey);
if (myString == NULL ||
CFGetTypeID(myString) != CFStringGetTypeID() ||
CFStringGetLength(myString) > 256) {
OSKextLogCFString( NULL,
kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
CFSTR("%s invalid kext bundle version value \n"),
__func__);
goto finish;
}
} result = 0;
finish:
return result;
}
Boolean doingSystemInstall(void)
{
CFURLRef myURL = NULL; Boolean result = false;
myURL = CFURLCreateWithString(NULL,
CFSTR("file://localhost/private/etc/rc.cdrom"),
NULL);
if (myURL) {
result = CFURLResourceIsReachable(myURL, NULL);
}
SAFE_RELEASE(myURL);
return result;
}
#endif