STATIC void __IPMonitorControlDeallocate(CFTypeRef cf) { IPMonitorControlRef control = (IPMonitorControlRef)cf; if (control->connection != NULL) { xpc_release(control->connection); } if (control->queue != NULL) { xpc_release(control->queue); } return; }
static void __XPC_Peer_Event_Handler(xpc_connection_t connection, xpc_object_t event) { syslog(LOG_NOTICE, "Received event in helper."); xpc_type_t type = xpc_get_type(event); if (type == XPC_TYPE_ERROR) { if (event == XPC_ERROR_CONNECTION_INVALID) { // The client process on the other end of the connection has either // crashed or cancelled the connection. After receiving this error, // the connection is in an invalid state, and you do not need to // call xpc_connection_cancel(). Just tear down any associated state // here. } else if (event == XPC_ERROR_TERMINATION_IMMINENT) { // Handle per-connection termination cleanup. } } else { xpc_object_t requestMessage = event; xpc_object_t replyMessage = xpc_dictionary_create_reply(requestMessage); // Process request and build a reply message. __XPC_Fetch_Process_Request(requestMessage, replyMessage); xpc_connection_send_message(connection, replyMessage); xpc_release(replyMessage); } }
void Connection::platformInvalidate() { if (!m_isConnected) return; m_isConnected = false; ASSERT(m_sendPort); ASSERT(m_receivePort); // Unregister our ports. m_connectionQueue.unregisterMachPortEventHandler(m_sendPort); m_sendPort = MACH_PORT_NULL; m_connectionQueue.unregisterMachPortEventHandler(m_receivePort); m_receivePort = MACH_PORT_NULL; if (m_exceptionPort) { m_connectionQueue.unregisterMachPortEventHandler(m_exceptionPort); m_exceptionPort = MACH_PORT_NULL; } #if HAVE(XPC) if (m_xpcConnection) { xpc_release(m_xpcConnection); m_xpcConnection = 0; } #endif }
void DNSXRefDeAlloc(DNSXConnRef connRef) { if (connRef == NULL) { os_log(OS_LOG_DEFAULT, "dns_services: DNSXRefDeAlloc called with NULL DNSXConnRef"); return; } // Schedule this work on the internal library queue dispatch_sync(connRef->lib_q, ^{ xpc_connection_set_event_handler((connRef)->conn_ref, ^(__unused xpc_object_t event){}); // ignore any more events xpc_release(connRef->conn_ref); connRef->conn_ref = NULL; dispatch_release(connRef->lib_q); connRef->lib_q = NULL; connRef->AppCallBack = NULL; os_log_info(OS_LOG_DEFAULT, "dns_services: DNSXRefDeAlloc successfully DeAllocated conn_ref & lib_q"); dispatch_async((connRef)->client_q, ^{ dispatch_release(connRef->client_q); connRef->client_q = NULL; free(connRef); os_log_info(OS_LOG_DEFAULT, "dns_services: DNSXRefDeAlloc successfully DeAllocated client_q & freed connRef"); }); });
static void xpcEventHandler(xpc_connection_t connection, xpc_object_t event) { syslog(LOG_NOTICE, "received event in helper"); xpc_type_t type = xpc_get_type(event); if (type == XPC_TYPE_ERROR) { if (event == XPC_ERROR_CONNECTION_INVALID) { // the client process on the other end of the connection has either // crashed or cancelled the connection. After receiving this error, // the connection is in an invalid state, and you do not need to // call xpc_connection_cancel(). Just tear down any associated state // here. } else if (event == XPC_ERROR_TERMINATION_IMMINENT) { // handle per-connection termination cleanup. } } else { xpc_connection_t remote = xpc_dictionary_get_remote_connection(event); const char* command = xpc_dictionary_get_string(event, "request"); syslog(LOG_NOTICE, "received command in helper: %s", command); system(command); xpc_object_t reply = xpc_dictionary_create_reply(event); xpc_dictionary_set_string(reply, "reply", "command has been executed"); xpc_connection_send_message(remote, reply); xpc_release(reply); } }
__attribute__((noreturn)) static void xpc_server_exit(int status) { xpc_connection_cancel(listener); xpc_release(listener); dispatch_release(serverq); exit(status); }
static void security_auth_event_handler(xpc_connection_t xpc_conn) { connection_t conn = server_register_connection(xpc_conn); if (conn) { xpc_connection_set_context(xpc_conn, conn); xpc_connection_set_finalizer_f(xpc_conn, connection_finalizer); xpc_connection_set_event_handler(xpc_conn, ^(xpc_object_t event) { xpc_retain(xpc_conn); xpc_retain(event); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ security_auth_peer_event_handler(xpc_conn, event); xpc_release(event); xpc_release(xpc_conn); }); });
// // Your standard server-side xpc main // int main (int argc, char * const argv[]) { const char *name = serviceName; if (const char *s = getenv("SYSPOLICYNAME")) name = s; // extern char *optarg; extern int optind; int arg; while ((arg = getopt(argc, argv, "v")) != -1) switch (arg) { case 'v': break; case '?': usage(); } if (optind < argc) usage(); dispatch_queue_t queue = dispatch_queue_create("server", 0); xpc_connection_t service = xpc_connection_create_mach_service(name, queue, XPC_CONNECTION_MACH_SERVICE_LISTENER /* | XPC_CONNECTION_MACH_SERVICE_PRIVILEGED */); xpc_connection_set_event_handler(service, ^(xpc_object_t cmsg) { if (xpc_get_type(cmsg) == XPC_TYPE_CONNECTION) { xpc_connection_t connection = xpc_connection_t(cmsg); syslog(LOG_DEBUG, "Connection from pid %d", xpc_connection_get_pid(connection)); xpc_connection_set_event_handler(connection, ^(xpc_object_t msg) { if (xpc_get_type(msg) == XPC_TYPE_DICTIONARY) { const char *function = xpc_dictionary_get_string(msg, "function"); syslog(LOG_DEBUG, "pid %d requested %s", xpc_connection_get_pid(connection), function); xpc_object_t reply = xpc_dictionary_create_reply(msg); try { if (function == NULL) { xpc_dictionary_set_int64(reply, "error", errSecCSInternalError); } else if (!strcmp(function, "assess")) { doAssess(msg, reply); } else if (!strcmp(function, "update")) { doUpdate(msg, reply); } else if (!strcmp(function, "record")) { doRecord(msg, reply, connection); } else { xpc_dictionary_set_int64(reply, "error", errSecCSInternalError); } } catch (...) { xpc_dictionary_set_int64(reply, "error", errSecCSInternalError); } xpc_connection_send_message(connection, reply); xpc_release(reply); } }); xpc_connection_resume(connection); } else {
void send() { xpc_object_t reply = xpc_connection_send_message_with_reply_sync(service, obj); xpc_release(obj); obj = NULL; xpc_type_t type = xpc_get_type(reply); if (type == XPC_TYPE_DICTIONARY) { obj = reply; if (int64_t error = xpc_dictionary_get_int64(obj, "error")) MacOSError::throwMe(error); } else if (type == XPC_TYPE_ERROR) { const char *s = xpc_copy_description(reply); printf("Error returned: %s\n", s); free((char*)s); MacOSError::throwMe(errSecCSInternalError); } else { const char *s = xpc_copy_description(reply); printf("Unexpected type of return object: %s\n", s); free((char*)s); } }
void ProcessLauncher::didFinishLaunchingProcess(PlatformProcessIdentifier processIdentifier, CoreIPC::Connection::Identifier identifier) { m_processIdentifier = processIdentifier; m_isLaunching = false; if (!m_client) { // FIXME: Make Identifier a move-only object and release port rights/connections in the destructor. #if PLATFORM(MAC) if (identifier.port) mach_port_mod_refs(mach_task_self(), identifier.port, MACH_PORT_RIGHT_RECEIVE, -1); #if HAVE(XPC) if (identifier.xpcConnection) { xpc_release(identifier.xpcConnection); identifier.xpcConnection = 0; } #endif #endif return; } m_client->didFinishLaunching(this, identifier); }
/***************************************************************************** * HandleTemporaryEventsForService * - * This method handles the firing of one shot events. Aka. Events that are * signaled when a service appears / disappears. They have a temporarly * signaled state. *****************************************************************************/ void HandleTemporaryEventsForService(BonjourUserEventsPlugin* plugin, NetBrowserInfo* browser, CFStringRef serviceName, CFMutableDictionaryRef eventsDictionary) { CFArrayRef events = (CFArrayRef)CFDictionaryGetValue(eventsDictionary, browser); // Get events for the browser we passed in. CFIndex i; CFIndex count; if (!events) // Somehow we have a orphan browser... return; count = CFArrayGetCount(events); // Go thru the events and run filters, notifity if they pass. for (i = 0; i < count; ++i) { CFDictionaryRef eventDict = (CFDictionaryRef)CFArrayGetValueAtIndex(events, i); CFStringRef eventServiceName = (CFStringRef)CFDictionaryGetValue(eventDict, sServiceNameKey); CFNumberRef token = (CFNumberRef) CFDictionaryGetValue(eventDict, sLaunchdTokenKey); CFDictionaryRef dict = (CFDictionaryRef) CFDictionaryGetValue(eventDict, sLaunchdDictKey); // Currently we only filter on service name, that makes this as simple as... if (!eventServiceName || CFEqual(serviceName, eventServiceName)) { uint64_t tokenUint64; // Signal Event: This is edge trigger. When the action has been taken, it will not // be remembered anymore. asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s HandleTemporaryEventsForService signal\n", sPluginIdentifier, __FUNCTION__); CFNumberGetValue(token, kCFNumberLongLongType, &tokenUint64); xpc_object_t jobRequest = _CFXPCCreateXPCObjectFromCFObject(dict); UserEventAgentFireEvent(plugin->_pluginContext, tokenUint64, jobRequest); xpc_release(jobRequest); } } }
~Message() { if (obj) xpc_release(obj); }
static void security_auth_peer_event_handler(xpc_connection_t connection, xpc_object_t event) { __block OSStatus status = errAuthorizationDenied; connection_t conn = (connection_t)xpc_connection_get_context(connection); require_action(conn != NULL, done, LOGE("xpc[%i]: process context not found", xpc_connection_get_pid(connection))); CFRetainSafe(conn); xpc_type_t type = xpc_get_type(event); if (type == XPC_TYPE_ERROR) { if (event == XPC_ERROR_CONNECTION_INVALID) { // The client process on the other end of the connection has either // crashed or cancelled the connection. After receiving this error, // the connection is in an invalid state, and you do not need to // call xpc_connection_cancel(). Just tear down any associated state // here. LOGV("xpc[%i]: client disconnected", xpc_connection_get_pid(connection)); connection_destory_agents(conn); } else if (event == XPC_ERROR_TERMINATION_IMMINENT) { // Handle per-connection termination cleanup. LOGD("xpc[%i]: per-connection termination", xpc_connection_get_pid(connection)); } } else { assert(type == XPC_TYPE_DICTIONARY); xpc_object_t reply = xpc_dictionary_create_reply(event); require(reply != NULL, done); uint64_t auth_type = xpc_dictionary_get_uint64(event, AUTH_XPC_TYPE); LOGV("xpc[%i]: received message type=%llu", connection_get_pid(conn), auth_type); switch (auth_type) { case AUTHORIZATION_CREATE: status = authorization_create(conn,event,reply); break; case AUTHORIZATION_CREATE_WITH_AUDIT_TOKEN: status = authorization_create_with_audit_token(conn,event,reply); break; case AUTHORIZATION_FREE: status = authorization_free(conn,event,reply); break; case AUTHORIZATION_COPY_RIGHTS: status = authorization_copy_rights(conn,event,reply); break; case AUTHORIZATION_COPY_INFO: status = authorization_copy_info(conn,event,reply); break; case AUTHORIZATION_MAKE_EXTERNAL_FORM: status = authorization_make_external_form(conn,event,reply); break; case AUTHORIZATION_CREATE_FROM_EXTERNAL_FORM: status = authorization_create_from_external_form(conn,event,reply); break; case AUTHORIZATION_RIGHT_GET: status = authorization_right_get(conn,event,reply); break; case AUTHORIZATION_RIGHT_SET: status = authorization_right_set(conn,event,reply); break; case AUTHORIZATION_RIGHT_REMOVE: status = authorization_right_remove(conn,event,reply); break; case SESSION_SET_USER_PREFERENCES: status = session_set_user_preferences(conn,event,reply); break; case AUTHORIZATION_DISMISS: connection_destory_agents(conn); status = errAuthorizationSuccess; break; case AUTHORIZATION_ENABLE_SMARTCARD: status = authorization_enable_smartcard(conn,event,reply); break; case AUTHORIZATION_SETUP: { mach_port_t bootstrap = xpc_dictionary_copy_mach_send(event, AUTH_XPC_BOOTSTRAP); if (!process_set_bootstrap(connection_get_process(conn), bootstrap)) { if (bootstrap != MACH_PORT_NULL) { mach_port_deallocate(mach_task_self(), bootstrap); } } } status = errAuthorizationSuccess; break; #if DEBUG case AUTHORIZATION_DEV: server_dev(); break; #endif default: break; } xpc_dictionary_set_int64(reply, AUTH_XPC_STATUS, status); xpc_connection_send_message(connection, reply); xpc_release(reply); } done: CFReleaseSafe(conn); }