int ppp_mach_start_server() { kern_return_t status; CFRunLoopSourceRef rls; mach_port_t our_port = MACH_PORT_NULL; CFMachPortContext context = { 0, (void *)1, NULL, NULL, serverMPCopyDescription }; status = bootstrap_check_in(bootstrap_port, PPPCONTROLLER_SERVER, &our_port); if (status != BOOTSTRAP_SUCCESS) { SCLog(TRUE, LOG_ERR, CFSTR("PPPController: bootstrap_check_in \"%s\" error = %s"), PPPCONTROLLER_SERVER, bootstrap_strerror(status)); return -1; } gServer_cfport = _SC_CFMachPortCreateWithPort("PPPController", our_port, server_handle_request, &context); if (!gServer_cfport) { SCLog(TRUE, LOG_ERR, CFSTR("PPPController: cannot create mach port")); return -1; } rls = CFMachPortCreateRunLoopSource(0, gServer_cfport, 0); if (!rls) { SCLog(TRUE, LOG_ERR, CFSTR("PPPController: cannot create rls")); CFRelease(gServer_cfport); gServer_cfport = NULL; return -1; } gControllerRunloop = CFRunLoopGetCurrent(); CFRunLoopAddSource(gControllerRunloop, rls, kCFRunLoopDefaultMode); CFRunLoopAddSource(gControllerRunloop, gTerminalrls, kCFRunLoopDefaultMode); CFRelease(rls); return 0; }
static void rlsSchedule(void *info, CFRunLoopRef rl, CFStringRef mode) { SCDynamicStoreRef store = (SCDynamicStoreRef)info; SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; #ifdef DEBUG SCLog(_sc_verbose, LOG_DEBUG, CFSTR("schedule notifications for mode %@"), (rl != NULL) ? mode : CFSTR("libdispatch")); #endif /* DEBUG */ if (storePrivate->rlList == NULL) { CFMachPortContext context = { 0 , (void *)store , CFRetain , CFRelease , notifyMPCopyDescription }; mach_port_t oldNotify; mach_port_t port; int sc_status; kern_return_t status; #ifdef DEBUG SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" activate callback runloop source")); #endif /* DEBUG */ /* Allocating port (for server response) */ status = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port); if (status != KERN_SUCCESS) { SCLog(TRUE, LOG_ERR, CFSTR("rlsSchedule mach_port_allocate(): %s"), mach_error_string(status)); return; } status = mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND); if (status != KERN_SUCCESS) { /* * We can't insert a send right into our own port! This should * only happen if someone stomped on OUR port (so let's leave * the port alone). */ SCLog(TRUE, LOG_ERR, CFSTR("rlsSchedule mach_port_insert_right(): %s"), mach_error_string(status)); return; } /* Request a notification when/if the server dies */ status = mach_port_request_notification(mach_task_self(), port, MACH_NOTIFY_NO_SENDERS, 1, port, MACH_MSG_TYPE_MAKE_SEND_ONCE, &oldNotify); if (status != KERN_SUCCESS) { /* * We can't request a notification for our own port! This should * only happen if someone stomped on OUR port (so let's leave * the port alone). */ SCLog(TRUE, LOG_ERR, CFSTR("rlsSchedule mach_port_request_notification(): %s"), mach_error_string(status)); return; } if (oldNotify != MACH_PORT_NULL) { SCLog(TRUE, LOG_ERR, CFSTR("rlsSchedule(): oldNotify != MACH_PORT_NULL")); } retry : __MACH_PORT_DEBUG(TRUE, "*** rlsSchedule", port); status = notifyviaport(storePrivate->server, port, 0, (int *)&sc_status); if (__SCDynamicStoreCheckRetryAndHandleError(store, status, &sc_status, "rlsSchedule notifyviaport()")) { goto retry; } if (status != KERN_SUCCESS) { if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) { /* remove the send right that we tried (but failed) to pass to the server */ (void) mach_port_deallocate(mach_task_self(), port); } /* remove our receive right */ (void) mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_RECEIVE, -1); return; } if (sc_status != kSCStatusOK) { /* something [else] didn't work, remove our receive right */ (void) mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_RECEIVE, -1); return; } __MACH_PORT_DEBUG(TRUE, "*** rlsSchedule (after notifyviaport)", port); storePrivate->rlsNotifyPort = _SC_CFMachPortCreateWithPort("SCDynamicStore", port, rlsCallback, &context); storePrivate->rlsNotifyRLS = CFMachPortCreateRunLoopSource(NULL, storePrivate->rlsNotifyPort, 0); storePrivate->rlList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); } if ((rl != NULL) && (storePrivate->rlsNotifyRLS != NULL)) { if (!_SC_isScheduled(store, rl, mode, storePrivate->rlList)) { /* * if we are not already scheduled with this runLoop / runLoopMode */ CFRunLoopAddSource(rl, storePrivate->rlsNotifyRLS, mode); __MACH_PORT_DEBUG(TRUE, "*** rlsSchedule (after CFRunLoopAddSource)", CFMachPortGetPort(storePrivate->rlsNotifyPort)); } _SC_schedule(store, rl, mode, storePrivate->rlList); } return; }
/* ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- */ __private_extern__ kern_return_t _pppcontroller_attach_proxy(mach_port_t server, xmlData_t nameRef, /* raw XML bytes */ mach_msg_type_number_t nameLen, mach_port_t bootstrap, mach_port_t notify, mach_port_t au_session, int uid, int gid, int pid, mach_port_t *session, int * result, audit_token_t audit_token) { CFStringRef serviceID = NULL; CFMachPortRef port = NULL; CFRunLoopSourceRef rls = NULL; struct client *client = NULL; mach_port_t oldport; uid_t audit_euid = -1; gid_t audit_egid = -1; pid_t audit_pid = -1; *session = MACH_PORT_NULL; /* un-serialize the serviceID */ if (!_SCUnserializeString(&serviceID, NULL, (void *)nameRef, nameLen)) { *result = kSCStatusFailed; goto failed; } if (!isA_CFString(serviceID)) { *result = kSCStatusInvalidArgument; goto failed; } /* only allow "root" callers to change the client uid/gid/pid */ audit_token_to_au32(audit_token, NULL, // auidp &audit_euid, // euid &audit_egid, // egid NULL, // ruid NULL, // rgid &audit_pid, // pid NULL, // asid NULL); // tid if ((audit_euid != 0) && ((uid != audit_euid) || (gid != audit_egid) || (pid != audit_pid))) { /* * the caller is NOT "root" and is trying to masquerade * as some other user/process. */ /* does caller has the right entitlement */ if (!(hasEntitlement(audit_token, kSCVPNConnectionEntitlementName, NULL))){ *result = kSCStatusAccessError; goto failed; } } //if ((findbyserviceID(serviceID)) == 0) { // *result = kSCStatusInvalidArgument; // goto failed; //} /* allocate session port */ (void) mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, session); /* * Note: we create the CFMachPort *before* we insert a send * right present to ensure that CF does not establish * it's dead name notification. */ port = _SC_CFMachPortCreateWithPort("PPPController/PPP", *session, server_handle_request, NULL); /* insert send right that will be moved to the client */ (void) mach_port_insert_right(mach_task_self(), *session, *session, MACH_MSG_TYPE_MAKE_SEND); /* Request a notification when/if the client dies */ (void) mach_port_request_notification(mach_task_self(), *session, MACH_NOTIFY_NO_SENDERS, 1, *session, MACH_MSG_TYPE_MAKE_SEND_ONCE, &oldport); /* add to runloop */ rls = CFMachPortCreateRunLoopSource(NULL, port, 0); CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); if (au_session != MACH_PORT_NULL) { if ((audit_session_join(au_session)) == AU_DEFAUDITSID) { SCLog(TRUE, LOG_ERR, CFSTR("_pppcontroller_attach audit_session_join fails")); } }else { SCLog(TRUE, LOG_ERR, CFSTR("_pppcontroller_attach au_session == NULL")); } client = client_new_mach(port, rls, serviceID, uid, gid, pid, bootstrap, notify, au_session); if (client == 0) { *result = kSCStatusFailed; goto failed; } *result = kSCStatusOK; my_CFRelease(&serviceID); my_CFRelease(&port); my_CFRelease(&rls); return KERN_SUCCESS; failed: my_CFRelease(&serviceID); if (port) { CFMachPortInvalidate(port); my_CFRelease(&port); } if (rls) { CFRunLoopRemoveSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); my_CFRelease(&rls); } if (*session != MACH_PORT_NULL) { mach_port_mod_refs(mach_task_self(), *session, MACH_PORT_RIGHT_SEND , -1); mach_port_mod_refs(mach_task_self(), *session, MACH_PORT_RIGHT_RECEIVE, -1); *session = MACH_PORT_NULL; } if (client) { client_dispose(client); } else { if (bootstrap != MACH_PORT_NULL) mach_port_deallocate(mach_task_self(), bootstrap); if (notify != MACH_PORT_NULL) mach_port_deallocate(mach_task_self(), notify); } return KERN_SUCCESS; }