/*
- * Copyright (c) 2004-2007 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2004-2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* @APPLE_LICENSE_HEADER_END@
*/
+#include <stdlib.h>
+#include <sys/errno.h>
+#include <mach/mach.h>
#include "membership.h"
#include "membershipPriv.h"
-#include "memberd.h"
-
-#include <sys/errno.h>
#include <servers/bootstrap.h>
-#include <mach/mach.h>
-#include <stdlib.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 mach_port_t GetServerPort()
-{
- 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);
- }
+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};
- return fServerPort;
-}
+#define COMPAT_PREFIX_LEN (sizeof(uuid_t) - sizeof(id_t))
-int mbr_uid_to_uuid(uid_t id, uuid_t uu)
-{
- struct kauth_identity_extlookup request;
- security_token_t token;
- int result = 0;
+#ifdef DS_AVAILABLE
- token.val[0] = -1;
- token.val[1] = -1;
+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));
- request.el_flags = KAUTH_EXTLOOKUP_VALID_UID | KAUTH_EXTLOOKUP_WANT_UGUID;
- request.el_uid = id;
- result = _mbr_DoMembershipCall(GetServerPort(), &request, &token);
- if (result != KERN_SUCCESS) return EIO;
- if (token.val[0] != 0) return EAUTH;
+#endif
- if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_UGUID) != 0)
- memcpy(uu, &request.el_uguid, sizeof(guid_t));
- else
- result = ENOENT;
+#ifdef DS_AVAILABLE
+static void
+_mbr_fork_child(void)
+{
+ 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
- return result;
+#ifdef DS_AVAILABLE
+static void
+_mbr_fork_prepare(void)
+{
+ 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;
- security_token_t token;
- kern_return_t result;
- int error = 0;
-
- token.val[0] = -1;
- token.val[1] = -1;
-
- request.el_flags = KAUTH_EXTLOOKUP_VALID_GID | KAUTH_EXTLOOKUP_WANT_GGUID;
- request.el_gid = id;
- result = _mbr_DoMembershipCall(GetServerPort(), &request, &token);
- if (result != KERN_SUCCESS) return EIO;
- if (token.val[0] != 0) return EAUTH;
-
- 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;
- security_token_t token;
- kern_return_t result;
- int error = 0;
-
- token.val[0] = -1;
- token.val[1] = -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));
- result = _mbr_DoMembershipCall(GetServerPort(), &request, &token);
- if (result != KERN_SUCCESS) return EIO;
- if (token.val[0] != 0) return EAUTH;
-
- if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_UID) != 0)
- {
- *id = request.el_uid;
- *id_type = ID_TYPE_UID;
+ 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;
}
- 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;
+
+ 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);
+ }
}
-
- return error;
+
+ 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;
- security_token_t token;
- kern_return_t result;
- int error = 0;
-
- token.val[0] = -1;
- token.val[1] = -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));
- result = _mbr_DoMembershipCall(GetServerPort(), &request, &token);
- if (result != KERN_SUCCESS) return EIO;
- if (token.val[0] != 0) return EAUTH;
-
- 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;
- security_token_t token;
- kern_return_t result;
- int error = 0;
-
- token.val[0] = -1;
- token.val[1] = -1;
-
- request.el_flags = KAUTH_EXTLOOKUP_VALID_GGUID | KAUTH_EXTLOOKUP_WANT_GSID;
- memcpy(&request.el_gguid, uu, sizeof(guid_t));
- result = _mbr_DoMembershipCall(GetServerPort(), &request, &token);
- if (result != KERN_SUCCESS) return EIO;
- if (token.val[0] != 0) return EAUTH;
-
- if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GSID) != 0)
- memcpy(sid, &request.el_gsid, sizeof(nt_sid_t));
- else
- error = ENOENT;
-
- return error;
+#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;
+
+ 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_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;
- security_token_t token;
- kern_return_t result;
- int error = 0;
-
- token.val[0] = -1;
- token.val[1] = -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));
- result = _mbr_DoMembershipCall(GetServerPort(), &request, &token);
- if (result != KERN_SUCCESS) return EIO;
- if (token.val[0] != 0) return EAUTH;
-
- 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;
- security_token_t token;
- kern_return_t result;
- int error = 0;
-
- token.val[0] = -1;
- token.val[1] = -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));
- result = _mbr_DoMembershipCall(GetServerPort(), &request, &token);
- if (result != KERN_SUCCESS) return EIO;
- if (token.val[0] != 0) return EAUTH;
-
- 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;
- security_token_t token;
- kern_return_t result;
- int error = 0;
-
- token.val[0] = -1;
- token.val[1] = -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;
- result = _mbr_DoMembershipCall(GetServerPort(), &request, &token);
- if (result != KERN_SUCCESS) return EIO;
- if (token.val[0] != 0) return EAUTH;
-
- if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_MEMBERSHIP) != 0)
- *ismember = ((request.el_flags & KAUTH_EXTLOOKUP_ISMEMBER) != 0);
- else
- error = ENOENT;
-
- return error;
+ 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 rc;
}
-int mbr_reset_cache()
+int
+mbr_sid_to_uuid(const nt_sid_t *sid, uuid_t uu)
{
- security_token_t token;
- kern_return_t result;
-
- token.val[0] = -1;
- token.val[1] = -1;
-
- result = _mbr_ClearCache(GetServerPort(), &token);
- if (result != KERN_SUCCESS) return EIO;
- if (token.val[0] != 0) return EAUTH;
-
- 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)
{
- security_token_t token;
- kern_return_t result;
+ 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;
+}
- if (name == NULL) return EINVAL;
- if (strlen(name) > 255) return EINVAL;
+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
+}
- token.val[0] = -1;
- token.val[1] = -1;
+int
+mbr_uuid_to_sid(const uuid_t uu, nt_sid_t *sid)
+{
+#ifdef DS_AVAILABLE
+ int type, status;
- result = _mbr_MapName(GetServerPort(), 1, (char *)name, (guid_t *)uu, &token);
- if (result == KERN_FAILURE) return ENOENT;
- else if (result != KERN_SUCCESS) return EIO;
+ type = 0;
- if (token.val[0] != 0) return EAUTH;
+ status = mbr_uuid_to_sid_type(uu, sid, &type);
+ if (status != 0) return status;
return 0;
+#else
+ return EIO;
+#endif
}
-int mbr_group_name_to_uuid(const char *name, uuid_t uu)
+int
+mbr_check_membership(const uuid_t user, const uuid_t group, int *ismember)
{
- security_token_t token;
- kern_return_t result;
-
- if (name == NULL) return EINVAL;
- if (strlen(name) > 255) return EINVAL;
+ return mbr_check_membership_ext(ID_TYPE_UUID, user, sizeof(uuid_t), ID_TYPE_UUID, group, 0, ismember);
+}
- token.val[0] = -1;
- token.val[1] = -1;
+int
+mbr_check_membership_refresh(const uuid_t user, uuid_t group, int *ismember)
+{
+ return mbr_check_membership_ext(ID_TYPE_UUID, user, sizeof(uuid_t), ID_TYPE_UUID, group, 1, ismember);
+}
- result = _mbr_MapName(GetServerPort(), 0, (char *)name, (guid_t *)uu, &token);
- if (result == KERN_FAILURE) return ENOENT;
- else if (result != KERN_SUCCESS) return EIO;
+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;
+
+ 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
+}
- if (token.val[0] != 0) return EAUTH;
+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;
-
- 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;
+ return mbr_identifier_to_uuid(ID_TYPE_USERNAME, name, -1, uu);
+}
- 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);
- }
+int
+mbr_group_name_to_uuid(const char *name, uuid_t 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';
buffer[23] = '0';
- if (value == 0) return &buffer[23];
+ if (value == 0)
+ return &buffer[23];
temp = &buffer[24];
while (value != 0)
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;
current++;
strcpy(current, ConvertBytesToDecimal(tempBuffer, temp));
- for (i = 0; i < sid->sid_authcount; i++)
+ for(i=0; i < sid->sid_authcount; i++)
{
current = current + strlen(current);
*current = '-';
}
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;
+ if (string[0] != 'S' || string[1] != '-') return EINVAL;
sid->sid_kind = strtol(current, ¤t, 10);
if (*current == '\0') return EINVAL;
/* convert to BigEndian before copying */
temp = OSSwapHostToBigInt64(temp);
memcpy(sid->sid_authority, ((char*)&temp)+2, 6);
- while ((*current != '\0') && (count < NTSID_MAX_AUTHORITIES))
+ 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++;
}
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 (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;
- }
-
- if (isFirstNibble)
- {
- uu[dataIndex] = nibble << 4;
- isFirstNibble = 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, "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;
}
- else
- {
- uu[dataIndex] |= nibble;
- dataIndex++;
- isFirstNibble = 1;
- }
-
- string++;
}
-
- if (dataIndex != 16) return EINVAL;
-
- return 0;
+
+ xpc_release(payload);
+
+ return rc;
+#else
+ return EIO;
+#endif
}