]>
Commit | Line | Data |
---|---|---|
c29f2fcc | 1 | /* |
1d9e5cb8 | 2 | * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. |
c29f2fcc A |
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> | |
1d9e5cb8 | 31 | #import <libkern/OSByteOrder.h> |
c29f2fcc A |
32 | |
33 | static mach_port_t GetServerPort() | |
34 | { | |
35 | kern_return_t result; | |
1d9e5cb8 A |
36 | static mach_port_t bsPort = 0; |
37 | static mach_port_t fServerPort = 0; | |
38 | ||
c29f2fcc A |
39 | if (bsPort == 0) |
40 | { | |
1d9e5cb8 A |
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 | // } | |
c29f2fcc A |
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 | ||
1d9e5cb8 | 59 | request.el_seqno = 1; // used as byte order field |
c29f2fcc A |
60 | request.el_flags = KAUTH_EXTLOOKUP_VALID_UID | KAUTH_EXTLOOKUP_WANT_UGUID; |
61 | request.el_uid = id; | |
1d9e5cb8 A |
62 | result = _mbr_DoMembershipCall(GetServerPort(), &request); |
63 | if (result != KERN_SUCCESS) | |
64 | return EIO; | |
65 | ||
c29f2fcc A |
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 | ||
1d9e5cb8 | 80 | request.el_seqno = 1; // used as byte order field |
c29f2fcc A |
81 | request.el_flags = KAUTH_EXTLOOKUP_VALID_GID | KAUTH_EXTLOOKUP_WANT_GGUID; |
82 | request.el_gid = id; | |
1d9e5cb8 A |
83 | result = _mbr_DoMembershipCall(GetServerPort(), &request); |
84 | if (result != KERN_SUCCESS) | |
85 | return EIO; | |
86 | ||
c29f2fcc A |
87 | if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GGUID) != 0) |
88 | memcpy(uu, &request.el_gguid, sizeof(guid_t)); | |
89 | else | |
90 | error = ENOENT; | |
1d9e5cb8 | 91 | |
c29f2fcc A |
92 | return error; |
93 | } | |
94 | ||
1d9e5cb8 | 95 | int mbr_uuid_to_id( const uuid_t uu, uid_t* id, int* id_type) |
c29f2fcc A |
96 | { |
97 | struct kauth_identity_extlookup request; | |
98 | kern_return_t result; | |
99 | int error = 0; | |
100 | ||
1d9e5cb8 A |
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; | |
c29f2fcc A |
104 | memcpy(&request.el_uguid, uu, sizeof(guid_t)); |
105 | memcpy(&request.el_gguid, uu, sizeof(guid_t)); | |
1d9e5cb8 A |
106 | result = _mbr_DoMembershipCall(GetServerPort(), &request); |
107 | if (result != KERN_SUCCESS) | |
108 | return EIO; | |
109 | ||
c29f2fcc A |
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; | |
1d9e5cb8 | 122 | |
c29f2fcc A |
123 | return error; |
124 | } | |
125 | ||
1d9e5cb8 | 126 | int mbr_sid_to_uuid(const nt_sid_t* sid, uuid_t uu) |
c29f2fcc A |
127 | { |
128 | struct kauth_identity_extlookup request; | |
129 | kern_return_t result; | |
130 | int error = 0; | |
131 | ||
1d9e5cb8 | 132 | request.el_seqno = 1; // used as byte order field |
c29f2fcc A |
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)); | |
1d9e5cb8 A |
136 | result = _mbr_DoMembershipCall(GetServerPort(), &request); |
137 | if (result != KERN_SUCCESS) | |
138 | return EIO; | |
139 | ||
c29f2fcc A |
140 | if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GGUID) != 0) |
141 | memcpy(uu, &request.el_gguid, sizeof(guid_t)); | |
142 | else | |
143 | error = ENOENT; | |
1d9e5cb8 | 144 | |
c29f2fcc A |
145 | return error; |
146 | } | |
147 | ||
1d9e5cb8 | 148 | int mbr_uuid_to_sid(const uuid_t uu, nt_sid_t* sid) |
c29f2fcc A |
149 | { |
150 | struct kauth_identity_extlookup request; | |
151 | kern_return_t result; | |
152 | int error = 0; | |
153 | ||
1d9e5cb8 | 154 | request.el_seqno = 1; // used as byte order field |
c29f2fcc A |
155 | request.el_flags = KAUTH_EXTLOOKUP_VALID_GGUID | KAUTH_EXTLOOKUP_WANT_GSID; |
156 | memcpy(&request.el_gguid, uu, sizeof(guid_t)); | |
1d9e5cb8 A |
157 | result = _mbr_DoMembershipCall(GetServerPort(), &request); |
158 | if (result != KERN_SUCCESS) | |
159 | return EIO; | |
160 | ||
c29f2fcc A |
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; | |
1d9e5cb8 | 165 | |
c29f2fcc A |
166 | return error; |
167 | } | |
168 | ||
1d9e5cb8 | 169 | int mbr_check_membership(uuid_t user, uuid_t group, int* ismember) |
c29f2fcc A |
170 | { |
171 | struct kauth_identity_extlookup request; | |
172 | kern_return_t result; | |
173 | int error = 0; | |
174 | ||
1d9e5cb8 A |
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; | |
c29f2fcc A |
178 | memcpy(&request.el_uguid, user, sizeof(guid_t)); |
179 | memcpy(&request.el_gguid, group, sizeof(guid_t)); | |
1d9e5cb8 A |
180 | result = _mbr_DoMembershipCall(GetServerPort(), &request); |
181 | if (result != KERN_SUCCESS) | |
182 | return EIO; | |
183 | ||
c29f2fcc | 184 | if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_MEMBERSHIP) != 0) |
1d9e5cb8 | 185 | { |
c29f2fcc | 186 | *ismember = ((request.el_flags & KAUTH_EXTLOOKUP_ISMEMBER) != 0); |
1d9e5cb8 | 187 | } |
c29f2fcc A |
188 | else |
189 | error = ENOENT; | |
1d9e5cb8 | 190 | |
c29f2fcc A |
191 | return error; |
192 | } | |
193 | ||
1d9e5cb8 | 194 | int mbr_check_membership_refresh(uuid_t user, uuid_t group, int* ismember) |
918ca66e A |
195 | { |
196 | struct kauth_identity_extlookup request; | |
197 | kern_return_t result; | |
198 | int error = 0; | |
199 | ||
1d9e5cb8 A |
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); | |
918ca66e A |
203 | memcpy(&request.el_uguid, user, sizeof(guid_t)); |
204 | memcpy(&request.el_gguid, group, sizeof(guid_t)); | |
1d9e5cb8 A |
205 | result = _mbr_DoMembershipCall(GetServerPort(), &request); |
206 | if (result != KERN_SUCCESS) | |
207 | return EIO; | |
208 | ||
918ca66e | 209 | if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_MEMBERSHIP) != 0) |
1d9e5cb8 | 210 | { |
918ca66e | 211 | *ismember = ((request.el_flags & KAUTH_EXTLOOKUP_ISMEMBER) != 0); |
1d9e5cb8 | 212 | } |
918ca66e A |
213 | else |
214 | error = ENOENT; | |
1d9e5cb8 | 215 | |
918ca66e A |
216 | return error; |
217 | } | |
218 | ||
1d9e5cb8 | 219 | int mbr_check_membership_by_id(uuid_t user, gid_t group, int* ismember) |
c29f2fcc A |
220 | { |
221 | struct kauth_identity_extlookup request; | |
222 | kern_return_t result; | |
223 | int error = 0; | |
224 | ||
1d9e5cb8 A |
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; | |
c29f2fcc A |
228 | memcpy(&request.el_uguid, user, sizeof(guid_t)); |
229 | request.el_gid = group; | |
1d9e5cb8 A |
230 | result = _mbr_DoMembershipCall(GetServerPort(), &request); |
231 | if (result != KERN_SUCCESS) | |
232 | return EIO; | |
233 | ||
c29f2fcc | 234 | if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_MEMBERSHIP) != 0) |
1d9e5cb8 | 235 | { |
c29f2fcc | 236 | *ismember = ((request.el_flags & KAUTH_EXTLOOKUP_ISMEMBER) != 0); |
1d9e5cb8 | 237 | } |
c29f2fcc A |
238 | else |
239 | error = ENOENT; | |
1d9e5cb8 | 240 | |
c29f2fcc A |
241 | return error; |
242 | } | |
243 | ||
244 | int mbr_reset_cache() | |
245 | { | |
246 | kern_return_t result; | |
1d9e5cb8 A |
247 | result = _mbr_ClearCache(GetServerPort()); |
248 | if (result != KERN_SUCCESS) | |
249 | return EIO; | |
c29f2fcc A |
250 | return 0; |
251 | } | |
252 | ||
1d9e5cb8 | 253 | int mbr_user_name_to_uuid(const char* name, uuid_t uu) |
c29f2fcc A |
254 | { |
255 | kern_return_t result; | |
1d9e5cb8 A |
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 | ||
c29f2fcc A |
267 | return 0; |
268 | } | |
269 | ||
1d9e5cb8 | 270 | int mbr_group_name_to_uuid(const char* name, uuid_t uu) |
c29f2fcc A |
271 | { |
272 | kern_return_t result; | |
1d9e5cb8 A |
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 | ||
c29f2fcc A |
284 | return 0; |
285 | } | |
286 | ||
1d9e5cb8 | 287 | int mbr_check_service_membership(const uuid_t user, const char* servicename, int* ismember) |
c29f2fcc | 288 | { |
1d9e5cb8 A |
289 | char* prefix = "com.apple.access_"; |
290 | char* all_services = "com.apple.access_all_services"; | |
c29f2fcc A |
291 | char groupName[256]; |
292 | uuid_t group_uu; | |
918ca66e | 293 | int result, dummy; |
1d9e5cb8 A |
294 | |
295 | if (strlen(servicename) > 255 - strlen(prefix)) | |
296 | return EINVAL; | |
297 | ||
298 | // start by checking "all services" | |
c29f2fcc | 299 | result = mbr_group_name_to_uuid(all_services, group_uu); |
1d9e5cb8 | 300 | |
c29f2fcc A |
301 | if (result == ENOENT) |
302 | { | |
1d9e5cb8 | 303 | // all_services group didn't exist, check individual group |
c29f2fcc A |
304 | memcpy(groupName, prefix, strlen(prefix)); |
305 | strcpy(groupName + strlen(prefix), servicename); | |
306 | result = mbr_group_name_to_uuid(groupName, group_uu); | |
307 | } | |
1d9e5cb8 | 308 | |
c29f2fcc | 309 | if (result == 0) |
918ca66e A |
310 | result = mbr_check_membership_refresh(user, group_uu, ismember); |
311 | else | |
312 | { | |
1d9e5cb8 | 313 | // just force cache update with bogus membership check |
918ca66e A |
314 | memset(group_uu, 0, sizeof(group_uu)); |
315 | mbr_check_membership_refresh(user, group_uu, &dummy); | |
316 | } | |
1d9e5cb8 | 317 | |
c29f2fcc A |
318 | return result; |
319 | } | |
320 | ||
1d9e5cb8 | 321 | static char* ConvertBytesToDecimal(char* buffer, unsigned long long value) |
c29f2fcc | 322 | { |
1d9e5cb8 | 323 | char* temp; |
c29f2fcc A |
324 | buffer[24] = '\0'; |
325 | buffer[23] = '0'; | |
1d9e5cb8 A |
326 | |
327 | if (value == 0) | |
328 | return &buffer[23]; | |
329 | ||
c29f2fcc A |
330 | temp = &buffer[24]; |
331 | while (value != 0) | |
332 | { | |
333 | temp--; | |
334 | *temp = '0' + (value % 10); | |
335 | value /= 10; | |
336 | } | |
1d9e5cb8 | 337 | |
c29f2fcc A |
338 | return temp; |
339 | } | |
340 | ||
1d9e5cb8 | 341 | int mbr_sid_to_string(const nt_sid_t* sid, char* string) |
c29f2fcc | 342 | { |
1d9e5cb8 | 343 | char* current = string; |
c29f2fcc A |
344 | long long temp = 0; |
345 | int i; | |
346 | char tempBuffer[25]; | |
1d9e5cb8 A |
347 | |
348 | if (sid->sid_authcount > NTSID_MAX_AUTHORITIES) | |
349 | return EINVAL; | |
350 | ||
918ca66e A |
351 | for (i = 0; i < 6; i++) |
352 | temp = (temp << 8) | sid->sid_authority[i]; | |
1d9e5cb8 | 353 | |
c29f2fcc A |
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)); | |
1d9e5cb8 A |
362 | |
363 | for(i=0; i < sid->sid_authcount; i++) | |
c29f2fcc A |
364 | { |
365 | current = current + strlen(current); | |
366 | *current = '-'; | |
367 | current++; | |
368 | strcpy(current, ConvertBytesToDecimal(tempBuffer, sid->sid_authorities[i])); | |
369 | } | |
1d9e5cb8 | 370 | |
c29f2fcc A |
371 | return 0; |
372 | } | |
373 | ||
1d9e5cb8 | 374 | int mbr_string_to_sid(const char* string, nt_sid_t* sid) |
c29f2fcc | 375 | { |
1d9e5cb8 | 376 | char* current = string+2; |
c29f2fcc A |
377 | int count = 0; |
378 | long long temp; | |
379 | ||
380 | memset(sid, 0, sizeof(nt_sid_t)); | |
1d9e5cb8 A |
381 | if (string[0] != 'S' || string[1] != '-') return EINVAL; |
382 | ||
c29f2fcc A |
383 | sid->sid_kind = strtol(current, ¤t, 10); |
384 | if (*current == '\0') return EINVAL; | |
385 | current++; | |
386 | temp = strtoll(current, ¤t, 10); | |
1d9e5cb8 | 387 | // convert to BigEndian before copying |
918ca66e | 388 | temp = OSSwapHostToBigInt64(temp); |
c29f2fcc | 389 | memcpy(sid->sid_authority, ((char*)&temp)+2, 6); |
1d9e5cb8 | 390 | while (*current != '\0' && count < NTSID_MAX_AUTHORITIES) |
c29f2fcc A |
391 | { |
392 | current++; | |
393 | sid->sid_authorities[count] = strtol(current, ¤t, 10); | |
394 | count++; | |
395 | } | |
1d9e5cb8 A |
396 | |
397 | if (*current != '\0') | |
398 | return EINVAL; | |
399 | ||
c29f2fcc | 400 | sid->sid_authcount = count; |
1d9e5cb8 | 401 | |
c29f2fcc A |
402 | return 0; |
403 | } | |
404 | ||
1d9e5cb8 | 405 | static void ConvertBytesToHex(char** string, char** data, int numBytes) |
c29f2fcc A |
406 | { |
407 | int i; | |
1d9e5cb8 A |
408 | |
409 | for (i=0; i < numBytes; i++) | |
c29f2fcc A |
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; | |
1d9e5cb8 | 417 | |
c29f2fcc A |
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 | ||
1d9e5cb8 | 430 | int mbr_uuid_to_string(const uuid_t uu, char* string) |
c29f2fcc | 431 | { |
1d9e5cb8 A |
432 | char* guid = (char*)uu; |
433 | char* strPtr = string; | |
c29f2fcc A |
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'; | |
1d9e5cb8 | 444 | |
c29f2fcc A |
445 | return 0; |
446 | } | |
447 | ||
1d9e5cb8 | 448 | int mbr_string_to_uuid(const char* string, uuid_t uu) |
c29f2fcc A |
449 | { |
450 | short dataIndex = 0; | |
451 | int isFirstNibble = 1; | |
1d9e5cb8 | 452 | |
c29f2fcc A |
453 | if (strlen(string) > MBR_UU_STRING_SIZE) |
454 | return EINVAL; | |
1d9e5cb8 | 455 | |
c29f2fcc A |
456 | while (*string != '\0' && dataIndex < 16) |
457 | { | |
458 | char nibble; | |
1d9e5cb8 A |
459 | |
460 | if (*string >= '0' && *string <= '9') | |
c29f2fcc | 461 | nibble = *string - '0'; |
1d9e5cb8 | 462 | else if (*string >= 'A' && *string <= 'F') |
c29f2fcc | 463 | nibble = *string - 'A' + 10; |
1d9e5cb8 | 464 | else if (*string >= 'a' && *string <= 'f') |
c29f2fcc A |
465 | nibble = *string - 'a' + 10; |
466 | else | |
467 | { | |
1d9e5cb8 A |
468 | if (*string != '-') |
469 | return EINVAL; | |
c29f2fcc A |
470 | string++; |
471 | continue; | |
472 | } | |
1d9e5cb8 | 473 | |
c29f2fcc A |
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 | } | |
1d9e5cb8 | 485 | |
c29f2fcc A |
486 | string++; |
487 | } | |
1d9e5cb8 A |
488 | |
489 | if (dataIndex != 16) | |
490 | return EINVAL; | |
491 | ||
c29f2fcc A |
492 | return 0; |
493 | } | |
1d9e5cb8 | 494 |