]> git.saurik.com Git - apple/configd.git/blobdiff - configd.tproj/_configopen.c
configd-293.8.tar.gz
[apple/configd.git] / configd.tproj / _configopen.c
index f462ee9cd90ba23b678e1edd45c76d20b549f88b..5f70aeb5338c17b6751e544c984670c0299e8eb5 100644 (file)
@@ -1,22 +1,23 @@
 /*
- * 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);
@@ -72,92 +79,123 @@ __SCDynamicStoreOpen(SCDynamicStoreRef *store, CFStringRef name)
 }
 
 
+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(),
@@ -168,16 +206,16 @@ _configopen(mach_port_t                   server,
                                                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"));
        }
 
        /*
@@ -185,7 +223,7 @@ _configopen(mach_port_t                     server,
         */
        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,
@@ -194,10 +232,19 @@ _configopen(mach_port_t                   server,
                                                    &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;
 }