]> git.saurik.com Git - apple/security.git/blob - SecurityServer/Authorization/Authorization.cpp
Security-179.tar.gz
[apple/security.git] / SecurityServer / Authorization / Authorization.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 //
20 // Authorization.cpp
21 //
22 // This file is the unified implementation of the Authorization and AuthSession APIs.
23 //
24 #include <Security/Authorization.h>
25 #include <Security/AuthorizationDB.h>
26 #include <Security/AuthorizationPriv.h>
27 #include <Security/AuthSession.h>
28 #include "AuthorizationWalkers.h"
29 #include <Security/mach++.h>
30 #include <Security/globalizer.h>
31 #include <Security/cssmalloc.h>
32 #include <Security/ssclient.h>
33 #include <Security/ktracecodes.h>
34
35 using namespace SecurityServer;
36 using namespace MachPlusPlus;
37
38
39 //
40 // Shared cached client object
41 //
42 class AuthClient : public SecurityServer::ClientSession {
43 public:
44 AuthClient()
45 : SecurityServer::ClientSession(CssmAllocator::standard(), CssmAllocator::standard())
46 { }
47 };
48
49 static ModuleNexus<AuthClient> server;
50
51
52 //
53 // Create an Authorization
54 //
55 OSStatus AuthorizationCreate(const AuthorizationRights *rights,
56 const AuthorizationEnvironment *environment,
57 AuthorizationFlags flags,
58 AuthorizationRef *authorization)
59 {
60 Debug::trace(kSecTraceAuthorizationCreateStart);
61 BEGIN_API
62 AuthorizationBlob result;
63 server().authCreate(rights, environment, flags, result);
64 if (authorization)
65 {
66 *authorization =
67 (AuthorizationRef) new(server().returnAllocator) AuthorizationBlob(result);
68 }
69 else
70 {
71 // If no authorizationRef is desired free the one we just created.
72 server().authRelease(result, flags);
73 }
74 Debug::trace(kSecTraceAuthorizationCreateEnd);
75 END_API(CSSM)
76 }
77
78
79 //
80 // Free an authorization reference
81 //
82 OSStatus AuthorizationFree(AuthorizationRef authorization, AuthorizationFlags flags)
83 {
84 BEGIN_API
85 AuthorizationBlob *auth = (AuthorizationBlob *)authorization;
86 server().authRelease(Required(auth, errAuthorizationInvalidRef), flags);
87 server().returnAllocator.free(auth);
88 END_API(CSSM)
89 }
90
91
92 //
93 // Augment and/or interrogate an authorization
94 //
95 OSStatus AuthorizationCopyRights(AuthorizationRef authorization,
96 const AuthorizationRights *rights,
97 const AuthorizationEnvironment *environment,
98 AuthorizationFlags flags,
99 AuthorizationRights **authorizedRights)
100 {
101 Debug::trace(kSecTraceAuthorizationCopyRightsStart);
102 BEGIN_API
103 AuthorizationBlob *auth = (AuthorizationBlob *)authorization;
104 server().authCopyRights(Required(auth, errAuthorizationInvalidRef),
105 rights, environment, flags, authorizedRights);
106 Debug::trace(kSecTraceAuthorizationCopyRightsEnd);
107 END_API(CSSM)
108 }
109
110
111 //
112 // Retrieve side-band information from an authorization
113 //
114 OSStatus AuthorizationCopyInfo(AuthorizationRef authorization,
115 AuthorizationString tag,
116 AuthorizationItemSet **info)
117 {
118 Debug::trace(kSecTraceAuthorizationCopyInfoStart);
119 BEGIN_API
120 AuthorizationBlob *auth = (AuthorizationBlob *)authorization;
121 server().authCopyInfo(Required(auth, errAuthorizationInvalidRef),
122 tag, Required(info));
123 Debug::trace(kSecTraceAuthorizationCopyInfoEnd);
124 END_API(CSSM)
125 }
126
127
128 //
129 // Externalize and internalize authorizations
130 //
131 OSStatus AuthorizationMakeExternalForm(AuthorizationRef authorization,
132 AuthorizationExternalForm *extForm)
133 {
134 BEGIN_API
135 AuthorizationBlob *auth = (AuthorizationBlob *)authorization;
136 server().authExternalize(Required(auth, errAuthorizationInvalidRef), *extForm);
137 END_API(CSSM)
138 }
139
140 OSStatus AuthorizationCreateFromExternalForm(const AuthorizationExternalForm *extForm,
141 AuthorizationRef *authorization)
142 {
143 BEGIN_API
144 AuthorizationBlob result;
145 server().authInternalize(*extForm, result);
146 Required(authorization, errAuthorizationInvalidRef) =
147 (AuthorizationRef) new(server().returnAllocator) AuthorizationBlob(result);
148
149 END_API(CSSM)
150 }
151
152
153 //
154 // Free an ItemSet structure returned from an API call. This is a local operation.
155 // Since we allocate returned ItemSets as compact blobs, this is just a simple
156 // free() call.
157 //
158 OSStatus AuthorizationFreeItemSet(AuthorizationItemSet *set)
159 {
160 BEGIN_API
161 server().returnAllocator.free(set);
162 return errAuthorizationSuccess;
163 END_API(CSSM)
164 }
165
166
167 //
168 // Get session information
169 //
170 OSStatus SessionGetInfo(SecuritySessionId session,
171 SecuritySessionId *sessionId,
172 SessionAttributeBits *attributes)
173 {
174 BEGIN_API
175 SecuritySessionId sid = session;
176 server().getSessionInfo(sid, *attributes);
177 if (sessionId)
178 *sessionId = sid;
179 END_API(CSSM)
180 }
181
182
183 //
184 // Create a new session
185 //
186 OSStatus SessionCreate(SessionCreationFlags flags,
187 SessionAttributeBits attributes)
188 {
189 BEGIN_API
190
191 // unless the (expert) caller has already done so, create a sub-bootstrap and set it
192 // note that this is inherently thread-unfriendly; we can't do anything about that
193 // (caller's responsibility)
194 Bootstrap bootstrap;
195 if (!(flags & sessionKeepCurrentBootstrap)) {
196 TaskPort self;
197 bootstrap = bootstrap.subset(TaskPort());
198 self.bootstrap(bootstrap);
199 }
200
201 // now call the SecurityServer and tell it to initialize the (new) session
202 server().setupSession(flags, attributes);
203
204 // retrieve the (new) session id and set it into the process environment
205 SecuritySessionId id = callerSecuritySession;
206 SessionAttributeBits attrs;
207 server().getSessionInfo(id, attrs);
208 char idString[80];
209 snprintf(idString, sizeof(idString), "%lx", id);
210 setenv("SECURITYSESSIONID", idString, 1);
211
212 END_API(CSSM)
213 }
214
215
216 //
217 // Modify Authorization rules
218 //
219
220 //
221 // AuthorizationRightGet
222 //
223 OSStatus AuthorizationRightGet(const char *rightName, CFDictionaryRef *rightDefinition)
224 {
225 BEGIN_API;
226 Required(rightName);
227 CssmDataContainer definition(server().returnAllocator);
228
229 server().authorizationdbGet(rightName, definition, server().returnAllocator);
230 // convert rightDefinition to dictionary
231
232 if (rightDefinition)
233 {
234 CFRef<CFDataRef> data(CFDataCreate(NULL, static_cast<UInt8 *>(definition.data()), definition.length()));
235 if (!data)
236 CssmError::throwMe(errAuthorizationInternal);
237
238 CFRef<CFDictionaryRef> rightDict(static_cast<CFDictionaryRef>(CFPropertyListCreateFromXMLData(NULL, data, kCFPropertyListImmutable, NULL)));
239 if (!rightDict
240 || CFGetTypeID(rightDict) != CFDictionaryGetTypeID())
241 CssmError::throwMe(errAuthorizationInternal);
242
243 CFRetain(rightDict);
244 *rightDefinition = rightDict;
245 }
246
247 END_API(CSSM);
248 }
249
250 //
251 // AuthorizationRightSet
252 //
253 OSStatus AuthorizationRightSet(AuthorizationRef authRef,
254 const char *rightName, CFTypeRef rightDefinition,
255 CFStringRef descriptionKey, CFBundleRef bundle, CFStringRef tableName)
256 {
257 BEGIN_API;
258 Required(rightName);
259 AuthorizationBlob *auth = (AuthorizationBlob *)authRef;
260
261 CFRef<CFMutableDictionaryRef> rightDefinitionDict;
262 if (rightDefinition && (CFGetTypeID(rightDefinition) == CFStringGetTypeID()))
263 {
264 rightDefinitionDict = CFDictionaryCreateMutable(NULL, 10, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
265 if (!rightDefinitionDict)
266 CssmError::throwMe(errAuthorizationInternal);
267 CFDictionarySetValue(rightDefinitionDict, CFSTR(kAuthorizationRightRule), rightDefinition);
268 }
269 else
270 if (rightDefinition && (CFGetTypeID(rightDefinition) == CFDictionaryGetTypeID()))
271 {
272 rightDefinitionDict = CFDictionaryCreateMutableCopy(NULL, 0, static_cast<CFDictionaryRef>(rightDefinition));
273 if (!rightDefinitionDict)
274 CssmError::throwMe(errAuthorizationInternal);
275 }
276 else
277 CssmError::throwMe(errAuthorizationDenied);
278
279 if (rightDefinitionDict)
280 CFRelease(rightDefinitionDict); // we just assigned things that were already retained
281
282 if (descriptionKey)
283 {
284 CFRef<CFMutableDictionaryRef> localizedDescriptions(CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
285
286 if (!localizedDescriptions)
287 CssmError::throwMe(errAuthorizationInternal);
288
289 // assigning to perform a retain on either
290 CFRef<CFBundleRef> clientBundle = bundle ? bundle : CFBundleGetMainBundle();
291
292 // looks like a list of CFStrings: English us_en etc.
293 CFRef<CFArrayRef> localizations(CFBundleCopyBundleLocalizations(clientBundle));
294
295 if (localizations)
296 {
297 // for every CFString in localizations do
298 CFIndex locIndex, allLocs = CFArrayGetCount(localizations);
299 for (locIndex = 0; locIndex < allLocs; locIndex++)
300 {
301 CFStringRef oneLocalization = static_cast<CFStringRef>(CFArrayGetValueAtIndex(localizations, locIndex));
302
303 if (!oneLocalization)
304 continue;
305
306 // @@@ no way to get "Localized" and "strings" as constants?
307 CFRef<CFURLRef> locURL(CFBundleCopyResourceURLForLocalization(clientBundle, tableName ? tableName : CFSTR("Localizable"), CFSTR("strings"), NULL /*subDirName*/, oneLocalization));
308
309 if (!locURL)
310 continue;
311
312 CFDataRef tableData;
313 SInt32 errCode;
314 CFStringRef errStr;
315 CFPropertyListRef stringTable;
316
317 CFURLCreateDataAndPropertiesFromResource(CFGetAllocator(clientBundle), locURL, &tableData, NULL, NULL, &errCode);
318
319 if (errCode)
320 {
321 CFRelease(tableData);
322 continue;
323 }
324
325 stringTable = CFPropertyListCreateFromXMLData(CFGetAllocator(clientBundle), tableData, kCFPropertyListImmutable, &errStr);
326 if (errStr != NULL) {
327 CFRelease(errStr);
328 errStr = NULL;
329 }
330 CFRelease(tableData);
331
332 CFStringRef value = static_cast<CFStringRef>(CFDictionaryGetValue(static_cast<CFDictionaryRef>(stringTable), descriptionKey));
333 if (value == NULL || CFEqual(value, CFSTR(""))) {
334 CFRelease(stringTable);
335 continue;
336 } else {
337 // oneLocalization/value into our dictionary
338 CFDictionarySetValue(localizedDescriptions, oneLocalization, value);
339 CFRelease(stringTable);
340 }
341 }
342 }
343
344 // add the description as the default localization into the dictionary
345 CFDictionarySetValue(localizedDescriptions, CFSTR(""), descriptionKey);
346
347 // stuff localization table into rule definition
348 CFDictionarySetValue(rightDefinitionDict, CFSTR(kAuthorizationRuleParameterDefaultPrompt), localizedDescriptions);
349
350 }
351
352 // serialize cfdictionary with data into rightDefinitionXML
353 CFDataRef rightDefinitionXML = CFPropertyListCreateXMLData(NULL, rightDefinitionDict);
354
355 server().authorizationdbSet(Required(auth), rightName, CFDataGetLength(rightDefinitionXML), CFDataGetBytePtr(rightDefinitionXML));
356
357 END_API(CSSM);
358 }
359
360 //
361 // AuthorizationRightRemove
362 //
363 OSStatus AuthorizationRightRemove(AuthorizationRef authRef, const char *rightName)
364 {
365 BEGIN_API;
366 Required(rightName);
367 AuthorizationBlob *auth = (AuthorizationBlob *)authRef;
368 server().authorizationdbRemove(Required(auth), rightName);
369 END_API(CSSM);
370 }
371