/*
- * 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_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 "membership.h"
+#include "membershipPriv.h"
#include <servers/bootstrap.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 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 | KAUTH_EXTLOOKUP_VALID_USID | KAUTH_EXTLOOKUP_WANT_UGUID;
- memset(&request.el_gsid, 0, sizeof(ntsid_t));
- memcpy(&request.el_gsid, sid, KAUTH_NTSID_SIZE(sid));
- memset(&request.el_usid, 0, sizeof(ntsid_t));
- memcpy(&request.el_usid, sid, KAUTH_NTSID_SIZE(sid));
-
- status = _mbr_MembershipCall(&request);
- if (status != 0) return status;
-
- if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GGUID) != 0) memcpy(uu, &request.el_gguid, sizeof(guid_t));
- else if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_UGUID) != 0) memcpy(uu, &request.el_uguid, sizeof(guid_t));
- else return ENOENT;
-
- 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;
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';
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;
}
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;
while (*current != '\0' && count < NTSID_MAX_AUTHORITIES)
{
current++;
+ 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 (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
}
-