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