/*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2009 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
- *
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License"). You may not use this file except in compliance with the
- * License. Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
- *
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
- *
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
* @APPLE_LICENSE_HEADER_END@
*/
#include "configd_server.h"
#include "session.h"
+#include <bsm/libbsm.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+__private_extern__
int
__SCDynamicStoreOpen(SCDynamicStoreRef *store, CFStringRef name)
{
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreOpen:"));
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" name = %@"), name);
-
/*
* allocate and initialize a new session
*/
- *store = __SCDynamicStoreCreatePrivate(NULL, name, NULL, NULL);
+ *store = (SCDynamicStoreRef)__SCDynamicStoreCreatePrivate(NULL, name, NULL, NULL);
/*
* If necessary, initialize the store and session data dictionaries
*/
if (storeData == NULL) {
+ sessionData = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
storeData = CFDictionaryCreateMutable(NULL,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
- sessionData = CFDictionaryCreateMutable(NULL,
+ patternData = CFDictionaryCreateMutable(NULL,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
}
+static CFStringRef
+openMPCopyDescription(const void *info)
+{
+ return CFStringCreateWithFormat(NULL, NULL, CFSTR("<SCDynamicStore MP>"));
+}
+
+
+__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)
+ int *sc_status,
+ audit_token_t audit_token)
{
- kern_return_t status;
- serverSessionRef mySession, newSession;
- CFDataRef xmlName; /* name (XML serialized) */
- CFStringRef name; /* name (un-serialized) */
- CFStringRef xmlError;
- mach_port_t oldNotify;
- CFStringRef sessionKey;
- CFDictionaryRef info;
- CFMutableDictionaryRef newInfo;
- CFMachPortRef mp;
-
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Open new session."));
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server);
+ 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 */
- xmlName = CFDataCreate(NULL, nameRef, nameLen);
- status = vm_deallocate(mach_task_self(), (vm_address_t)nameRef, nameLen);
- if (status != KERN_SUCCESS) {
- CFRelease(xmlName);
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status));
- /* non-fatal???, proceed */
+ if (!_SCUnserializeString(&name, NULL, (void *)nameRef, nameLen)) {
+ *sc_status = kSCStatusFailed;
}
- name = CFPropertyListCreateFromXMLData(NULL,
- xmlName,
- kCFPropertyListImmutable,
- &xmlError);
- CFRelease(xmlName);
- if (!name) {
- if (xmlError) {
- SCLog(_configd_verbose, LOG_DEBUG,
- CFSTR("CFPropertyListCreateFromXMLData() name: %@"),
- xmlError);
- CFRelease(xmlError);
+
+ if ((optionsRef != NULL) && (optionsLen > 0)) {
+ /* un-serialize the [session] options */
+ if (!_SCUnserialize((CFPropertyListRef *)&options, NULL, (void *)optionsRef, optionsLen)) {
+ *sc_status = kSCStatusFailed;
}
- *sc_status = kSCStatusFailed;
- return KERN_SUCCESS;
- } else if (!isA_CFString(name)) {
- CFRelease(name);
+ }
+
+ if (*sc_status != kSCStatusOK) {
+ goto done;
+ }
+
+ if (!isA_CFString(name)) {
*sc_status = kSCStatusInvalidArgument;
- return KERN_SUCCESS;
+ 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;
+ }
+ }
}
mySession = getSession(server);
- if (mySession->store) {
- CFRelease(name);
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" Sorry, this session is already open."));
+ if ((mySession != NULL) && (mySession->store != 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 */
- return KERN_SUCCESS;
+ goto done;
}
- /* Create the server port for this session */
- mp = CFMachPortCreate(NULL, configdCallback, NULL, NULL);
-
- /* return the newly allocated port to be used for this session */
- *newServer = CFMachPortGetPort(mp);
-
/*
* establish the new session
*/
- newSession = addSession(mp);
+ mySession = addSession(MACH_PORT_NULL, openMPCopyDescription);
+ *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 */
- newSession->serverRunLoopSource = CFMachPortCreateRunLoopSource(NULL, mp, 0);
+ mySession->serverRunLoopSource = CFMachPortCreateRunLoopSource(NULL, mySession->serverPort, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(),
- newSession->serverRunLoopSource,
+ mySession->serverRunLoopSource,
kCFRunLoopDefaultMode);
- /*
- * save the credentials associated with the caller.
- */
- newSession->callerEUID = mySession->callerEUID;
- newSession->callerEGID = mySession->callerEGID;
+ if (_configd_trace) {
+ SCTrace(TRUE, _configd_trace,
+ CFSTR("open : %5d : %@\n"),
+ *newServer,
+ name);
+ }
- *sc_status = __SCDynamicStoreOpen(&newSession->store, 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
*/
- ((SCDynamicStorePrivateRef)newSession->store)->server = *newServer;
+ if (useSessionKeys != NULL) {
+ storePrivate->useSessionKeys = CFBooleanGetValue(useSessionKeys);
+ }
/* Request a notification when/if the client dies */
status = mach_port_request_notification(mach_task_self(),
MACH_MSG_TYPE_MAKE_SEND_ONCE,
&oldNotify);
if (status != KERN_SUCCESS) {
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status));
- CFRelease(name);
+ 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;
- return KERN_SUCCESS;
+ goto done;
}
+ __MACH_PORT_DEBUG(TRUE, "*** _configopen (after mach_port_request_notification)", *newServer);
if (oldNotify != MACH_PORT_NULL) {
- SCLog(_configd_verbose, LOG_ERR, CFSTR("_configopen(): why is oldNotify != MACH_PORT_NULL?"));
+ SCLog(TRUE, LOG_ERR, CFSTR("_configopen(): oldNotify != MACH_PORT_NULL"));
}
/*
*/
sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), *newServer);
info = CFDictionaryGetValue(sessionData, sessionKey);
- if (info) {
+ if (info != NULL) {
newInfo = CFDictionaryCreateMutableCopy(NULL, 0, info);
} else {
newInfo = CFDictionaryCreateMutable(NULL,
&kCFTypeDictionaryValueCallBacks);
}
CFDictionarySetValue(newInfo, kSCDName, name);
- CFRelease(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;
}