#include "includes.h"
BOOL lookup_name(TALLOC_CTX *mem_ctx,
const char *full_name, int flags,
const char **ret_domain, const char **ret_name,
DOM_SID *ret_sid, enum lsa_SidType *ret_type)
{
char *p;
const char *tmp;
const char *domain = NULL;
const char *name = NULL;
uint32 rid;
DOM_SID sid;
enum lsa_SidType type;
TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
if (tmp_ctx == NULL) {
DEBUG(0, ("talloc_new failed\n"));
return False;
}
p = strchr_m(full_name, '\\');
if (p != NULL) {
domain = talloc_strndup(tmp_ctx, full_name,
PTR_DIFF(p, full_name));
name = talloc_strdup(tmp_ctx, p+1);
} else {
domain = talloc_strdup(tmp_ctx, "");
name = talloc_strdup(tmp_ctx, full_name);
}
DEBUG(10,("lookup_name: %s => %s (domain), %s (name)\n",
full_name, domain, name));
if ((domain == NULL) || (name == NULL)) {
DEBUG(0, ("talloc failed\n"));
TALLOC_FREE(tmp_ctx);
return False;
}
if (strequal(domain, get_global_sam_name())) {
if (lookup_global_sam_name(name, flags, &rid, &type)) {
sid_copy(&sid, get_global_sam_sid());
sid_append_rid(&sid, rid);
goto ok;
}
TALLOC_FREE(tmp_ctx);
return False;
}
if (strequal(domain, builtin_domain_name())) {
if (lookup_builtin_name(name, &rid)) {
sid_copy(&sid, &global_sid_Builtin);
sid_append_rid(&sid, rid);
type = SID_NAME_ALIAS;
goto ok;
}
TALLOC_FREE(tmp_ctx);
return False;
}
if ((domain[0] != '\0') &&
(winbind_lookup_name(domain, name, &sid, &type))) {
goto ok;
}
if (strequal(domain, unix_users_domain_name())) {
if (lookup_unix_user_name(name, &sid)) {
type = SID_NAME_USER;
goto ok;
}
TALLOC_FREE(tmp_ctx);
return False;
}
if (strequal(domain, unix_groups_domain_name())) {
if (lookup_unix_group_name(name, &sid)) {
type = SID_NAME_DOM_GRP;
goto ok;
}
TALLOC_FREE(tmp_ctx);
return False;
}
if ((domain[0] == '\0') && (!(flags & LOOKUP_NAME_ISOLATED))) {
TALLOC_FREE(tmp_ctx);
return False;
}
if (lookup_wellknown_name(tmp_ctx, name, &sid, &domain)) {
type = SID_NAME_WKN_GRP;
goto ok;
}
if (strequal(name, builtin_domain_name())) {
tmp = name; name = domain; domain = tmp;
sid_copy(&sid, &global_sid_Builtin);
type = SID_NAME_DOMAIN;
goto ok;
}
if (strequal(name, get_global_sam_name())) {
if (!secrets_fetch_domain_sid(name, &sid)) {
DEBUG(3, ("Could not fetch my SID\n"));
TALLOC_FREE(tmp_ctx);
return False;
}
tmp = name; name = domain; domain = tmp;
type = SID_NAME_DOMAIN;
goto ok;
}
if (!IS_DC && strequal(name, lp_workgroup())) {
if (!secrets_fetch_domain_sid(name, &sid)) {
DEBUG(3, ("Could not fetch the domain SID\n"));
TALLOC_FREE(tmp_ctx);
return False;
}
tmp = name; name = domain; domain = tmp;
type = SID_NAME_DOMAIN;
goto ok;
}
if (IS_DC && (secrets_fetch_trusted_domain_password(name, NULL,
&sid, NULL))) {
tmp = name; name = domain; domain = tmp;
type = SID_NAME_DOMAIN;
goto ok;
}
if (lookup_builtin_name(name, &rid)) {
domain = talloc_strdup(tmp_ctx, builtin_domain_name());
sid_copy(&sid, &global_sid_Builtin);
sid_append_rid(&sid, rid);
type = SID_NAME_ALIAS;
goto ok;
}
if (lookup_global_sam_name(name, flags, &rid, &type)) {
domain = talloc_strdup(tmp_ctx, get_global_sam_name());
sid_copy(&sid, get_global_sam_sid());
sid_append_rid(&sid, rid);
goto ok;
}
if (!(flags & LOOKUP_NAME_REMOTE)) {
TALLOC_FREE(tmp_ctx);
return False;
}
if (!IS_DC &&
(winbind_lookup_name(lp_workgroup(), name, &sid, &type))) {
domain = talloc_strdup(tmp_ctx, lp_workgroup());
goto ok;
}
if (IS_DC && winbind_lookup_name("", name, &sid, &type)) {
DOM_SID dom_sid;
uint32 tmp_rid;
enum lsa_SidType domain_type;
if (type == SID_NAME_DOMAIN) {
tmp = name; name = domain; domain = tmp;
goto ok;
}
sid_copy(&dom_sid, &sid);
sid_split_rid(&dom_sid, &tmp_rid);
if (!winbind_lookup_sid(tmp_ctx, &dom_sid, &domain, NULL,
&domain_type) ||
(domain_type != SID_NAME_DOMAIN)) {
DEBUG(2, ("winbind could not find the domain's name "
"it just looked up for us\n"));
TALLOC_FREE(tmp_ctx);
return False;
}
goto ok;
}
if (lookup_unix_user_name(name, &sid)) {
domain = talloc_strdup(tmp_ctx, unix_users_domain_name());
type = SID_NAME_USER;
goto ok;
}
if (lookup_unix_group_name(name, &sid)) {
domain = talloc_strdup(tmp_ctx, unix_groups_domain_name());
type = SID_NAME_DOM_GRP;
goto ok;
}
TALLOC_FREE(tmp_ctx);
return False;
ok:
if ((domain == NULL) || (name == NULL)) {
DEBUG(0, ("talloc failed\n"));
TALLOC_FREE(tmp_ctx);
return False;
}
if ((ret_name != NULL) &&
!(*ret_name = talloc_strdup(mem_ctx, name))) {
DEBUG(0, ("talloc failed\n"));
TALLOC_FREE(tmp_ctx);
return False;
}
if (ret_domain != NULL) {
char *tmp_dom;
if (!(tmp_dom = talloc_strdup(mem_ctx, domain))) {
DEBUG(0, ("talloc failed\n"));
TALLOC_FREE(tmp_ctx);
return False;
}
strupper_m(tmp_dom);
*ret_domain = tmp_dom;
}
if (ret_sid != NULL) {
sid_copy(ret_sid, &sid);
}
if (ret_type != NULL) {
*ret_type = type;
}
TALLOC_FREE(tmp_ctx);
return True;
}
BOOL lookup_name_smbconf(TALLOC_CTX *mem_ctx,
const char *full_name, int flags,
const char **ret_domain, const char **ret_name,
DOM_SID *ret_sid, enum lsa_SidType *ret_type)
{
char *qualified_name;
const char *p;
if ((p = strchr_m(full_name, *lp_winbind_separator())) != NULL) {
if (*lp_winbind_separator() != '\\') {
char *tmp;
tmp = talloc_strdup(mem_ctx, full_name);
if (!tmp) {
return False;
}
tmp[p - full_name] = '\\';
full_name = tmp;
}
return lookup_name(mem_ctx, full_name, flags,
ret_domain, ret_name,
ret_sid, ret_type);
}
qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
get_global_sam_name(),
full_name );
if (!qualified_name) {
return False;
}
if (lookup_name(mem_ctx, qualified_name, flags,
ret_domain, ret_name,
ret_sid, ret_type)) {
return True;
}
qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
flags & LOOKUP_NAME_GROUP ?
unix_groups_domain_name() :
unix_users_domain_name(),
full_name );
if (!qualified_name) {
return False;
}
return lookup_name(mem_ctx, qualified_name, flags,
ret_domain, ret_name,
ret_sid, ret_type);
}
static BOOL wb_lookup_rids(TALLOC_CTX *mem_ctx,
const DOM_SID *domain_sid,
int num_rids, uint32 *rids,
const char **domain_name,
const char **names, enum lsa_SidType *types)
{
int i;
const char **my_names;
enum lsa_SidType *my_types;
TALLOC_CTX *tmp_ctx;
if (!(tmp_ctx = talloc_init("wb_lookup_rids"))) {
return False;
}
if (!winbind_lookup_rids(tmp_ctx, domain_sid, num_rids, rids,
domain_name, &my_names, &my_types)) {
*domain_name = "";
for (i=0; i<num_rids; i++) {
names[i] = "";
types[i] = SID_NAME_UNKNOWN;
}
TALLOC_FREE(tmp_ctx);
return True;
}
if (!(*domain_name = talloc_strdup(mem_ctx, *domain_name))) {
TALLOC_FREE(tmp_ctx);
return False;
}
for (i=0; i<num_rids; i++) {
if (my_names[i] == NULL) {
TALLOC_FREE(tmp_ctx);
return False;
}
if (!(names[i] = talloc_strdup(names, my_names[i]))) {
TALLOC_FREE(tmp_ctx);
return False;
}
types[i] = my_types[i];
}
TALLOC_FREE(tmp_ctx);
return True;
}
static BOOL lookup_rids(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid,
int num_rids, uint32_t *rids,
const char **domain_name,
const char ***names, enum lsa_SidType **types)
{
int i;
if (num_rids) {
*names = TALLOC_ARRAY(mem_ctx, const char *, num_rids);
*types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids);
if ((*names == NULL) || (*types == NULL)) {
return False;
}
} else {
*names = NULL;
*types = NULL;
}
if (sid_check_is_domain(domain_sid)) {
NTSTATUS result;
if (*domain_name == NULL) {
*domain_name = talloc_strdup(
mem_ctx, get_global_sam_name());
}
if (*domain_name == NULL) {
return False;
}
become_root();
result = pdb_lookup_rids(domain_sid, num_rids, rids,
*names, *types);
unbecome_root();
return (NT_STATUS_IS_OK(result) ||
NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
}
if (sid_check_is_builtin(domain_sid)) {
if (*domain_name == NULL) {
*domain_name = talloc_strdup(
mem_ctx, builtin_domain_name());
}
if (*domain_name == NULL) {
return False;
}
for (i=0; i<num_rids; i++) {
if (lookup_builtin_rid(*names, rids[i],
&(*names)[i])) {
if ((*names)[i] == NULL) {
return False;
}
(*types)[i] = SID_NAME_ALIAS;
} else {
(*types)[i] = SID_NAME_UNKNOWN;
}
}
return True;
}
if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
for (i=0; i<num_rids; i++) {
DOM_SID sid;
sid_copy(&sid, domain_sid);
sid_append_rid(&sid, rids[i]);
if (lookup_wellknown_sid(mem_ctx, &sid,
domain_name, &(*names)[i])) {
if ((*names)[i] == NULL) {
return False;
}
(*types)[i] = SID_NAME_WKN_GRP;
} else {
(*types)[i] = SID_NAME_UNKNOWN;
}
}
return True;
}
if (sid_check_is_unix_users(domain_sid)) {
if (*domain_name == NULL) {
*domain_name = talloc_strdup(
mem_ctx, unix_users_domain_name());
}
for (i=0; i<num_rids; i++) {
(*names)[i] = talloc_strdup(
(*names), uidtoname(rids[i]));
(*types)[i] = SID_NAME_USER;
}
return True;
}
if (sid_check_is_unix_groups(domain_sid)) {
if (*domain_name == NULL) {
*domain_name = talloc_strdup(
mem_ctx, unix_groups_domain_name());
}
for (i=0; i<num_rids; i++) {
(*names)[i] = talloc_strdup(
(*names), gidtoname(rids[i]));
(*types)[i] = SID_NAME_DOM_GRP;
}
return True;
}
return wb_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
domain_name, *names, *types);
}
static BOOL lookup_as_domain(const DOM_SID *sid, TALLOC_CTX *mem_ctx,
const char **name)
{
const char *tmp;
enum lsa_SidType type;
if (sid_check_is_domain(sid)) {
*name = talloc_strdup(mem_ctx, get_global_sam_name());
return True;
}
if (sid_check_is_builtin(sid)) {
*name = talloc_strdup(mem_ctx, builtin_domain_name());
return True;
}
if (sid_check_is_wellknown_domain(sid, &tmp)) {
*name = talloc_strdup(mem_ctx, tmp);
return True;
}
if (sid->num_auths != 4) {
return False;
}
if (IS_DC) {
uint32 i, num_domains;
struct trustdom_info **domains;
if (!NT_STATUS_IS_OK(secrets_trusted_domains(mem_ctx,
&num_domains,
&domains))) {
return False;
}
for (i=0; i<num_domains; i++) {
if (sid_equal(sid, &domains[i]->sid)) {
*name = talloc_strdup(mem_ctx,
domains[i]->name);
return True;
}
}
return False;
}
if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
(type == SID_NAME_DOMAIN)) {
*name = tmp;
return True;
}
return False;
}
static BOOL check_dom_sid_to_level(const DOM_SID *sid, int level)
{
int ret = False;
switch(level) {
case 1:
ret = True;
break;
case 2:
ret = (!sid_check_is_builtin(sid) &&
!sid_check_is_wellknown_domain(sid, NULL));
break;
case 3:
case 4:
case 6:
ret = sid_check_is_domain(sid);
break;
case 5:
ret = False;
break;
}
DEBUG(10, ("%s SID %s in level %d\n",
ret ? "Accepting" : "Rejecting",
sid_string_static(sid), level));
return ret;
}
NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
const DOM_SID **sids, int level,
struct lsa_dom_info **ret_domains,
struct lsa_name_info **ret_names)
{
TALLOC_CTX *tmp_ctx;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
struct lsa_name_info *name_infos;
struct lsa_dom_info *dom_infos = NULL;
int i, j;
if (!(tmp_ctx = talloc_new(mem_ctx))) {
DEBUG(0, ("talloc_new failed\n"));
return NT_STATUS_NO_MEMORY;
}
if (num_sids) {
name_infos = TALLOC_ARRAY(mem_ctx, struct lsa_name_info, num_sids);
if (name_infos == NULL) {
result = NT_STATUS_NO_MEMORY;
goto fail;
}
} else {
name_infos = NULL;
}
dom_infos = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_dom_info,
MAX_REF_DOMAINS);
if (dom_infos == NULL) {
result = NT_STATUS_NO_MEMORY;
goto fail;
}
for (i=0; i<num_sids; i++) {
DOM_SID sid;
uint32 rid;
const char *domain_name = NULL;
sid_copy(&sid, sids[i]);
name_infos[i].type = SID_NAME_USE_NONE;
if (lookup_as_domain(&sid, name_infos, &domain_name)) {
if (domain_name == NULL) {
result = NT_STATUS_NO_MEMORY;
goto fail;
}
name_infos[i].rid = 0;
name_infos[i].type = SID_NAME_DOMAIN;
name_infos[i].name = NULL;
if (sid_check_is_builtin(&sid)) {
name_infos[i].name = talloc_strdup(
name_infos, builtin_domain_name());
if (name_infos[i].name == NULL) {
result = NT_STATUS_NO_MEMORY;
goto fail;
}
}
} else {
if (!sid_split_rid(&sid, &rid)) {
result = NT_STATUS_INVALID_PARAMETER;
goto fail;
}
}
if (!check_dom_sid_to_level(&sid, level)) {
name_infos[i].rid = 0;
name_infos[i].type = SID_NAME_UNKNOWN;
name_infos[i].name = NULL;
continue;
}
for (j=0; j<MAX_REF_DOMAINS; j++) {
if (!dom_infos[j].valid) {
break;
}
if (sid_equal(&sid, &dom_infos[j].sid)) {
break;
}
}
if (j == MAX_REF_DOMAINS) {
result = NT_STATUS_NONE_MAPPED;
goto fail;
}
if (!dom_infos[j].valid) {
dom_infos[j].valid = True;
sid_copy(&dom_infos[j].sid, &sid);
if (domain_name != NULL) {
dom_infos[j].name =
talloc_strdup(dom_infos, domain_name);
if (dom_infos[j].name == NULL) {
result = NT_STATUS_NO_MEMORY;
goto fail;
}
} else {
dom_infos[j].name = NULL;
}
}
name_infos[i].dom_idx = j;
if (name_infos[i].type == SID_NAME_USE_NONE) {
name_infos[i].rid = rid;
ADD_TO_ARRAY(dom_infos, int, i, &dom_infos[j].idxs,
&dom_infos[j].num_idxs);
if (dom_infos[j].idxs == NULL) {
result = NT_STATUS_NO_MEMORY;
goto fail;
}
}
}
for (i=0; i<MAX_REF_DOMAINS; i++) {
uint32_t *rids;
const char *domain_name = NULL;
const char **names;
enum lsa_SidType *types;
struct lsa_dom_info *dom = &dom_infos[i];
if (!dom->valid) {
break;
}
if (dom->num_idxs) {
if (!(rids = TALLOC_ARRAY(tmp_ctx, uint32, dom->num_idxs))) {
result = NT_STATUS_NO_MEMORY;
goto fail;
}
} else {
rids = NULL;
}
for (j=0; j<dom->num_idxs; j++) {
rids[j] = name_infos[dom->idxs[j]].rid;
}
if (!lookup_rids(tmp_ctx, &dom->sid,
dom->num_idxs, rids, &domain_name,
&names, &types)) {
result = NT_STATUS_NO_MEMORY;
goto fail;
}
if (!(dom->name = talloc_strdup(dom_infos, domain_name))) {
result = NT_STATUS_NO_MEMORY;
goto fail;
}
for (j=0; j<dom->num_idxs; j++) {
int idx = dom->idxs[j];
name_infos[idx].type = types[j];
if (types[j] != SID_NAME_UNKNOWN) {
name_infos[idx].name =
talloc_strdup(name_infos, names[j]);
if (name_infos[idx].name == NULL) {
result = NT_STATUS_NO_MEMORY;
goto fail;
}
} else {
name_infos[idx].name = NULL;
}
}
}
*ret_domains = dom_infos;
*ret_names = name_infos;
return NT_STATUS_OK;
fail:
TALLOC_FREE(dom_infos);
TALLOC_FREE(name_infos);
TALLOC_FREE(tmp_ctx);
return result;
}
BOOL lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
const char **ret_domain, const char **ret_name,
enum lsa_SidType *ret_type)
{
struct lsa_dom_info *domain;
struct lsa_name_info *name;
TALLOC_CTX *tmp_ctx;
BOOL ret = False;
if (!(tmp_ctx = talloc_new(mem_ctx))) {
DEBUG(0, ("talloc_new failed\n"));
return False;
}
if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
&domain, &name))) {
goto done;
}
if (name->type == SID_NAME_UNKNOWN) {
goto done;
}
if ((ret_domain != NULL) &&
!(*ret_domain = talloc_strdup(mem_ctx, domain->name))) {
goto done;
}
if ((ret_name != NULL) &&
!(*ret_name = talloc_strdup(mem_ctx, name->name))) {
goto done;
}
if (ret_type != NULL) {
*ret_type = name->type;
}
ret = True;
done:
if (ret) {
DEBUG(10, ("Sid %s -> %s\\%s(%d)\n",
sid_string_static(sid), domain->name,
name->name, name->type));
} else {
DEBUG(10, ("failed to lookup sid %s\n",
sid_string_static(sid)));
}
TALLOC_FREE(tmp_ctx);
return ret;
}
#define MAX_UID_SID_CACHE_SIZE 100
#define TURNOVER_UID_SID_CACHE_SIZE 10
#define MAX_GID_SID_CACHE_SIZE 100
#define TURNOVER_GID_SID_CACHE_SIZE 10
static size_t n_uid_sid_cache = 0;
static size_t n_gid_sid_cache = 0;
static struct uid_sid_cache {
struct uid_sid_cache *next, *prev;
uid_t uid;
DOM_SID sid;
enum lsa_SidType sidtype;
} *uid_sid_cache_head;
static struct gid_sid_cache {
struct gid_sid_cache *next, *prev;
gid_t gid;
DOM_SID sid;
enum lsa_SidType sidtype;
} *gid_sid_cache_head;
static BOOL fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid)
{
struct uid_sid_cache *pc;
for (pc = uid_sid_cache_head; pc; pc = pc->next) {
if (pc->uid == uid) {
*psid = pc->sid;
DEBUG(3,("fetch sid from uid cache %u -> %s\n",
(unsigned int)uid, sid_string_static(psid)));
DLIST_PROMOTE(uid_sid_cache_head, pc);
return True;
}
}
return False;
}
static BOOL fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid )
{
struct uid_sid_cache *pc;
for (pc = uid_sid_cache_head; pc; pc = pc->next) {
if (sid_compare(&pc->sid, psid) == 0) {
*puid = pc->uid;
DEBUG(3,("fetch uid from cache %u -> %s\n",
(unsigned int)*puid, sid_string_static(psid)));
DLIST_PROMOTE(uid_sid_cache_head, pc);
return True;
}
}
return False;
}
void store_uid_sid_cache(const DOM_SID *psid, uid_t uid)
{
struct uid_sid_cache *pc;
if ( sid_check_is_in_unix_users( psid ) )
return;
if (n_uid_sid_cache >= MAX_UID_SID_CACHE_SIZE && n_uid_sid_cache > TURNOVER_UID_SID_CACHE_SIZE) {
struct uid_sid_cache *pc_next;
size_t i;
for (i = 0, pc = uid_sid_cache_head; i < (n_uid_sid_cache - TURNOVER_UID_SID_CACHE_SIZE); i++, pc = pc->next)
;
for(; pc; pc = pc_next) {
pc_next = pc->next;
DLIST_REMOVE(uid_sid_cache_head,pc);
SAFE_FREE(pc);
n_uid_sid_cache--;
}
}
pc = SMB_MALLOC_P(struct uid_sid_cache);
if (!pc)
return;
pc->uid = uid;
sid_copy(&pc->sid, psid);
DLIST_ADD(uid_sid_cache_head, pc);
n_uid_sid_cache++;
}
static BOOL fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid)
{
struct gid_sid_cache *pc;
for (pc = gid_sid_cache_head; pc; pc = pc->next) {
if (pc->gid == gid) {
*psid = pc->sid;
DEBUG(3,("fetch sid from gid cache %u -> %s\n",
(unsigned int)gid, sid_string_static(psid)));
DLIST_PROMOTE(gid_sid_cache_head, pc);
return True;
}
}
return False;
}
static BOOL fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid)
{
struct gid_sid_cache *pc;
for (pc = gid_sid_cache_head; pc; pc = pc->next) {
if (sid_compare(&pc->sid, psid) == 0) {
*pgid = pc->gid;
DEBUG(3,("fetch gid from cache %u -> %s\n",
(unsigned int)*pgid, sid_string_static(psid)));
DLIST_PROMOTE(gid_sid_cache_head, pc);
return True;
}
}
return False;
}
void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
{
struct gid_sid_cache *pc;
if ( sid_check_is_in_unix_groups( psid ) )
return;
if (n_gid_sid_cache >= MAX_GID_SID_CACHE_SIZE && n_gid_sid_cache > TURNOVER_GID_SID_CACHE_SIZE) {
struct gid_sid_cache *pc_next;
size_t i;
for (i = 0, pc = gid_sid_cache_head; i < (n_gid_sid_cache - TURNOVER_GID_SID_CACHE_SIZE); i++, pc = pc->next)
;
for(; pc; pc = pc_next) {
pc_next = pc->next;
DLIST_REMOVE(gid_sid_cache_head,pc);
SAFE_FREE(pc);
n_gid_sid_cache--;
}
}
pc = SMB_MALLOC_P(struct gid_sid_cache);
if (!pc)
return;
pc->gid = gid;
sid_copy(&pc->sid, psid);
DLIST_ADD(gid_sid_cache_head, pc);
DEBUG(3,("store_gid_sid_cache: gid %u in cache -> %s\n", (unsigned int)gid,
sid_string_static(psid)));
n_gid_sid_cache++;
}
static void legacy_uid_to_sid(DOM_SID *psid, uid_t uid)
{
uint32 rid;
BOOL ret;
ZERO_STRUCTP(psid);
become_root();
ret = pdb_uid_to_rid(uid, &rid);
unbecome_root();
if (ret) {
sid_copy(psid, get_global_sam_sid());
sid_append_rid(psid, rid);
goto done;
}
uid_to_unix_users_sid(uid, psid);
done:
DEBUG(10,("LEGACY: uid %u -> sid %s\n", (unsigned int)uid,
sid_string_static(psid)));
store_uid_sid_cache(psid, uid);
return;
}
static void legacy_gid_to_sid(DOM_SID *psid, gid_t gid)
{
BOOL ret;
ZERO_STRUCTP(psid);
become_root();
ret = pdb_gid_to_sid(gid, psid);
unbecome_root();
if (ret) {
goto done;
}
gid_to_unix_groups_sid(gid, psid);
done:
DEBUG(10,("LEGACY: gid %u -> sid %s\n", (unsigned int)gid,
sid_string_static(psid)));
store_gid_sid_cache(psid, gid);
return;
}
static BOOL legacy_sid_to_uid(const DOM_SID *psid, uid_t *puid)
{
enum lsa_SidType type;
uint32 rid;
if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
union unid_t id;
BOOL ret;
become_root();
ret = pdb_sid_to_id(psid, &id, &type);
unbecome_root();
if (ret) {
if (type != SID_NAME_USER) {
DEBUG(5, ("sid %s is a %s, expected a user\n",
sid_string_static(psid),
sid_type_lookup(type)));
return False;
}
*puid = id.uid;
goto done;
}
}
DEBUG(10,("LEGACY: mapping failed for sid %s\n", sid_string_static(psid)));
return False;
done:
DEBUG(10,("LEGACY: sid %s -> uid %u\n", sid_string_static(psid),
(unsigned int)*puid ));
store_uid_sid_cache(psid, *puid);
return True;
}
static BOOL legacy_sid_to_gid(const DOM_SID *psid, gid_t *pgid)
{
uint32 rid;
GROUP_MAP map;
union unid_t id;
enum lsa_SidType type;
if ((sid_check_is_in_builtin(psid) ||
sid_check_is_in_wellknown_domain(psid))) {
BOOL ret;
become_root();
ret = pdb_getgrsid(&map, *psid);
unbecome_root();
if (ret) {
*pgid = map.gid;
goto done;
}
DEBUG(10,("LEGACY: mapping failed for sid %s\n", sid_string_static(psid)));
return False;
}
if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
BOOL ret;
become_root();
ret = pdb_sid_to_id(psid, &id, &type);
unbecome_root();
if (ret) {
if ((type != SID_NAME_DOM_GRP) &&
(type != SID_NAME_ALIAS)) {
DEBUG(5, ("LEGACY: sid %s is a %s, expected a group\n",
sid_string_static(psid),
sid_type_lookup(type)));
return False;
}
*pgid = id.gid;
goto done;
}
}
DEBUG(10,("LEGACY: mapping failed for sid %s\n", sid_string_static(psid)));
return False;
done:
DEBUG(10,("LEGACY: sid %s -> gid %u\n", sid_string_static(psid),
(unsigned int)*pgid ));
store_gid_sid_cache(psid, *pgid);
return True;
}
void uid_to_sid(DOM_SID *psid, uid_t uid)
{
ZERO_STRUCTP(psid);
if (fetch_sid_from_uid_cache(psid, uid))
return;
if (!winbind_uid_to_sid(psid, uid)) {
if (!winbind_ping()) {
legacy_uid_to_sid(psid, uid);
return;
}
DEBUG(5, ("uid_to_sid: winbind failed to find a sid for uid %u\n",
uid));
return;
}
DEBUG(10,("uid %u -> sid %s\n",
(unsigned int)uid, sid_string_static(psid)));
store_uid_sid_cache(psid, uid);
return;
}
void gid_to_sid(DOM_SID *psid, gid_t gid)
{
ZERO_STRUCTP(psid);
if (fetch_sid_from_gid_cache(psid, gid))
return;
if (!winbind_gid_to_sid(psid, gid)) {
if (!winbind_ping()) {
legacy_gid_to_sid(psid, gid);
return;
}
DEBUG(5, ("gid_to_sid: winbind failed to find a sid for gid %u\n",
gid));
return;
}
DEBUG(10,("gid %u -> sid %s\n",
(unsigned int)gid, sid_string_static(psid)));
store_gid_sid_cache(psid, gid);
return;
}
BOOL sid_to_uid(const DOM_SID *psid, uid_t *puid)
{
uint32 rid;
gid_t gid;
if (fetch_uid_from_cache(puid, psid))
return True;
if (fetch_gid_from_cache(&gid, psid)) {
return False;
}
if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) {
uid_t uid = rid;
*puid = uid;
DEBUG(10,("sid %s -> uid %u\n", sid_string_static(psid),
(unsigned int)*puid ));
return True;
}
if (!winbind_sid_to_uid(puid, psid)) {
if (!winbind_ping()) {
return legacy_sid_to_uid(psid, puid);
}
DEBUG(5, ("winbind failed to find a uid for sid %s\n",
sid_string_static(psid)));
return False;
}
DEBUG(10,("sid %s -> uid %u\n", sid_string_static(psid),
(unsigned int)*puid ));
store_uid_sid_cache(psid, *puid);
return True;
}
BOOL sid_to_gid(const DOM_SID *psid, gid_t *pgid)
{
uint32 rid;
uid_t uid;
if (fetch_gid_from_cache(pgid, psid))
return True;
if (fetch_uid_from_cache(&uid, psid))
return False;
if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
gid_t gid = rid;
*pgid = gid;
DEBUG(10,("sid %s -> gid %u\n", sid_string_static(psid),
(unsigned int)*pgid ));
return True;
}
if ( !winbind_sid_to_gid(pgid, psid) ) {
if (!winbind_ping()) {
return legacy_sid_to_gid(psid, pgid);
}
DEBUG(10,("winbind failed to find a gid for sid %s\n",
sid_string_static(psid)));
return False;
}
DEBUG(10,("sid %s -> gid %u\n", sid_string_static(psid),
(unsigned int)*pgid ));
store_gid_sid_cache(psid, *pgid);
return True;
}