idmap_lsa.c revision b3700b074e637f8c6991b70754c88a2cfffb246b
/*
* 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 2014 Nexenta Systems, Inc. All rights reserved.
*/
/*
* LSA lookups
*/
#include <stdio.h>
#include <note.h>
#include <assert.h>
#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_sid(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_name(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();
}