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((int)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 (CFGetTypeID(value
) == CFURLGetTypeID()) {
104 CFRef
<CFStringRef
> path
= CFURLCopyFileSystemPath(CFURLRef(value
), kCFURLPOSIXPathStyle
);
105 CFDictionaryAddValue(target
, key
, path
);
107 CFDictionaryAddValue(target
, key
, value
);
111 void xpcEngineAssess(CFURLRef path
, SecAssessmentFlags flags
, CFDictionaryRef context
, CFMutableDictionaryRef result
)
113 Message
msg("assess");
114 xpc_dictionary_set_string(msg
, "path", cfString(path
).c_str());
115 xpc_dictionary_set_int64(msg
, "flags", flags
);
116 CFRef
<CFMutableDictionaryRef
> ctx
= makeCFMutableDictionary();
118 CFDictionaryApplyFunction(context
, copyCFDictionary
, ctx
);
119 CFRef
<CFDataRef
> contextData
= makeCFData(CFDictionaryRef(ctx
));
120 xpc_dictionary_set_data(msg
, "context", CFDataGetBytePtr(contextData
), CFDataGetLength(contextData
));
124 if (int64_t error
= xpc_dictionary_get_int64(msg
, "error"))
125 MacOSError::throwMe((int)error
);
128 const void *resultData
= xpc_dictionary_get_data(msg
, "result", &resultLength
);
129 CFRef
<CFDictionaryRef
> resultDict
= makeCFDictionaryFrom(resultData
, resultLength
);
130 CFDictionaryApplyFunction(resultDict
, copyCFDictionary
, result
);
131 CFDictionaryAddValue(result
, CFSTR("assessment:remote"), kCFBooleanTrue
);
135 CFDictionaryRef
xpcEngineUpdate(CFTypeRef target
, SecAssessmentFlags flags
, CFDictionaryRef context
)
137 Message
msg("update");
138 // target can be NULL, a CFURLRef, a SecRequirementRef, or a CFNumberRef
140 if (CFGetTypeID(target
) == CFNumberGetTypeID())
141 xpc_dictionary_set_uint64(msg
, "rule", cfNumber
<int64_t>(CFNumberRef(target
)));
142 else if (CFGetTypeID(target
) == CFURLGetTypeID())
143 xpc_dictionary_set_string(msg
, "url", cfString(CFURLRef(target
)).c_str());
144 else if (CFGetTypeID(target
) == SecRequirementGetTypeID()) {
145 CFRef
<CFDataRef
> data
;
146 MacOSError::check(SecRequirementCopyData(SecRequirementRef(target
), kSecCSDefaultFlags
, &data
.aref()));
147 xpc_dictionary_set_data(msg
, "requirement", CFDataGetBytePtr(data
), CFDataGetLength(data
));
149 MacOSError::throwMe(errSecCSInvalidObjectRef
);
151 xpc_dictionary_set_int64(msg
, "flags", flags
);
152 CFRef
<CFMutableDictionaryRef
> ctx
= makeCFMutableDictionary();
154 CFDictionaryApplyFunction(context
, copyCFDictionary
, ctx
);
155 AuthorizationRef localAuthorization
= NULL
;
156 if (CFDictionaryGetValue(ctx
, kSecAssessmentUpdateKeyAuthorization
) == NULL
) { // no caller-provided authorization
157 MacOSError::check(AuthorizationCreate(NULL
, NULL
, kAuthorizationFlagDefaults
, &localAuthorization
));
158 AuthorizationExternalForm extForm
;
159 MacOSError::check(AuthorizationMakeExternalForm(localAuthorization
, &extForm
));
160 CFDictionaryAddValue(ctx
, kSecAssessmentUpdateKeyAuthorization
, CFTempData(&extForm
, sizeof(extForm
)));
162 CFRef
<CFDataRef
> contextData
= makeCFData(CFDictionaryRef(ctx
));
163 xpc_dictionary_set_data(msg
, "context", CFDataGetBytePtr(contextData
), CFDataGetLength(contextData
));
167 if (localAuthorization
)
168 AuthorizationFree(localAuthorization
, kAuthorizationFlagDefaults
);
170 if (int64_t error
= xpc_dictionary_get_int64(msg
, "error"))
171 MacOSError::throwMe((int)error
);
174 const void *resultData
= xpc_dictionary_get_data(msg
, "result", &resultLength
);
175 return makeCFDictionaryFrom(resultData
, resultLength
);
179 bool xpcEngineControl(const char *control
)
181 Message
msg("control");
182 xpc_dictionary_set_string(msg
, "control", control
);
188 void xpcEngineRecord(CFDictionaryRef info
)
190 Message
msg("record");
191 CFRef
<CFDataRef
> infoData
= makeCFData(CFDictionaryRef(info
));
192 xpc_dictionary_set_data(msg
, "info", CFDataGetBytePtr(infoData
), CFDataGetLength(infoData
));
198 } // end namespace CodeSigning
199 } // end namespace Security