Libinfo-222.3.5.tar.gz
[apple/libinfo.git] / membership.subproj / membership.c
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, &current, 10);
412 if (*current == '\0') return EINVAL;
413 current++;
414 temp = strtoll(current, &current, 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, &current, 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 }