mirror of
https://github.com/samba-team/samba.git
synced 2025-01-26 10:04:02 +03:00
4ab9d91428
damn, this one is bad. started, at least two days ago, to add an authentication mechanism to the smbd<->msrpc redirector/relay, such that sufficient unix / nt information could be transferred across the unix socket to do a become_user() on the other side of the socket. it is necessary that the msrpc daemon inherit the same unix and nt credentials as the smbd process from which it was spawned, until such time as the msrpc daemon receives an authentication request of its own, whereupon the msrpc daemon is responsible for authenticating the new credentials and doing yet another become_user() etc sequence. (This used to be commit 30c7fdd6ef10ecd35594311c1b250b95ff895489)
1316 lines
33 KiB
C
1316 lines
33 KiB
C
/*
|
|
Unix SMB/Netbios implementation.
|
|
Version 1.9.
|
|
Groupname handling
|
|
Copyright (C) Jeremy Allison 1998.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
/*
|
|
* UNIX gid and Local or Domain SID resolution. This module resolves
|
|
* only those entries in the map files, it is *NOT* responsible for
|
|
* resolving UNIX groups not listed: that is an entirely different
|
|
* matter, altogether...
|
|
*/
|
|
|
|
/*
|
|
*
|
|
*
|
|
|
|
format of the file is:
|
|
|
|
unixname NT Group name
|
|
unixname Domain Admins (well-known Domain Group)
|
|
unixname DOMAIN_NAME\NT Group name
|
|
unixname OTHER_DOMAIN_NAME\NT Group name
|
|
unixname DOMAIN_NAME\Domain Admins (well-known Domain Group)
|
|
....
|
|
|
|
if the DOMAIN_NAME\ component is left off, then your own domain is assumed.
|
|
|
|
*
|
|
*
|
|
*/
|
|
|
|
|
|
#include "includes.h"
|
|
extern int DEBUGLEVEL;
|
|
|
|
extern fstring global_myworkgroup;
|
|
extern DOM_SID global_member_sid;
|
|
extern fstring global_sam_name;
|
|
extern DOM_SID global_sam_sid;
|
|
extern DOM_SID global_sid_S_1_5_20;
|
|
|
|
/*******************************************************************
|
|
converts UNIX uid to an NT User RID. NOTE: IS SOMETHING SPECIFIC TO SAMBA
|
|
********************************************************************/
|
|
static uid_t pwdb_user_rid_to_uid(uint32 user_rid)
|
|
{
|
|
return ((user_rid & (~RID_TYPE_USER))- 1000)/RID_MULTIPLIER;
|
|
}
|
|
|
|
/*******************************************************************
|
|
converts NT Group RID to a UNIX uid. NOTE: IS SOMETHING SPECIFIC TO SAMBA
|
|
********************************************************************/
|
|
static uint32 pwdb_group_rid_to_gid(uint32 group_rid)
|
|
{
|
|
return ((group_rid & (~RID_TYPE_GROUP))- 1000)/RID_MULTIPLIER;
|
|
}
|
|
|
|
/*******************************************************************
|
|
converts NT Alias RID to a UNIX uid. NOTE: IS SOMETHING SPECIFIC TO SAMBA
|
|
********************************************************************/
|
|
static uint32 pwdb_alias_rid_to_gid(uint32 alias_rid)
|
|
{
|
|
return ((alias_rid & (~RID_TYPE_ALIAS))- 1000)/RID_MULTIPLIER;
|
|
}
|
|
|
|
/*******************************************************************
|
|
converts NT Group RID to a UNIX uid. NOTE: IS SOMETHING SPECIFIC TO SAMBA
|
|
********************************************************************/
|
|
static uint32 pwdb_gid_to_group_rid(uint32 gid)
|
|
{
|
|
uint32 grp_rid = ((((gid)*RID_MULTIPLIER) + 1000) | RID_TYPE_GROUP);
|
|
return grp_rid;
|
|
}
|
|
|
|
/******************************************************************
|
|
converts UNIX gid to an NT Alias RID. NOTE: IS SOMETHING SPECIFIC TO SAMBA
|
|
********************************************************************/
|
|
static uint32 pwdb_gid_to_alias_rid(uint32 gid)
|
|
{
|
|
uint32 alias_rid = ((((gid)*RID_MULTIPLIER) + 1000) | RID_TYPE_ALIAS);
|
|
return alias_rid;
|
|
}
|
|
|
|
/*******************************************************************
|
|
converts UNIX uid to an NT User RID. NOTE: IS SOMETHING SPECIFIC TO SAMBA
|
|
********************************************************************/
|
|
static uint32 pwdb_uid_to_user_rid(uint32 uid)
|
|
{
|
|
uint32 user_rid = ((((uid)*RID_MULTIPLIER) + 1000) | RID_TYPE_USER);
|
|
return user_rid;
|
|
}
|
|
|
|
/******************************************************************
|
|
converts SID + SID_NAME_USE type to a UNIX id. the Domain SID is,
|
|
and can only be, our own SID.
|
|
********************************************************************/
|
|
static BOOL pwdb_sam_sid_to_unixid(DOM_SID *sid, uint8 type, uint32 *id)
|
|
{
|
|
DOM_SID tmp_sid;
|
|
uint32 rid;
|
|
|
|
sid_copy(&tmp_sid, sid);
|
|
sid_split_rid(&tmp_sid, &rid);
|
|
if (!sid_equal(&global_sam_sid, &tmp_sid))
|
|
{
|
|
return False;
|
|
}
|
|
|
|
switch (type)
|
|
{
|
|
case SID_NAME_USER:
|
|
{
|
|
*id = pwdb_user_rid_to_uid(rid);
|
|
return True;
|
|
}
|
|
case SID_NAME_ALIAS:
|
|
{
|
|
*id = pwdb_alias_rid_to_gid(rid);
|
|
return True;
|
|
}
|
|
case SID_NAME_DOM_GRP:
|
|
case SID_NAME_WKN_GRP:
|
|
{
|
|
*id = pwdb_group_rid_to_gid(rid);
|
|
return True;
|
|
}
|
|
}
|
|
return False;
|
|
}
|
|
|
|
/******************************************************************
|
|
converts UNIX gid + SID_NAME_USE type to a SID. the Domain SID is,
|
|
and can only be, our own SID.
|
|
********************************************************************/
|
|
static BOOL pwdb_unixid_to_sam_sid(uint32 id, uint8 type, DOM_SID *sid)
|
|
{
|
|
sid_copy(sid, &global_sam_sid);
|
|
switch (type)
|
|
{
|
|
case SID_NAME_USER:
|
|
{
|
|
sid_append_rid(sid, pwdb_uid_to_user_rid(id));
|
|
return True;
|
|
}
|
|
case SID_NAME_ALIAS:
|
|
{
|
|
sid_append_rid(sid, pwdb_gid_to_alias_rid(id));
|
|
return True;
|
|
}
|
|
case SID_NAME_DOM_GRP:
|
|
case SID_NAME_WKN_GRP:
|
|
{
|
|
sid_append_rid(sid, pwdb_gid_to_group_rid(id));
|
|
return True;
|
|
}
|
|
}
|
|
return False;
|
|
}
|
|
|
|
/*******************************************************************
|
|
Decides if a RID is a well known RID.
|
|
********************************************************************/
|
|
static BOOL pwdb_rid_is_well_known(uint32 rid)
|
|
{
|
|
return (rid < 1000);
|
|
}
|
|
|
|
/*******************************************************************
|
|
determines a rid's type. NOTE: THIS IS SOMETHING SPECIFIC TO SAMBA
|
|
********************************************************************/
|
|
static uint32 pwdb_rid_type(uint32 rid)
|
|
{
|
|
/* lkcl i understand that NT attaches an enumeration to a RID
|
|
* such that it can be identified as either a user, group etc
|
|
* type: SID_ENUM_TYPE.
|
|
*/
|
|
if (pwdb_rid_is_well_known(rid))
|
|
{
|
|
/*
|
|
* The only well known user RIDs are DOMAIN_USER_RID_ADMIN
|
|
* and DOMAIN_USER_RID_GUEST.
|
|
*/
|
|
if (rid == DOMAIN_USER_RID_ADMIN || rid == DOMAIN_USER_RID_GUEST)
|
|
{
|
|
return RID_TYPE_USER;
|
|
}
|
|
if (DOMAIN_GROUP_RID_ADMINS <= rid && rid <= DOMAIN_GROUP_RID_GUESTS)
|
|
{
|
|
return RID_TYPE_GROUP;
|
|
}
|
|
if (BUILTIN_ALIAS_RID_ADMINS <= rid && rid <= BUILTIN_ALIAS_RID_REPLICATOR)
|
|
{
|
|
return RID_TYPE_ALIAS;
|
|
}
|
|
}
|
|
return (rid & RID_TYPE_MASK);
|
|
}
|
|
|
|
/*******************************************************************
|
|
checks whether rid is a user rid. NOTE: THIS IS SOMETHING SPECIFIC TO SAMBA
|
|
********************************************************************/
|
|
BOOL pwdb_rid_is_user(uint32 rid)
|
|
{
|
|
return pwdb_rid_type(rid) == RID_TYPE_USER;
|
|
}
|
|
|
|
/**************************************************************************
|
|
Groupname map functionality. The code loads a groupname map file and
|
|
(currently) loads it into a linked list. This is slow and memory
|
|
hungry, but can be changed into a more efficient storage format
|
|
if the demands on it become excessive.
|
|
***************************************************************************/
|
|
|
|
typedef struct name_map
|
|
{
|
|
ubi_slNode next;
|
|
DOM_NAME_MAP grp;
|
|
|
|
} name_map_entry;
|
|
|
|
static ubi_slList groupname_map_list;
|
|
static ubi_slList aliasname_map_list;
|
|
static ubi_slList ntusrname_map_list;
|
|
|
|
static void delete_name_entry(name_map_entry *gmep)
|
|
{
|
|
if (gmep->grp.nt_name)
|
|
{
|
|
free(gmep->grp.nt_name);
|
|
}
|
|
if (gmep->grp.nt_domain)
|
|
{
|
|
free(gmep->grp.nt_domain);
|
|
}
|
|
if (gmep->grp.unix_name)
|
|
{
|
|
free(gmep->grp.unix_name);
|
|
}
|
|
free((char*)gmep);
|
|
}
|
|
|
|
/**************************************************************************
|
|
Delete all the entries in the name map list.
|
|
***************************************************************************/
|
|
|
|
static void delete_map_list(ubi_slList *map_list)
|
|
{
|
|
name_map_entry *gmep;
|
|
|
|
while ((gmep = (name_map_entry *)ubi_slRemHead(map_list )) != NULL)
|
|
{
|
|
delete_name_entry(gmep);
|
|
}
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
makes a group sid out of a domain sid and a _unix_ gid.
|
|
***************************************************************************/
|
|
static BOOL make_mydomain_sid(DOM_NAME_MAP *grp, DOM_MAP_TYPE type)
|
|
{
|
|
int ret = False;
|
|
fstring sid_str;
|
|
|
|
if (!map_domain_name_to_sid(&grp->sid, &(grp->nt_domain)))
|
|
{
|
|
DEBUG(0,("make_mydomain_sid: unknown domain %s\n",
|
|
grp->nt_domain));
|
|
return False;
|
|
}
|
|
|
|
if (sid_equal(&grp->sid, &global_sid_S_1_5_20))
|
|
{
|
|
/*
|
|
* only builtin aliases are recognised in S-1-5-20
|
|
*/
|
|
DEBUG(10,("make_mydomain_sid: group %s in builtin domain\n",
|
|
grp->nt_name));
|
|
|
|
if (lookup_builtin_alias_name(grp->nt_name, "BUILTIN", &grp->sid, &grp->type) != 0x0)
|
|
{
|
|
DEBUG(0,("unix group %s mapped to an unrecognised BUILTIN domain name %s\n",
|
|
grp->unix_name, grp->nt_name));
|
|
return False;
|
|
}
|
|
ret = True;
|
|
}
|
|
else if (lookup_wk_user_name(grp->nt_name, grp->nt_domain, &grp->sid, &grp->type) == 0x0)
|
|
{
|
|
if (type != DOM_MAP_USER)
|
|
{
|
|
DEBUG(0,("well-known NT user %s\\%s listed in wrong map file\n",
|
|
grp->nt_domain, grp->nt_name));
|
|
return False;
|
|
}
|
|
ret = True;
|
|
}
|
|
else if (lookup_wk_group_name(grp->nt_name, grp->nt_domain, &grp->sid, &grp->type) == 0x0)
|
|
{
|
|
if (type != DOM_MAP_DOMAIN)
|
|
{
|
|
DEBUG(0,("well-known NT group %s\\%s listed in wrong map file\n",
|
|
grp->nt_domain, grp->nt_name));
|
|
return False;
|
|
}
|
|
ret = True;
|
|
}
|
|
else
|
|
{
|
|
switch (type)
|
|
{
|
|
case DOM_MAP_USER:
|
|
{
|
|
grp->type = SID_NAME_USER;
|
|
break;
|
|
}
|
|
case DOM_MAP_DOMAIN:
|
|
{
|
|
grp->type = SID_NAME_DOM_GRP;
|
|
break;
|
|
}
|
|
case DOM_MAP_LOCAL:
|
|
{
|
|
grp->type = SID_NAME_ALIAS;
|
|
break;
|
|
}
|
|
}
|
|
|
|
ret = pwdb_unixid_to_sam_sid(grp->unix_id, grp->type, &grp->sid);
|
|
}
|
|
|
|
sid_to_string(sid_str, &grp->sid);
|
|
DEBUG(10,("nt name %s\\%s gid %d mapped to %s\n",
|
|
grp->nt_domain, grp->nt_name, grp->unix_id, sid_str));
|
|
return ret;
|
|
}
|
|
|
|
/**************************************************************************
|
|
makes a group sid out of an nt domain, nt group name or a unix group name.
|
|
***************************************************************************/
|
|
static BOOL unix_name_to_nt_name_info(DOM_NAME_MAP *map, DOM_MAP_TYPE type)
|
|
{
|
|
/*
|
|
* Attempt to get the unix gid_t for this name.
|
|
*/
|
|
|
|
DEBUG(5,("unix_name_to_nt_name_info: unix_name:%s\n", map->unix_name));
|
|
|
|
if (type == DOM_MAP_USER)
|
|
{
|
|
const struct passwd *pwptr = Get_Pwnam(map->unix_name, False);
|
|
if (pwptr == NULL)
|
|
{
|
|
DEBUG(0,("unix_name_to_nt_name_info: Get_Pwnam for user %s\
|
|
failed. Error was %s.\n", map->unix_name, strerror(errno) ));
|
|
return False;
|
|
}
|
|
|
|
map->unix_id = (uint32)pwptr->pw_uid;
|
|
}
|
|
else
|
|
{
|
|
struct group *gptr = getgrnam(map->unix_name);
|
|
if (gptr == NULL)
|
|
{
|
|
DEBUG(0,("unix_name_to_nt_name_info: getgrnam for group %s\
|
|
failed. Error was %s.\n", map->unix_name, strerror(errno) ));
|
|
return False;
|
|
}
|
|
|
|
map->unix_id = (uint32)gptr->gr_gid;
|
|
}
|
|
|
|
DEBUG(5,("unix_name_to_nt_name_info: unix gid:%d\n", map->unix_id));
|
|
|
|
/*
|
|
* Now map the name to an NT SID+RID.
|
|
*/
|
|
|
|
if (map->nt_domain != NULL && !strequal(map->nt_domain, global_sam_name))
|
|
{
|
|
/* Must add client-call lookup code here, to
|
|
* resolve remote domain's sid and the group's rid,
|
|
* in that domain.
|
|
*
|
|
* NOTE: it is _incorrect_ to put code here that assumes
|
|
* we are responsible for lookups for foriegn domains' RIDs.
|
|
*
|
|
* for foriegn domains for which we are *NOT* the PDC, all
|
|
* we can be responsible for is the unix gid_t to which
|
|
* the foriegn SID+rid maps to, on this _local_ machine.
|
|
* we *CANNOT* make any short-cuts or assumptions about
|
|
* RIDs in a foriegn domain.
|
|
*/
|
|
|
|
if (!map_domain_name_to_sid(&map->sid, &(map->nt_domain)))
|
|
{
|
|
DEBUG(0,("unix_name_to_nt_name_info: no known sid for %s\n",
|
|
map->nt_domain));
|
|
return False;
|
|
}
|
|
}
|
|
|
|
return make_mydomain_sid(map, type);
|
|
}
|
|
|
|
static BOOL make_name_entry(name_map_entry **new_ep,
|
|
char *nt_domain, char *nt_group, char *unix_group,
|
|
DOM_MAP_TYPE type)
|
|
{
|
|
/*
|
|
* Create the list entry and add it onto the list.
|
|
*/
|
|
|
|
DEBUG(5,("make_name_entry:%s,%s,%s\n", nt_domain, nt_group, unix_group));
|
|
|
|
(*new_ep) = (name_map_entry *)malloc(sizeof(name_map_entry));
|
|
if ((*new_ep) == NULL)
|
|
{
|
|
DEBUG(0,("make_name_entry: malloc fail for name_map_entry.\n"));
|
|
return False;
|
|
}
|
|
|
|
ZERO_STRUCTP(*new_ep);
|
|
|
|
(*new_ep)->grp.nt_name = strdup(nt_group );
|
|
(*new_ep)->grp.nt_domain = strdup(nt_domain );
|
|
(*new_ep)->grp.unix_name = strdup(unix_group);
|
|
|
|
if ((*new_ep)->grp.nt_name == NULL ||
|
|
(*new_ep)->grp.unix_name == NULL)
|
|
{
|
|
DEBUG(0,("make_name_entry: malloc fail for names in name_map_entry.\n"));
|
|
delete_name_entry((*new_ep));
|
|
return False;
|
|
}
|
|
|
|
/*
|
|
* look up the group names, make the Group-SID and unix gid
|
|
*/
|
|
|
|
if (!unix_name_to_nt_name_info(&(*new_ep)->grp, type))
|
|
{
|
|
delete_name_entry((*new_ep));
|
|
return False;
|
|
}
|
|
|
|
return True;
|
|
}
|
|
|
|
/**************************************************************************
|
|
Load a name map file. Sets last accessed timestamp.
|
|
***************************************************************************/
|
|
static ubi_slList *load_name_map(DOM_MAP_TYPE type)
|
|
{
|
|
static time_t groupmap_file_last_modified = (time_t)0;
|
|
static time_t aliasmap_file_last_modified = (time_t)0;
|
|
static time_t ntusrmap_file_last_modified = (time_t)0;
|
|
static BOOL initialised_group = False;
|
|
static BOOL initialised_alias = False;
|
|
static BOOL initialised_ntusr = False;
|
|
char *groupname_map_file = lp_groupname_map();
|
|
char *aliasname_map_file = lp_aliasname_map();
|
|
char *ntusrname_map_file = lp_ntusrname_map();
|
|
|
|
FILE *fp;
|
|
char *s;
|
|
pstring buf;
|
|
name_map_entry *new_ep;
|
|
|
|
time_t *file_last_modified = NULL;
|
|
int *initialised = NULL;
|
|
char *map_file = NULL;
|
|
ubi_slList *map_list = NULL;
|
|
|
|
switch (type)
|
|
{
|
|
case DOM_MAP_DOMAIN:
|
|
{
|
|
file_last_modified = &groupmap_file_last_modified;
|
|
initialised = &initialised_group;
|
|
map_file = groupname_map_file;
|
|
map_list = &groupname_map_list;
|
|
|
|
break;
|
|
}
|
|
case DOM_MAP_LOCAL:
|
|
{
|
|
file_last_modified = &aliasmap_file_last_modified;
|
|
initialised = &initialised_alias;
|
|
map_file = aliasname_map_file;
|
|
map_list = &aliasname_map_list;
|
|
|
|
break;
|
|
}
|
|
case DOM_MAP_USER:
|
|
{
|
|
file_last_modified = &ntusrmap_file_last_modified;
|
|
initialised = &initialised_ntusr;
|
|
map_file = ntusrname_map_file;
|
|
map_list = &ntusrname_map_list;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!(*initialised))
|
|
{
|
|
DEBUG(10,("initialising map %s\n", map_file));
|
|
ubi_slInitList(map_list);
|
|
(*initialised) = True;
|
|
}
|
|
|
|
if (!*map_file)
|
|
{
|
|
return map_list;
|
|
}
|
|
|
|
/*
|
|
* Load the file.
|
|
*/
|
|
|
|
fp = open_file_if_modified(map_file, "r", file_last_modified);
|
|
if (!fp)
|
|
{
|
|
return map_list;
|
|
}
|
|
|
|
/*
|
|
* Throw away any previous list.
|
|
*/
|
|
delete_map_list(map_list);
|
|
|
|
DEBUG(4,("load_name_map: Scanning name map %s\n",map_file));
|
|
|
|
while ((s = fgets_slash(buf, sizeof(buf), fp)) != NULL)
|
|
{
|
|
pstring unixname;
|
|
pstring nt_name;
|
|
fstring nt_domain;
|
|
fstring ntname;
|
|
char *p;
|
|
|
|
DEBUG(10,("Read line |%s|\n", s));
|
|
|
|
memset(nt_name, 0, sizeof(nt_name));
|
|
|
|
if (!*s || strchr("#;",*s))
|
|
continue;
|
|
|
|
if (!next_token(&s,unixname, "\t\n\r=", sizeof(unixname)))
|
|
continue;
|
|
|
|
if (!next_token(&s,nt_name, "\t\n\r=", sizeof(nt_name)))
|
|
continue;
|
|
|
|
trim_string(unixname, " ", " ");
|
|
trim_string(nt_name, " ", " ");
|
|
|
|
if (!*nt_name)
|
|
continue;
|
|
|
|
if (!*unixname)
|
|
continue;
|
|
|
|
p = strchr(nt_name, '\\');
|
|
|
|
if (p == NULL)
|
|
{
|
|
memset(nt_domain, 0, sizeof(nt_domain));
|
|
fstrcpy(ntname, nt_name);
|
|
}
|
|
else
|
|
{
|
|
*p = 0;
|
|
p++;
|
|
fstrcpy(nt_domain, nt_name);
|
|
fstrcpy(ntname , p);
|
|
}
|
|
|
|
if (make_name_entry(&new_ep, nt_domain, ntname, unixname, type))
|
|
{
|
|
ubi_slAddTail(map_list, (ubi_slNode *)new_ep);
|
|
DEBUG(5,("unixname = %s, ntname = %s\\%s type = %d\n",
|
|
new_ep->grp.unix_name,
|
|
new_ep->grp.nt_domain,
|
|
new_ep->grp.nt_name,
|
|
new_ep->grp.type));
|
|
}
|
|
}
|
|
|
|
DEBUG(10,("load_name_map: Added %ld entries to name map.\n",
|
|
ubi_slCount(map_list)));
|
|
|
|
fclose(fp);
|
|
|
|
return map_list;
|
|
}
|
|
|
|
static void copy_grp_map_entry(DOM_NAME_MAP *grp, const DOM_NAME_MAP *from)
|
|
{
|
|
sid_copy(&grp->sid, &from->sid);
|
|
grp->unix_id = from->unix_id;
|
|
grp->nt_name = from->nt_name;
|
|
grp->nt_domain = from->nt_domain;
|
|
grp->unix_name = from->unix_name;
|
|
grp->type = from->type;
|
|
}
|
|
|
|
#if 0
|
|
/***********************************************************
|
|
Lookup unix name.
|
|
************************************************************/
|
|
static BOOL map_unixname(DOM_MAP_TYPE type,
|
|
char *unixname, DOM_NAME_MAP *grp_info)
|
|
{
|
|
name_map_entry *gmep;
|
|
ubi_slList *map_list;
|
|
|
|
/*
|
|
* Initialise and load if not already loaded.
|
|
*/
|
|
map_list = load_name_map(type);
|
|
|
|
for (gmep = (name_map_entry *)ubi_slFirst(map_list);
|
|
gmep != NULL;
|
|
gmep = (name_map_entry *)ubi_slNext(gmep ))
|
|
{
|
|
if (strequal(gmep->grp.unix_name, unixname))
|
|
{
|
|
copy_grp_map_entry(grp_info, &gmep->grp);
|
|
DEBUG(7,("map_unixname: Mapping unix name %s to nt group %s.\n",
|
|
gmep->grp.unix_name, gmep->grp.nt_name ));
|
|
return True;
|
|
}
|
|
}
|
|
|
|
return False;
|
|
}
|
|
|
|
#endif
|
|
|
|
/***********************************************************
|
|
Lookup nt name.
|
|
************************************************************/
|
|
static BOOL map_ntname(DOM_MAP_TYPE type, char *ntname, char *ntdomain,
|
|
DOM_NAME_MAP *grp_info)
|
|
{
|
|
name_map_entry *gmep;
|
|
ubi_slList *map_list;
|
|
|
|
/*
|
|
* Initialise and load if not already loaded.
|
|
*/
|
|
map_list = load_name_map(type);
|
|
|
|
for (gmep = (name_map_entry *)ubi_slFirst(map_list);
|
|
gmep != NULL;
|
|
gmep = (name_map_entry *)ubi_slNext(gmep ))
|
|
{
|
|
if (strequal(gmep->grp.nt_name , ntname) &&
|
|
strequal(gmep->grp.nt_domain, ntdomain))
|
|
{
|
|
copy_grp_map_entry(grp_info, &gmep->grp);
|
|
DEBUG(7,("map_ntname: Mapping unix name %s to nt name %s.\n",
|
|
gmep->grp.unix_name, gmep->grp.nt_name ));
|
|
return True;
|
|
}
|
|
}
|
|
|
|
return False;
|
|
}
|
|
|
|
|
|
/***********************************************************
|
|
Lookup by SID
|
|
************************************************************/
|
|
static BOOL map_sid(DOM_MAP_TYPE type,
|
|
DOM_SID *psid, DOM_NAME_MAP *grp_info)
|
|
{
|
|
name_map_entry *gmep;
|
|
ubi_slList *map_list;
|
|
|
|
/*
|
|
* Initialise and load if not already loaded.
|
|
*/
|
|
map_list = load_name_map(type);
|
|
|
|
for (gmep = (name_map_entry *)ubi_slFirst(map_list);
|
|
gmep != NULL;
|
|
gmep = (name_map_entry *)ubi_slNext(gmep ))
|
|
{
|
|
if (sid_equal(&gmep->grp.sid, psid))
|
|
{
|
|
copy_grp_map_entry(grp_info, &gmep->grp);
|
|
DEBUG(7,("map_sid: Mapping unix name %s to nt name %s.\n",
|
|
gmep->grp.unix_name, gmep->grp.nt_name ));
|
|
return True;
|
|
}
|
|
}
|
|
|
|
return False;
|
|
}
|
|
|
|
/***********************************************************
|
|
Lookup by gid_t.
|
|
************************************************************/
|
|
static BOOL map_unixid(DOM_MAP_TYPE type, uint32 unix_id, DOM_NAME_MAP *grp_info)
|
|
{
|
|
name_map_entry *gmep;
|
|
ubi_slList *map_list;
|
|
|
|
/*
|
|
* Initialise and load if not already loaded.
|
|
*/
|
|
map_list = load_name_map(type);
|
|
|
|
for (gmep = (name_map_entry *)ubi_slFirst(map_list);
|
|
gmep != NULL;
|
|
gmep = (name_map_entry *)ubi_slNext(gmep ))
|
|
{
|
|
fstring sid_str;
|
|
sid_to_string(sid_str, &gmep->grp.sid);
|
|
DEBUG(10,("map_unixid: enum entry unix group %s %d nt %s %s\n",
|
|
gmep->grp.unix_name, gmep->grp.unix_id, gmep->grp.nt_name, sid_str));
|
|
if (gmep->grp.unix_id == unix_id)
|
|
{
|
|
copy_grp_map_entry(grp_info, &gmep->grp);
|
|
DEBUG(7,("map_unixid: Mapping unix name %s to nt name %s type %d\n",
|
|
gmep->grp.unix_name, gmep->grp.nt_name, gmep->grp.type));
|
|
return True;
|
|
}
|
|
}
|
|
|
|
return False;
|
|
}
|
|
|
|
/***********************************************************
|
|
*
|
|
* Call four functions to resolve unix group ids and either
|
|
* local group SIDs or domain group SIDs listed in the local group
|
|
* or domain group map files.
|
|
*
|
|
* Note that it is *NOT* the responsibility of these functions to
|
|
* resolve entries that are not in the map files.
|
|
*
|
|
* Any SID can be in the map files (i.e from any Domain).
|
|
*
|
|
***********************************************************/
|
|
|
|
#if 0
|
|
|
|
/***********************************************************
|
|
Lookup a UNIX Group entry by name.
|
|
************************************************************/
|
|
BOOL map_unix_group_name(char *group_name, DOM_NAME_MAP *grp_info)
|
|
{
|
|
return map_unixname(DOM_MAP_DOMAIN, group_name, grp_info);
|
|
}
|
|
|
|
/***********************************************************
|
|
Lookup a UNIX Alias entry by name.
|
|
************************************************************/
|
|
BOOL map_unix_alias_name(char *alias_name, DOM_NAME_MAP *grp_info)
|
|
{
|
|
return map_unixname(DOM_MAP_LOCAL, alias_name, grp_info);
|
|
}
|
|
|
|
/***********************************************************
|
|
Lookup an Alias name entry
|
|
************************************************************/
|
|
BOOL map_nt_alias_name(char *ntalias_name, char *nt_domain, DOM_NAME_MAP *grp_info)
|
|
{
|
|
return map_ntname(DOM_MAP_LOCAL, ntalias_name, nt_domain, grp_info);
|
|
}
|
|
|
|
/***********************************************************
|
|
Lookup a Group entry
|
|
************************************************************/
|
|
BOOL map_nt_group_name(char *ntgroup_name, char *nt_domain, DOM_NAME_MAP *grp_info)
|
|
{
|
|
return map_ntname(DOM_MAP_DOMAIN, ntgroup_name, nt_domain, grp_info);
|
|
}
|
|
|
|
#endif
|
|
|
|
/***********************************************************
|
|
Lookup a Username entry by name.
|
|
************************************************************/
|
|
static BOOL map_nt_username(char *nt_name, char *nt_domain, DOM_NAME_MAP *grp_info)
|
|
{
|
|
return map_ntname(DOM_MAP_USER, nt_name, nt_domain, grp_info);
|
|
}
|
|
|
|
/***********************************************************
|
|
Lookup a Username entry by SID.
|
|
************************************************************/
|
|
static BOOL map_username_sid(DOM_SID *sid, DOM_NAME_MAP *grp_info)
|
|
{
|
|
return map_sid(DOM_MAP_USER, sid, grp_info);
|
|
}
|
|
|
|
/***********************************************************
|
|
Lookup a Username SID entry by uid.
|
|
************************************************************/
|
|
static BOOL map_username_uid(uid_t gid, DOM_NAME_MAP *grp_info)
|
|
{
|
|
return map_unixid(DOM_MAP_USER, (uint32)gid, grp_info);
|
|
}
|
|
|
|
/***********************************************************
|
|
Lookup an Alias SID entry by name.
|
|
************************************************************/
|
|
BOOL map_alias_sid(DOM_SID *psid, DOM_NAME_MAP *grp_info)
|
|
{
|
|
return map_sid(DOM_MAP_LOCAL, psid, grp_info);
|
|
}
|
|
|
|
/***********************************************************
|
|
Lookup a Group entry by sid.
|
|
************************************************************/
|
|
BOOL map_group_sid(DOM_SID *psid, DOM_NAME_MAP *grp_info)
|
|
{
|
|
return map_sid(DOM_MAP_DOMAIN, psid, grp_info);
|
|
}
|
|
|
|
/***********************************************************
|
|
Lookup an Alias SID entry by gid_t.
|
|
************************************************************/
|
|
static BOOL map_alias_gid(gid_t gid, DOM_NAME_MAP *grp_info)
|
|
{
|
|
return map_unixid(DOM_MAP_LOCAL, (uint32)gid, grp_info);
|
|
}
|
|
|
|
/***********************************************************
|
|
Lookup a Group SID entry by gid_t.
|
|
************************************************************/
|
|
static BOOL map_group_gid( gid_t gid, DOM_NAME_MAP *grp_info)
|
|
{
|
|
return map_unixid(DOM_MAP_DOMAIN, (uint32)gid, grp_info);
|
|
}
|
|
|
|
|
|
/************************************************************************
|
|
Routine to look up User details by UNIX name
|
|
*************************************************************************/
|
|
BOOL lookupsmbpwnam(const char *unix_usr_name, DOM_NAME_MAP *grp)
|
|
{
|
|
uid_t uid;
|
|
DEBUG(10,("lookupsmbpwnam: unix user name %s\n", unix_usr_name));
|
|
if (nametouid(unix_usr_name, &uid))
|
|
{
|
|
return lookupsmbpwuid(uid, grp);
|
|
}
|
|
else
|
|
{
|
|
return False;
|
|
}
|
|
}
|
|
|
|
/************************************************************************
|
|
Routine to look up a remote nt name
|
|
*************************************************************************/
|
|
static BOOL lookup_remote_ntname(const char *ntname, DOM_SID *sid, uint8 *type)
|
|
{
|
|
struct cli_state cli;
|
|
POLICY_HND lsa_pol;
|
|
fstring srv_name;
|
|
extern struct ntuser_creds *usr_creds;
|
|
struct ntuser_creds usr;
|
|
|
|
BOOL res3 = True;
|
|
BOOL res4 = True;
|
|
uint32 num_sids;
|
|
DOM_SID *sids;
|
|
uint8 *types;
|
|
char *names[1];
|
|
|
|
usr_creds = &usr;
|
|
|
|
ZERO_STRUCT(usr);
|
|
pwd_set_nullpwd(&usr.pwd);
|
|
|
|
DEBUG(5,("lookup_remote_ntname: %s\n", ntname));
|
|
|
|
if (!cli_connect_serverlist(&cli, lp_passwordserver()))
|
|
{
|
|
return False;
|
|
}
|
|
|
|
names[0] = ntname;
|
|
|
|
fstrcpy(srv_name, "\\\\");
|
|
fstrcat(srv_name, cli.desthost);
|
|
strupper(srv_name);
|
|
|
|
/* lookup domain controller; receive a policy handle */
|
|
res3 = res3 ? lsa_open_policy( srv_name,
|
|
&lsa_pol, True) : False;
|
|
|
|
/* send lsa lookup sids call */
|
|
res4 = res3 ? lsa_lookup_names( &lsa_pol,
|
|
1, names,
|
|
&sids, &types, &num_sids) : False;
|
|
|
|
res3 = res3 ? lsa_close(&lsa_pol) : False;
|
|
|
|
if (res4 && res3 && sids != NULL && types != NULL)
|
|
{
|
|
sid_copy(sid, &sids[0]);
|
|
*type = types[0];
|
|
}
|
|
else
|
|
{
|
|
res3 = False;
|
|
}
|
|
if (types != NULL)
|
|
{
|
|
free(types);
|
|
}
|
|
|
|
if (sids != NULL)
|
|
{
|
|
free(sids);
|
|
}
|
|
|
|
return res3 && res4;
|
|
}
|
|
|
|
/************************************************************************
|
|
Routine to look up a remote nt name
|
|
*************************************************************************/
|
|
static BOOL get_sid_and_type(const char *fullntname, uint8 expected_type,
|
|
DOM_NAME_MAP *gmep)
|
|
{
|
|
/*
|
|
* check with the PDC to see if it owns the name. if so,
|
|
* the SID is resolved with the PDC database.
|
|
*/
|
|
|
|
if (lp_server_role() == ROLE_DOMAIN_MEMBER)
|
|
{
|
|
if (lookup_remote_ntname(fullntname, &gmep->sid, &gmep->type))
|
|
{
|
|
if (sid_front_equal(&gmep->sid, &global_member_sid) &&
|
|
strequal(gmep->nt_domain, global_myworkgroup) &&
|
|
gmep->type == expected_type)
|
|
{
|
|
return True;
|
|
}
|
|
return False;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ... otherwise, it's one of ours. map the sid ourselves,
|
|
* which can only happen in our own SAM database.
|
|
*/
|
|
|
|
if (!strequal(gmep->nt_domain, global_sam_name))
|
|
{
|
|
return False;
|
|
}
|
|
if (!pwdb_unixid_to_sam_sid(gmep->unix_id, gmep->type, &gmep->sid))
|
|
{
|
|
return False;
|
|
}
|
|
|
|
return True;
|
|
}
|
|
|
|
/*
|
|
* used by lookup functions below
|
|
*/
|
|
|
|
static fstring nt_name;
|
|
static fstring unix_name;
|
|
static fstring nt_domain;
|
|
|
|
/*************************************************************************
|
|
looks up a uid, returns User Information.
|
|
*************************************************************************/
|
|
BOOL lookupsmbpwuid(uid_t uid, DOM_NAME_MAP *gmep)
|
|
{
|
|
DEBUG(10,("lookupsmbpwuid: unix uid %d\n", uid));
|
|
if (map_username_uid(uid, gmep))
|
|
{
|
|
return True;
|
|
}
|
|
if (lp_server_role() != ROLE_DOMAIN_NONE)
|
|
{
|
|
gmep->nt_name = nt_name;
|
|
gmep->unix_name = unix_name;
|
|
gmep->nt_domain = nt_domain;
|
|
|
|
gmep->unix_id = (uint32)uid;
|
|
|
|
/*
|
|
* ok, assume it's one of ours. then double-check it
|
|
* if we are a member of a domain
|
|
*/
|
|
|
|
gmep->type = SID_NAME_USER;
|
|
fstrcpy(gmep->nt_name, uidtoname(uid));
|
|
fstrcpy(gmep->unix_name, gmep->nt_name);
|
|
|
|
/*
|
|
* here we should do a LsaLookupNames() call
|
|
* to check the status of the name with the PDC.
|
|
* if the PDC know nothing of the name, it's ours.
|
|
*/
|
|
|
|
if (lp_server_role() == ROLE_DOMAIN_MEMBER)
|
|
{
|
|
#if 0
|
|
lsa_lookup_names(global_myworkgroup, gmep->nt_name, &gmep->sid...);
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* ok, it's one of ours.
|
|
*/
|
|
|
|
gmep->nt_domain = global_sam_name;
|
|
pwdb_unixid_to_sam_sid(gmep->unix_id, gmep->type, &gmep->sid);
|
|
|
|
return True;
|
|
}
|
|
|
|
/* oops. */
|
|
|
|
return False;
|
|
}
|
|
|
|
/*************************************************************************
|
|
looks up by NT name, returns User Information.
|
|
*************************************************************************/
|
|
BOOL lookupsmbpwntnam(const char *fullntname, DOM_NAME_MAP *gmep)
|
|
{
|
|
DEBUG(10,("lookupsmbpwntnam: nt user name %s\n", fullntname));
|
|
|
|
if (!split_domain_name(fullntname, nt_domain, nt_name))
|
|
{
|
|
return False;
|
|
}
|
|
|
|
if (map_nt_username(nt_name, nt_domain, gmep))
|
|
{
|
|
return True;
|
|
}
|
|
if (lp_server_role() != ROLE_DOMAIN_NONE)
|
|
{
|
|
uid_t uid;
|
|
gmep->nt_name = nt_name;
|
|
gmep->unix_name = unix_name;
|
|
gmep->nt_domain = nt_domain;
|
|
|
|
/*
|
|
* ok, it's one of ours. we therefore "create" an nt user named
|
|
* after the unix user. this is the point where "appliance mode"
|
|
* should get its teeth in, as unix users won't really exist,
|
|
* they will only be numbers...
|
|
*/
|
|
|
|
gmep->type = SID_NAME_USER;
|
|
fstrcpy(gmep->unix_name, gmep->nt_name);
|
|
if (!nametouid(gmep->unix_name, &uid))
|
|
{
|
|
return False;
|
|
}
|
|
gmep->unix_id = (uint32)uid;
|
|
|
|
return get_sid_and_type(fullntname, gmep->type, gmep);
|
|
}
|
|
|
|
/* oops. */
|
|
|
|
return False;
|
|
}
|
|
|
|
/*************************************************************************
|
|
looks up by RID, returns User Information.
|
|
*************************************************************************/
|
|
BOOL lookupsmbpwsid(DOM_SID *sid, DOM_NAME_MAP *gmep)
|
|
{
|
|
fstring sid_str;
|
|
sid_to_string(sid_str, sid);
|
|
DEBUG(10,("lookupsmbpwsid: nt sid %s\n", sid_str));
|
|
|
|
if (map_username_sid(sid, gmep))
|
|
{
|
|
return True;
|
|
}
|
|
if (lp_server_role() != ROLE_DOMAIN_NONE)
|
|
{
|
|
gmep->nt_name = nt_name;
|
|
gmep->unix_name = unix_name;
|
|
gmep->nt_domain = nt_domain;
|
|
|
|
/*
|
|
* here we should do a LsaLookupNames() call
|
|
* to check the status of the name with the PDC.
|
|
* if the PDC know nothing of the name, it's ours.
|
|
*/
|
|
|
|
if (lp_server_role() == ROLE_DOMAIN_MEMBER)
|
|
{
|
|
#if 0
|
|
if (lookup_remote_sid(global_myworkgroup, gmep->sid, gmep->nt_name, gmep->nt_domain...);
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* ok, it's one of ours. we therefore "create" an nt user named
|
|
* after the unix user. this is the point where "appliance mode"
|
|
* should get its teeth in, as unix users won't really exist,
|
|
* they will only be numbers...
|
|
*/
|
|
|
|
gmep->type = SID_NAME_USER;
|
|
sid_copy(&gmep->sid, sid);
|
|
if (!pwdb_sam_sid_to_unixid(&gmep->sid, gmep->type, &gmep->unix_id))
|
|
{
|
|
return False;
|
|
}
|
|
fstrcpy(gmep->nt_name, uidtoname((uid_t)gmep->unix_id));
|
|
fstrcpy(gmep->unix_name, gmep->nt_name);
|
|
gmep->nt_domain = global_sam_name;
|
|
|
|
return True;
|
|
}
|
|
|
|
/* oops. */
|
|
|
|
return False;
|
|
}
|
|
|
|
/************************************************************************
|
|
Routine to look up group / alias / well-known group RID by UNIX name
|
|
*************************************************************************/
|
|
BOOL lookupsmbgrpnam(const char *unix_grp_name, DOM_NAME_MAP *grp)
|
|
{
|
|
gid_t gid;
|
|
DEBUG(10,("lookupsmbgrpnam: unix user group %s\n", unix_grp_name));
|
|
if (nametogid(unix_grp_name, &gid))
|
|
{
|
|
return lookupsmbgrpgid(gid, grp);
|
|
}
|
|
else
|
|
{
|
|
return False;
|
|
}
|
|
}
|
|
|
|
/*************************************************************************
|
|
looks up a SID, returns name map entry
|
|
*************************************************************************/
|
|
BOOL lookupsmbgrpsid(DOM_SID *sid, DOM_NAME_MAP *gmep)
|
|
{
|
|
fstring sid_str;
|
|
sid_to_string(sid_str, sid);
|
|
DEBUG(10,("lookupsmbgrpsid: nt sid %s\n", sid_str));
|
|
|
|
if (map_alias_sid(sid, gmep))
|
|
{
|
|
return True;
|
|
}
|
|
if (map_group_sid(sid, gmep))
|
|
{
|
|
return True;
|
|
}
|
|
if (lp_server_role() != ROLE_DOMAIN_NONE)
|
|
{
|
|
gmep->nt_name = nt_name;
|
|
gmep->unix_name = unix_name;
|
|
gmep->nt_domain = nt_domain;
|
|
|
|
/*
|
|
* here we should do a LsaLookupNames() call
|
|
* to check the status of the name with the PDC.
|
|
* if the PDC know nothing of the name, it's ours.
|
|
*/
|
|
|
|
if (lp_server_role() == ROLE_DOMAIN_MEMBER)
|
|
{
|
|
#if 0
|
|
lsa_lookup_sids(global_myworkgroup, gmep->sid, gmep->nt_name, gmep->nt_domain...);
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* ok, it's one of ours. we therefore "create" an nt group or
|
|
* alias name named after the unix group. this is the point
|
|
* where "appliance mode" should get its teeth in, as unix
|
|
* groups won't really exist, they will only be numbers...
|
|
*/
|
|
|
|
/* name is not explicitly mapped
|
|
* with map files or the PDC
|
|
* so we are responsible for it...
|
|
*/
|
|
|
|
if (lp_server_role() == ROLE_DOMAIN_MEMBER)
|
|
{
|
|
/* ... as a LOCAL group. */
|
|
gmep->type = SID_NAME_ALIAS;
|
|
}
|
|
else
|
|
{
|
|
/* ... as a DOMAIN group. */
|
|
gmep->type = SID_NAME_DOM_GRP;
|
|
}
|
|
|
|
sid_copy(&gmep->sid, sid);
|
|
if (!pwdb_sam_sid_to_unixid(&gmep->sid, gmep->type, &gmep->unix_id))
|
|
{
|
|
return False;
|
|
}
|
|
fstrcpy(gmep->nt_name, gidtoname((gid_t)gmep->unix_id));
|
|
fstrcpy(gmep->unix_name, gmep->nt_name);
|
|
gmep->nt_domain = global_sam_name;
|
|
|
|
return True;
|
|
}
|
|
|
|
/* oops */
|
|
return False;
|
|
}
|
|
|
|
/*************************************************************************
|
|
looks up a gid, returns RID and type local, domain or well-known domain group
|
|
*************************************************************************/
|
|
BOOL lookupsmbgrpgid(gid_t gid, DOM_NAME_MAP *gmep)
|
|
{
|
|
DEBUG(10,("lookupsmbgrpgid: unix gid %d\n", (int)gid));
|
|
if (map_alias_gid(gid, gmep))
|
|
{
|
|
return True;
|
|
}
|
|
if (map_group_gid(gid, gmep))
|
|
{
|
|
return True;
|
|
}
|
|
if (lp_server_role() != ROLE_DOMAIN_NONE)
|
|
{
|
|
gmep->nt_name = nt_name;
|
|
gmep->unix_name = unix_name;
|
|
gmep->nt_domain = nt_domain;
|
|
|
|
gmep->unix_id = (uint32)gid;
|
|
|
|
/*
|
|
* here we should do a LsaLookupNames() call
|
|
* to check the status of the name with the PDC.
|
|
* if the PDC know nothing of the name, it's ours.
|
|
*/
|
|
|
|
if (lp_server_role() == ROLE_DOMAIN_MEMBER)
|
|
{
|
|
#if 0
|
|
if (lsa_lookup_names(global_myworkgroup, gmep->nt_name, &gmep->sid...);
|
|
{
|
|
return True;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* ok, it's one of ours. we therefore "create" an nt group or
|
|
* alias name named after the unix group. this is the point
|
|
* where "appliance mode" should get its teeth in, as unix
|
|
* groups won't really exist, they will only be numbers...
|
|
*/
|
|
|
|
/* name is not explicitly mapped
|
|
* with map files or the PDC
|
|
* so we are responsible for it...
|
|
*/
|
|
|
|
if (lp_server_role() == ROLE_DOMAIN_MEMBER)
|
|
{
|
|
/* ... as a LOCAL group. */
|
|
gmep->type = SID_NAME_ALIAS;
|
|
}
|
|
else
|
|
{
|
|
/* ... as a DOMAIN group. */
|
|
gmep->type = SID_NAME_DOM_GRP;
|
|
}
|
|
fstrcpy(gmep->nt_name, gidtoname(gid));
|
|
fstrcpy(gmep->unix_name, gmep->nt_name);
|
|
|
|
return get_sid_and_type(gmep->nt_name, gmep->type, gmep);
|
|
}
|
|
|
|
/* oops */
|
|
return False;
|
|
}
|
|
|