]>
Commit | Line | Data |
---|---|---|
c29f2fcc A |
1 | /* |
2 | * Copyright (c) 2004 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> | |
918ca66e | 31 | #import <libkern/OSByteOrder.h> |
c29f2fcc A |
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 | // if the port lookup failed, the rpc will fail and we will return EIO | |
45 | // if (result != MACH_MSG_SUCCESS) | |
46 | // { | |
47 | // printf("Got error %d on lookup (is memberd running?)\n", result); | |
48 | // } | |
49 | } | |
50 | ||
51 | return fServerPort; | |
52 | } | |
53 | ||
54 | int mbr_uid_to_uuid(uid_t id, uuid_t uu) | |
55 | { | |
56 | struct kauth_identity_extlookup request; | |
57 | int result = 0; | |
58 | ||
59 | request.el_flags = KAUTH_EXTLOOKUP_VALID_UID | KAUTH_EXTLOOKUP_WANT_UGUID; | |
60 | request.el_uid = id; | |
61 | result = _mbr_DoMembershipCall(GetServerPort(), &request); | |
62 | if (result != KERN_SUCCESS) | |
63 | return EIO; | |
64 | ||
65 | if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_UGUID) != 0) | |
66 | memcpy(uu, &request.el_uguid, sizeof(guid_t)); | |
67 | else | |
68 | result = ENOENT; | |
69 | ||
70 | return result; | |
71 | } | |
72 | ||
73 | int mbr_gid_to_uuid(gid_t id, uuid_t uu) | |
74 | { | |
75 | struct kauth_identity_extlookup request; | |
76 | kern_return_t result; | |
77 | int error = 0; | |
78 | ||
79 | request.el_flags = KAUTH_EXTLOOKUP_VALID_GID | KAUTH_EXTLOOKUP_WANT_GGUID; | |
80 | request.el_gid = id; | |
81 | result = _mbr_DoMembershipCall(GetServerPort(), &request); | |
82 | if (result != KERN_SUCCESS) | |
83 | return EIO; | |
84 | ||
85 | if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GGUID) != 0) | |
86 | memcpy(uu, &request.el_gguid, sizeof(guid_t)); | |
87 | else | |
88 | error = ENOENT; | |
89 | ||
90 | return error; | |
91 | } | |
92 | ||
93 | int mbr_uuid_to_id( const uuid_t uu, uid_t* id, int* id_type) | |
94 | { | |
95 | struct kauth_identity_extlookup request; | |
96 | kern_return_t result; | |
97 | int error = 0; | |
98 | ||
99 | request.el_flags = KAUTH_EXTLOOKUP_VALID_UGUID | KAUTH_EXTLOOKUP_VALID_GGUID | | |
100 | KAUTH_EXTLOOKUP_WANT_UID | KAUTH_EXTLOOKUP_WANT_GID; | |
101 | memcpy(&request.el_uguid, uu, sizeof(guid_t)); | |
102 | memcpy(&request.el_gguid, uu, sizeof(guid_t)); | |
103 | result = _mbr_DoMembershipCall(GetServerPort(), &request); | |
104 | if (result != KERN_SUCCESS) | |
105 | return EIO; | |
106 | ||
107 | if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_UID) != 0) | |
108 | { | |
109 | *id = request.el_uid; | |
110 | *id_type = ID_TYPE_UID; | |
111 | } | |
112 | else if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GID) != 0) | |
113 | { | |
114 | *id = request.el_gid; | |
115 | *id_type = ID_TYPE_GID; | |
116 | } | |
117 | else | |
118 | error = ENOENT; | |
119 | ||
120 | return error; | |
121 | } | |
122 | ||
123 | int mbr_sid_to_uuid(const nt_sid_t* sid, uuid_t uu) | |
124 | { | |
125 | struct kauth_identity_extlookup request; | |
126 | kern_return_t result; | |
127 | int error = 0; | |
128 | ||
129 | request.el_flags = KAUTH_EXTLOOKUP_VALID_GSID | KAUTH_EXTLOOKUP_WANT_GGUID; | |
130 | memset(&request.el_gsid, 0, sizeof(ntsid_t)); | |
131 | memcpy(&request.el_gsid, sid, KAUTH_NTSID_SIZE(sid)); | |
132 | result = _mbr_DoMembershipCall(GetServerPort(), &request); | |
133 | if (result != KERN_SUCCESS) | |
134 | return EIO; | |
135 | ||
136 | if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GGUID) != 0) | |
137 | memcpy(uu, &request.el_gguid, sizeof(guid_t)); | |
138 | else | |
139 | error = ENOENT; | |
140 | ||
141 | return error; | |
142 | } | |
143 | ||
144 | int mbr_uuid_to_sid(const uuid_t uu, nt_sid_t* sid) | |
145 | { | |
146 | struct kauth_identity_extlookup request; | |
147 | kern_return_t result; | |
148 | int error = 0; | |
149 | ||
150 | request.el_flags = KAUTH_EXTLOOKUP_VALID_GGUID | KAUTH_EXTLOOKUP_WANT_GSID; | |
151 | memcpy(&request.el_gguid, uu, sizeof(guid_t)); | |
152 | result = _mbr_DoMembershipCall(GetServerPort(), &request); | |
153 | if (result != KERN_SUCCESS) | |
154 | return EIO; | |
155 | ||
156 | if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GSID) != 0) | |
157 | memcpy(sid, &request.el_gsid, sizeof(nt_sid_t)); | |
158 | else | |
159 | error = ENOENT; | |
160 | ||
161 | return error; | |
162 | } | |
163 | ||
164 | int mbr_check_membership(uuid_t user, uuid_t group, int* ismember) | |
165 | { | |
166 | struct kauth_identity_extlookup request; | |
167 | kern_return_t result; | |
168 | int error = 0; | |
169 | ||
170 | request.el_flags = KAUTH_EXTLOOKUP_VALID_UGUID | KAUTH_EXTLOOKUP_VALID_GGUID | | |
171 | KAUTH_EXTLOOKUP_WANT_MEMBERSHIP; | |
172 | memcpy(&request.el_uguid, user, sizeof(guid_t)); | |
173 | memcpy(&request.el_gguid, group, sizeof(guid_t)); | |
174 | result = _mbr_DoMembershipCall(GetServerPort(), &request); | |
175 | if (result != KERN_SUCCESS) | |
176 | return EIO; | |
177 | ||
178 | if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_MEMBERSHIP) != 0) | |
179 | { | |
180 | *ismember = ((request.el_flags & KAUTH_EXTLOOKUP_ISMEMBER) != 0); | |
181 | } | |
182 | else | |
183 | error = ENOENT; | |
184 | ||
185 | return error; | |
186 | } | |
187 | ||
918ca66e A |
188 | int mbr_check_membership_refresh(uuid_t user, uuid_t group, int* ismember) |
189 | { | |
190 | struct kauth_identity_extlookup request; | |
191 | kern_return_t result; | |
192 | int error = 0; | |
193 | ||
918ca66e A |
194 | request.el_flags = KAUTH_EXTLOOKUP_VALID_UGUID | KAUTH_EXTLOOKUP_VALID_GGUID | |
195 | KAUTH_EXTLOOKUP_WANT_MEMBERSHIP | (1<<15); | |
196 | memcpy(&request.el_uguid, user, sizeof(guid_t)); | |
197 | memcpy(&request.el_gguid, group, sizeof(guid_t)); | |
198 | result = _mbr_DoMembershipCall(GetServerPort(), &request); | |
199 | if (result != KERN_SUCCESS) | |
200 | return EIO; | |
201 | ||
202 | if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_MEMBERSHIP) != 0) | |
203 | { | |
204 | *ismember = ((request.el_flags & KAUTH_EXTLOOKUP_ISMEMBER) != 0); | |
205 | } | |
206 | else | |
207 | error = ENOENT; | |
208 | ||
209 | return error; | |
210 | } | |
211 | ||
c29f2fcc A |
212 | int mbr_check_membership_by_id(uuid_t user, gid_t group, int* ismember) |
213 | { | |
214 | struct kauth_identity_extlookup request; | |
215 | kern_return_t result; | |
216 | int error = 0; | |
217 | ||
218 | request.el_flags = KAUTH_EXTLOOKUP_VALID_UGUID | KAUTH_EXTLOOKUP_VALID_GID | | |
219 | KAUTH_EXTLOOKUP_WANT_MEMBERSHIP; | |
220 | memcpy(&request.el_uguid, user, sizeof(guid_t)); | |
221 | request.el_gid = group; | |
222 | result = _mbr_DoMembershipCall(GetServerPort(), &request); | |
223 | if (result != KERN_SUCCESS) | |
224 | return EIO; | |
225 | ||
226 | if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_MEMBERSHIP) != 0) | |
227 | { | |
228 | *ismember = ((request.el_flags & KAUTH_EXTLOOKUP_ISMEMBER) != 0); | |
229 | } | |
230 | else | |
231 | error = ENOENT; | |
232 | ||
233 | return error; | |
234 | } | |
235 | ||
236 | int mbr_reset_cache() | |
237 | { | |
238 | kern_return_t result; | |
239 | result = _mbr_ClearCache(GetServerPort()); | |
240 | if (result != KERN_SUCCESS) | |
241 | return EIO; | |
242 | return 0; | |
243 | } | |
244 | ||
245 | int mbr_user_name_to_uuid(const char* name, uuid_t uu) | |
246 | { | |
247 | kern_return_t result; | |
248 | ||
249 | if (strlen(name) > 255) | |
250 | return EINVAL; | |
251 | ||
252 | result = _mbr_MapName(GetServerPort(), 1, (char*)name, (guid_t*)uu); | |
253 | ||
254 | if (result == KERN_FAILURE) | |
255 | return ENOENT; | |
256 | else if (result != KERN_SUCCESS) | |
257 | return EIO; | |
258 | ||
259 | return 0; | |
260 | } | |
261 | ||
262 | int mbr_group_name_to_uuid(const char* name, uuid_t uu) | |
263 | { | |
264 | kern_return_t result; | |
265 | ||
266 | if (strlen(name) > 255) | |
267 | return EINVAL; | |
268 | ||
269 | result = _mbr_MapName(GetServerPort(), 0, (char*)name, (guid_t*)uu); | |
270 | ||
271 | if (result == KERN_FAILURE) | |
272 | return ENOENT; | |
273 | else if (result != KERN_SUCCESS) | |
274 | return EIO; | |
275 | ||
276 | return 0; | |
277 | } | |
278 | ||
279 | int mbr_check_service_membership(const uuid_t user, const char* servicename, int* ismember) | |
280 | { | |
281 | char* prefix = "com.apple.access_"; | |
282 | char* all_services = "com.apple.access_all_services"; | |
283 | char groupName[256]; | |
284 | uuid_t group_uu; | |
918ca66e | 285 | int result, dummy; |
c29f2fcc A |
286 | |
287 | if (strlen(servicename) > 255 - strlen(prefix)) | |
288 | return EINVAL; | |
289 | ||
290 | // start by checking "all services" | |
291 | result = mbr_group_name_to_uuid(all_services, group_uu); | |
292 | ||
293 | if (result == ENOENT) | |
294 | { | |
295 | // all_services group didn't exist, check individual group | |
296 | memcpy(groupName, prefix, strlen(prefix)); | |
297 | strcpy(groupName + strlen(prefix), servicename); | |
298 | result = mbr_group_name_to_uuid(groupName, group_uu); | |
299 | } | |
300 | ||
301 | if (result == 0) | |
918ca66e A |
302 | result = mbr_check_membership_refresh(user, group_uu, ismember); |
303 | else | |
304 | { | |
305 | // just force cache update with bogus membership check | |
306 | memset(group_uu, 0, sizeof(group_uu)); | |
307 | mbr_check_membership_refresh(user, group_uu, &dummy); | |
308 | } | |
c29f2fcc A |
309 | |
310 | return result; | |
311 | } | |
312 | ||
313 | static char* ConvertBytesToDecimal(char* buffer, unsigned long long value) | |
314 | { | |
315 | char* temp; | |
316 | buffer[24] = '\0'; | |
317 | buffer[23] = '0'; | |
318 | ||
319 | if (value == 0) | |
320 | return &buffer[23]; | |
321 | ||
322 | temp = &buffer[24]; | |
323 | while (value != 0) | |
324 | { | |
325 | temp--; | |
326 | *temp = '0' + (value % 10); | |
327 | value /= 10; | |
328 | } | |
329 | ||
330 | return temp; | |
331 | } | |
332 | ||
333 | int mbr_sid_to_string(const nt_sid_t* sid, char* string) | |
334 | { | |
335 | char* current = string; | |
336 | long long temp = 0; | |
337 | int i; | |
338 | char tempBuffer[25]; | |
339 | ||
340 | if (sid->sid_authcount > NTSID_MAX_AUTHORITIES) | |
341 | return EINVAL; | |
342 | ||
918ca66e A |
343 | for (i = 0; i < 6; i++) |
344 | temp = (temp << 8) | sid->sid_authority[i]; | |
c29f2fcc A |
345 | |
346 | current[0] = 'S'; | |
347 | current[1] = '-'; | |
348 | current += 2; | |
349 | strcpy(current, ConvertBytesToDecimal(tempBuffer, sid->sid_kind)); | |
350 | current = current + strlen(current); | |
351 | *current = '-'; | |
352 | current++; | |
353 | strcpy(current, ConvertBytesToDecimal(tempBuffer, temp)); | |
354 | ||
355 | for(i=0; i < sid->sid_authcount; i++) | |
356 | { | |
357 | current = current + strlen(current); | |
358 | *current = '-'; | |
359 | current++; | |
360 | strcpy(current, ConvertBytesToDecimal(tempBuffer, sid->sid_authorities[i])); | |
361 | } | |
362 | ||
363 | return 0; | |
364 | } | |
365 | ||
366 | int mbr_string_to_sid(const char* string, nt_sid_t* sid) | |
367 | { | |
368 | char* current = string+2; | |
369 | int count = 0; | |
370 | long long temp; | |
371 | ||
372 | memset(sid, 0, sizeof(nt_sid_t)); | |
373 | if (string[0] != 'S' || string[1] != '-') return EINVAL; | |
374 | ||
375 | sid->sid_kind = strtol(current, ¤t, 10); | |
376 | if (*current == '\0') return EINVAL; | |
377 | current++; | |
378 | temp = strtoll(current, ¤t, 10); | |
918ca66e A |
379 | // convert to BigEndian before copying |
380 | temp = OSSwapHostToBigInt64(temp); | |
c29f2fcc A |
381 | memcpy(sid->sid_authority, ((char*)&temp)+2, 6); |
382 | while (*current != '\0' && count < NTSID_MAX_AUTHORITIES) | |
383 | { | |
384 | current++; | |
385 | sid->sid_authorities[count] = strtol(current, ¤t, 10); | |
386 | count++; | |
387 | } | |
388 | ||
389 | if (*current != '\0') | |
390 | return EINVAL; | |
391 | ||
392 | sid->sid_authcount = count; | |
393 | ||
394 | return 0; | |
395 | } | |
396 | ||
397 | static void ConvertBytesToHex(char** string, char** data, int numBytes) | |
398 | { | |
399 | int i; | |
400 | ||
401 | for (i=0; i < numBytes; i++) | |
402 | { | |
403 | unsigned char hi = ((**data) >> 4) & 0xf; | |
404 | unsigned char low = (**data) & 0xf; | |
405 | if (hi < 10) | |
406 | **string = '0' + hi; | |
407 | else | |
408 | **string = 'A' + hi - 10; | |
409 | ||
410 | (*string)++; | |
411 | ||
412 | if (low < 10) | |
413 | **string = '0' + low; | |
414 | else | |
415 | **string = 'A' + low - 10; | |
416 | ||
417 | (*string)++; | |
418 | (*data)++; | |
419 | } | |
420 | } | |
421 | ||
422 | int mbr_uuid_to_string(const uuid_t uu, char* string) | |
423 | { | |
424 | char* guid = (char*)uu; | |
425 | char* strPtr = string; | |
426 | ConvertBytesToHex(&strPtr, &guid, 4); | |
427 | *strPtr = '-'; strPtr++; | |
428 | ConvertBytesToHex(&strPtr, &guid, 2); | |
429 | *strPtr = '-'; strPtr++; | |
430 | ConvertBytesToHex(&strPtr, &guid, 2); | |
431 | *strPtr = '-'; strPtr++; | |
432 | ConvertBytesToHex(&strPtr, &guid, 2); | |
433 | *strPtr = '-'; strPtr++; | |
434 | ConvertBytesToHex(&strPtr, &guid, 6); | |
435 | *strPtr = '\0'; | |
436 | ||
437 | return 0; | |
438 | } | |
439 | ||
440 | int mbr_string_to_uuid(const char* string, uuid_t uu) | |
441 | { | |
442 | short dataIndex = 0; | |
443 | int isFirstNibble = 1; | |
444 | ||
445 | if (strlen(string) > MBR_UU_STRING_SIZE) | |
446 | return EINVAL; | |
447 | ||
448 | while (*string != '\0' && dataIndex < 16) | |
449 | { | |
450 | char nibble; | |
451 | ||
452 | if (*string >= '0' && *string <= '9') | |
453 | nibble = *string - '0'; | |
454 | else if (*string >= 'A' && *string <= 'F') | |
455 | nibble = *string - 'A' + 10; | |
456 | else if (*string >= 'a' && *string <= 'f') | |
457 | nibble = *string - 'a' + 10; | |
458 | else | |
459 | { | |
460 | if (*string != '-') | |
461 | return EINVAL; | |
462 | string++; | |
463 | continue; | |
464 | } | |
465 | ||
466 | if (isFirstNibble) | |
467 | { | |
468 | uu[dataIndex] = nibble << 4; | |
469 | isFirstNibble = 0; | |
470 | } | |
471 | else | |
472 | { | |
473 | uu[dataIndex] |= nibble; | |
474 | dataIndex++; | |
475 | isFirstNibble = 1; | |
476 | } | |
477 | ||
478 | string++; | |
479 | } | |
480 | ||
481 | if (dataIndex != 16) | |
482 | return EINVAL; | |
483 | ||
484 | return 0; | |
485 | } | |
486 |