mirror of
https://github.com/samba-team/samba.git
synced 2024-12-24 21:34:56 +03:00
Fix bug 327 (again and I think for the last time). Make sure that
pam_smbpass.so will load ok. Had to move some functions around to work
around dependency problems (hence the new passdb/lookup_sid.c)
Also make sure that libsmbclient.a is built and installed when
we support shared libraries.
(This used to be commit 780055f442
)
This commit is contained in:
parent
2f70d0d9a7
commit
c2983f9323
@ -282,7 +282,7 @@ PASSDB_GET_SET_OBJ = passdb/pdb_get_set.o
|
||||
|
||||
PASSDB_OBJ = $(PASSDB_GET_SET_OBJ) passdb/passdb.o passdb/pdb_interface.o \
|
||||
passdb/machine_sid.o passdb/util_sam_sid.o passdb/pdb_compat.o \
|
||||
passdb/privileges.o @PDB_STATIC@
|
||||
passdb/privileges.o passdb/lookup_sid.o @PDB_STATIC@
|
||||
|
||||
XML_OBJ = passdb/pdb_xml.o
|
||||
MYSQL_OBJ = passdb/pdb_mysql.o
|
||||
@ -583,9 +583,8 @@ LIBSMBCLIENT_PICOBJS = $(LIBSMBCLIENT_OBJ:.o=.po)
|
||||
|
||||
PAM_SMBPASS_OBJ_0 = pam_smbpass/pam_smb_auth.o pam_smbpass/pam_smb_passwd.o \
|
||||
pam_smbpass/pam_smb_acct.o pam_smbpass/support.o \
|
||||
libsmb/smbencrypt.o libsmb/smbdes.o libsmb/nterr.o lib/dummyroot.o \
|
||||
$(PARAM_OBJ) $(LIB_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
|
||||
$(SECRETS_OBJ) $(UBIQX_OBJ) $(SMBLDAP_OBJ)
|
||||
lib/dummyroot.o $(PARAM_OBJ) $(LIB_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
|
||||
$(SECRETS_OBJ) $(UBIQX_OBJ) $(SMBLDAP_OBJ) $(LIBSAMBA_OBJ)
|
||||
|
||||
PAM_SMBPASS_PICOOBJ = $(PAM_SMBPASS_OBJ_0:.o=.po)
|
||||
|
||||
|
@ -3178,6 +3178,8 @@ AC_ARG_WITH(libsmbclient,
|
||||
*)
|
||||
if test $BLDSHARED = true; then
|
||||
INSTALLCLIENTCMD_SH="\$(INSTALLCMD)"
|
||||
## build the static version of libsmbclient as well
|
||||
INSTALLCLIENTCMD_A="\$(INSTALLCMD)"
|
||||
LIBSMBCLIENT_SHARED=bin/libsmbclient.$SHLIBEXT
|
||||
LIBSMBCLIENT=libsmbclient
|
||||
AC_MSG_RESULT(yes)
|
||||
|
488
source3/passdb/lookup_sid.c
Normal file
488
source3/passdb/lookup_sid.c
Normal file
@ -0,0 +1,488 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
uid/user handling
|
||||
Copyright (C) Andrew Tridgell 1992-1998
|
||||
Copyright (C) Gerald (Jerry) Carter 2003
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
/*****************************************************************
|
||||
*THE CANONICAL* convert name to SID function.
|
||||
Tries local lookup first - for local domains - then uses winbind.
|
||||
*****************************************************************/
|
||||
|
||||
BOOL lookup_name(const char *domain, const char *name, DOM_SID *psid, enum SID_NAME_USE *name_type)
|
||||
{
|
||||
fstring sid;
|
||||
BOOL local_lookup = False;
|
||||
|
||||
*name_type = SID_NAME_UNKNOWN;
|
||||
|
||||
/* If we are looking up a domain user, make sure it is
|
||||
for the local machine only */
|
||||
|
||||
if (strequal(global_myname(), domain)) {
|
||||
local_lookup = True;
|
||||
} else if (lp_server_role() == ROLE_DOMAIN_PDC ||
|
||||
lp_server_role() == ROLE_DOMAIN_BDC) {
|
||||
if (strequal(domain, lp_workgroup())) {
|
||||
local_lookup = True;
|
||||
}
|
||||
}
|
||||
|
||||
if (local_lookup) {
|
||||
if (local_lookup_name(name, psid, name_type)) {
|
||||
DEBUG(10,
|
||||
("lookup_name: (local) [%s]\\[%s] -> SID %s (type %s: %u)\n",
|
||||
domain, name, sid_to_string(sid,psid),
|
||||
sid_type_lookup(*name_type), (unsigned int)*name_type));
|
||||
return True;
|
||||
}
|
||||
} else {
|
||||
/* Remote */
|
||||
if (winbind_lookup_name(domain, name, psid, name_type)) {
|
||||
|
||||
DEBUG(10,("lookup_name (winbindd): [%s]\\[%s] -> SID %s (type %u)\n",
|
||||
domain, name, sid_to_string(sid, psid),
|
||||
(unsigned int)*name_type));
|
||||
return True;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG(10, ("lookup_name: %s lookup for [%s]\\[%s] failed\n",
|
||||
local_lookup ? "local" : "winbind", domain, name));
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
*THE CANONICAL* convert SID to name function.
|
||||
Tries local lookup first - for local sids, then tries winbind.
|
||||
*****************************************************************/
|
||||
|
||||
BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE *name_type)
|
||||
{
|
||||
if (!name_type)
|
||||
return False;
|
||||
|
||||
*name_type = SID_NAME_UNKNOWN;
|
||||
|
||||
/* Check if this is our own sid. This should perhaps be done by
|
||||
winbind? For the moment handle it here. */
|
||||
|
||||
if (sid->num_auths == 5) {
|
||||
DOM_SID tmp_sid;
|
||||
uint32 rid;
|
||||
|
||||
sid_copy(&tmp_sid, sid);
|
||||
sid_split_rid(&tmp_sid, &rid);
|
||||
|
||||
if (sid_equal(get_global_sam_sid(), &tmp_sid)) {
|
||||
|
||||
return map_domain_sid_to_name(&tmp_sid, dom_name) &&
|
||||
local_lookup_sid(sid, name, name_type);
|
||||
}
|
||||
}
|
||||
|
||||
if (!winbind_lookup_sid(sid, dom_name, name, name_type)) {
|
||||
fstring sid_str;
|
||||
DOM_SID tmp_sid;
|
||||
uint32 rid;
|
||||
|
||||
DEBUG(10,("lookup_sid: winbind lookup for SID %s failed - trying local.\n", sid_to_string(sid_str, sid) ));
|
||||
|
||||
sid_copy(&tmp_sid, sid);
|
||||
sid_split_rid(&tmp_sid, &rid);
|
||||
return map_domain_sid_to_name(&tmp_sid, dom_name) &&
|
||||
lookup_known_rid(&tmp_sid, rid, name, name_type);
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
Id mapping cache. This is to avoid Winbind mappings already
|
||||
seen by smbd to be queried too frequently, keeping winbindd
|
||||
busy, and blocking smbd while winbindd is busy with other
|
||||
stuff. Written by Michael Steffens <michael.steffens@hp.com>,
|
||||
modified to use linked lists by jra.
|
||||
*****************************************************************/
|
||||
|
||||
#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 SID_NAME_USE sidtype;
|
||||
} *uid_sid_cache_head;
|
||||
|
||||
static struct gid_sid_cache {
|
||||
struct gid_sid_cache *next, *prev;
|
||||
gid_t gid;
|
||||
DOM_SID sid;
|
||||
enum SID_NAME_USE sidtype;
|
||||
} *gid_sid_cache_head;
|
||||
|
||||
/*****************************************************************
|
||||
Find a SID given a uid.
|
||||
*****************************************************************/
|
||||
|
||||
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) {
|
||||
fstring sid;
|
||||
*psid = pc->sid;
|
||||
DEBUG(3,("fetch sid from uid cache %u -> %s\n",
|
||||
(unsigned int)uid, sid_to_string(sid, psid)));
|
||||
DLIST_PROMOTE(uid_sid_cache_head, pc);
|
||||
return True;
|
||||
}
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
Find a uid given a SID.
|
||||
*****************************************************************/
|
||||
|
||||
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) {
|
||||
fstring sid;
|
||||
*puid = pc->uid;
|
||||
DEBUG(3,("fetch uid from cache %u -> %s\n",
|
||||
(unsigned int)*puid, sid_to_string(sid, psid)));
|
||||
DLIST_PROMOTE(uid_sid_cache_head, pc);
|
||||
return True;
|
||||
}
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
Store uid to SID mapping in cache.
|
||||
*****************************************************************/
|
||||
|
||||
static void store_uid_sid_cache(const DOM_SID *psid, uid_t uid)
|
||||
{
|
||||
struct uid_sid_cache *pc;
|
||||
|
||||
if (n_uid_sid_cache >= MAX_UID_SID_CACHE_SIZE && n_uid_sid_cache > TURNOVER_UID_SID_CACHE_SIZE) {
|
||||
/* Delete the last TURNOVER_UID_SID_CACHE_SIZE entries. */
|
||||
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 = (struct uid_sid_cache *)malloc(sizeof(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++;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
Find a SID given a gid.
|
||||
*****************************************************************/
|
||||
|
||||
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) {
|
||||
fstring sid;
|
||||
*psid = pc->sid;
|
||||
DEBUG(3,("fetch sid from gid cache %u -> %s\n",
|
||||
(unsigned int)gid, sid_to_string(sid, psid)));
|
||||
DLIST_PROMOTE(gid_sid_cache_head, pc);
|
||||
return True;
|
||||
}
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
Find a gid given a SID.
|
||||
*****************************************************************/
|
||||
|
||||
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) {
|
||||
fstring sid;
|
||||
*pgid = pc->gid;
|
||||
DEBUG(3,("fetch uid from cache %u -> %s\n",
|
||||
(unsigned int)*pgid, sid_to_string(sid, psid)));
|
||||
DLIST_PROMOTE(gid_sid_cache_head, pc);
|
||||
return True;
|
||||
}
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
Store gid to SID mapping in cache.
|
||||
*****************************************************************/
|
||||
|
||||
static void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
|
||||
{
|
||||
struct gid_sid_cache *pc;
|
||||
|
||||
if (n_gid_sid_cache >= MAX_GID_SID_CACHE_SIZE && n_gid_sid_cache > TURNOVER_GID_SID_CACHE_SIZE) {
|
||||
/* Delete the last TURNOVER_GID_SID_CACHE_SIZE entries. */
|
||||
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 = (struct gid_sid_cache *)malloc(sizeof(struct gid_sid_cache));
|
||||
if (!pc)
|
||||
return;
|
||||
pc->gid = gid;
|
||||
sid_copy(&pc->sid, psid);
|
||||
DLIST_ADD(gid_sid_cache_head, pc);
|
||||
n_gid_sid_cache++;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
*THE CANONICAL* convert uid_t to SID function.
|
||||
*****************************************************************/
|
||||
|
||||
NTSTATUS uid_to_sid(DOM_SID *psid, uid_t uid)
|
||||
{
|
||||
uid_t low, high;
|
||||
fstring sid;
|
||||
|
||||
ZERO_STRUCTP(psid);
|
||||
|
||||
if (fetch_sid_from_uid_cache(psid, uid))
|
||||
return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
|
||||
|
||||
if (lp_idmap_uid(&low, &high) && uid >= low && uid <= high) {
|
||||
if (winbind_uid_to_sid(psid, uid)) {
|
||||
|
||||
DEBUG(10,("uid_to_sid: winbindd %u -> %s\n",
|
||||
(unsigned int)uid, sid_to_string(sid, psid)));
|
||||
|
||||
if (psid)
|
||||
store_uid_sid_cache(psid, uid);
|
||||
return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
|
||||
}
|
||||
}
|
||||
|
||||
if (!local_uid_to_sid(psid, uid)) {
|
||||
DEBUG(10,("uid_to_sid: local %u failed to map to sid\n", (unsigned int)uid ));
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid, sid_to_string(sid, psid)));
|
||||
|
||||
store_uid_sid_cache(psid, uid);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
*THE CANONICAL* convert gid_t to SID function.
|
||||
*****************************************************************/
|
||||
|
||||
NTSTATUS gid_to_sid(DOM_SID *psid, gid_t gid)
|
||||
{
|
||||
gid_t low, high;
|
||||
fstring sid;
|
||||
|
||||
ZERO_STRUCTP(psid);
|
||||
|
||||
if (fetch_sid_from_gid_cache(psid, gid))
|
||||
return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
|
||||
|
||||
if (lp_idmap_gid(&low, &high) && gid >= low && gid <= high) {
|
||||
if (winbind_gid_to_sid(psid, gid)) {
|
||||
|
||||
DEBUG(10,("gid_to_sid: winbindd %u -> %s\n",
|
||||
(unsigned int)gid, sid_to_string(sid, psid)));
|
||||
|
||||
if (psid)
|
||||
store_gid_sid_cache(psid, gid);
|
||||
return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
|
||||
}
|
||||
}
|
||||
|
||||
if (!local_gid_to_sid(psid, gid)) {
|
||||
DEBUG(10,("gid_to_sid: local %u failed to map to sid\n", (unsigned int)gid ));
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid, sid_to_string(sid, psid)));
|
||||
|
||||
store_gid_sid_cache(psid, gid);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
*THE CANONICAL* convert SID to uid function.
|
||||
*****************************************************************/
|
||||
|
||||
NTSTATUS sid_to_uid(const DOM_SID *psid, uid_t *puid)
|
||||
{
|
||||
fstring dom_name, name, sid_str;
|
||||
enum SID_NAME_USE name_type;
|
||||
|
||||
if (fetch_uid_from_cache(puid, psid))
|
||||
return NT_STATUS_OK;
|
||||
|
||||
/* if this is our SID then go straight to a local lookup */
|
||||
|
||||
if ( sid_compare_domain(get_global_sam_sid(), psid) == 0 ) {
|
||||
DEBUG(10,("sid_to_uid: my domain (%s) - trying local.\n",
|
||||
sid_string_static(psid) ));
|
||||
|
||||
if ( local_sid_to_uid(puid, psid, &name_type) )
|
||||
goto success;
|
||||
|
||||
DEBUG(10,("sid_to_uid: local lookup failed\n"));
|
||||
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* If it is not our local domain, only hope is winbindd */
|
||||
|
||||
if ( !winbind_lookup_sid(psid, dom_name, name, &name_type) ) {
|
||||
DEBUG(10,("sid_to_uid: winbind lookup for non-local sid %s failed\n",
|
||||
sid_string_static(psid) ));
|
||||
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* If winbindd does know the SID, ensure this is a user */
|
||||
|
||||
if (name_type != SID_NAME_USER) {
|
||||
DEBUG(10,("sid_to_uid: winbind lookup succeeded but SID is not a user (%u)\n",
|
||||
(unsigned int)name_type ));
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* get the uid. Has to work or else we are dead in the water */
|
||||
|
||||
if ( !winbind_sid_to_uid(puid, psid) ) {
|
||||
DEBUG(10,("sid_to_uid: winbind failed to allocate a new uid for sid %s\n",
|
||||
sid_to_string(sid_str, psid) ));
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
success:
|
||||
DEBUG(10,("sid_to_uid: %s -> %u\n", sid_to_string(sid_str, psid),
|
||||
(unsigned int)*puid ));
|
||||
|
||||
store_uid_sid_cache(psid, *puid);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
/*****************************************************************
|
||||
*THE CANONICAL* convert SID to gid function.
|
||||
Group mapping is used for gids that maps to Wellknown SIDs
|
||||
*****************************************************************/
|
||||
|
||||
NTSTATUS sid_to_gid(const DOM_SID *psid, gid_t *pgid)
|
||||
{
|
||||
fstring dom_name, name, sid_str;
|
||||
enum SID_NAME_USE name_type;
|
||||
|
||||
if (fetch_gid_from_cache(pgid, psid))
|
||||
return NT_STATUS_OK;
|
||||
|
||||
/*
|
||||
* First we must look up the name and decide if this is a group sid.
|
||||
* Group mapping can deal with foreign SIDs
|
||||
*/
|
||||
|
||||
if (!winbind_lookup_sid(psid, dom_name, name, &name_type)) {
|
||||
DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed - trying local.\n",
|
||||
sid_to_string(sid_str, psid) ));
|
||||
|
||||
if ( local_sid_to_gid(pgid, psid, &name_type) )
|
||||
goto success;
|
||||
|
||||
DEBUG(10,("sid_to_gid: no one knows this SID\n"));
|
||||
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* winbindd knows it; Ensure this is a group sid */
|
||||
|
||||
if ((name_type != SID_NAME_DOM_GRP) && (name_type != SID_NAME_ALIAS) && (name_type != SID_NAME_WKN_GRP)) {
|
||||
DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is not a known group (%u)\n",
|
||||
(unsigned int)name_type ));
|
||||
|
||||
/* winbindd is running and knows about this SID. Just the wrong type.
|
||||
Don't fallback to a local lookup here */
|
||||
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* winbindd knows it and it is a type of group; sid_to_gid must succeed
|
||||
or we are dead in the water */
|
||||
|
||||
if ( !winbind_sid_to_gid(pgid, psid) ) {
|
||||
DEBUG(10,("sid_to_uid: winbind failed to allocate a new gid for sid %s\n",
|
||||
sid_to_string(sid_str, psid) ));
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
success:
|
||||
DEBUG(10,("sid_to_gid: %s -> %u\n", sid_to_string(sid_str, psid),
|
||||
(unsigned int)*pgid ));
|
||||
|
||||
store_gid_sid_cache(psid, *pgid);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
@ -437,467 +437,4 @@ void add_supplementary_nt_login_groups(int *n_groups, gid_t **pp_groups, NT_USER
|
||||
*pptok = new_tok;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
*THE CANONICAL* convert name to SID function.
|
||||
Tries local lookup first - for local domains - then uses winbind.
|
||||
*****************************************************************/
|
||||
|
||||
BOOL lookup_name(const char *domain, const char *name, DOM_SID *psid, enum SID_NAME_USE *name_type)
|
||||
{
|
||||
fstring sid;
|
||||
BOOL local_lookup = False;
|
||||
|
||||
*name_type = SID_NAME_UNKNOWN;
|
||||
|
||||
/* If we are looking up a domain user, make sure it is
|
||||
for the local machine only */
|
||||
|
||||
if (strequal(global_myname(), domain)) {
|
||||
local_lookup = True;
|
||||
} else if (lp_server_role() == ROLE_DOMAIN_PDC ||
|
||||
lp_server_role() == ROLE_DOMAIN_BDC) {
|
||||
if (strequal(domain, lp_workgroup())) {
|
||||
local_lookup = True;
|
||||
}
|
||||
}
|
||||
|
||||
if (local_lookup) {
|
||||
if (local_lookup_name(name, psid, name_type)) {
|
||||
DEBUG(10,
|
||||
("lookup_name: (local) [%s]\\[%s] -> SID %s (type %s: %u)\n",
|
||||
domain, name, sid_to_string(sid,psid),
|
||||
sid_type_lookup(*name_type), (unsigned int)*name_type));
|
||||
return True;
|
||||
}
|
||||
} else {
|
||||
/* Remote */
|
||||
if (winbind_lookup_name(domain, name, psid, name_type)) {
|
||||
|
||||
DEBUG(10,("lookup_name (winbindd): [%s]\\[%s] -> SID %s (type %u)\n",
|
||||
domain, name, sid_to_string(sid, psid),
|
||||
(unsigned int)*name_type));
|
||||
return True;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG(10, ("lookup_name: %s lookup for [%s]\\[%s] failed\n",
|
||||
local_lookup ? "local" : "winbind", domain, name));
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
*THE CANONICAL* convert SID to name function.
|
||||
Tries local lookup first - for local sids, then tries winbind.
|
||||
*****************************************************************/
|
||||
|
||||
BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE *name_type)
|
||||
{
|
||||
if (!name_type)
|
||||
return False;
|
||||
|
||||
*name_type = SID_NAME_UNKNOWN;
|
||||
|
||||
/* Check if this is our own sid. This should perhaps be done by
|
||||
winbind? For the moment handle it here. */
|
||||
|
||||
if (sid->num_auths == 5) {
|
||||
DOM_SID tmp_sid;
|
||||
uint32 rid;
|
||||
|
||||
sid_copy(&tmp_sid, sid);
|
||||
sid_split_rid(&tmp_sid, &rid);
|
||||
|
||||
if (sid_equal(get_global_sam_sid(), &tmp_sid)) {
|
||||
|
||||
return map_domain_sid_to_name(&tmp_sid, dom_name) &&
|
||||
local_lookup_sid(sid, name, name_type);
|
||||
}
|
||||
}
|
||||
|
||||
if (!winbind_lookup_sid(sid, dom_name, name, name_type)) {
|
||||
fstring sid_str;
|
||||
DOM_SID tmp_sid;
|
||||
uint32 rid;
|
||||
|
||||
DEBUG(10,("lookup_sid: winbind lookup for SID %s failed - trying local.\n", sid_to_string(sid_str, sid) ));
|
||||
|
||||
sid_copy(&tmp_sid, sid);
|
||||
sid_split_rid(&tmp_sid, &rid);
|
||||
return map_domain_sid_to_name(&tmp_sid, dom_name) &&
|
||||
lookup_known_rid(&tmp_sid, rid, name, name_type);
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
Id mapping cache. This is to avoid Winbind mappings already
|
||||
seen by smbd to be queried too frequently, keeping winbindd
|
||||
busy, and blocking smbd while winbindd is busy with other
|
||||
stuff. Written by Michael Steffens <michael.steffens@hp.com>,
|
||||
modified to use linked lists by jra.
|
||||
*****************************************************************/
|
||||
|
||||
#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 SID_NAME_USE sidtype;
|
||||
} *uid_sid_cache_head;
|
||||
|
||||
static struct gid_sid_cache {
|
||||
struct gid_sid_cache *next, *prev;
|
||||
gid_t gid;
|
||||
DOM_SID sid;
|
||||
enum SID_NAME_USE sidtype;
|
||||
} *gid_sid_cache_head;
|
||||
|
||||
/*****************************************************************
|
||||
Find a SID given a uid.
|
||||
*****************************************************************/
|
||||
|
||||
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) {
|
||||
fstring sid;
|
||||
*psid = pc->sid;
|
||||
DEBUG(3,("fetch sid from uid cache %u -> %s\n",
|
||||
(unsigned int)uid, sid_to_string(sid, psid)));
|
||||
DLIST_PROMOTE(uid_sid_cache_head, pc);
|
||||
return True;
|
||||
}
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
Find a uid given a SID.
|
||||
*****************************************************************/
|
||||
|
||||
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) {
|
||||
fstring sid;
|
||||
*puid = pc->uid;
|
||||
DEBUG(3,("fetch uid from cache %u -> %s\n",
|
||||
(unsigned int)*puid, sid_to_string(sid, psid)));
|
||||
DLIST_PROMOTE(uid_sid_cache_head, pc);
|
||||
return True;
|
||||
}
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
Store uid to SID mapping in cache.
|
||||
*****************************************************************/
|
||||
|
||||
static void store_uid_sid_cache(const DOM_SID *psid, uid_t uid)
|
||||
{
|
||||
struct uid_sid_cache *pc;
|
||||
|
||||
if (n_uid_sid_cache >= MAX_UID_SID_CACHE_SIZE && n_uid_sid_cache > TURNOVER_UID_SID_CACHE_SIZE) {
|
||||
/* Delete the last TURNOVER_UID_SID_CACHE_SIZE entries. */
|
||||
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 = (struct uid_sid_cache *)malloc(sizeof(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++;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
Find a SID given a gid.
|
||||
*****************************************************************/
|
||||
|
||||
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) {
|
||||
fstring sid;
|
||||
*psid = pc->sid;
|
||||
DEBUG(3,("fetch sid from gid cache %u -> %s\n",
|
||||
(unsigned int)gid, sid_to_string(sid, psid)));
|
||||
DLIST_PROMOTE(gid_sid_cache_head, pc);
|
||||
return True;
|
||||
}
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
Find a gid given a SID.
|
||||
*****************************************************************/
|
||||
|
||||
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) {
|
||||
fstring sid;
|
||||
*pgid = pc->gid;
|
||||
DEBUG(3,("fetch uid from cache %u -> %s\n",
|
||||
(unsigned int)*pgid, sid_to_string(sid, psid)));
|
||||
DLIST_PROMOTE(gid_sid_cache_head, pc);
|
||||
return True;
|
||||
}
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
Store gid to SID mapping in cache.
|
||||
*****************************************************************/
|
||||
|
||||
static void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
|
||||
{
|
||||
struct gid_sid_cache *pc;
|
||||
|
||||
if (n_gid_sid_cache >= MAX_GID_SID_CACHE_SIZE && n_gid_sid_cache > TURNOVER_GID_SID_CACHE_SIZE) {
|
||||
/* Delete the last TURNOVER_GID_SID_CACHE_SIZE entries. */
|
||||
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 = (struct gid_sid_cache *)malloc(sizeof(struct gid_sid_cache));
|
||||
if (!pc)
|
||||
return;
|
||||
pc->gid = gid;
|
||||
sid_copy(&pc->sid, psid);
|
||||
DLIST_ADD(gid_sid_cache_head, pc);
|
||||
n_gid_sid_cache++;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
*THE CANONICAL* convert uid_t to SID function.
|
||||
*****************************************************************/
|
||||
|
||||
NTSTATUS uid_to_sid(DOM_SID *psid, uid_t uid)
|
||||
{
|
||||
uid_t low, high;
|
||||
fstring sid;
|
||||
|
||||
ZERO_STRUCTP(psid);
|
||||
|
||||
if (fetch_sid_from_uid_cache(psid, uid))
|
||||
return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
|
||||
|
||||
if (lp_idmap_uid(&low, &high) && uid >= low && uid <= high) {
|
||||
if (winbind_uid_to_sid(psid, uid)) {
|
||||
|
||||
DEBUG(10,("uid_to_sid: winbindd %u -> %s\n",
|
||||
(unsigned int)uid, sid_to_string(sid, psid)));
|
||||
|
||||
if (psid)
|
||||
store_uid_sid_cache(psid, uid);
|
||||
return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
|
||||
}
|
||||
}
|
||||
|
||||
if (!local_uid_to_sid(psid, uid)) {
|
||||
DEBUG(10,("uid_to_sid: local %u failed to map to sid\n", (unsigned int)uid ));
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid, sid_to_string(sid, psid)));
|
||||
|
||||
store_uid_sid_cache(psid, uid);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
*THE CANONICAL* convert gid_t to SID function.
|
||||
*****************************************************************/
|
||||
|
||||
NTSTATUS gid_to_sid(DOM_SID *psid, gid_t gid)
|
||||
{
|
||||
gid_t low, high;
|
||||
fstring sid;
|
||||
|
||||
ZERO_STRUCTP(psid);
|
||||
|
||||
if (fetch_sid_from_gid_cache(psid, gid))
|
||||
return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
|
||||
|
||||
if (lp_idmap_gid(&low, &high) && gid >= low && gid <= high) {
|
||||
if (winbind_gid_to_sid(psid, gid)) {
|
||||
|
||||
DEBUG(10,("gid_to_sid: winbindd %u -> %s\n",
|
||||
(unsigned int)gid, sid_to_string(sid, psid)));
|
||||
|
||||
if (psid)
|
||||
store_gid_sid_cache(psid, gid);
|
||||
return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
|
||||
}
|
||||
}
|
||||
|
||||
if (!local_gid_to_sid(psid, gid)) {
|
||||
DEBUG(10,("gid_to_sid: local %u failed to map to sid\n", (unsigned int)gid ));
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid, sid_to_string(sid, psid)));
|
||||
|
||||
store_gid_sid_cache(psid, gid);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
*THE CANONICAL* convert SID to uid function.
|
||||
*****************************************************************/
|
||||
|
||||
NTSTATUS sid_to_uid(const DOM_SID *psid, uid_t *puid)
|
||||
{
|
||||
fstring dom_name, name, sid_str;
|
||||
enum SID_NAME_USE name_type;
|
||||
|
||||
if (fetch_uid_from_cache(puid, psid))
|
||||
return NT_STATUS_OK;
|
||||
|
||||
/* if this is our SID then go straight to a local lookup */
|
||||
|
||||
if ( sid_compare_domain(get_global_sam_sid(), psid) == 0 ) {
|
||||
DEBUG(10,("sid_to_uid: my domain (%s) - trying local.\n",
|
||||
sid_string_static(psid) ));
|
||||
|
||||
if ( local_sid_to_uid(puid, psid, &name_type) )
|
||||
goto success;
|
||||
|
||||
DEBUG(10,("sid_to_uid: local lookup failed\n"));
|
||||
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* If it is not our local domain, only hope is winbindd */
|
||||
|
||||
if ( !winbind_lookup_sid(psid, dom_name, name, &name_type) ) {
|
||||
DEBUG(10,("sid_to_uid: winbind lookup for non-local sid %s failed\n",
|
||||
sid_string_static(psid) ));
|
||||
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* If winbindd does know the SID, ensure this is a user */
|
||||
|
||||
if (name_type != SID_NAME_USER) {
|
||||
DEBUG(10,("sid_to_uid: winbind lookup succeeded but SID is not a user (%u)\n",
|
||||
(unsigned int)name_type ));
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* get the uid. Has to work or else we are dead in the water */
|
||||
|
||||
if ( !winbind_sid_to_uid(puid, psid) ) {
|
||||
DEBUG(10,("sid_to_uid: winbind failed to allocate a new uid for sid %s\n",
|
||||
sid_to_string(sid_str, psid) ));
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
success:
|
||||
DEBUG(10,("sid_to_uid: %s -> %u\n", sid_to_string(sid_str, psid),
|
||||
(unsigned int)*puid ));
|
||||
|
||||
store_uid_sid_cache(psid, *puid);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
/*****************************************************************
|
||||
*THE CANONICAL* convert SID to gid function.
|
||||
Group mapping is used for gids that maps to Wellknown SIDs
|
||||
*****************************************************************/
|
||||
|
||||
NTSTATUS sid_to_gid(const DOM_SID *psid, gid_t *pgid)
|
||||
{
|
||||
fstring dom_name, name, sid_str;
|
||||
enum SID_NAME_USE name_type;
|
||||
|
||||
if (fetch_gid_from_cache(pgid, psid))
|
||||
return NT_STATUS_OK;
|
||||
|
||||
/*
|
||||
* First we must look up the name and decide if this is a group sid.
|
||||
* Group mapping can deal with foreign SIDs
|
||||
*/
|
||||
|
||||
if (!winbind_lookup_sid(psid, dom_name, name, &name_type)) {
|
||||
DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed - trying local.\n",
|
||||
sid_to_string(sid_str, psid) ));
|
||||
|
||||
if ( local_sid_to_gid(pgid, psid, &name_type) )
|
||||
goto success;
|
||||
|
||||
DEBUG(10,("sid_to_gid: no one knows this SID\n"));
|
||||
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* winbindd knows it; Ensure this is a group sid */
|
||||
|
||||
if ((name_type != SID_NAME_DOM_GRP) && (name_type != SID_NAME_ALIAS) && (name_type != SID_NAME_WKN_GRP)) {
|
||||
DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is not a known group (%u)\n",
|
||||
(unsigned int)name_type ));
|
||||
|
||||
/* winbindd is running and knows about this SID. Just the wrong type.
|
||||
Don't fallback to a local lookup here */
|
||||
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* winbindd knows it and it is a type of group; sid_to_gid must succeed
|
||||
or we are dead in the water */
|
||||
|
||||
if ( !winbind_sid_to_gid(pgid, psid) ) {
|
||||
DEBUG(10,("sid_to_uid: winbind failed to allocate a new gid for sid %s\n",
|
||||
sid_to_string(sid_str, psid) ));
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
success:
|
||||
DEBUG(10,("sid_to_gid: %s -> %u\n", sid_to_string(sid_str, psid),
|
||||
(unsigned int)*pgid ));
|
||||
|
||||
store_gid_sid_cache(psid, *pgid);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user