__private_extern__ kern_return_t _configremove(mach_port_t server, xmlData_t keyRef, /* raw XML bytes */ mach_msg_type_number_t keyLen, int *sc_status, audit_token_t audit_token) { CFStringRef key = NULL; /* key (un-serialized) */ serverSessionRef mySession; /* un-serialize the key */ if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) { *sc_status = kSCStatusFailed; goto done; } if (!isA_CFString(key)) { *sc_status = kSCStatusInvalidArgument; goto done; } mySession = getSession(server); if (mySession == NULL) { mySession = tempSession(server, CFSTR("SCDynamicStoreRemoveValue"), audit_token); if (mySession == NULL) { /* you must have an open session to play */ *sc_status = kSCStatusNoStoreSession; goto done; } } if (!hasWriteAccess(mySession, key)) { *sc_status = kSCStatusAccessError; goto done; } *sc_status = __SCDynamicStoreRemoveValue(mySession->store, key, FALSE); done : if (key) CFRelease(key); return KERN_SUCCESS; }
__private_extern__ kern_return_t _notifyremove(mach_port_t server, xmlData_t keyRef, /* raw XML bytes */ mach_msg_type_number_t keyLen, int isRegex, int *sc_status ) { CFStringRef key = NULL; /* key (un-serialized) */ serverSessionRef mySession; /* un-serialize the key */ if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) { *sc_status = kSCStatusFailed; goto done; } if (!isA_CFString(key)) { *sc_status = kSCStatusInvalidArgument; goto done; } mySession = getSession(server); if (mySession == NULL) { *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */ goto done; } *sc_status = __SCDynamicStoreRemoveWatchedKey(mySession->store, key, isRegex != 0, FALSE); done : if (key) CFRelease(key); return KERN_SUCCESS; }
__private_extern__ kern_return_t _configopen(mach_port_t server, xmlData_t nameRef, /* raw XML bytes */ mach_msg_type_number_t nameLen, xmlData_t optionsRef, /* raw XML bytes */ mach_msg_type_number_t optionsLen, mach_port_t *newServer, int *sc_status, audit_token_t audit_token) { CFDictionaryRef info; serverSessionRef mySession; CFStringRef name = NULL; /* name (un-serialized) */ CFMutableDictionaryRef newInfo; mach_port_t oldNotify; CFDictionaryRef options = NULL; /* options (un-serialized) */ CFStringRef sessionKey; kern_return_t status; SCDynamicStorePrivateRef storePrivate; CFBooleanRef useSessionKeys = NULL; *sc_status = kSCStatusOK; /* un-serialize the name */ if (!_SCUnserializeString(&name, NULL, (void *)nameRef, nameLen)) { *sc_status = kSCStatusFailed; } if ((optionsRef != NULL) && (optionsLen > 0)) { /* un-serialize the [session] options */ if (!_SCUnserialize((CFPropertyListRef *)&options, NULL, (void *)optionsRef, optionsLen)) { *sc_status = kSCStatusFailed; } } if (*sc_status != kSCStatusOK) { goto done; } if (!isA_CFString(name)) { *sc_status = kSCStatusInvalidArgument; goto done; } if (options != NULL) { if (!isA_CFDictionary(options)) { *sc_status = kSCStatusInvalidArgument; goto done; } /* * [pre-]process any provided options */ useSessionKeys = CFDictionaryGetValue(options, kSCDynamicStoreUseSessionKeys); if (useSessionKeys != NULL) { if (!isA_CFBoolean(useSessionKeys)) { *sc_status = kSCStatusInvalidArgument; goto done; } } } /* * establish the new session */ mySession = addSession(server, openMPCopyDescription); if (mySession == NULL) { #ifdef DEBUG SCLog(TRUE, LOG_DEBUG, CFSTR("_configopen(): session is already open.")); #endif /* DEBUG */ *sc_status = kSCStatusFailed; /* you can't re-open an "open" session */ goto done; } *newServer = mySession->key; __MACH_PORT_DEBUG(TRUE, "*** _configopen (after addSession)", *newServer); /* save the audit_token in case we need to check the callers credentials */ mySession->auditToken = audit_token; /* Create and add a run loop source for the port */ mySession->serverRunLoopSource = CFMachPortCreateRunLoopSource(NULL, mySession->serverPort, 0); CFRunLoopAddSource(CFRunLoopGetCurrent(), mySession->serverRunLoopSource, kCFRunLoopDefaultMode); if (_configd_trace) { SCTrace(TRUE, _configd_trace, CFSTR("open : %5d : %@\n"), *newServer, name); } *sc_status = __SCDynamicStoreOpen(&mySession->store, name); storePrivate = (SCDynamicStorePrivateRef)mySession->store; /* * Make the server port accessible to the framework routines. * ... and be sure to clear before calling CFRelease(store) */ storePrivate->server = *newServer; /* * Process any provided [session] options */ if (useSessionKeys != NULL) { storePrivate->useSessionKeys = CFBooleanGetValue(useSessionKeys); } /* Request a notification when/if the client dies */ status = mach_port_request_notification(mach_task_self(), *newServer, MACH_NOTIFY_NO_SENDERS, 1, *newServer, MACH_MSG_TYPE_MAKE_SEND_ONCE, &oldNotify); if (status != KERN_SUCCESS) { SCLog(TRUE, LOG_ERR, CFSTR("_configopen() mach_port_request_notification() failed: %s"), mach_error_string(status)); cleanupSession(*newServer); *newServer = MACH_PORT_NULL; *sc_status = kSCStatusFailed; goto done; } __MACH_PORT_DEBUG(TRUE, "*** _configopen (after mach_port_request_notification)", *newServer); if (oldNotify != MACH_PORT_NULL) { SCLog(TRUE, LOG_ERR, CFSTR("_configopen(): oldNotify != MACH_PORT_NULL")); } /* * Save the name of the calling application / plug-in with the session data. */ sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), *newServer); info = CFDictionaryGetValue(sessionData, sessionKey); if (info != NULL) { newInfo = CFDictionaryCreateMutableCopy(NULL, 0, info); } else { newInfo = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } CFDictionarySetValue(newInfo, kSCDName, name); CFDictionarySetValue(sessionData, sessionKey, newInfo); CFRelease(newInfo); CFRelease(sessionKey); /* * Note: at this time we should be holding ONE send right and * ONE receive right to the server. The send right is * moved to the caller. */ done : if (name != NULL) CFRelease(name); if (options != NULL) CFRelease(options); return KERN_SUCCESS; }
/* ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- */ __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; }