Libinfo-222.1.tar.gz
[apple/libinfo.git] / membership.subproj / membership.c
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>
31 #import <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 // 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
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
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
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;
285 int result, dummy;
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)
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 }
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
343 for (i = 0; i < 6; i++)
344 temp = (temp << 8) | sid->sid_authority[i];
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, &current, 10);
376 if (*current == '\0') return EINVAL;
377 current++;
378 temp = strtoll(current, &current, 10);
379 // convert to BigEndian before copying
380 temp = OSSwapHostToBigInt64(temp);
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, &current, 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