#include <os/trace.h>
#include <os/log_private.h>
#include <sqlite3.h>
+#include <os/lock_private.h>
+
+const char *api_trace = "api_trace";
-const uint8_t _os_trace_type_map[8] = {
- OS_TRACE_TYPE_FAULT, // ASL_LEVEL_EMERG
- OS_TRACE_TYPE_FAULT, // ASL_LEVEL_ALERT
- OS_TRACE_TYPE_FAULT, // ASL_LEVEL_CRIT
- OS_TRACE_TYPE_ERROR, // ASL_LEVEL_ERR
- OS_TRACE_TYPE_RELEASE, // ASL_LEVEL_WARNING
- OS_TRACE_TYPE_RELEASE, // ASL_LEVEL_NOTICE
- OS_TRACE_TYPE_RELEASE, // ASL_LEVEL_INFO
- OS_TRACE_TYPE_DEBUG // ASL_LEVEL_DEBUG
-};
-
-const char *_asl_string_map[8] = {
- ASL_STRING_EMERG, // ASL_LEVEL_EMERG
- ASL_STRING_ALERT, // ASL_LEVEL_ALERT
- ASL_STRING_CRIT, // ASL_LEVEL_CRIT
- ASL_STRING_ERR, // ASL_LEVEL_ERR
- ASL_STRING_WARNING, // ASL_LEVEL_WARNING
- ASL_STRING_NOTICE, // ASL_LEVEL_NOTICE
- ASL_STRING_INFO, // ASL_LEVEL_INFO
- ASL_STRING_DEBUG // ASL_LEVEL_DEBUG
-};
const CFStringRef kStringNegate = CFSTR("-");
const CFStringRef kStringAll = CFSTR("all");
}
-
-static CFStringRef copyScopeName(const char *scope, CFIndex scopeLen) {
- return CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8 *)scope,
- scopeLen, kCFStringEncodingUTF8, false);
-}
-
static CFMutableSetRef CopyScopesFromScopeList(CFStringRef scopes) {
CFMutableSetRef resultSet = CFSetCreateMutableForCFTypes(kCFAllocatorDefault);
static int string_to_log_level(CFStringRef string) {
if (CFEqual(string, CFSTR(ASL_STRING_EMERG)))
- return ASL_LEVEL_EMERG;
+ return SECLOG_LEVEL_EMERG;
else if (CFEqual(string, CFSTR(ASL_STRING_ALERT)))
- return ASL_LEVEL_ALERT;
+ return SECLOG_LEVEL_ALERT;
else if (CFEqual(string, CFSTR(ASL_STRING_CRIT)))
- return ASL_LEVEL_CRIT;
+ return SECLOG_LEVEL_CRIT;
else if (CFEqual(string, CFSTR(ASL_STRING_ERR)))
- return ASL_LEVEL_ERR;
+ return SECLOG_LEVEL_ERR;
else if (CFEqual(string, CFSTR(ASL_STRING_WARNING)))
- return ASL_LEVEL_WARNING;
+ return SECLOG_LEVEL_WARNING;
else if (CFEqual(string, CFSTR(ASL_STRING_NOTICE)))
- return ASL_LEVEL_NOTICE;
+ return SECLOG_LEVEL_NOTICE;
else if (CFEqual(string, CFSTR(ASL_STRING_INFO)))
- return ASL_LEVEL_INFO;
+ return SECLOG_LEVEL_INFO;
else if (CFEqual(string, CFSTR(ASL_STRING_DEBUG)))
- return ASL_LEVEL_DEBUG;
+ return SECLOG_LEVEL_DEBUG;
else
return -1;
}
#pragma mark - Log Handlers to catch log information
-static CFMutableArrayRef sSecurityLogHandlers;
-
/*
* Instead of using CFPropertyListReadFromFile we use a
ApplyScopeListForIDC(cur_scope, kScopeIDEnvironment);
}
-#define XPCSCOPESTRWANT "api,account,accountChange,circle,circleChange,circleCreat,flush,fresh,keygen,signing,talkwithkvs"
-#define XPCSCOPESTRDONTWANT "-event,http,item,keytrace,lockassertions,otr_keysetup,securityd,server,serverxpc,session,sync,titc,transport,trust,updates,xpc"
-static void setup_xpcdefault_scopes() {
-
- CFDictionaryRef noticeLogging = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
- CFSTR(ASL_STRING_NOTICE), CFSTR(XPCSCOPESTRDONTWANT), NULL);
-
- ApplyScopeDictionaryForID(noticeLogging, kScopeIDXPC);
-
- CFReleaseNull(noticeLogging);
-}
void __security_debug_init(void) {
static dispatch_once_t sdOnceToken;
setup_environment_scopes();
setup_config_settings();
setup_defaults_settings();
- //setup_xpcdefault_scopes();
setup_circle_defaults_settings();
});
}
-// MARK: Log handler recording (e.g. grabbing security logging and sending it to test results).
-static void clean_aslclient(void *client)
-{
- asl_close(client);
-}
-
-static aslclient get_aslclient()
-{
- static dispatch_once_t once;
- static pthread_key_t asl_client_key;
- dispatch_once(&once, ^{
- pthread_key_create(&asl_client_key, clean_aslclient);
- });
- aslclient client = pthread_getspecific(asl_client_key);
- if (!client) {
- client = asl_open(NULL, "SecLogging", 0);
- asl_set_filter(client, ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG));
- pthread_setspecific(asl_client_key, client);
- }
-
- return client;
-}
-
-static CFMutableArrayRef get_log_handlers()
-{
- static dispatch_once_t handlers_once;
-
- dispatch_once(&handlers_once, ^{
- sSecurityLogHandlers = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
-
- CFArrayAppendValue(sSecurityLogHandlers, ^(int level, CFStringRef scope, const char *function,
- const char *file, int line, CFStringRef message){
- CFStringRef logStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ %s %@\n"), scope ? scope : CFSTR(""), function, message);
- CFStringPerformWithCString(logStr, ^(const char *logMsg) {
- aslmsg msg = asl_new(ASL_TYPE_MSG);
- if (scope) {
- CFStringPerformWithCString(scope, ^(const char *scopeStr) {
- asl_set(msg, ASL_KEY_FACILITY, scopeStr);
- });
- }
- asl_log(get_aslclient(), msg, level, "%s", logMsg);
- asl_free(msg);
- });
- CFReleaseSafe(logStr);
- });
- });
-
- return sSecurityLogHandlers;
-}
-static void log_api_trace_v(const char *api, const char *caller_info, CFStringRef format, va_list args)
-{
- aslmsg msg = asl_new(ASL_TYPE_MSG);
- asl_set(msg, ASL_KEY_LEVEL, ASL_STRING_DEBUG);
- CFStringPerformWithCString(kAPIScope, ^(const char *scopeStr) {
- asl_set(msg, ASL_KEY_FACILITY, scopeStr);
- });
- asl_set(msg, "SecAPITrace", api);
- asl_set(msg, caller_info ? "ENTER" : "RETURN", "");
- if (format) {
- CFStringRef message = CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, NULL, format, args);
- CFStringPerformWithCString(message, ^(const char *utf8Str) {
- asl_set(msg, ASL_KEY_MSG, utf8Str);
- });
- CFReleaseSafe(message);
- }
- if (caller_info) {
- asl_set(msg, "CALLER", caller_info);
+static char *copyScopeStr(CFStringRef scope, char *alternative) {
+ char *scopeStr = NULL;
+ if(scope) {
+ scopeStr = CFStringToCString(scope);
+ } else {
+ scopeStr = strdup("noScope");
}
-
- asl_send(get_aslclient(), msg);
- asl_free(msg);
+ return scopeStr;
}
-void __security_trace_enter_api(const char *api, CFStringRef format, ...)
+os_log_t
+secLogObjForCFScope(CFStringRef scope)
{
- if (!IsScopeActive(ASL_LEVEL_DEBUG, kAPIScope))
- return;
-
- va_list args;
- va_start(args, format);
-
- {
- char stack_info[80];
-
- snprintf(stack_info, sizeof(stack_info), "C%p F%p", __builtin_return_address(1), __builtin_frame_address(2));
+ os_log_t retval = OS_LOG_DISABLED;
+ static os_unfair_lock lock = OS_UNFAIR_LOCK_INIT;
+ static CFMutableDictionaryRef scopeMap = NULL;
- log_api_trace_v(api, stack_info, format, args);
+ if (scope == NULL) {
+ scope = CFSTR("logging");
}
- va_end(args);
-}
+ os_unfair_lock_lock_with_options(&lock, OS_UNFAIR_LOCK_DATA_SYNCHRONIZATION);
-void __security_trace_return_api(const char *api, CFStringRef format, ...)
-{
- if (!IsScopeActive(ASL_LEVEL_DEBUG, kAPIScope))
- return;
+ if (scopeMap == NULL) {
+ scopeMap = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFCopyStringDictionaryKeyCallBacks, NULL);
+ }
- va_list args;
- va_start(args, format);
+ retval = (os_log_t)CFDictionaryGetValue(scopeMap, scope);
+ if (retval == NULL) {
+ CFStringPerformWithCString(scope, ^(const char *scopeStr) {
+ CFDictionaryAddValue(scopeMap, scope, os_log_create("com.apple.securityd", scopeStr));
+ });
+ retval = (os_log_t)CFDictionaryGetValue(scopeMap, scope);
+ }
- log_api_trace_v(api, NULL, format, args);
+ os_unfair_lock_unlock(&lock);
- va_end(args);
+ return retval;
}
+static bool loggingEnabled = true;
+static pthread_mutex_t loggingMutex = PTHREAD_MUTEX_INITIALIZER;
-void add_security_log_handler(security_log_handler handler)
-{
- CFArrayAppendValue(get_log_handlers(), handler);
+bool secLogEnabled(void) {
+ bool r = false;
+ pthread_mutex_lock(&loggingMutex);
+ r = loggingEnabled;
+ pthread_mutex_unlock(&loggingMutex);
+ return r;
}
-
-void remove_security_log_handler(security_log_handler handler)
-{
- CFArrayRemoveAllValue(get_log_handlers(), handler);
+void secLogDisable(void) {
+ pthread_mutex_lock(&loggingMutex);
+ loggingEnabled = false;
+ pthread_mutex_unlock(&loggingMutex);
}
-static void __security_post_msg(int level, CFStringRef scope, const char *function,
- const char *file, int line, CFStringRef message)
-{
- CFArrayForEach(get_log_handlers(), ^(const void *value) {
- security_log_handler handler = (security_log_handler) value;
- if (handler) {
- handler(level, scope, function, file, line, message);
- }
- });
+void secLogEnable(void) {
+ pthread_mutex_lock(&loggingMutex);
+ loggingEnabled = true;
+ pthread_mutex_unlock(&loggingMutex);
}
-static void __security_log_msg_v(int level, CFStringRef scope, const char *function,
- const char *file, int line, CFStringRef format, va_list args)
-{
- __security_debug_init();
-
- if (!IsScopeActive(level, scope))
- return;
-
- CFStringRef message = CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, NULL, format, args);
- __security_post_msg(level, scope, function, file, line, message);
- CFRelease(message);
-
+os_log_t secLogObjForScope(const char *scope) {
+ if (!secLogEnabled())
+ return OS_LOG_DISABLED;
+ CFStringRef cfscope = NULL;
+ if(scope) cfscope = CFStringCreateWithCString(kCFAllocatorDefault, scope, kCFStringEncodingASCII);
+ os_log_t retval = secLogObjForCFScope(cfscope);
+ CFReleaseNull(cfscope);
+ return retval;
}
-void __security_debug(CFStringRef scope, const char *function,
- const char *file, int line, CFStringRef format, ...)
-{
- va_list args;
- va_start(args, format);
- __security_log_msg_v(ASL_LEVEL_DEBUG, scope, function, file, line, format, args);
- va_end(args);
-}
+CFStringRef SecLogAPICreate(bool apiIn, const char *api, CFStringRef format, ... ) {
+ CFMutableStringRef outStr = CFStringCreateMutable(kCFAllocatorDefault, 0);
-static void __os_log_shim(void *addr, int32_t level, CFStringRef format, va_list in_args) {
- if ((level & 0x7) == level) {
- va_list args;
- va_copy(args, in_args);
- os_log_shim_with_CFString(addr, OS_LOG_DEFAULT, _os_trace_type_map[level], format, args, NULL);
- va_end(args);
- }
-}
-
-void __security_log(int level, CFStringRef scope, const char *function,
- const char *file, int line, CFStringRef format, ...)
-{
+ char *direction = apiIn ? "ENTER" : "RETURN";
va_list args;
va_start(args, format);
- __os_log_shim(__builtin_return_address(0), level, format, args);
+ CFStringAppend(outStr, CFSTR("SecAPITrace "));
+ CFStringAppendCString(outStr, api, kCFStringEncodingASCII);
+ CFStringAppendCString(outStr, direction, kCFStringEncodingASCII);
- if (os_log_shim_legacy_logging_enabled()) {
- __security_log_msg_v(level, scope, function, file, line, format, args);
+ if (format) {
+ CFStringRef message = CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, NULL, format, args);
+ CFStringAppend(outStr, message);
+ CFReleaseSafe(message);
+ }
+
+ if (apiIn) {
+ char caller_info[80];
+ snprintf(caller_info, sizeof(caller_info), "C%p F%p", __builtin_return_address(1), __builtin_frame_address(2));
+ CFStringAppend(outStr, CFSTR("CALLER "));
+ CFStringAppendCString(outStr, caller_info, kCFStringEncodingASCII);
}
-
va_end(args);
-}
+
+ return outStr;
+}
+
+#if TARGET_OS_OSX
+// Functions for weak-linking os_log functions
+#include <dlfcn.h>
+
+#define weak_log_f(fname, newname, rettype, fallthrough) \
+ rettype newname(log_args) { \
+ static dispatch_once_t onceToken = 0; \
+ static rettype (*newname)(log_args) = NULL; \
+ \
+ dispatch_once(&onceToken, ^{ \
+ void* libtrace = dlopen("/usr/lib/system/libsystem_trace.dylib", RTLD_LAZY | RTLD_LOCAL); \
+ if (libtrace) { \
+ newname = (rettype(*)(log_args)) dlsym(libtrace, #fname); \
+ } \
+ }); \
+ \
+ if(newname) { \
+ return newname(log_argnames); \
+ } \
+ fallthrough;\
+}
+
+#define log_args void *dso, os_log_t log, os_log_type_t type, const char *format, uint8_t *buf, unsigned int size
+#define log_argnames dso, log, type, format, buf, size
+weak_log_f(_os_log_impl, weak_os_log_impl, void, return);
+#undef log_args
+#undef log_argnames
+
+#define log_args const char *subsystem, const char *category
+#define log_argnames subsystem, category
+weak_log_f(os_log_create, weak_os_log_create, os_log_t, return NULL);
+#undef log_args
+#undef log_argnames
+
+#define log_args os_log_t oslog, os_log_type_t type
+#define log_argnames oslog, type
+weak_log_f(os_log_type_enabled, weak_os_log_type_enabled, bool, return false);
+#undef log_args
+#undef log_argnames
+
+#undef weak_log_f
+
+#endif // TARGET_OS_OSX
+