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