X-Git-Url: https://git.saurik.com/apple/libinfo.git/blobdiff_plain/b3dd680f589a1f02e301659e04768ef61be3b843..87ed6543bc006aa76a15562f3c11d4be1ad2902b:/membership.subproj/membership.c?ds=inline diff --git a/membership.subproj/membership.c b/membership.subproj/membership.c index a650f90..3074ed5 100644 --- a/membership.subproj/membership.c +++ b/membership.subproj/membership.c @@ -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@ * @@ -20,261 +20,375 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include "membership.h" -#include "membershipPriv.h" -#include "DSmemberdMIG.h" -#include "DSmemberdMIG_types.h" +#include #include #include +#include "membership.h" +#include "membershipPriv.h" #include -#include #include +#ifdef DS_AVAILABLE +#include +#include +#include +#include +#include +#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; @@ -283,120 +397,145 @@ int mbr_uuid_to_sid(const uuid_t uu, nt_sid_t *sid) 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; +#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'; @@ -415,9 +554,12 @@ static char *ConvertBytesToDecimal(char *buffer, unsigned long long value) 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; @@ -446,10 +588,15 @@ int mbr_sid_to_string(const nt_sid_t *sid, char *string) } 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; @@ -470,7 +617,11 @@ int mbr_string_to_sid(const char *string, nt_sid_t *sid) while (*current != '\0' && count < NTSID_MAX_AUTHORITIES) { current++; - sid->sid_authorities[count] = strtol(current, ¤t, 10); + errno = 0; + sid->sid_authorities[count] = (u_int32_t)strtoll(current, ¤t, 10); + if ((sid->sid_authorities[count] == 0) && (errno == EINVAL)) { + return EINVAL; + } count++; } @@ -479,94 +630,53 @@ int mbr_string_to_sid(const char *string, nt_sid_t *sid) 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 } -