void print_mach_service(launch_data_t obj, const char *key, void *context) { if (launch_data_get_type(obj) == LAUNCH_DATA_MACHPORT) { fprintf(stdout, "%s: %d\n", key, launch_data_get_machport(obj)); mach_port_deallocate(mach_task_self(), launch_data_get_machport(obj)); mach_port_mod_refs(mach_task_self(), launch_data_get_machport(obj), MACH_PORT_RIGHT_RECEIVE, -1); } else { fprintf(stdout, "%s: not a mach port\n", key); } }
static mach_port_t checkin(char *service_name) { kern_return_t kr = KERN_SUCCESS; mach_port_t port = MACH_PORT_NULL; launch_data_t msg = NULL, reply = NULL, datum = NULL; if (NULL == (msg = launch_data_new_string(LAUNCH_KEY_CHECKIN))) { helplog(ASL_LEVEL_ERR, "Could not create checkin message for launchd."); goto fin; } if (NULL == (reply = launch_msg(msg))) { helplog(ASL_LEVEL_ERR, "Could not message launchd."); goto fin; } if (LAUNCH_DATA_ERRNO == launch_data_get_type(reply)) { if (launch_data_get_errno(reply) == EACCES) { launch_data_free(msg); launch_data_free(reply); return(MACH_PORT_NULL); } helplog(ASL_LEVEL_ERR, "Launchd checkin failed: %s.", strerror(launch_data_get_errno(reply))); goto fin; } if (NULL == (datum = launch_data_dict_lookup(reply, LAUNCH_JOBKEY_MACHSERVICES)) || LAUNCH_DATA_DICTIONARY != launch_data_get_type(datum)) { helplog(ASL_LEVEL_ERR, "Launchd reply does not contain %s dictionary.", LAUNCH_JOBKEY_MACHSERVICES); goto fin; } if (NULL == (datum = launch_data_dict_lookup(datum, service_name)) || LAUNCH_DATA_MACHPORT != launch_data_get_type(datum)) { helplog(ASL_LEVEL_ERR, "Launchd reply does not contain %s Mach port.", service_name); goto fin; } if (MACH_PORT_NULL == (port = launch_data_get_machport(datum))) { helplog(ASL_LEVEL_ERR, "Launchd gave me a null Mach port."); goto fin; } if (KERN_SUCCESS != (kr = mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND))) { helplog(ASL_LEVEL_ERR, "mach_port_insert_right: %s", mach_error_string(kr)); goto fin; } fin: if (NULL != msg) launch_data_free(msg); if (NULL != reply) launch_data_free(reply); if (MACH_PORT_NULL == port) exit(EXIT_FAILURE); return port; }
/* * Lookup the audit mach port in the launchd dictionary. */ static mach_port_t lookup_machport(const char *label) { launch_data_t msg, msd, ld, cdict, to; mach_port_t mp = MACH_PORT_NULL; msg = launch_data_new_string(LAUNCH_KEY_CHECKIN); cdict = launch_msg(msg); if (cdict == NULL) { auditd_log_err("launch_msg(\"" LAUNCH_KEY_CHECKIN "\") IPC failure: %m"); return (MACH_PORT_NULL); } if (launch_data_get_type(cdict) == LAUNCH_DATA_ERRNO) { errno = launch_data_get_errno(cdict); auditd_log_err("launch_data_get_type() can't get dict: %m"); return (MACH_PORT_NULL); } to = launch_data_dict_lookup(cdict, LAUNCH_JOBKEY_TIMEOUT); if (to) { max_idletime = launch_data_get_integer(to); auditd_log_debug("launchd timeout set to %d", max_idletime); } else { auditd_log_debug("launchd timeout not set, setting to 60"); max_idletime = 60; } msd = launch_data_dict_lookup(cdict, LAUNCH_JOBKEY_MACHSERVICES); if (msd == NULL) { auditd_log_err( "launch_data_dict_lookup() can't get mach services"); return (MACH_PORT_NULL); } ld = launch_data_dict_lookup(msd, label); if (ld == NULL) { auditd_log_err("launch_data_dict_lookup can't find %s", label); return (MACH_PORT_NULL); } mp = launch_data_get_machport(ld); return (mp); }
/* Get the Mach port upon which we'll receive requests from our parent */ static mach_port_t get_hex_fiend_receive_port(void) { mach_port_t launchdReceivePort = MACH_PORT_NULL, hexFiendReceivePort = MACH_PORT_NULL; launch_data_t resp = NULL, machServices = NULL, msg = NULL, service = NULL; int err = 0; /* Check in with launchd */ msg = launch_data_new_string(LAUNCH_KEY_CHECKIN); resp = launch_msg(msg); if (resp == NULL) { if (ERR_FILE) fprintf(ERR_FILE, "launch_msg(): %s\n", strerror(errno)); exit(EXIT_FAILURE); } /* Guard against errors */ if (launch_data_get_type(resp) == LAUNCH_DATA_ERRNO) { errno = launch_data_get_errno(resp); if (ERR_FILE) fprintf(ERR_FILE, "launch_msg() response: %s\n", strerror(errno)); exit(EXIT_FAILURE); } /* Get our MachServices dictioanry */ machServices = launch_data_dict_lookup(resp, LAUNCH_JOBKEY_MACHSERVICES); /* Die if it's not there */ if (machServices == NULL) { if (ERR_FILE) fprintf(ERR_FILE, "No mach services found!\n"); exit(EXIT_FAILURE); } /* Get the one we care about */ service = launch_data_dict_lookup(machServices, kPrivilegedHelperLaunchdLabel); if (service == NULL) { if (ERR_FILE) fprintf(ERR_FILE, "Mach service %s not found!\n", kPrivilegedHelperLaunchdLabel); exit(EXIT_FAILURE); } /* Make sure we've got a mach port */ if (launch_data_get_type(service) != LAUNCH_DATA_MACHPORT) { if (ERR_FILE) fprintf(ERR_FILE, "%s: not a mach port\n", kPrivilegedHelperLaunchdLabel); exit(EXIT_FAILURE); } /* Now get the launchd mach port */ launchdReceivePort = launch_data_get_machport(service); /* We don't want to use launchd's port - we want one from Hex Fiend (so we can get a no senders notification). So receive a port from Hex Fiend on our launchd port. */ hexFiendReceivePort = MACH_PORT_NULL; if ((err = recv_port(launchdReceivePort, &hexFiendReceivePort))) { if (ERR_FILE) fprintf(ERR_FILE, "recv_port() failed with Mach error %d\n", err); exit(EXIT_FAILURE); } /* Make sure we got something back */ if (hexFiendReceivePort == MACH_PORT_NULL) { if (ERR_FILE) fprintf(ERR_FILE, "recv_port() returned a null Mach port\n"); exit(EXIT_FAILURE); } /* Clean up */ if (msg) launch_data_free(msg); if (resp) launch_data_free(resp); return hexFiendReceivePort; }
CFTypeRef GTMCFTypeCreateFromLaunchData(launch_data_t ldata, bool convert_non_standard_objects, CFErrorRef *error) { CFTypeRef cf_type_ref = NULL; CFErrorRef local_error = NULL; if (ldata == NULL) { local_error = GTMCFLaunchCreateUnlocalizedError(EINVAL, CFSTR("NULL ldata")); goto exit; } launch_data_type_t ldata_type = launch_data_get_type(ldata); switch (ldata_type) { case LAUNCH_DATA_STRING: cf_type_ref = CFStringCreateWithCString(kCFAllocatorDefault, launch_data_get_string(ldata), kCFStringEncodingUTF8); break; case LAUNCH_DATA_INTEGER: { long long value = launch_data_get_integer(ldata); cf_type_ref = CFNumberCreate(kCFAllocatorDefault, kCFNumberLongLongType, &value); break; } case LAUNCH_DATA_REAL: { double value = launch_data_get_real(ldata); cf_type_ref = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value); break; } case LAUNCH_DATA_BOOL: { bool value = launch_data_get_bool(ldata); cf_type_ref = value ? kCFBooleanTrue : kCFBooleanFalse; CFRetain(cf_type_ref); break; } case LAUNCH_DATA_OPAQUE: { size_t size = launch_data_get_opaque_size(ldata); void *data = launch_data_get_opaque(ldata); cf_type_ref = CFDataCreate(kCFAllocatorDefault, data, size); break; } case LAUNCH_DATA_ARRAY: { size_t count = launch_data_array_get_count(ldata); cf_type_ref = CFArrayCreateMutable(kCFAllocatorDefault, count, &kCFTypeArrayCallBacks); if (cf_type_ref) { for (size_t i = 0; !local_error && i < count; i++) { launch_data_t l_sub_data = launch_data_array_get_index(ldata, i); CFTypeRef cf_sub_type = GTMCFTypeCreateFromLaunchData(l_sub_data, convert_non_standard_objects, &local_error); if (cf_sub_type) { CFArrayAppendValue((CFMutableArrayRef)cf_type_ref, cf_sub_type); CFRelease(cf_sub_type); } } } break; } case LAUNCH_DATA_DICTIONARY: cf_type_ref = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (cf_type_ref) { GTMLToCFDictContext context = { (CFMutableDictionaryRef)cf_type_ref, convert_non_standard_objects, &local_error }; launch_data_dict_iterate(ldata, GTMConvertLaunchDataDictEntryToCFDictEntry, &context); } break; case LAUNCH_DATA_FD: if (convert_non_standard_objects) { int file_descriptor = launch_data_get_fd(ldata); cf_type_ref = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &file_descriptor); } break; case LAUNCH_DATA_MACHPORT: if (convert_non_standard_objects) { mach_port_t port = launch_data_get_machport(ldata); cf_type_ref = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &port); } break; default: local_error = GTMCFLaunchCreateUnlocalizedError(EINVAL, CFSTR("Unknown launchd type %d"), ldata_type); break; } exit: if (error) { *error = local_error; } else if (local_error) { #ifdef DEBUG CFShow(local_error); #endif // DEBUG CFRelease(local_error); } return cf_type_ref; }