]> git.saurik.com Git - apple/libinfo.git/blobdiff - membership.subproj/membership.c
Libinfo-459.20.1.tar.gz
[apple/libinfo.git] / membership.subproj / membership.c
index a650f90c9244cbc879d97444652214eeb089f9c8..3074ed595495654afb52bc90fe241d7b8fe17809 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2004-2007 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2010 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  *
  *
  * @APPLE_LICENSE_HEADER_START@
  *
  * @APPLE_LICENSE_HEADER_END@
  */
 
  * @APPLE_LICENSE_HEADER_END@
  */
 
-#include "membership.h"
-#include "membershipPriv.h"
-#include "DSmemberdMIG.h"
-#include "DSmemberdMIG_types.h"
+#include <stdlib.h>
 #include <sys/errno.h>
 #include <mach/mach.h>
 #include <sys/errno.h>
 #include <mach/mach.h>
+#include "membership.h"
+#include "membershipPriv.h"
 #include <servers/bootstrap.h>
 #include <servers/bootstrap.h>
-#include <stdlib.h>
 #include <libkern/OSByteOrder.h>
 #include <libkern/OSByteOrder.h>
+#ifdef DS_AVAILABLE
+#include <xpc/xpc.h>
+#include <xpc/private.h>
+#include <opendirectory/odipc.h>
+#include <pthread.h>
+#include <mach-o/dyld_priv.h>
+#endif
+
+static const uuid_t _user_compat_prefix = {0xff, 0xff, 0xee, 0xee, 0xdd, 0xdd, 0xcc, 0xcc, 0xbb, 0xbb, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00};
+static const uuid_t _group_compat_prefix = {0xab, 0xcd, 0xef, 0xab, 0xcd, 0xef, 0xab, 0xcd, 0xef, 0xab, 0xcd, 0xef, 0x00, 0x00, 0x00, 0x00};
 
 
+#define COMPAT_PREFIX_LEN      (sizeof(uuid_t) - sizeof(id_t))
 
 
-extern mach_port_t _ds_port;
-extern int _ds_running(void);
+#ifdef DS_AVAILABLE
 
 
-static const uint8_t _mbr_root_uuid[] = {0xff, 0xff, 0xee, 0xee, 0xdd, 0xdd, 0xcc, 0xcc, 0xbb, 0xbb, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00};
+int _si_opendirectory_disabled;
+static xpc_pipe_t __mbr_pipe; /* use accessor */
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+__private_extern__ xpc_object_t _od_rpc_call(const char *procname, xpc_object_t payload, xpc_pipe_t (*get_pipe)(bool));
 
 
-#define MAX_LOOKUP_ATTEMPTS 10
+#endif
 
 
-__private_extern__ uid_t
-audit_token_uid(audit_token_t a)
+#ifdef DS_AVAILABLE
+static void
+_mbr_fork_child(void)
 {
 {
-       /*
-        * This should really call audit_token_to_au32,
-        * but that's in libbsm, not in a Libsystem library.
-        */
-       return (uid_t)a.val[1];
+       if (__mbr_pipe != NULL) {
+               xpc_pipe_invalidate(__mbr_pipe);
+               /* disable release due to 10649340, it will cause a minor leak for each fork without exec */
+               // xpc_release(__mbr_pipe);
+               __mbr_pipe = NULL;
+       }
+       
+       pthread_mutex_unlock(&mutex);
 }
 }
+#endif
 
 
-static int
-_mbr_MembershipCall(struct kauth_identity_extlookup *req)
+#ifdef DS_AVAILABLE
+static void
+_mbr_fork_prepare(void)
 {
 {
-       audit_token_t token;
-       kern_return_t status;
-       uint32_t i;
-
-       if (_ds_running() == 0) return EIO;
-       if (_ds_port == MACH_PORT_NULL) return EIO;
+       pthread_mutex_lock(&mutex);
+}
+#endif
 
 
-       memset(&token, 0, sizeof(audit_token_t));
+#ifdef DS_AVAILABLE
+static void
+_mbr_fork_parent(void)
+{
+       pthread_mutex_unlock(&mutex);
+}
+#endif
 
 
-       status = MIG_SERVER_DIED;
-       for (i = 0; (_ds_port != MACH_PORT_NULL) && (status == MIG_SERVER_DIED) && (i < MAX_LOOKUP_ATTEMPTS); i++)
-       {
-               status = memberdDSmig_MembershipCall(_ds_port, req, &token);
-               if (status == MACH_SEND_INVALID_DEST)
-               {
-                       mach_port_mod_refs(mach_task_self(), _ds_port, MACH_PORT_RIGHT_SEND, -1);
-                       _ds_port = MACH_PORT_NULL;
-                       _ds_running();
-                       status = MIG_SERVER_DIED;
+#ifdef DS_AVAILABLE
+XPC_RETURNS_RETAINED
+static xpc_pipe_t
+_mbr_xpc_pipe(bool resetPipe)
+{
+       static dispatch_once_t once;
+       xpc_pipe_t pipe = NULL;
+       
+       dispatch_once(&once, ^(void) {
+               char *xbs_disable;
+               
+               /* if this is a build environment we ignore opendirectoryd */
+               xbs_disable = getenv("XBS_DISABLE_LIBINFO");
+               if (xbs_disable != NULL && strcmp(xbs_disable, "YES") == 0) {
+                       _si_opendirectory_disabled = 1;
+                       return;
                }
                }
+               
+               pthread_atfork(_mbr_fork_prepare, _mbr_fork_parent, _mbr_fork_child);
+       });
+       
+       if (_si_opendirectory_disabled == 1) {
+               return NULL;
        }
        }
-
-       if (status != KERN_SUCCESS) return EIO;
-       if (audit_token_uid(token) != 0) return EAUTH;
-
-       return 0;
+       
+       pthread_mutex_lock(&mutex);
+       if (resetPipe) {
+               xpc_release(__mbr_pipe);
+               __mbr_pipe = NULL;
+       }
+       
+       if (__mbr_pipe == NULL) {
+               if (!dyld_process_is_restricted() && getenv("OD_DEBUG_MODE") != NULL) {
+                       __mbr_pipe = xpc_pipe_create(kODMachMembershipPortNameDebug, 0);
+               } else {
+                       __mbr_pipe = xpc_pipe_create(kODMachMembershipPortName, XPC_PIPE_FLAG_PRIVILEGED);
+               }
+       }
+       
+       if (__mbr_pipe != NULL) pipe = xpc_retain(__mbr_pipe);
+       pthread_mutex_unlock(&mutex);
+       
+       return pipe;
 }
 }
+#endif
 
 
-static int
-_mbr_MapName(char *name, int type, guid_t *uu)
+static bool
+_mbr_od_available(void)
 {
 {
-       kern_return_t status;
-       audit_token_t token;
-       uint32_t i;
-
-       if (name == NULL) return EINVAL;
-       if (strlen(name) > 255) return EINVAL;
-
-       if (_ds_running() == 0) return EIO;
-       if (_ds_port == MACH_PORT_NULL) return EIO;
-
-       memset(&token, 0, sizeof(audit_token_t));
-
-       status = MIG_SERVER_DIED;
-       for (i = 0; (_ds_port != MACH_PORT_NULL) && (status == MIG_SERVER_DIED) && (i < MAX_LOOKUP_ATTEMPTS); i++)
-       {
-               status = memberdDSmig_MapName(_ds_port, type, name, uu, &token);
-               if (status == KERN_FAILURE) return ENOENT;
-
-               if (status == MACH_SEND_INVALID_DEST)
-               {
-                       mach_port_mod_refs(mach_task_self(), _ds_port, MACH_PORT_RIGHT_SEND, -1);
-                       _ds_port = MACH_PORT_NULL;
-                       _ds_running();
-                       status = MIG_SERVER_DIED;
-               }
+#if DS_AVAILABLE
+       xpc_pipe_t pipe = _mbr_xpc_pipe(false);
+       if (pipe != NULL) {
+               xpc_release(pipe);
+               return true;
        }
        }
-
-       if (status != KERN_SUCCESS) return EIO;
-       if (audit_token_uid(token) != 0) return EAUTH;
-
-       return 0;
+#endif
+       return false;
 }
 
 }
 
-static int
-_mbr_ClearCache()
+int
+mbr_identifier_translate(int id_type, const void *identifier, size_t identifier_size, int target_type, void **result, int *rec_type)
 {
 {
-       kern_return_t status;
-       uint32_t i;
-
-       if (_ds_running() == 0) return EIO;
-       if (_ds_port == MACH_PORT_NULL) return EIO;
-
-       status = MIG_SERVER_DIED;
-       for (i = 0; (_ds_port != MACH_PORT_NULL) && (status == MIG_SERVER_DIED) && (i < MAX_LOOKUP_ATTEMPTS); i++)
-       {
-               status = memberdDSmig_ClearCache(_ds_port);
-               if (status == MACH_SEND_INVALID_DEST)
-               {
-                       mach_port_mod_refs(mach_task_self(), _ds_port, MACH_PORT_RIGHT_SEND, -1);
-                       _ds_port = MACH_PORT_NULL;
-                       _ds_running();
-                       status = MIG_SERVER_DIED;
+#if DS_AVAILABLE
+       xpc_object_t payload, reply;
+#endif
+       id_t tempID;
+       size_t identifier_len;
+       int rc = EIO;
+       
+       if (identifier == NULL || result == NULL || identifier_size == 0) return EIO;
+       
+       if (identifier_size == -1) {
+               identifier_size = strlen(identifier);
+       } else {
+               /* 10898647: For types that are known to be strings, send the smallest necessary amount of data. */
+               switch (id_type) {
+               case ID_TYPE_USERNAME:
+               case ID_TYPE_GROUPNAME:
+               case ID_TYPE_GROUP_NFS:
+               case ID_TYPE_USER_NFS:
+               case ID_TYPE_X509_DN:
+               case ID_TYPE_KERBEROS:
+               case ID_TYPE_NAME:
+                       identifier_len = strlen(identifier);
+                       if (identifier_size > identifier_len) {
+                               identifier_size = identifier_len;
+                       }
+                       break;
                }
        }
 
                }
        }
 
-       if (status != KERN_SUCCESS) return EIO;
-
-       return 0;
+       switch (target_type) {
+               case ID_TYPE_GID:
+               case ID_TYPE_UID:
+               case ID_TYPE_UID_OR_GID:
+                       /* shortcut UUIDs using compatibilty prefixes */
+                       if (id_type == ID_TYPE_UUID) {
+                               const uint8_t *uu = identifier;
+                               
+                               if (identifier_size != sizeof(uuid_t)) return EINVAL;
+                               
+                               if (memcmp(uu, _user_compat_prefix, COMPAT_PREFIX_LEN) == 0) {
+                                       id_t *tempRes = malloc(sizeof(*tempRes));
+                                       memcpy(&tempID, &uu[COMPAT_PREFIX_LEN], sizeof(tempID));
+                                       (*tempRes) = ntohl(tempID);
+                                       (*result) = tempRes;
+                                       if (rec_type != NULL) {
+                                               (*rec_type) = MBR_REC_TYPE_USER;
+                                       }
+                                       return 0;
+                               } else if (memcmp(uu, _group_compat_prefix, COMPAT_PREFIX_LEN) == 0) {
+                                       id_t *tempRes = malloc(sizeof(*tempRes));
+                                       memcpy(&tempID, &uu[COMPAT_PREFIX_LEN], sizeof(tempID));
+                                       (*tempRes) = ntohl(tempID);
+                                       (*result) = tempRes;
+                                       if (rec_type != NULL) {
+                                               (*rec_type) = MBR_REC_TYPE_GROUP;
+                                       }
+                                       return 0;
+                               }
+                       }
+                       break;
+                       
+               case ID_TYPE_UUID:
+                       /* if this is a UID or GID translation, we shortcut UID/GID 0 */
+                       /* or if no OD, we return compatibility UUIDs */
+                       switch (id_type) {
+                               case ID_TYPE_UID:
+                                       if (identifier_size != sizeof(tempID)) return EINVAL;
+                                       
+                                       tempID = *((id_t *) identifier);
+                                       if ((tempID == 0) || (_mbr_od_available() == false)) {
+                                               uint8_t *tempUU = malloc(sizeof(uuid_t));
+                                               uuid_copy(tempUU, _user_compat_prefix);
+                                               *((id_t *) &tempUU[COMPAT_PREFIX_LEN]) = htonl(tempID);
+                                               (*result) = tempUU;
+                                               if (rec_type != NULL) {
+                                                       (*rec_type) = MBR_REC_TYPE_USER;
+                                               }
+                                               return 0;
+                                       }
+                                       break;
+                                       
+                               case ID_TYPE_GID:
+                                       if (identifier_size != sizeof(tempID)) return EINVAL;
+                                       
+                                       tempID = *((id_t *) identifier);
+                                       if ((tempID == 0) || (_mbr_od_available() == false)) {
+                                               uint8_t *tempUU = malloc(sizeof(uuid_t));
+                                               uuid_copy(tempUU, _group_compat_prefix);
+                                               *((id_t *) &tempUU[COMPAT_PREFIX_LEN]) = htonl(tempID);
+                                               (*result) = tempUU;
+                                               if (rec_type != NULL) {
+                                                       (*rec_type) = MBR_REC_TYPE_GROUP;
+                                               }
+                                               return 0;
+                                       }
+                                       break;
+                       }
+                       break;
+       }
+       
+#if DS_AVAILABLE
+       payload = xpc_dictionary_create(NULL, NULL, 0);
+       if (payload == NULL) return EIO;
+       
+       xpc_dictionary_set_int64(payload, "requesting", target_type);
+       xpc_dictionary_set_int64(payload, "type", id_type);
+       xpc_dictionary_set_data(payload, "identifier", identifier, identifier_size);
+       
+       reply = _od_rpc_call("mbr_identifier_translate", payload, _mbr_xpc_pipe);
+       if (reply != NULL) {
+               const void *reply_id;
+               size_t idLen;
+               
+               rc = (int) xpc_dictionary_get_int64(reply, "error");
+               if (rc == 0) {
+                       reply_id = xpc_dictionary_get_data(reply, "identifier", &idLen);
+                       if (reply_id != NULL) {
+                               char *identifier = malloc(idLen);
+                               
+                               memcpy(identifier, reply_id, idLen); // should already be NULL terminated, etc.
+                               (*result) = identifier;
+                               
+                               if (rec_type != NULL) {
+                                       (*rec_type) = (int) xpc_dictionary_get_int64(reply, "rectype");
+                               }
+                       } else {
+                               (*result) = NULL;
+                               rc = ENOENT;
+                       }
+               }
+               
+               xpc_release(reply);
+       }
+       
+       xpc_release(payload);
+#endif
+       
+       return rc;
 }
 
 }
 
-int mbr_uid_to_uuid(uid_t id, uuid_t uu)
+int
+mbr_uid_to_uuid(uid_t id, uuid_t uu)
 {
 {
-       struct kauth_identity_extlookup request;
-       int status;
-
-       if (id == 0)
-       {
-               memcpy(uu, _mbr_root_uuid, sizeof(uuid_t));
-               return 0;
-       }
-
-       /* used as a byte order field */
-       request.el_seqno = 1;
-       request.el_flags = KAUTH_EXTLOOKUP_VALID_UID | KAUTH_EXTLOOKUP_WANT_UGUID;
-       request.el_uid = id;
-
-       status = _mbr_MembershipCall(&request);
-       if (status != 0) return status;
-       if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_UGUID) == 0) return ENOENT;
-
-       memcpy(uu, &request.el_uguid, sizeof(guid_t));
-       return 0;
+       return mbr_identifier_to_uuid(ID_TYPE_UID, &id, sizeof(id), uu);
 }
 
 }
 
-int mbr_gid_to_uuid(gid_t id, uuid_t uu)
+int
+mbr_gid_to_uuid(gid_t id, uuid_t uu)
 {
 {
-       struct kauth_identity_extlookup request;
-       int status;
-
-       request.el_seqno = 1;
-       request.el_flags = KAUTH_EXTLOOKUP_VALID_GID | KAUTH_EXTLOOKUP_WANT_GGUID;
-       request.el_gid = id;
-
-       status = _mbr_MembershipCall(&request);
-       if (status != 0) return status;
-       if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GGUID) == 0) return ENOENT;
-
-       memcpy(uu, &request.el_gguid, sizeof(guid_t));
-       return 0;
+       return mbr_identifier_to_uuid(ID_TYPE_GID, &id, sizeof(id), uu);
 }
 
 }
 
-int mbr_uuid_to_id(const uuid_t uu, uid_t *id, int *id_type)
+int
+mbr_uuid_to_id(const uuid_t uu, uid_t *id, int *id_type)
 {
 {
-       struct kauth_identity_extlookup request;
-       int status;
-
-       if (id == NULL) return EIO;
-       if (id_type == NULL) return EIO;
-
-       if (!memcmp(uu, _mbr_root_uuid, sizeof(uuid_t)))
-       {
-               *id = 0;
-               *id_type = ID_TYPE_UID;
-               return 0;
-       }
-
-       request.el_seqno = 1;
-       request.el_flags = KAUTH_EXTLOOKUP_VALID_UGUID | KAUTH_EXTLOOKUP_VALID_GGUID | KAUTH_EXTLOOKUP_WANT_UID | KAUTH_EXTLOOKUP_WANT_GID;
-       memcpy(&request.el_uguid, uu, sizeof(guid_t));
-       memcpy(&request.el_gguid, uu, sizeof(guid_t));
-
-       status = _mbr_MembershipCall(&request);
-       if (status != 0) return status;
-
-       if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_UID) != 0)
-       {
-               *id = request.el_uid;
-               *id_type = ID_TYPE_UID;
-       }
-       else if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GID) != 0)
-       {
-               *id = request.el_gid;
-               *id_type = ID_TYPE_GID;
-       }
-       else
-       {
-               return ENOENT;
+       id_t *result;
+       int local_type;
+       int rc;
+       
+       rc = mbr_identifier_translate(ID_TYPE_UUID, uu, sizeof(uuid_t), ID_TYPE_UID_OR_GID, (void **) &result, &local_type);
+       if (rc == 0) {
+               switch (local_type) {
+                       case MBR_REC_TYPE_GROUP:
+                               (*id_type) = ID_TYPE_GID;
+                               break;
+                               
+                       case MBR_REC_TYPE_USER:
+                               (*id_type) = ID_TYPE_UID;
+                               break;
+                               
+                       default:
+                               (*id_type) = -1;
+                               break;
+               }
+               
+               (*id) = (*result);
+               free(result);
        }
        }
-
-       return 0;
+       
+       return rc;
 }
 
 }
 
-int mbr_sid_to_uuid(const nt_sid_t *sid, uuid_t uu)
+int
+mbr_sid_to_uuid(const nt_sid_t *sid, uuid_t uu)
 {
 {
-       struct kauth_identity_extlookup request;
-       int status;
-
-       request.el_seqno = 1;
-       request.el_flags = KAUTH_EXTLOOKUP_VALID_GSID | KAUTH_EXTLOOKUP_WANT_GGUID;
-       memset(&request.el_gsid, 0, sizeof(ntsid_t));
-       memcpy(&request.el_gsid, sid, KAUTH_NTSID_SIZE(sid));
-
-       status = _mbr_MembershipCall(&request);
-       if (status != 0) return status;
-       if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GGUID) == 0) return ENOENT;
-
-       memcpy(uu, &request.el_gguid, sizeof(guid_t));
-       return 0;
+#ifdef DS_AVAILABLE
+       return mbr_identifier_to_uuid(ID_TYPE_SID, sid, sizeof(*sid), uu);
+#else
+       return EIO;
+#endif
 }
 
 }
 
-int mbr_uuid_to_sid_type(const uuid_t uu, nt_sid_t *sid, int *id_type)
+int
+mbr_identifier_to_uuid(int id_type, const void *identifier, size_t identifier_size, uuid_t uu)
 {
 {
-       struct kauth_identity_extlookup request;
-       int status;
-
-       request.el_seqno = 1;
-       request.el_flags = KAUTH_EXTLOOKUP_VALID_UGUID | KAUTH_EXTLOOKUP_VALID_GGUID | KAUTH_EXTLOOKUP_WANT_USID | KAUTH_EXTLOOKUP_WANT_GSID;
-       memcpy(&request.el_uguid, uu, sizeof(guid_t));
-       memcpy(&request.el_gguid, uu, sizeof(guid_t));
-
-       status = _mbr_MembershipCall(&request);
-       if (status != 0) return status;
-
-       if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_USID) != 0)
-       {
-               *id_type = SID_TYPE_USER;
-               memcpy(sid, &request.el_usid, sizeof(nt_sid_t));
-       }
-       else if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GSID) != 0)
-       {
-               *id_type = SID_TYPE_GROUP;
-               memcpy(sid, &request.el_gsid, sizeof(nt_sid_t));
-       }
-       else
-       {
-               return ENOENT;
+       uint8_t *result;
+       int rc;
+       
+       rc = mbr_identifier_translate(id_type, identifier, identifier_size, ID_TYPE_UUID, (void **) &result, NULL);
+       if (rc == 0) {
+               uuid_copy(uu, result);
+               free(result);
        }
        }
+       
+       return rc;
+}
 
 
-       return 0;
+int
+mbr_uuid_to_sid_type(const uuid_t uu, nt_sid_t *sid, int *id_type)
+{
+#ifdef DS_AVAILABLE
+       void *result;
+       int local_type;
+       int rc;
+       
+       rc = mbr_identifier_translate(ID_TYPE_UUID, uu, sizeof(uuid_t), ID_TYPE_SID, &result, &local_type);
+       if (rc == 0) {
+               memcpy(sid, result, sizeof(nt_sid_t));
+               if (id_type != NULL) {
+                       /* remap ID types */
+                       switch (local_type) {
+                               case MBR_REC_TYPE_USER:
+                                       (*id_type) = SID_TYPE_USER;
+                                       break;
+
+                               case MBR_REC_TYPE_GROUP:
+                                       (*id_type) = SID_TYPE_GROUP;
+                                       break;
+
+                               default:
+                                       break;
+                       }
+               }
+               
+               free(result);
+       }
+       
+       return rc;
+#else
+       return EIO;
+#endif
 }
 
 }
 
-int mbr_uuid_to_sid(const uuid_t uu, nt_sid_t *sid)
+int
+mbr_uuid_to_sid(const uuid_t uu, nt_sid_t *sid)
 {
 {
+#ifdef DS_AVAILABLE
        int type, status;
 
        type = 0;
        int type, status;
 
        type = 0;
@@ -283,120 +397,145 @@ int mbr_uuid_to_sid(const uuid_t uu, nt_sid_t *sid)
        if (status != 0) return status;
 
        return 0;
        if (status != 0) return status;
 
        return 0;
+#else
+       return EIO;
+#endif
 }
 
 }
 
-int mbr_check_membership(uuid_t user, uuid_t group, int *ismember)
+int
+mbr_check_membership(const uuid_t user, const uuid_t group, int *ismember)
 {
 {
-       struct kauth_identity_extlookup request;
-       int status;
-
-       request.el_seqno = 1;
-       request.el_flags = KAUTH_EXTLOOKUP_VALID_UGUID | KAUTH_EXTLOOKUP_VALID_GGUID | KAUTH_EXTLOOKUP_WANT_MEMBERSHIP;
-       memcpy(&request.el_uguid, user, sizeof(guid_t));
-       memcpy(&request.el_gguid, group, sizeof(guid_t));
-
-       status = _mbr_MembershipCall(&request);
-       if (status != 0) return status;
-       if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_MEMBERSHIP) == 0) return ENOENT;
-
-       *ismember = ((request.el_flags & KAUTH_EXTLOOKUP_ISMEMBER) != 0);
-       return 0;
+       return mbr_check_membership_ext(ID_TYPE_UUID, user, sizeof(uuid_t), ID_TYPE_UUID, group, 0, ismember);
 }
 
 }
 
-int mbr_check_membership_refresh(const uuid_t user, uuid_t group, int *ismember)
+int
+mbr_check_membership_refresh(const uuid_t user, uuid_t group, int *ismember)
 {
 {
-       struct kauth_identity_extlookup request;
-       int status;
-
-       request.el_seqno = 1;
-       request.el_flags = KAUTH_EXTLOOKUP_VALID_UGUID | KAUTH_EXTLOOKUP_VALID_GGUID | KAUTH_EXTLOOKUP_WANT_MEMBERSHIP | (1<<15);
-       memcpy(&request.el_uguid, user, sizeof(guid_t));
-       memcpy(&request.el_gguid, group, sizeof(guid_t));
-
-       status = _mbr_MembershipCall(&request);
-       if (status != 0) return status;
-       if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_MEMBERSHIP) == 0) return ENOENT;
-
-       *ismember = ((request.el_flags & KAUTH_EXTLOOKUP_ISMEMBER) != 0);
-       return 0;
+       return mbr_check_membership_ext(ID_TYPE_UUID, user, sizeof(uuid_t), ID_TYPE_UUID, group, 1, ismember);
 }
 
 }
 
-int mbr_check_membership_by_id(uuid_t user, gid_t group, int *ismember)
+int
+mbr_check_membership_ext(int userid_type, const void *userid, size_t userid_size, int groupid_type, const void *groupid, int refresh, int *isMember)
 {
 {
-       struct kauth_identity_extlookup request;
-       int status;
-
-       request.el_seqno = 1;
-       request.el_flags = KAUTH_EXTLOOKUP_VALID_UGUID | KAUTH_EXTLOOKUP_VALID_GID | KAUTH_EXTLOOKUP_WANT_MEMBERSHIP;
-       memcpy(&request.el_uguid, user, sizeof(guid_t));
-       request.el_gid = group;
-
-       status = _mbr_MembershipCall(&request);
-       if (status != 0) return status;
-       if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_MEMBERSHIP) == 0) return ENOENT;
-
-       *ismember = ((request.el_flags & KAUTH_EXTLOOKUP_ISMEMBER) != 0);
-       return 0;
+#ifdef DS_AVAILABLE
+       xpc_object_t payload, reply;
+       int rc = 0;
+       
+       payload = xpc_dictionary_create(NULL, NULL, 0);
+       if (payload == NULL) return ENOMEM;
+
+       xpc_dictionary_set_int64(payload, "user_idtype", userid_type);
+       xpc_dictionary_set_data(payload, "user_id", userid, userid_size);
+       xpc_dictionary_set_int64(payload, "group_idtype", groupid_type);
+       
+       switch (groupid_type) {
+               case ID_TYPE_GROUPNAME:
+               case ID_TYPE_GROUP_NFS:
+                       xpc_dictionary_set_data(payload, "group_id", groupid, strlen(groupid));
+                       break;
+                       
+               case ID_TYPE_GID:
+                       xpc_dictionary_set_data(payload, "group_id", groupid, sizeof(id_t));
+                       break;
+                       
+               case ID_TYPE_SID:
+                       xpc_dictionary_set_data(payload, "group_id", groupid, sizeof(nt_sid_t));
+                       break;
+                       
+               case ID_TYPE_UUID:
+                       xpc_dictionary_set_data(payload, "group_id", groupid, sizeof(uuid_t));
+                       break;
+                       
+               default:
+                       rc = EINVAL;
+                       break;
+       }
+       
+       if (rc == 0) {
+               reply = _od_rpc_call("mbr_check_membership", payload, _mbr_xpc_pipe);
+               if (reply != NULL) {
+                       rc = (int) xpc_dictionary_get_int64(reply, "error");
+                       (*isMember) = xpc_dictionary_get_bool(reply, "ismember");
+                       xpc_release(reply);
+               } else {
+                       rc = EIO;
+               }
+       }
+       
+       xpc_release(payload);
+       
+       return rc;
+#else
+       return EIO;
+#endif
 }
 
 }
 
-int mbr_reset_cache()
+int
+mbr_check_membership_by_id(uuid_t user, gid_t group, int *ismember)
 {
 {
-       return _mbr_ClearCache();
+       return mbr_check_membership_ext(ID_TYPE_UUID, user, sizeof(uuid_t), ID_TYPE_GID, &group, 0, ismember);
 }
 
 }
 
-int mbr_user_name_to_uuid(const char *name, uuid_t uu)
+int
+mbr_reset_cache()
 {
 {
-       return _mbr_MapName((char *)name, 1, (guid_t *)uu);
+#ifdef DS_AVAILABLE
+       _od_rpc_call("mbr_cache_flush", NULL, _mbr_xpc_pipe);
+       return 0;
+#else
+       return EIO;
+#endif
 }
 
 }
 
-int mbr_group_name_to_uuid(const char *name, uuid_t uu)
+int
+mbr_user_name_to_uuid(const char *name, uuid_t uu)
 {
 {
-       return _mbr_MapName((char *)name, 0, (guid_t *)uu);
+       return mbr_identifier_to_uuid(ID_TYPE_USERNAME, name, -1, uu);
 }
 
 }
 
-int mbr_check_service_membership(const uuid_t user, const char *servicename, int *ismember)
+int
+mbr_group_name_to_uuid(const char *name, uuid_t uu)
 {
 {
-       char *prefix = "com.apple.access_";
-       char *all_services = "com.apple.access_all_services";
-       char groupName[256];
-       uuid_t group_uu;
-       int result, dummy;
-
-       if (servicename == NULL) return EINVAL;
-       if (strlen(servicename) > 255 - strlen(prefix)) return EINVAL;
-
-       /* start by checking "all services" */
-       result = mbr_group_name_to_uuid(all_services, group_uu);
-
-       if (result == EAUTH) return result;
-
-       if (result == ENOENT)
-       {
-               /* all_services group didn't exist, check individual group */
-               memcpy(groupName, prefix, strlen(prefix));
-               strcpy(groupName + strlen(prefix), servicename);
-               result = mbr_group_name_to_uuid(groupName, group_uu);
-       }
+       return mbr_identifier_to_uuid(ID_TYPE_GROUPNAME, name, -1, uu);
+}
 
 
-       if (result == 0)
-       {
-               result = mbr_check_membership_refresh(user, group_uu, ismember);
-       }
-       else if (result == EAUTH)
-       {
-               return result;
-       }
-       else
-       {
-               /* just force cache update with bogus membership check */
-               memset(group_uu, 0, sizeof(group_uu));
-               mbr_check_membership_refresh(user, group_uu, &dummy);
+int
+mbr_check_service_membership(const uuid_t user, const char *servicename, int *ismember)
+{
+#ifdef DS_AVAILABLE
+       xpc_object_t payload, reply;
+       int result = EIO;
+
+       if (ismember == NULL || servicename == NULL) return EINVAL;
+       
+       payload = xpc_dictionary_create(NULL, NULL, 0);
+       if (payload == NULL) return EIO;
+       
+       xpc_dictionary_set_data(payload, "user_id", user, sizeof(uuid_t));
+       xpc_dictionary_set_int64(payload, "user_idtype", ID_TYPE_UUID);
+       xpc_dictionary_set_string(payload, "service", servicename);
+       
+       reply = _od_rpc_call("mbr_check_service_membership", payload, _mbr_xpc_pipe);
+       if (reply != NULL) {
+               result = (int) xpc_dictionary_get_int64(reply, "error");
+               (*ismember) = xpc_dictionary_get_bool(reply, "ismember");
+               
+               xpc_release(reply);
+       } else {
+               (*ismember) = 0;
        }
        }
+       
+       xpc_release(payload);
 
        return result;
 
        return result;
+#else
+       return EIO;
+#endif
 }
 
 }
 
-static char *ConvertBytesToDecimal(char *buffer, unsigned long long value)
+#ifdef DS_AVAILABLE
+static char *
+ConvertBytesToDecimal(char *buffer, unsigned long long value)
 {
        char *temp;
        buffer[24] = '\0';
 {
        char *temp;
        buffer[24] = '\0';
@@ -415,9 +554,12 @@ static char *ConvertBytesToDecimal(char *buffer, unsigned long long value)
 
        return temp;
 }
 
        return temp;
 }
+#endif
 
 
-int mbr_sid_to_string(const nt_sid_t *sid, char *string)
+int
+mbr_sid_to_string(const nt_sid_t *sid, char *string)
 {
 {
+#ifdef DS_AVAILABLE
        char *current = string;
        long long temp = 0;
        int i;
        char *current = string;
        long long temp = 0;
        int i;
@@ -446,10 +588,15 @@ int mbr_sid_to_string(const nt_sid_t *sid, char *string)
        }
 
        return 0;
        }
 
        return 0;
+#else
+       return EIO;
+#endif
 }
 
 }
 
-int mbr_string_to_sid(const char *string, nt_sid_t *sid)
+int
+mbr_string_to_sid(const char *string, nt_sid_t *sid)
 {
 {
+#ifdef DS_AVAILABLE
        char *current = (char *)string+2;
        int count = 0;
        long long temp;
        char *current = (char *)string+2;
        int count = 0;
        long long temp;
@@ -470,7 +617,11 @@ int mbr_string_to_sid(const char *string, nt_sid_t *sid)
        while (*current != '\0' && count < NTSID_MAX_AUTHORITIES)
        {
                current++;
        while (*current != '\0' && count < NTSID_MAX_AUTHORITIES)
        {
                current++;
-               sid->sid_authorities[count] = strtol(current, &current, 10);
+               errno = 0;
+               sid->sid_authorities[count] = (u_int32_t)strtoll(current, &current, 10);
+               if ((sid->sid_authorities[count] == 0) && (errno == EINVAL)) {
+                       return EINVAL;
+               }
                count++;
        }
 
                count++;
        }
 
@@ -479,94 +630,53 @@ int mbr_string_to_sid(const char *string, nt_sid_t *sid)
        sid->sid_authcount = count;
 
        return 0;
        sid->sid_authcount = count;
 
        return 0;
+#else
+       return EIO;
+#endif
 }
 
 }
 
-static void ConvertBytesToHex(char **string, char **data, int numBytes)
+int
+mbr_uuid_to_string(const uuid_t uu, char *string)
 {
 {
-       int i;
-
-       for (i=0; i < numBytes; i++)
-       {
-               unsigned char hi = ((**data) >> 4) & 0xf;
-               unsigned char low = (**data) & 0xf;
-               if (hi < 10)
-                       **string = '0' + hi;
-               else
-                       **string = 'A' + hi - 10;
-
-               (*string)++;
-
-               if (low < 10)
-                       **string = '0' + low;
-               else
-                       **string = 'A' + low - 10;
-
-               (*string)++;
-               (*data)++;
-       }
+       uuid_unparse_upper(uu, string);
+       
+       return 0;
 }
 
 }
 
-int mbr_uuid_to_string(const uuid_t uu, char *string)
+int
+mbr_string_to_uuid(const char *string, uuid_t uu)
 {
 {
-       char *guid = (char*)uu;
-       char *strPtr = string;
-       ConvertBytesToHex(&strPtr, &guid, 4);
-       *strPtr = '-'; strPtr++;
-       ConvertBytesToHex(&strPtr, &guid, 2);
-       *strPtr = '-'; strPtr++;
-       ConvertBytesToHex(&strPtr, &guid, 2);
-       *strPtr = '-'; strPtr++;
-       ConvertBytesToHex(&strPtr, &guid, 2);
-       *strPtr = '-'; strPtr++;
-       ConvertBytesToHex(&strPtr, &guid, 6);
-       *strPtr = '\0';
-
-       return 0;
+       return uuid_parse(string, uu);
 }
 
 }
 
-int mbr_string_to_uuid(const char *string, uuid_t uu)
+int 
+mbr_set_identifier_ttl(int id_type, const void *identifier, size_t identifier_size, unsigned int seconds)
 {
 {
-       short dataIndex = 0;
-       int isFirstNibble = 1;
-
-       if (string == NULL) return EINVAL;
-       if (strlen(string) > MBR_UU_STRING_SIZE) return EINVAL;
-
-       while (*string != '\0' && dataIndex < 16)
-       {
-               char nibble;
-
-               if (*string >= '0' && *string <= '9')
-                       nibble = *string - '0';
-               else if (*string >= 'A' && *string <= 'F')
-                       nibble = *string - 'A' + 10;
-               else if (*string >= 'a' && *string <= 'f')
-                       nibble = *string - 'a' + 10;
-               else
-               {
-                       if (*string != '-')
-                               return EINVAL;
-                       string++;
-                       continue;
+#ifdef DS_AVAILABLE
+       xpc_object_t payload, reply;
+       int rc = 0;
+       
+       payload = xpc_dictionary_create(NULL, NULL, 0);
+       if (payload == NULL) return ENOMEM;
+       
+       xpc_dictionary_set_int64(payload, "type", id_type);
+       xpc_dictionary_set_data(payload, "identifier", identifier, identifier_size);
+       xpc_dictionary_set_int64(payload, "ttl", seconds);
+       
+       if (rc == 0) {
+               reply = _od_rpc_call("mbr_set_identifier_ttl", payload, _mbr_xpc_pipe);
+               if (reply != NULL) {
+                       rc = (int) xpc_dictionary_get_int64(reply, "error");
+                       xpc_release(reply);
+               } else {
+                       rc = EIO;
                }
                }
-
-               if (isFirstNibble)
-               {
-                       uu[dataIndex] = nibble << 4;
-                       isFirstNibble = 0;
-               }
-               else
-               {
-                       uu[dataIndex] |= nibble;
-                       dataIndex++;
-                       isFirstNibble = 1;
-               }
-
-               string++;
        }
        }
-
-       if (dataIndex != 16) return EINVAL;
-
-       return 0;
+       
+       xpc_release(payload);
+       
+       return rc;
+#else
+       return EIO;
+#endif
 }
 }
-