#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)
}
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);
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);
}
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);
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);
}
void
notify_dc_changed(void)
{
int rc;
rc = smb_notify_dc_changed();
if (rc != 0) {
idmapdlog(LOG_WARNING,
"Warning: smb_notify_dc_changed, rc=%d", rc);
}
}