/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2019 Nexenta Systems, Inc. All rights reserved. */ /* * LSA lookups */ #include #include #include #include "idmapd.h" #include "libsmb.h" idmap_retcode idmap_lsa_xlate_sid_type(const lsa_account_t *acct, idmap_id_type *ret_type) { switch (acct->a_sidtype) { case SidTypeUser: case SidTypeComputer: case SidTypeDomain: case SidTypeDeletedAccount: case SidTypeUnknown: case SidTypeLabel: *ret_type = IDMAP_USID; return (IDMAP_SUCCESS); case SidTypeGroup: case SidTypeAlias: case SidTypeWellKnownGroup: *ret_type = IDMAP_GSID; return (IDMAP_SUCCESS); case SidTypeNull: case SidTypeInvalid: default: idmapdlog(LOG_WARNING, "LSA lookup: bad type %d for %s@%s", acct->a_sidtype, acct->a_name, acct->a_domain); return (IDMAP_ERR_OTHER); } NOTE(NOTREACHED) } /* Given SID, look up name and type */ idmap_retcode lookup_lsa_by_sid( const char *sidprefix, uint32_t rid, char **ret_name, char **ret_domain, idmap_id_type *ret_type) { lsa_account_t acct; char sid[SMB_SID_STRSZ + 1]; idmap_retcode ret; int rc; (void) memset(&acct, 0, sizeof (acct)); *ret_name = NULL; *ret_domain = NULL; (void) snprintf(sid, sizeof (sid), "%s-%u", sidprefix, rid); rc = smb_lookup_lsid(sid, &acct); if (rc != 0) { idmapdlog(LOG_ERR, "Error: SMB lookup SID failed."); idmapdlog(LOG_ERR, "Check SMB service (svc:/network/smb/server)."); idmapdlog(LOG_ERR, "Check connectivity to Active Directory."); ret = IDMAP_ERR_OTHER; goto out; } if (acct.a_status == NT_STATUS_NONE_MAPPED) { ret = IDMAP_ERR_NOTFOUND; goto out; } if (acct.a_status != NT_STATUS_SUCCESS) { idmapdlog(LOG_WARNING, "Warning: SMB lookup SID(%s) failed (0x%x)", sid, acct.a_status); /* Fail soft */ ret = IDMAP_ERR_NOTFOUND; goto out; } ret = idmap_lsa_xlate_sid_type(&acct, ret_type); if (ret != IDMAP_SUCCESS) goto out; *ret_name = strdup(acct.a_name); if (*ret_name == NULL) { ret = IDMAP_ERR_MEMORY; goto out; } *ret_domain = strdup(acct.a_domain); if (*ret_domain == NULL) { ret = IDMAP_ERR_MEMORY; goto out; } ret = IDMAP_SUCCESS; out: if (ret != IDMAP_SUCCESS) { free(*ret_name); *ret_name = NULL; free(*ret_domain); *ret_domain = NULL; } return (ret); } /* Given name and optional domain, look up SID, type, and canonical name */ idmap_retcode lookup_lsa_by_name( const char *name, const char *domain, char **ret_sidprefix, uint32_t *ret_rid, char **ret_name, char **ret_domain, idmap_id_type *ret_type) { lsa_account_t acct; char *namedom = NULL; idmap_retcode ret; int rc; (void) memset(&acct, 0, sizeof (acct)); *ret_sidprefix = NULL; if (ret_name != NULL) *ret_name = NULL; if (ret_domain != NULL) *ret_domain = NULL; if (domain != NULL) (void) asprintf(&namedom, "%s@%s", name, domain); else namedom = strdup(name); if (namedom == NULL) { ret = IDMAP_ERR_MEMORY; goto out; } rc = smb_lookup_lname(namedom, SidTypeUnknown, &acct); if (rc != 0) { idmapdlog(LOG_ERR, "Error: SMB lookup name failed."); idmapdlog(LOG_ERR, "Check SMB service (svc:/network/smb/server)."); idmapdlog(LOG_ERR, "Check connectivity to Active Directory."); ret = IDMAP_ERR_OTHER; goto out; } if (acct.a_status == NT_STATUS_NONE_MAPPED) { ret = IDMAP_ERR_NOTFOUND; goto out; } if (acct.a_status != NT_STATUS_SUCCESS) { idmapdlog(LOG_WARNING, "Warning: SMB lookup name(%s) failed (0x%x)", namedom, acct.a_status); /* Fail soft */ ret = IDMAP_ERR_NOTFOUND; goto out; } rc = smb_sid_splitstr(acct.a_sid, ret_rid); assert(rc == 0); *ret_sidprefix = strdup(acct.a_sid); if (*ret_sidprefix == NULL) { ret = IDMAP_ERR_MEMORY; goto out; } ret = idmap_lsa_xlate_sid_type(&acct, ret_type); if (ret != IDMAP_SUCCESS) goto out; if (ret_name != NULL) { *ret_name = strdup(acct.a_name); if (*ret_name == NULL) { ret = IDMAP_ERR_MEMORY; goto out; } } if (ret_domain != NULL) { *ret_domain = strdup(acct.a_domain); if (*ret_domain == NULL) { ret = IDMAP_ERR_MEMORY; goto out; } } ret = IDMAP_SUCCESS; out: free(namedom); if (ret != IDMAP_SUCCESS) { if (ret_name != NULL) { free(*ret_name); *ret_name = NULL; } if (ret_domain != NULL) { free(*ret_domain); *ret_domain = NULL; } free(*ret_sidprefix); *ret_sidprefix = NULL; } return (ret); } /* * This exists just so we can avoid exposing all of idmapd to libsmb.h. * Like the above functions, it's a door call over to smbd. */ void notify_dc_changed(void) { smb_notify_dc_changed(); }