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