2  * Copyright (c) 2000-2009, 2011, 2015-2017 Apple Inc. All rights reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. Please obtain a copy of the License at 
  10  * http://www.opensource.apple.com/apsl/ and read it before using this 
  13  * The Original Code and all software distributed under the License are 
  14  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  15  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  16  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  17  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  18  * Please see the License for the specific language governing rights and 
  19  * limitations under the License. 
  21  * @APPLE_LICENSE_HEADER_END@ 
  25  * Modification History 
  27  * June 1, 2001                 Allan Nathanson <ajn@apple.com> 
  28  * - public API conversion 
  30  * March 24, 2000               Allan Nathanson <ajn@apple.com> 
  35 #include "configd_server.h" 
  38 #include <bsm/libbsm.h> 
  39 #include <sys/types.h> 
  44 __SCDynamicStoreOpen(SCDynamicStoreRef 
*store
, CFStringRef name
) 
  47          * allocate and initialize a new session 
  49         *store 
= (SCDynamicStoreRef
)__SCDynamicStoreCreatePrivate(NULL
, name
, NULL
, NULL
); 
  52          * If necessary, initialize the store and session data dictionaries 
  54         if (storeData 
== NULL
) { 
  55                 sessionData        
= CFDictionaryCreateMutable(NULL
, 
  57                                                                &kCFTypeDictionaryKeyCallBacks
, 
  58                                                                &kCFTypeDictionaryValueCallBacks
); 
  59                 storeData          
= CFDictionaryCreateMutable(NULL
, 
  61                                                                &kCFTypeDictionaryKeyCallBacks
, 
  62                                                                &kCFTypeDictionaryValueCallBacks
); 
  63                 patternData        
= CFDictionaryCreateMutable(NULL
, 
  65                                                                &kCFTypeDictionaryKeyCallBacks
, 
  66                                                                &kCFTypeDictionaryValueCallBacks
); 
  67                 changedKeys        
= CFSetCreateMutable(NULL
, 
  69                                                         &kCFTypeSetCallBacks
); 
  70                 deferredRemovals   
= CFSetCreateMutable(NULL
, 
  72                                                         &kCFTypeSetCallBacks
); 
  73                 removedSessionKeys 
= CFSetCreateMutable(NULL
, 
  75                                                         &kCFTypeSetCallBacks
); 
  83 openMPCopyDescription(const void *info
) 
  86         return CFStringCreateWithFormat(NULL
, NULL
, CFSTR("<SCDynamicStore MP>")); 
  92 _configopen(mach_port_t                 server
, 
  93             xmlData_t                   nameRef
,                /* raw XML bytes */ 
  94             mach_msg_type_number_t      nameLen
, 
  95             xmlData_t                   optionsRef
,             /* raw XML bytes */ 
  96             mach_msg_type_number_t      optionsLen
, 
  97             mach_port_t                 
*newServer
, 
  99             audit_token_t               audit_token
) 
 101         CFDictionaryRef                 info
; 
 102         serverSessionRef                mySession
; 
 103         CFStringRef                     name            
= NULL
; /* name (un-serialized) */ 
 104         CFMutableDictionaryRef          newInfo
; 
 105         mach_port_t                     oldNotify
; 
 106         CFDictionaryRef                 options         
= NULL
; /* options (un-serialized) */ 
 107         CFStringRef                     sessionKey
; 
 108         kern_return_t                   status
; 
 109         SCDynamicStorePrivateRef        storePrivate
; 
 110         CFBooleanRef                    useSessionKeys  
= NULL
; 
 112         *sc_status 
= kSCStatusOK
; 
 114         /* un-serialize the name */ 
 115         if (!_SCUnserializeString(&name
, NULL
, (void *)nameRef
, nameLen
)) { 
 116                 *sc_status 
= kSCStatusFailed
; 
 119         if ((optionsRef 
!= NULL
) && (optionsLen 
> 0)) { 
 120                 /* un-serialize the [session] options */ 
 121                 if (!_SCUnserialize((CFPropertyListRef 
*)&options
, NULL
, (void *)optionsRef
, optionsLen
)) { 
 122                         *sc_status 
= kSCStatusFailed
; 
 126         if (*sc_status 
!= kSCStatusOK
) { 
 130         if (!isA_CFString(name
)) { 
 131                 *sc_status 
= kSCStatusInvalidArgument
; 
 135         if (options 
!= NULL
) { 
 136                 if (!isA_CFDictionary(options
)) { 
 137                         *sc_status 
= kSCStatusInvalidArgument
; 
 142                  * [pre-]process any provided options 
 144                 useSessionKeys 
= CFDictionaryGetValue(options
, kSCDynamicStoreUseSessionKeys
); 
 145                 if (useSessionKeys 
!= NULL
) { 
 146                         if (!isA_CFBoolean(useSessionKeys
)) { 
 147                                 *sc_status 
= kSCStatusInvalidArgument
; 
 154          * establish the new session 
 156         mySession 
= addSession(server
, openMPCopyDescription
); 
 157         if (mySession 
== NULL
) { 
 158                 SC_log(LOG_NOTICE
, "session is already open"); 
 159                 *sc_status 
= kSCStatusFailed
;   /* you can't re-open an "open" session */ 
 163         *newServer 
= mySession
->key
; 
 164         __MACH_PORT_DEBUG(TRUE
, "*** _configopen (after addSession)", *newServer
); 
 166         /* save the audit_token in case we need to check the callers credentials */ 
 167         mySession
->auditToken 
= audit_token
; 
 169         /* Create and add a run loop source for the port */ 
 170         mySession
->serverRunLoopSource 
= CFMachPortCreateRunLoopSource(NULL
, mySession
->serverPort
, 0); 
 171         CFRunLoopAddSource(CFRunLoopGetCurrent(), 
 172                            mySession
->serverRunLoopSource
, 
 173                            kCFRunLoopDefaultMode
); 
 175         SC_trace("open    : %5d : %@", 
 179         *sc_status 
= __SCDynamicStoreOpen(&mySession
->store
, name
); 
 180         storePrivate 
= (SCDynamicStorePrivateRef
)mySession
->store
; 
 183          * Make the server port accessible to the framework routines. 
 184          * ... and be sure to clear before calling CFRelease(store) 
 186         storePrivate
->server 
= *newServer
; 
 189          * Process any provided [session] options 
 191         if (useSessionKeys 
!= NULL
) { 
 192                 storePrivate
->useSessionKeys 
= CFBooleanGetValue(useSessionKeys
); 
 195         /* Request a notification when/if the client dies */ 
 196         status 
= mach_port_request_notification(mach_task_self(), 
 198                                                 MACH_NOTIFY_NO_SENDERS
, 
 201                                                 MACH_MSG_TYPE_MAKE_SEND_ONCE
, 
 203         if (status 
!= KERN_SUCCESS
) { 
 204                 SC_log(LOG_NOTICE
, "mach_port_request_notification() failed: %s", mach_error_string(status
)); 
 205                 cleanupSession(*newServer
); 
 206                 *newServer 
= MACH_PORT_NULL
; 
 207                 *sc_status 
= kSCStatusFailed
; 
 210         __MACH_PORT_DEBUG(TRUE
, "*** _configopen (after mach_port_request_notification)", *newServer
); 
 212         if (oldNotify 
!= MACH_PORT_NULL
) { 
 213                 SC_log(LOG_NOTICE
, "oldNotify != MACH_PORT_NULL"); 
 217          * Save the name of the calling application / plug-in with the session data. 
 219         sessionKey 
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%d"), *newServer
); 
 220         info 
= CFDictionaryGetValue(sessionData
, sessionKey
); 
 222                 newInfo 
= CFDictionaryCreateMutableCopy(NULL
, 0, info
); 
 224                 newInfo 
= CFDictionaryCreateMutable(NULL
, 
 226                                                     &kCFTypeDictionaryKeyCallBacks
, 
 227                                                     &kCFTypeDictionaryValueCallBacks
); 
 229         CFDictionarySetValue(newInfo
, kSCDName
, name
); 
 230         CFDictionarySetValue(sessionData
, sessionKey
, newInfo
); 
 232         CFRelease(sessionKey
); 
 235          * Note: at this time we should be holding ONE send right and 
 236          *       ONE receive right to the server.  The send right is 
 237          *       moved to the caller. 
 242         if (name 
!= NULL
)       CFRelease(name
); 
 243         if (options 
!= NULL
)    CFRelease(options
);