2 * Copyright (c) 2004-2007 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
23 #include "membership.h"
24 #include "membershipPriv.h"
25 #include "DSmemberdMIG.h"
26 #include "DSmemberdMIG_types.h"
27 #include <sys/errno.h>
28 #include <mach/mach.h>
29 #include <servers/bootstrap.h>
31 #include <libkern/OSByteOrder.h>
34 extern mach_port_t _ds_port
;
35 extern int _ds_running(void);
37 static const uint8_t _mbr_root_uuid
[] = {0xff, 0xff, 0xee, 0xee, 0xdd, 0xdd, 0xcc, 0xcc, 0xbb, 0xbb, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00};
39 #define MAX_LOOKUP_ATTEMPTS 10
41 __private_extern__ uid_t
42 audit_token_uid(audit_token_t a
)
45 * This should really call audit_token_to_au32,
46 * but that's in libbsm, not in a Libsystem library.
48 return (uid_t
)a
.val
[1];
52 _mbr_MembershipCall(struct kauth_identity_extlookup
*req
)
58 if (_ds_running() == 0) return EIO
;
59 if (_ds_port
== MACH_PORT_NULL
) return EIO
;
61 memset(&token
, 0, sizeof(audit_token_t
));
63 status
= MIG_SERVER_DIED
;
64 for (i
= 0; (_ds_port
!= MACH_PORT_NULL
) && (status
== MIG_SERVER_DIED
) && (i
< MAX_LOOKUP_ATTEMPTS
); i
++)
66 status
= memberdDSmig_MembershipCall(_ds_port
, req
, &token
);
67 if (status
== MACH_SEND_INVALID_DEST
)
69 mach_port_mod_refs(mach_task_self(), _ds_port
, MACH_PORT_RIGHT_SEND
, -1);
70 _ds_port
= MACH_PORT_NULL
;
72 status
= MIG_SERVER_DIED
;
76 if (status
!= KERN_SUCCESS
) return EIO
;
77 if (audit_token_uid(token
) != 0) return EAUTH
;
83 _mbr_MapName(char *name
, int type
, guid_t
*uu
)
89 if (name
== NULL
) return EINVAL
;
90 if (strlen(name
) > 255) return EINVAL
;
92 if (_ds_running() == 0) return EIO
;
93 if (_ds_port
== MACH_PORT_NULL
) return EIO
;
95 memset(&token
, 0, sizeof(audit_token_t
));
97 status
= MIG_SERVER_DIED
;
98 for (i
= 0; (_ds_port
!= MACH_PORT_NULL
) && (status
== MIG_SERVER_DIED
) && (i
< MAX_LOOKUP_ATTEMPTS
); i
++)
100 status
= memberdDSmig_MapName(_ds_port
, type
, name
, uu
, &token
);
101 if (status
== KERN_FAILURE
) return ENOENT
;
103 if (status
== MACH_SEND_INVALID_DEST
)
105 mach_port_mod_refs(mach_task_self(), _ds_port
, MACH_PORT_RIGHT_SEND
, -1);
106 _ds_port
= MACH_PORT_NULL
;
108 status
= MIG_SERVER_DIED
;
112 if (status
!= KERN_SUCCESS
) return EIO
;
113 if (audit_token_uid(token
) != 0) return EAUTH
;
121 kern_return_t status
;
124 if (_ds_running() == 0) return EIO
;
125 if (_ds_port
== MACH_PORT_NULL
) return EIO
;
127 status
= MIG_SERVER_DIED
;
128 for (i
= 0; (_ds_port
!= MACH_PORT_NULL
) && (status
== MIG_SERVER_DIED
) && (i
< MAX_LOOKUP_ATTEMPTS
); i
++)
130 status
= memberdDSmig_ClearCache(_ds_port
);
131 if (status
== MACH_SEND_INVALID_DEST
)
133 mach_port_mod_refs(mach_task_self(), _ds_port
, MACH_PORT_RIGHT_SEND
, -1);
134 _ds_port
= MACH_PORT_NULL
;
136 status
= MIG_SERVER_DIED
;
140 if (status
!= KERN_SUCCESS
) return EIO
;
145 int mbr_uid_to_uuid(uid_t id
, uuid_t uu
)
147 struct kauth_identity_extlookup request
;
152 memcpy(uu
, _mbr_root_uuid
, sizeof(uuid_t
));
156 /* used as a byte order field */
157 request
.el_seqno
= 1;
158 request
.el_flags
= KAUTH_EXTLOOKUP_VALID_UID
| KAUTH_EXTLOOKUP_WANT_UGUID
;
161 status
= _mbr_MembershipCall(&request
);
162 if (status
!= 0) return status
;
163 if ((request
.el_flags
& KAUTH_EXTLOOKUP_VALID_UGUID
) == 0) return ENOENT
;
165 memcpy(uu
, &request
.el_uguid
, sizeof(guid_t
));
169 int mbr_gid_to_uuid(gid_t id
, uuid_t uu
)
171 struct kauth_identity_extlookup request
;
174 request
.el_seqno
= 1;
175 request
.el_flags
= KAUTH_EXTLOOKUP_VALID_GID
| KAUTH_EXTLOOKUP_WANT_GGUID
;
178 status
= _mbr_MembershipCall(&request
);
179 if (status
!= 0) return status
;
180 if ((request
.el_flags
& KAUTH_EXTLOOKUP_VALID_GGUID
) == 0) return ENOENT
;
182 memcpy(uu
, &request
.el_gguid
, sizeof(guid_t
));
186 int mbr_uuid_to_id(const uuid_t uu
, uid_t
*id
, int *id_type
)
188 struct kauth_identity_extlookup request
;
191 if (id
== NULL
) return EIO
;
192 if (id_type
== NULL
) return EIO
;
194 if (!memcmp(uu
, _mbr_root_uuid
, sizeof(uuid_t
)))
197 *id_type
= ID_TYPE_UID
;
201 request
.el_seqno
= 1;
202 request
.el_flags
= KAUTH_EXTLOOKUP_VALID_UGUID
| KAUTH_EXTLOOKUP_VALID_GGUID
| KAUTH_EXTLOOKUP_WANT_UID
| KAUTH_EXTLOOKUP_WANT_GID
;
203 memcpy(&request
.el_uguid
, uu
, sizeof(guid_t
));
204 memcpy(&request
.el_gguid
, uu
, sizeof(guid_t
));
206 status
= _mbr_MembershipCall(&request
);
207 if (status
!= 0) return status
;
209 if ((request
.el_flags
& KAUTH_EXTLOOKUP_VALID_UID
) != 0)
211 *id
= request
.el_uid
;
212 *id_type
= ID_TYPE_UID
;
214 else if ((request
.el_flags
& KAUTH_EXTLOOKUP_VALID_GID
) != 0)
216 *id
= request
.el_gid
;
217 *id_type
= ID_TYPE_GID
;
227 int mbr_sid_to_uuid(const nt_sid_t
*sid
, uuid_t uu
)
229 struct kauth_identity_extlookup request
;
232 request
.el_seqno
= 1;
233 request
.el_flags
= KAUTH_EXTLOOKUP_VALID_GSID
| KAUTH_EXTLOOKUP_WANT_GGUID
| KAUTH_EXTLOOKUP_VALID_USID
| KAUTH_EXTLOOKUP_WANT_UGUID
;
234 memset(&request
.el_gsid
, 0, sizeof(ntsid_t
));
235 memcpy(&request
.el_gsid
, sid
, KAUTH_NTSID_SIZE(sid
));
236 memset(&request
.el_usid
, 0, sizeof(ntsid_t
));
237 memcpy(&request
.el_usid
, sid
, KAUTH_NTSID_SIZE(sid
));
239 status
= _mbr_MembershipCall(&request
);
240 if (status
!= 0) return status
;
242 if ((request
.el_flags
& KAUTH_EXTLOOKUP_VALID_GGUID
) != 0) memcpy(uu
, &request
.el_gguid
, sizeof(guid_t
));
243 else if ((request
.el_flags
& KAUTH_EXTLOOKUP_VALID_UGUID
) != 0) memcpy(uu
, &request
.el_uguid
, sizeof(guid_t
));
249 int mbr_uuid_to_sid_type(const uuid_t uu
, nt_sid_t
*sid
, int *id_type
)
251 struct kauth_identity_extlookup request
;
254 request
.el_seqno
= 1;
255 request
.el_flags
= KAUTH_EXTLOOKUP_VALID_UGUID
| KAUTH_EXTLOOKUP_VALID_GGUID
| KAUTH_EXTLOOKUP_WANT_USID
| KAUTH_EXTLOOKUP_WANT_GSID
;
256 memcpy(&request
.el_uguid
, uu
, sizeof(guid_t
));
257 memcpy(&request
.el_gguid
, uu
, sizeof(guid_t
));
259 status
= _mbr_MembershipCall(&request
);
260 if (status
!= 0) return status
;
262 if ((request
.el_flags
& KAUTH_EXTLOOKUP_VALID_USID
) != 0)
264 *id_type
= SID_TYPE_USER
;
265 memcpy(sid
, &request
.el_usid
, sizeof(nt_sid_t
));
267 else if ((request
.el_flags
& KAUTH_EXTLOOKUP_VALID_GSID
) != 0)
269 *id_type
= SID_TYPE_GROUP
;
270 memcpy(sid
, &request
.el_gsid
, sizeof(nt_sid_t
));
280 int mbr_uuid_to_sid(const uuid_t uu
, nt_sid_t
*sid
)
286 status
= mbr_uuid_to_sid_type(uu
, sid
, &type
);
287 if (status
!= 0) return status
;
292 int mbr_check_membership(uuid_t user
, uuid_t group
, int *ismember
)
294 struct kauth_identity_extlookup request
;
297 request
.el_seqno
= 1;
298 request
.el_flags
= KAUTH_EXTLOOKUP_VALID_UGUID
| KAUTH_EXTLOOKUP_VALID_GGUID
| KAUTH_EXTLOOKUP_WANT_MEMBERSHIP
;
299 memcpy(&request
.el_uguid
, user
, sizeof(guid_t
));
300 memcpy(&request
.el_gguid
, group
, sizeof(guid_t
));
302 status
= _mbr_MembershipCall(&request
);
303 if (status
!= 0) return status
;
304 if ((request
.el_flags
& KAUTH_EXTLOOKUP_VALID_MEMBERSHIP
) == 0) return ENOENT
;
306 *ismember
= ((request
.el_flags
& KAUTH_EXTLOOKUP_ISMEMBER
) != 0);
310 int mbr_check_membership_refresh(const uuid_t user
, uuid_t group
, int *ismember
)
312 struct kauth_identity_extlookup request
;
315 request
.el_seqno
= 1;
316 request
.el_flags
= KAUTH_EXTLOOKUP_VALID_UGUID
| KAUTH_EXTLOOKUP_VALID_GGUID
| KAUTH_EXTLOOKUP_WANT_MEMBERSHIP
| (1<<15);
317 memcpy(&request
.el_uguid
, user
, sizeof(guid_t
));
318 memcpy(&request
.el_gguid
, group
, sizeof(guid_t
));
320 status
= _mbr_MembershipCall(&request
);
321 if (status
!= 0) return status
;
322 if ((request
.el_flags
& KAUTH_EXTLOOKUP_VALID_MEMBERSHIP
) == 0) return ENOENT
;
324 *ismember
= ((request
.el_flags
& KAUTH_EXTLOOKUP_ISMEMBER
) != 0);
328 int mbr_check_membership_by_id(uuid_t user
, gid_t group
, int *ismember
)
330 struct kauth_identity_extlookup request
;
333 request
.el_seqno
= 1;
334 request
.el_flags
= KAUTH_EXTLOOKUP_VALID_UGUID
| KAUTH_EXTLOOKUP_VALID_GID
| KAUTH_EXTLOOKUP_WANT_MEMBERSHIP
;
335 memcpy(&request
.el_uguid
, user
, sizeof(guid_t
));
336 request
.el_gid
= group
;
338 status
= _mbr_MembershipCall(&request
);
339 if (status
!= 0) return status
;
340 if ((request
.el_flags
& KAUTH_EXTLOOKUP_VALID_MEMBERSHIP
) == 0) return ENOENT
;
342 *ismember
= ((request
.el_flags
& KAUTH_EXTLOOKUP_ISMEMBER
) != 0);
346 int mbr_reset_cache()
348 return _mbr_ClearCache();
351 int mbr_user_name_to_uuid(const char *name
, uuid_t uu
)
353 return _mbr_MapName((char *)name
, 1, (guid_t
*)uu
);
356 int mbr_group_name_to_uuid(const char *name
, uuid_t uu
)
358 return _mbr_MapName((char *)name
, 0, (guid_t
*)uu
);
361 int mbr_check_service_membership(const uuid_t user
, const char *servicename
, int *ismember
)
363 char *prefix
= "com.apple.access_";
364 char *all_services
= "com.apple.access_all_services";
369 if (servicename
== NULL
) return EINVAL
;
370 if (strlen(servicename
) > 255 - strlen(prefix
)) return EINVAL
;
372 /* start by checking "all services" */
373 result
= mbr_group_name_to_uuid(all_services
, group_uu
);
375 if (result
== EAUTH
) return result
;
377 if (result
== ENOENT
)
379 /* all_services group didn't exist, check individual group */
380 memcpy(groupName
, prefix
, strlen(prefix
));
381 strcpy(groupName
+ strlen(prefix
), servicename
);
382 result
= mbr_group_name_to_uuid(groupName
, group_uu
);
387 result
= mbr_check_membership_refresh(user
, group_uu
, ismember
);
389 else if (result
== EAUTH
)
395 /* just force cache update with bogus membership check */
396 memset(group_uu
, 0, sizeof(group_uu
));
397 mbr_check_membership_refresh(user
, group_uu
, &dummy
);
403 static char *ConvertBytesToDecimal(char *buffer
, unsigned long long value
)
416 *temp
= '0' + (value
% 10);
423 int mbr_sid_to_string(const nt_sid_t
*sid
, char *string
)
425 char *current
= string
;
430 if (sid
->sid_authcount
> NTSID_MAX_AUTHORITIES
) return EINVAL
;
432 for (i
= 0; i
< 6; i
++)
433 temp
= (temp
<< 8) | sid
->sid_authority
[i
];
438 strcpy(current
, ConvertBytesToDecimal(tempBuffer
, sid
->sid_kind
));
439 current
= current
+ strlen(current
);
442 strcpy(current
, ConvertBytesToDecimal(tempBuffer
, temp
));
444 for(i
=0; i
< sid
->sid_authcount
; i
++)
446 current
= current
+ strlen(current
);
449 strcpy(current
, ConvertBytesToDecimal(tempBuffer
, sid
->sid_authorities
[i
]));
455 int mbr_string_to_sid(const char *string
, nt_sid_t
*sid
)
457 char *current
= (char *)string
+2;
461 if (string
== NULL
) return EINVAL
;
463 memset(sid
, 0, sizeof(nt_sid_t
));
464 if (string
[0] != 'S' || string
[1] != '-') return EINVAL
;
466 sid
->sid_kind
= strtol(current
, ¤t
, 10);
467 if (*current
== '\0') return EINVAL
;
469 temp
= strtoll(current
, ¤t
, 10);
471 /* convert to BigEndian before copying */
472 temp
= OSSwapHostToBigInt64(temp
);
473 memcpy(sid
->sid_authority
, ((char*)&temp
)+2, 6);
474 while (*current
!= '\0' && count
< NTSID_MAX_AUTHORITIES
)
477 sid
->sid_authorities
[count
] = (u_int32_t
)strtoll(current
, ¤t
, 10);
481 if (*current
!= '\0') return EINVAL
;
483 sid
->sid_authcount
= count
;
488 static void ConvertBytesToHex(char **string
, char **data
, int numBytes
)
492 for (i
=0; i
< numBytes
; i
++)
494 unsigned char hi
= ((**data
) >> 4) & 0xf;
495 unsigned char low
= (**data
) & 0xf;
499 **string
= 'A' + hi
- 10;
504 **string
= '0' + low
;
506 **string
= 'A' + low
- 10;
513 int mbr_uuid_to_string(const uuid_t uu
, char *string
)
515 char *guid
= (char*)uu
;
516 char *strPtr
= string
;
517 ConvertBytesToHex(&strPtr
, &guid
, 4);
518 *strPtr
= '-'; strPtr
++;
519 ConvertBytesToHex(&strPtr
, &guid
, 2);
520 *strPtr
= '-'; strPtr
++;
521 ConvertBytesToHex(&strPtr
, &guid
, 2);
522 *strPtr
= '-'; strPtr
++;
523 ConvertBytesToHex(&strPtr
, &guid
, 2);
524 *strPtr
= '-'; strPtr
++;
525 ConvertBytesToHex(&strPtr
, &guid
, 6);
531 int mbr_string_to_uuid(const char *string
, uuid_t uu
)
534 int isFirstNibble
= 1;
536 if (string
== NULL
) return EINVAL
;
537 if (strlen(string
) > MBR_UU_STRING_SIZE
) return EINVAL
;
539 while (*string
!= '\0' && dataIndex
< 16)
543 if (*string
>= '0' && *string
<= '9')
544 nibble
= *string
- '0';
545 else if (*string
>= 'A' && *string
<= 'F')
546 nibble
= *string
- 'A' + 10;
547 else if (*string
>= 'a' && *string
<= 'f')
548 nibble
= *string
- 'a' + 10;
559 uu
[dataIndex
] = nibble
<< 4;
564 uu
[dataIndex
] |= nibble
;
572 if (dataIndex
!= 16) return EINVAL
;