X-Git-Url: https://git.saurik.com/apple/libinfo.git/blobdiff_plain/1d9e5cb8ce34c6120503c023c843076e0804d8c8..87ed6543bc006aa76a15562f3c11d4be1ad2902b:/membership.subproj/membership.c?ds=sidebyside diff --git a/membership.subproj/membership.c b/membership.subproj/membership.c index de01653..3074ed5 100644 --- a/membership.subproj/membership.c +++ b/membership.subproj/membership.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2004-2010 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -20,313 +20,530 @@ * @APPLE_LICENSE_HEADER_END@ */ +#include +#include +#include #include "membership.h" #include "membershipPriv.h" -#include "memberd.h" - -#include #include -#include -#include -#import +#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)) + +#ifdef DS_AVAILABLE + +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)); -static mach_port_t GetServerPort() +#endif + +#ifdef DS_AVAILABLE +static void +_mbr_fork_child(void) { - kern_return_t result; - static mach_port_t bsPort = 0; - static mach_port_t fServerPort = 0; - - if (bsPort == 0) - { - result = task_get_bootstrap_port( mach_task_self(), &bsPort ); - result = bootstrap_look_up( bsPort, "com.apple.memberd", &fServerPort ); - -// if the port lookup failed, the rpc will fail and we will return EIO -// if (result != MACH_MSG_SUCCESS) -// { -// printf("Got error %d on lookup (is memberd running?)\n", result); -// } + 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; } - - return fServerPort; + + pthread_mutex_unlock(&mutex); } +#endif -int mbr_uid_to_uuid(uid_t id, uuid_t uu) +#ifdef DS_AVAILABLE +static void +_mbr_fork_prepare(void) { - struct kauth_identity_extlookup request; - int result = 0; - - request.el_seqno = 1; // used as byte order field - request.el_flags = KAUTH_EXTLOOKUP_VALID_UID | KAUTH_EXTLOOKUP_WANT_UGUID; - request.el_uid = id; - result = _mbr_DoMembershipCall(GetServerPort(), &request); - if (result != KERN_SUCCESS) - return EIO; - - if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_UGUID) != 0) - memcpy(uu, &request.el_uguid, sizeof(guid_t)); - else - result = ENOENT; - - return result; + pthread_mutex_lock(&mutex); } +#endif -int mbr_gid_to_uuid(gid_t id, uuid_t uu) +#ifdef DS_AVAILABLE +static void +_mbr_fork_parent(void) { - struct kauth_identity_extlookup request; - kern_return_t result; - int error = 0; - - request.el_seqno = 1; // used as byte order field - request.el_flags = KAUTH_EXTLOOKUP_VALID_GID | KAUTH_EXTLOOKUP_WANT_GGUID; - request.el_gid = id; - result = _mbr_DoMembershipCall(GetServerPort(), &request); - if (result != KERN_SUCCESS) - return EIO; - - if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GGUID) != 0) - memcpy(uu, &request.el_gguid, sizeof(guid_t)); - else - error = ENOENT; - - return error; + pthread_mutex_unlock(&mutex); } +#endif -int mbr_uuid_to_id( const uuid_t uu, uid_t* id, int* id_type) +#ifdef DS_AVAILABLE +XPC_RETURNS_RETAINED +static xpc_pipe_t +_mbr_xpc_pipe(bool resetPipe) { - struct kauth_identity_extlookup request; - kern_return_t result; - int error = 0; - - request.el_seqno = 1; // used as byte order field - 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)); - result = _mbr_DoMembershipCall(GetServerPort(), &request); - if (result != KERN_SUCCESS) - return EIO; + static dispatch_once_t once; + xpc_pipe_t pipe = NULL; + + dispatch_once(&once, ^(void) { + char *xbs_disable; - if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_UID) != 0) - { - *id = request.el_uid; - *id_type = ID_TYPE_UID; + /* 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; } - else if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GID) != 0) - { - *id = request.el_gid; - *id_type = ID_TYPE_GID; + + pthread_mutex_lock(&mutex); + if (resetPipe) { + xpc_release(__mbr_pipe); + __mbr_pipe = NULL; } - else - error = ENOENT; - - return error; + + 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 -int mbr_sid_to_uuid(const nt_sid_t* sid, uuid_t uu) +static bool +_mbr_od_available(void) { - struct kauth_identity_extlookup request; - kern_return_t result; - int error = 0; - - request.el_seqno = 1; // used as byte order field - 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)); - result = _mbr_DoMembershipCall(GetServerPort(), &request); - if (result != KERN_SUCCESS) - return EIO; - - if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GGUID) != 0) - memcpy(uu, &request.el_gguid, sizeof(guid_t)); - else - error = ENOENT; - - return error; +#if DS_AVAILABLE + xpc_pipe_t pipe = _mbr_xpc_pipe(false); + if (pipe != NULL) { + xpc_release(pipe); + return true; + } +#endif + return false; } -int mbr_uuid_to_sid(const uuid_t uu, nt_sid_t* sid) +int +mbr_identifier_translate(int id_type, const void *identifier, size_t identifier_size, int target_type, void **result, int *rec_type) { - struct kauth_identity_extlookup request; - kern_return_t result; - int error = 0; - - request.el_seqno = 1; // used as byte order field - request.el_flags = KAUTH_EXTLOOKUP_VALID_GGUID | KAUTH_EXTLOOKUP_WANT_GSID; - memcpy(&request.el_gguid, uu, sizeof(guid_t)); - result = _mbr_DoMembershipCall(GetServerPort(), &request); - if (result != KERN_SUCCESS) - return EIO; +#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; + } + } + + 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; - if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GSID) != 0) - memcpy(sid, &request.el_gsid, sizeof(nt_sid_t)); - else - error = ENOENT; + 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; + } + } - return error; + xpc_release(reply); + } + + xpc_release(payload); +#endif + + return rc; } -int mbr_check_membership(uuid_t user, uuid_t group, int* ismember) +int +mbr_uid_to_uuid(uid_t id, uuid_t uu) { - struct kauth_identity_extlookup request; - kern_return_t result; - int error = 0; - - request.el_seqno = 1; // used as byte order field - 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)); - result = _mbr_DoMembershipCall(GetServerPort(), &request); - if (result != KERN_SUCCESS) - return EIO; - - if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_MEMBERSHIP) != 0) - { - *ismember = ((request.el_flags & KAUTH_EXTLOOKUP_ISMEMBER) != 0); - } - else - error = ENOENT; - - return error; + return mbr_identifier_to_uuid(ID_TYPE_UID, &id, sizeof(id), uu); } -int mbr_check_membership_refresh(uuid_t user, uuid_t group, int* ismember) +int +mbr_gid_to_uuid(gid_t id, uuid_t uu) { - struct kauth_identity_extlookup request; - kern_return_t result; - int error = 0; - - request.el_seqno = 1; // used as byte order field - 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)); - result = _mbr_DoMembershipCall(GetServerPort(), &request); - if (result != KERN_SUCCESS) - return EIO; - - if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_MEMBERSHIP) != 0) - { - *ismember = ((request.el_flags & KAUTH_EXTLOOKUP_ISMEMBER) != 0); - } - else - error = ENOENT; - - return error; + return mbr_identifier_to_uuid(ID_TYPE_GID, &id, sizeof(id), uu); } -int mbr_check_membership_by_id(uuid_t user, gid_t group, int* ismember) +int +mbr_uuid_to_id(const uuid_t uu, uid_t *id, int *id_type) { - struct kauth_identity_extlookup request; - kern_return_t result; - int error = 0; - - request.el_seqno = 1; // used as byte order field - 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; - result = _mbr_DoMembershipCall(GetServerPort(), &request); - if (result != KERN_SUCCESS) - return EIO; + 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; + } - if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_MEMBERSHIP) != 0) - { - *ismember = ((request.el_flags & KAUTH_EXTLOOKUP_ISMEMBER) != 0); + (*id) = (*result); + free(result); } - else - error = ENOENT; - - return error; + + return rc; } -int mbr_reset_cache() +int +mbr_sid_to_uuid(const nt_sid_t *sid, uuid_t uu) { - kern_return_t result; - result = _mbr_ClearCache(GetServerPort()); - if (result != KERN_SUCCESS) - return EIO; - return 0; +#ifdef DS_AVAILABLE + return mbr_identifier_to_uuid(ID_TYPE_SID, sid, sizeof(*sid), uu); +#else + return EIO; +#endif } -int mbr_user_name_to_uuid(const char* name, uuid_t uu) +int +mbr_identifier_to_uuid(int id_type, const void *identifier, size_t identifier_size, uuid_t uu) { - kern_return_t result; + uint8_t *result; + int rc; - if (strlen(name) > 255) - return EINVAL; + rc = mbr_identifier_translate(id_type, identifier, identifier_size, ID_TYPE_UUID, (void **) &result, NULL); + if (rc == 0) { + uuid_copy(uu, result); + free(result); + } - result = _mbr_MapName(GetServerPort(), 1, (char*)name, (guid_t*)uu); + return rc; +} + +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; - if (result == KERN_FAILURE) - return ENOENT; - else if (result != KERN_SUCCESS) - return EIO; + 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) +{ +#ifdef DS_AVAILABLE + int type, status; + + type = 0; + + status = mbr_uuid_to_sid_type(uu, sid, &type); + if (status != 0) return status; + return 0; +#else + return EIO; +#endif +} + +int +mbr_check_membership(const uuid_t user, const uuid_t group, int *ismember) +{ + return mbr_check_membership_ext(ID_TYPE_UUID, user, sizeof(uuid_t), ID_TYPE_UUID, group, 0, ismember); } -int mbr_group_name_to_uuid(const char* name, uuid_t uu) +int +mbr_check_membership_refresh(const uuid_t user, uuid_t group, int *ismember) { - kern_return_t result; + return mbr_check_membership_ext(ID_TYPE_UUID, user, sizeof(uuid_t), ID_TYPE_UUID, group, 1, 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) +{ +#ifdef DS_AVAILABLE + xpc_object_t payload, reply; + int rc = 0; - if (strlen(name) > 255) - return EINVAL; + 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); - result = _mbr_MapName(GetServerPort(), 0, (char*)name, (guid_t*)uu); + 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 (result == KERN_FAILURE) - return ENOENT; - else if (result != KERN_SUCCESS) - return EIO; - + 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_check_membership_by_id(uuid_t user, gid_t group, int *ismember) +{ + return mbr_check_membership_ext(ID_TYPE_UUID, user, sizeof(uuid_t), ID_TYPE_GID, &group, 0, ismember); +} + +int +mbr_reset_cache() +{ +#ifdef DS_AVAILABLE + _od_rpc_call("mbr_cache_flush", NULL, _mbr_xpc_pipe); return 0; +#else + return EIO; +#endif } -int mbr_check_service_membership(const uuid_t user, const char* servicename, int* ismember) +int +mbr_user_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; + return mbr_identifier_to_uuid(ID_TYPE_USERNAME, name, -1, uu); +} + +int +mbr_group_name_to_uuid(const char *name, uuid_t uu) +{ + return mbr_identifier_to_uuid(ID_TYPE_GROUPNAME, name, -1, uu); +} + +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; - if (strlen(servicename) > 255 - strlen(prefix)) - return EINVAL; + payload = xpc_dictionary_create(NULL, NULL, 0); + if (payload == NULL) return EIO; - // start by checking "all services" - result = mbr_group_name_to_uuid(all_services, group_uu); + 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); - 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); + 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; } - if (result == 0) - result = mbr_check_membership_refresh(user, group_uu, ismember); - else - { - // just force cache update with bogus membership check - memset(group_uu, 0, sizeof(group_uu)); - mbr_check_membership_refresh(user, group_uu, &dummy); - } - + 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; + char *temp; buffer[24] = '\0'; buffer[23] = '0'; - + if (value == 0) return &buffer[23]; - + temp = &buffer[24]; while (value != 0) { @@ -334,23 +551,25 @@ static char* ConvertBytesToDecimal(char* buffer, unsigned long long value) *temp = '0' + (value % 10); value /= 10; } - + 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) { - char* current = string; +#ifdef DS_AVAILABLE + char *current = string; long long temp = 0; int i; char tempBuffer[25]; - - if (sid->sid_authcount > NTSID_MAX_AUTHORITIES) - return EINVAL; - + + if (sid->sid_authcount > NTSID_MAX_AUTHORITIES) return EINVAL; + for (i = 0; i < 6; i++) temp = (temp << 8) | sid->sid_authority[i]; - + current[0] = 'S'; current[1] = '-'; current += 2; @@ -359,7 +578,7 @@ int mbr_sid_to_string(const nt_sid_t* sid, char* string) *current = '-'; current++; strcpy(current, ConvertBytesToDecimal(tempBuffer, temp)); - + for(i=0; i < sid->sid_authcount; i++) { current = current + strlen(current); @@ -367,128 +586,97 @@ int mbr_sid_to_string(const nt_sid_t* sid, char* string) current++; strcpy(current, ConvertBytesToDecimal(tempBuffer, sid->sid_authorities[i])); } - + 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) { - char* current = string+2; +#ifdef DS_AVAILABLE + char *current = (char *)string+2; int count = 0; long long temp; + if (string == NULL) return EINVAL; + memset(sid, 0, sizeof(nt_sid_t)); if (string[0] != 'S' || string[1] != '-') return EINVAL; - + sid->sid_kind = strtol(current, ¤t, 10); if (*current == '\0') return EINVAL; current++; temp = strtoll(current, ¤t, 10); - // convert to BigEndian before copying + + /* convert to BigEndian before copying */ temp = OSSwapHostToBigInt64(temp); memcpy(sid->sid_authority, ((char*)&temp)+2, 6); 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++; } - - if (*current != '\0') - return EINVAL; - + + if (*current != '\0') return EINVAL; + 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; + uuid_unparse_upper(uu, string); - 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)++; - } + 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; +#ifdef DS_AVAILABLE + xpc_object_t payload, reply; + int rc = 0; - if (strlen(string) > MBR_UU_STRING_SIZE) - return EINVAL; + payload = xpc_dictionary_create(NULL, NULL, 0); + if (payload == NULL) return ENOMEM; - 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; - } - - if (isFirstNibble) - { - uu[dataIndex] = nibble << 4; - isFirstNibble = 0; - } - else - { - uu[dataIndex] |= nibble; - dataIndex++; - isFirstNibble = 1; + 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; } - - string++; } - if (dataIndex != 16) - return EINVAL; - - return 0; + xpc_release(payload); + + return rc; +#else + return EIO; +#endif } -