]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (c) 2004-2007 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * The contents of this file constitute Original Code as defined in and | |
7 | * are subject to the Apple Public Source License Version 1.1 (the | |
8 | * "License"). You may not use this file except in compliance with the | |
9 | * License. Please obtain a copy of the License at | |
10 | * http://www.apple.com/publicsource and read it before using this file. | |
11 | * | |
12 | * This Original Code and all software distributed under the License are | |
13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the | |
17 | * License for the specific language governing rights and limitations | |
18 | * under the License. | |
19 | * | |
20 | * @APPLE_LICENSE_HEADER_END@ | |
21 | */ | |
22 | ||
23 | #include "membership.h" | |
24 | #include "membershipPriv.h" | |
25 | #include "memberd.h" | |
26 | ||
27 | #include <sys/errno.h> | |
28 | #include <servers/bootstrap.h> | |
29 | #include <mach/mach.h> | |
30 | #include <stdlib.h> | |
31 | #include <libkern/OSByteOrder.h> | |
32 | ||
33 | static mach_port_t GetServerPort() | |
34 | { | |
35 | kern_return_t result; | |
36 | static mach_port_t bsPort = 0; | |
37 | static mach_port_t fServerPort = 0; | |
38 | ||
39 | if (bsPort == 0) | |
40 | { | |
41 | result = task_get_bootstrap_port(mach_task_self(), &bsPort); | |
42 | result = bootstrap_look_up(bsPort, "com.apple.memberd", &fServerPort); | |
43 | } | |
44 | ||
45 | return fServerPort; | |
46 | } | |
47 | ||
48 | int mbr_uid_to_uuid(uid_t id, uuid_t uu) | |
49 | { | |
50 | struct kauth_identity_extlookup request; | |
51 | security_token_t token; | |
52 | int result = 0; | |
53 | ||
54 | token.val[0] = -1; | |
55 | token.val[1] = -1; | |
56 | ||
57 | request.el_flags = KAUTH_EXTLOOKUP_VALID_UID | KAUTH_EXTLOOKUP_WANT_UGUID; | |
58 | request.el_uid = id; | |
59 | result = _mbr_DoMembershipCall(GetServerPort(), &request, &token); | |
60 | if (result != KERN_SUCCESS) return EIO; | |
61 | if (token.val[0] != 0) return EAUTH; | |
62 | ||
63 | if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_UGUID) != 0) | |
64 | memcpy(uu, &request.el_uguid, sizeof(guid_t)); | |
65 | else | |
66 | result = ENOENT; | |
67 | ||
68 | return result; | |
69 | } | |
70 | ||
71 | int mbr_gid_to_uuid(gid_t id, uuid_t uu) | |
72 | { | |
73 | struct kauth_identity_extlookup request; | |
74 | security_token_t token; | |
75 | kern_return_t result; | |
76 | int error = 0; | |
77 | ||
78 | token.val[0] = -1; | |
79 | token.val[1] = -1; | |
80 | ||
81 | request.el_flags = KAUTH_EXTLOOKUP_VALID_GID | KAUTH_EXTLOOKUP_WANT_GGUID; | |
82 | request.el_gid = id; | |
83 | result = _mbr_DoMembershipCall(GetServerPort(), &request, &token); | |
84 | if (result != KERN_SUCCESS) return EIO; | |
85 | if (token.val[0] != 0) return EAUTH; | |
86 | ||
87 | if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GGUID) != 0) | |
88 | memcpy(uu, &request.el_gguid, sizeof(guid_t)); | |
89 | else | |
90 | error = ENOENT; | |
91 | ||
92 | return error; | |
93 | } | |
94 | ||
95 | int mbr_uuid_to_id(const uuid_t uu, uid_t *id, int *id_type) | |
96 | { | |
97 | struct kauth_identity_extlookup request; | |
98 | security_token_t token; | |
99 | kern_return_t result; | |
100 | int error = 0; | |
101 | ||
102 | token.val[0] = -1; | |
103 | token.val[1] = -1; | |
104 | ||
105 | request.el_flags = KAUTH_EXTLOOKUP_VALID_UGUID | KAUTH_EXTLOOKUP_VALID_GGUID | KAUTH_EXTLOOKUP_WANT_UID | KAUTH_EXTLOOKUP_WANT_GID; | |
106 | memcpy(&request.el_uguid, uu, sizeof(guid_t)); | |
107 | memcpy(&request.el_gguid, uu, sizeof(guid_t)); | |
108 | result = _mbr_DoMembershipCall(GetServerPort(), &request, &token); | |
109 | if (result != KERN_SUCCESS) return EIO; | |
110 | if (token.val[0] != 0) return EAUTH; | |
111 | ||
112 | if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_UID) != 0) | |
113 | { | |
114 | *id = request.el_uid; | |
115 | *id_type = ID_TYPE_UID; | |
116 | } | |
117 | else if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GID) != 0) | |
118 | { | |
119 | *id = request.el_gid; | |
120 | *id_type = ID_TYPE_GID; | |
121 | } | |
122 | else | |
123 | { | |
124 | error = ENOENT; | |
125 | } | |
126 | ||
127 | return error; | |
128 | } | |
129 | ||
130 | int mbr_sid_to_uuid(const nt_sid_t *sid, uuid_t uu) | |
131 | { | |
132 | struct kauth_identity_extlookup request; | |
133 | security_token_t token; | |
134 | kern_return_t result; | |
135 | int error = 0; | |
136 | ||
137 | token.val[0] = -1; | |
138 | token.val[1] = -1; | |
139 | ||
140 | request.el_flags = KAUTH_EXTLOOKUP_VALID_GSID | KAUTH_EXTLOOKUP_WANT_GGUID; | |
141 | memset(&request.el_gsid, 0, sizeof(ntsid_t)); | |
142 | memcpy(&request.el_gsid, sid, KAUTH_NTSID_SIZE(sid)); | |
143 | result = _mbr_DoMembershipCall(GetServerPort(), &request, &token); | |
144 | if (result != KERN_SUCCESS) return EIO; | |
145 | if (token.val[0] != 0) return EAUTH; | |
146 | ||
147 | if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GGUID) != 0) | |
148 | memcpy(uu, &request.el_gguid, sizeof(guid_t)); | |
149 | else | |
150 | error = ENOENT; | |
151 | ||
152 | return error; | |
153 | } | |
154 | ||
155 | int mbr_uuid_to_sid(const uuid_t uu, nt_sid_t *sid) | |
156 | { | |
157 | struct kauth_identity_extlookup request; | |
158 | security_token_t token; | |
159 | kern_return_t result; | |
160 | int error = 0; | |
161 | ||
162 | token.val[0] = -1; | |
163 | token.val[1] = -1; | |
164 | ||
165 | request.el_flags = KAUTH_EXTLOOKUP_VALID_GGUID | KAUTH_EXTLOOKUP_WANT_GSID; | |
166 | memcpy(&request.el_gguid, uu, sizeof(guid_t)); | |
167 | result = _mbr_DoMembershipCall(GetServerPort(), &request, &token); | |
168 | if (result != KERN_SUCCESS) return EIO; | |
169 | if (token.val[0] != 0) return EAUTH; | |
170 | ||
171 | if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GSID) != 0) | |
172 | memcpy(sid, &request.el_gsid, sizeof(nt_sid_t)); | |
173 | else | |
174 | error = ENOENT; | |
175 | ||
176 | return error; | |
177 | } | |
178 | ||
179 | int mbr_check_membership(uuid_t user, uuid_t group, int *ismember) | |
180 | { | |
181 | struct kauth_identity_extlookup request; | |
182 | security_token_t token; | |
183 | kern_return_t result; | |
184 | int error = 0; | |
185 | ||
186 | token.val[0] = -1; | |
187 | token.val[1] = -1; | |
188 | ||
189 | request.el_flags = KAUTH_EXTLOOKUP_VALID_UGUID | KAUTH_EXTLOOKUP_VALID_GGUID | KAUTH_EXTLOOKUP_WANT_MEMBERSHIP; | |
190 | memcpy(&request.el_uguid, user, sizeof(guid_t)); | |
191 | memcpy(&request.el_gguid, group, sizeof(guid_t)); | |
192 | result = _mbr_DoMembershipCall(GetServerPort(), &request, &token); | |
193 | if (result != KERN_SUCCESS) return EIO; | |
194 | if (token.val[0] != 0) return EAUTH; | |
195 | ||
196 | if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_MEMBERSHIP) != 0) | |
197 | *ismember = ((request.el_flags & KAUTH_EXTLOOKUP_ISMEMBER) != 0); | |
198 | else | |
199 | error = ENOENT; | |
200 | ||
201 | return error; | |
202 | } | |
203 | ||
204 | int mbr_check_membership_refresh(uuid_t user, uuid_t group, int *ismember) | |
205 | { | |
206 | struct kauth_identity_extlookup request; | |
207 | security_token_t token; | |
208 | kern_return_t result; | |
209 | int error = 0; | |
210 | ||
211 | token.val[0] = -1; | |
212 | token.val[1] = -1; | |
213 | ||
214 | request.el_flags = KAUTH_EXTLOOKUP_VALID_UGUID | KAUTH_EXTLOOKUP_VALID_GGUID | KAUTH_EXTLOOKUP_WANT_MEMBERSHIP | (1 << 15); | |
215 | memcpy(&request.el_uguid, user, sizeof(guid_t)); | |
216 | memcpy(&request.el_gguid, group, sizeof(guid_t)); | |
217 | result = _mbr_DoMembershipCall(GetServerPort(), &request, &token); | |
218 | if (result != KERN_SUCCESS) return EIO; | |
219 | if (token.val[0] != 0) return EAUTH; | |
220 | ||
221 | if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_MEMBERSHIP) != 0) | |
222 | *ismember = ((request.el_flags & KAUTH_EXTLOOKUP_ISMEMBER) != 0); | |
223 | else | |
224 | error = ENOENT; | |
225 | ||
226 | return error; | |
227 | } | |
228 | ||
229 | int mbr_check_membership_by_id(uuid_t user, gid_t group, int *ismember) | |
230 | { | |
231 | struct kauth_identity_extlookup request; | |
232 | security_token_t token; | |
233 | kern_return_t result; | |
234 | int error = 0; | |
235 | ||
236 | token.val[0] = -1; | |
237 | token.val[1] = -1; | |
238 | ||
239 | request.el_flags = KAUTH_EXTLOOKUP_VALID_UGUID | KAUTH_EXTLOOKUP_VALID_GID | KAUTH_EXTLOOKUP_WANT_MEMBERSHIP; | |
240 | memcpy(&request.el_uguid, user, sizeof(guid_t)); | |
241 | request.el_gid = group; | |
242 | result = _mbr_DoMembershipCall(GetServerPort(), &request, &token); | |
243 | if (result != KERN_SUCCESS) return EIO; | |
244 | if (token.val[0] != 0) return EAUTH; | |
245 | ||
246 | if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_MEMBERSHIP) != 0) | |
247 | *ismember = ((request.el_flags & KAUTH_EXTLOOKUP_ISMEMBER) != 0); | |
248 | else | |
249 | error = ENOENT; | |
250 | ||
251 | return error; | |
252 | } | |
253 | ||
254 | int mbr_reset_cache() | |
255 | { | |
256 | security_token_t token; | |
257 | kern_return_t result; | |
258 | ||
259 | token.val[0] = -1; | |
260 | token.val[1] = -1; | |
261 | ||
262 | result = _mbr_ClearCache(GetServerPort(), &token); | |
263 | if (result != KERN_SUCCESS) return EIO; | |
264 | if (token.val[0] != 0) return EAUTH; | |
265 | ||
266 | return 0; | |
267 | } | |
268 | ||
269 | int mbr_user_name_to_uuid(const char *name, uuid_t uu) | |
270 | { | |
271 | security_token_t token; | |
272 | kern_return_t result; | |
273 | ||
274 | if (name == NULL) return EINVAL; | |
275 | if (strlen(name) > 255) return EINVAL; | |
276 | ||
277 | token.val[0] = -1; | |
278 | token.val[1] = -1; | |
279 | ||
280 | result = _mbr_MapName(GetServerPort(), 1, (char *)name, (guid_t *)uu, &token); | |
281 | if (result == KERN_FAILURE) return ENOENT; | |
282 | else if (result != KERN_SUCCESS) return EIO; | |
283 | ||
284 | if (token.val[0] != 0) return EAUTH; | |
285 | ||
286 | return 0; | |
287 | } | |
288 | ||
289 | int mbr_group_name_to_uuid(const char *name, uuid_t uu) | |
290 | { | |
291 | security_token_t token; | |
292 | kern_return_t result; | |
293 | ||
294 | if (name == NULL) return EINVAL; | |
295 | if (strlen(name) > 255) return EINVAL; | |
296 | ||
297 | token.val[0] = -1; | |
298 | token.val[1] = -1; | |
299 | ||
300 | result = _mbr_MapName(GetServerPort(), 0, (char *)name, (guid_t *)uu, &token); | |
301 | if (result == KERN_FAILURE) return ENOENT; | |
302 | else if (result != KERN_SUCCESS) return EIO; | |
303 | ||
304 | if (token.val[0] != 0) return EAUTH; | |
305 | ||
306 | return 0; | |
307 | } | |
308 | ||
309 | int mbr_check_service_membership(const uuid_t user, const char *servicename, int *ismember) | |
310 | { | |
311 | char *prefix = "com.apple.access_"; | |
312 | char *all_services = "com.apple.access_all_services"; | |
313 | char groupName[256]; | |
314 | uuid_t group_uu; | |
315 | int result, dummy; | |
316 | ||
317 | if (servicename == NULL) return EINVAL; | |
318 | if (strlen(servicename) > (255 - strlen(prefix))) return EINVAL; | |
319 | ||
320 | /* start by checking "all services" */ | |
321 | result = mbr_group_name_to_uuid(all_services, group_uu); | |
322 | ||
323 | if (result == EAUTH) return result; | |
324 | ||
325 | if (result == ENOENT) | |
326 | { | |
327 | /* all_services group didn't exist, check individual group */ | |
328 | memcpy(groupName, prefix, strlen(prefix)); | |
329 | strcpy(groupName + strlen(prefix), servicename); | |
330 | result = mbr_group_name_to_uuid(groupName, group_uu); | |
331 | } | |
332 | ||
333 | if (result == 0) | |
334 | { | |
335 | result = mbr_check_membership_refresh(user, group_uu, ismember); | |
336 | } | |
337 | else if (result == EAUTH) | |
338 | { | |
339 | return result; | |
340 | } | |
341 | else | |
342 | { | |
343 | /* just force cache update with bogus membership check */ | |
344 | memset(group_uu, 0, sizeof(group_uu)); | |
345 | mbr_check_membership_refresh(user, group_uu, &dummy); | |
346 | } | |
347 | ||
348 | return result; | |
349 | } | |
350 | ||
351 | static char *ConvertBytesToDecimal(char *buffer, unsigned long long value) | |
352 | { | |
353 | char *temp; | |
354 | buffer[24] = '\0'; | |
355 | buffer[23] = '0'; | |
356 | ||
357 | if (value == 0) return &buffer[23]; | |
358 | ||
359 | temp = &buffer[24]; | |
360 | while (value != 0) | |
361 | { | |
362 | temp--; | |
363 | *temp = '0' + (value % 10); | |
364 | value /= 10; | |
365 | } | |
366 | ||
367 | return temp; | |
368 | } | |
369 | ||
370 | int mbr_sid_to_string(const nt_sid_t *sid, char *string) | |
371 | { | |
372 | char *current = string; | |
373 | long long temp = 0; | |
374 | int i; | |
375 | char tempBuffer[25]; | |
376 | ||
377 | if (sid->sid_authcount > NTSID_MAX_AUTHORITIES) return EINVAL; | |
378 | ||
379 | for (i = 0; i < 6; i++) | |
380 | temp = (temp << 8) | sid->sid_authority[i]; | |
381 | ||
382 | current[0] = 'S'; | |
383 | current[1] = '-'; | |
384 | current += 2; | |
385 | strcpy(current, ConvertBytesToDecimal(tempBuffer, sid->sid_kind)); | |
386 | current = current + strlen(current); | |
387 | *current = '-'; | |
388 | current++; | |
389 | strcpy(current, ConvertBytesToDecimal(tempBuffer, temp)); | |
390 | ||
391 | for (i = 0; i < sid->sid_authcount; i++) | |
392 | { | |
393 | current = current + strlen(current); | |
394 | *current = '-'; | |
395 | current++; | |
396 | strcpy(current, ConvertBytesToDecimal(tempBuffer, sid->sid_authorities[i])); | |
397 | } | |
398 | ||
399 | return 0; | |
400 | } | |
401 | ||
402 | int mbr_string_to_sid(const char *string, nt_sid_t *sid) | |
403 | { | |
404 | char *current = string+2; | |
405 | int count = 0; | |
406 | long long temp; | |
407 | ||
408 | memset(sid, 0, sizeof(nt_sid_t)); | |
409 | if ((string[0] != 'S') || (string[1] != '-')) return EINVAL; | |
410 | ||
411 | sid->sid_kind = strtol(current, ¤t, 10); | |
412 | if (*current == '\0') return EINVAL; | |
413 | current++; | |
414 | temp = strtoll(current, ¤t, 10); | |
415 | ||
416 | /* convert to BigEndian before copying */ | |
417 | temp = OSSwapHostToBigInt64(temp); | |
418 | memcpy(sid->sid_authority, ((char*)&temp)+2, 6); | |
419 | while ((*current != '\0') && (count < NTSID_MAX_AUTHORITIES)) | |
420 | { | |
421 | current++; | |
422 | sid->sid_authorities[count] = strtol(current, ¤t, 10); | |
423 | count++; | |
424 | } | |
425 | ||
426 | if (*current != '\0') return EINVAL; | |
427 | ||
428 | sid->sid_authcount = count; | |
429 | ||
430 | return 0; | |
431 | } | |
432 | ||
433 | static void ConvertBytesToHex(char **string, char **data, int numBytes) | |
434 | { | |
435 | int i; | |
436 | ||
437 | for (i = 0; i < numBytes; i++) | |
438 | { | |
439 | unsigned char hi = ((**data) >> 4) & 0xf; | |
440 | unsigned char low = (**data) & 0xf; | |
441 | if (hi < 10) | |
442 | **string = '0' + hi; | |
443 | else | |
444 | **string = 'A' + hi - 10; | |
445 | ||
446 | (*string)++; | |
447 | ||
448 | if (low < 10) | |
449 | **string = '0' + low; | |
450 | else | |
451 | **string = 'A' + low - 10; | |
452 | ||
453 | (*string)++; | |
454 | (*data)++; | |
455 | } | |
456 | } | |
457 | ||
458 | int mbr_uuid_to_string(const uuid_t uu, char *string) | |
459 | { | |
460 | char *guid = (char *)uu; | |
461 | char *strPtr = string; | |
462 | ConvertBytesToHex(&strPtr, &guid, 4); | |
463 | *strPtr = '-'; strPtr++; | |
464 | ConvertBytesToHex(&strPtr, &guid, 2); | |
465 | *strPtr = '-'; strPtr++; | |
466 | ConvertBytesToHex(&strPtr, &guid, 2); | |
467 | *strPtr = '-'; strPtr++; | |
468 | ConvertBytesToHex(&strPtr, &guid, 2); | |
469 | *strPtr = '-'; strPtr++; | |
470 | ConvertBytesToHex(&strPtr, &guid, 6); | |
471 | *strPtr = '\0'; | |
472 | ||
473 | return 0; | |
474 | } | |
475 | ||
476 | int mbr_string_to_uuid(const char *string, uuid_t uu) | |
477 | { | |
478 | short dataIndex = 0; | |
479 | int isFirstNibble = 1; | |
480 | ||
481 | if (strlen(string) > MBR_UU_STRING_SIZE) | |
482 | return EINVAL; | |
483 | ||
484 | while (*string != '\0' && dataIndex < 16) | |
485 | { | |
486 | char nibble; | |
487 | ||
488 | if ((*string >= '0') && (*string <= '9')) | |
489 | { | |
490 | nibble = *string - '0'; | |
491 | } | |
492 | else if ((*string >= 'A') && (*string <= 'F')) | |
493 | { | |
494 | nibble = *string - 'A' + 10; | |
495 | } | |
496 | else if ((*string >= 'a') && (*string <= 'f')) | |
497 | { | |
498 | nibble = *string - 'a' + 10; | |
499 | } | |
500 | else | |
501 | { | |
502 | if (*string != '-') return EINVAL; | |
503 | string++; | |
504 | continue; | |
505 | } | |
506 | ||
507 | if (isFirstNibble) | |
508 | { | |
509 | uu[dataIndex] = nibble << 4; | |
510 | isFirstNibble = 0; | |
511 | } | |
512 | else | |
513 | { | |
514 | uu[dataIndex] |= nibble; | |
515 | dataIndex++; | |
516 | isFirstNibble = 1; | |
517 | } | |
518 | ||
519 | string++; | |
520 | } | |
521 | ||
522 | if (dataIndex != 16) return EINVAL; | |
523 | ||
524 | return 0; | |
525 | } |