2 * Copyright (c) 2011 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@
23 #include "xpcengine.h"
24 #include <xpc/connection.h>
26 #include <CoreFoundation/CoreFoundation.h>
27 #include <security_utilities/cfutilities.h>
31 namespace CodeSigning
{
33 static const char serviceName
[] = "com.apple.security.syspolicy";
36 static dispatch_once_t dispatchInit
; // one-time init marker
37 static xpc_connection_t service
; // connection to spd
38 static dispatch_queue_t queue
; // dispatch queue for service
42 dispatch_once(&dispatchInit
, ^void(void) {
43 const char *name
= serviceName
;
44 if (const char *env
= getenv("SYSPOLICYNAME"))
46 queue
= dispatch_queue_create("spd-client", 0);
47 service
= xpc_connection_create_mach_service(name
, queue
, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED
);
48 xpc_connection_set_event_handler(service
, ^(xpc_object_t ev
) {
50 xpc_connection_resume(service
);
56 // Your standard XPC client-side machinery
62 Message(const char *function
)
65 obj
= xpc_dictionary_create(NULL
, NULL
, 0);
66 xpc_dictionary_set_string(obj
, "function", function
);
73 operator xpc_object_t () { return obj
; }
77 xpc_object_t reply
= xpc_connection_send_message_with_reply_sync(service
, obj
);
80 xpc_type_t type
= xpc_get_type(reply
);
81 if (type
== XPC_TYPE_DICTIONARY
) {
83 if (int64_t error
= xpc_dictionary_get_int64(obj
, "error"))
84 MacOSError::throwMe(error
);
85 } else if (type
== XPC_TYPE_ERROR
) {
86 const char *s
= xpc_copy_description(reply
);
87 printf("Error returned: %s\n", s
);
89 MacOSError::throwMe(errSecCSInternalError
);
91 const char *s
= xpc_copy_description(reply
);
92 printf("Unexpected type of return object: %s\n", s
);
100 static void copyCFDictionary(const void *key
, const void *value
, void *ctx
)
102 CFMutableDictionaryRef target
= CFMutableDictionaryRef(ctx
);
103 if (CFEqual(key
, kSecAssessmentContextKeyCertificates
)) // obsolete
105 if (CFGetTypeID(value
) == CFURLGetTypeID()) {
106 CFRef
<CFStringRef
> path
= CFURLCopyFileSystemPath(CFURLRef(value
), kCFURLPOSIXPathStyle
);
107 CFDictionaryAddValue(target
, key
, path
);
109 CFDictionaryAddValue(target
, key
, value
);
113 void xpcEngineAssess(CFURLRef path
, uint flags
, CFDictionaryRef context
, CFMutableDictionaryRef result
)
115 Message
msg("assess");
116 xpc_dictionary_set_string(msg
, "path", cfString(path
).c_str());
117 xpc_dictionary_set_int64(msg
, "flags", flags
);
118 CFRef
<CFMutableDictionaryRef
> ctx
= makeCFMutableDictionary();
120 CFDictionaryApplyFunction(context
, copyCFDictionary
, ctx
);
121 CFRef
<CFDataRef
> contextData
= makeCFData(CFDictionaryRef(ctx
));
122 xpc_dictionary_set_data(msg
, "context", CFDataGetBytePtr(contextData
), CFDataGetLength(contextData
));
126 if (int64_t error
= xpc_dictionary_get_int64(msg
, "error"))
127 MacOSError::throwMe(error
);
130 const void *resultData
= xpc_dictionary_get_data(msg
, "result", &resultLength
);
131 CFRef
<CFDictionaryRef
> resultDict
= makeCFDictionaryFrom(resultData
, resultLength
);
132 CFDictionaryApplyFunction(resultDict
, copyCFDictionary
, result
);
133 CFDictionaryAddValue(result
, CFSTR("assessment:remote"), kCFBooleanTrue
);
137 CFDictionaryRef
xpcEngineUpdate(CFTypeRef target
, uint flags
, CFDictionaryRef context
)
139 Message
msg("update");
140 // target can be NULL, a CFURLRef, a SecRequirementRef, or a CFNumberRef
142 if (CFGetTypeID(target
) == CFNumberGetTypeID())
143 xpc_dictionary_set_uint64(msg
, "rule", cfNumber
<int64_t>(CFNumberRef(target
)));
144 else if (CFGetTypeID(target
) == CFURLGetTypeID())
145 xpc_dictionary_set_string(msg
, "url", cfString(CFURLRef(target
)).c_str());
146 else if (CFGetTypeID(target
) == SecRequirementGetTypeID()) {
147 CFRef
<CFDataRef
> data
;
148 MacOSError::check(SecRequirementCopyData(SecRequirementRef(target
), kSecCSDefaultFlags
, &data
.aref()));
149 xpc_dictionary_set_data(msg
, "requirement", CFDataGetBytePtr(data
), CFDataGetLength(data
));
151 MacOSError::throwMe(errSecCSInvalidObjectRef
);
153 xpc_dictionary_set_int64(msg
, "flags", flags
);
154 CFRef
<CFMutableDictionaryRef
> ctx
= makeCFMutableDictionary();
156 CFDictionaryApplyFunction(context
, copyCFDictionary
, ctx
);
157 AuthorizationRef localAuthorization
= NULL
;
158 if (CFDictionaryGetValue(ctx
, kSecAssessmentUpdateKeyAuthorization
) == NULL
) { // no caller-provided authorization
159 MacOSError::check(AuthorizationCreate(NULL
, NULL
, kAuthorizationFlagDefaults
, &localAuthorization
));
160 AuthorizationExternalForm extForm
;
161 MacOSError::check(AuthorizationMakeExternalForm(localAuthorization
, &extForm
));
162 CFDictionaryAddValue(ctx
, kSecAssessmentUpdateKeyAuthorization
, CFTempData(&extForm
, sizeof(extForm
)));
164 CFRef
<CFDataRef
> contextData
= makeCFData(CFDictionaryRef(ctx
));
165 xpc_dictionary_set_data(msg
, "context", CFDataGetBytePtr(contextData
), CFDataGetLength(contextData
));
169 if (localAuthorization
)
170 AuthorizationFree(localAuthorization
, kAuthorizationFlagDefaults
);
172 if (int64_t error
= xpc_dictionary_get_int64(msg
, "error"))
173 MacOSError::throwMe(error
);
176 const void *resultData
= xpc_dictionary_get_data(msg
, "result", &resultLength
);
177 return makeCFDictionaryFrom(resultData
, resultLength
);
181 bool xpcEngineControl(const char *control
)
183 Message
msg("control");
184 xpc_dictionary_set_string(msg
, "control", control
);
190 } // end namespace CodeSigning
191 } // end namespace Security