2003-08-28 00:52:56 +04:00
/*
Unix SMB / CIFS implementation .
uid / user handling
Copyright ( C ) Andrew Tridgell 1992 - 1998
Copyright ( C ) Gerald ( Jerry ) Carter 2003
2006-02-04 01:19:41 +03:00
Copyright ( C ) Volker Lendecke 2005
2003-08-28 00:52:56 +04:00
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 0213 9 , USA .
*/
# include "includes.h"
/*****************************************************************
2005-12-03 21:34:13 +03:00
Dissect a user - provided name into domain , name , sid and type .
If an explicit domain name was given in the form domain \ user , it
has to try that . If no explicit domain name was given , we have
to do guesswork .
2003-08-28 00:52:56 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-12-03 21:34:13 +03:00
BOOL lookup_name ( TALLOC_CTX * mem_ctx ,
const char * full_name , int flags ,
2005-12-10 14:22:01 +03:00
const char * * ret_domain , const char * * ret_name ,
2005-12-03 21:34:13 +03:00
DOM_SID * ret_sid , enum SID_NAME_USE * ret_type )
2003-08-28 00:52:56 +04:00
{
2005-12-10 14:22:01 +03:00
char * p ;
const char * tmp ;
const char * domain = NULL ;
const char * name = NULL ;
2005-12-03 21:34:13 +03:00
uint32 rid ;
DOM_SID sid ;
enum SID_NAME_USE type ;
2005-12-10 14:22:01 +03:00
TALLOC_CTX * tmp_ctx = talloc_new ( mem_ctx ) ;
2006-06-07 00:18:11 +04:00
struct group * grp ;
2005-12-10 14:22:01 +03:00
if ( tmp_ctx = = NULL ) {
DEBUG ( 0 , ( " talloc_new failed \n " ) ) ;
return False ;
}
2005-12-03 21:34:13 +03:00
p = strchr_m ( full_name , ' \\ ' ) ;
if ( p ! = NULL ) {
2005-12-10 14:22:01 +03:00
domain = talloc_strndup ( tmp_ctx , full_name ,
2005-12-03 21:34:13 +03:00
PTR_DIFF ( p , full_name ) ) ;
2005-12-10 14:22:01 +03:00
name = talloc_strdup ( tmp_ctx , p + 1 ) ;
2005-12-03 21:34:13 +03:00
} else {
2005-12-10 14:22:01 +03:00
domain = talloc_strdup ( tmp_ctx , " " ) ;
name = talloc_strdup ( tmp_ctx , full_name ) ;
2005-12-03 21:34:13 +03:00
}
if ( ( domain = = NULL ) | | ( name = = NULL ) ) {
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
return False ;
}
2003-08-28 00:52:56 +04:00
2004-03-07 11:22:06 +03:00
if ( strequal ( domain , get_global_sam_name ( ) ) ) {
2005-12-03 21:34:13 +03:00
/* It's our own domain, lookup the name in passdb */
2006-02-04 01:19:41 +03:00
if ( lookup_global_sam_name ( name , flags , & rid , & type ) ) {
2005-12-03 21:34:13 +03:00
sid_copy ( & sid , get_global_sam_sid ( ) ) ;
sid_append_rid ( & sid , rid ) ;
goto ok ;
2003-08-28 00:52:56 +04:00
}
2005-12-10 14:22:01 +03:00
goto failed ;
2005-12-03 21:34:13 +03:00
}
if ( strequal ( domain , builtin_domain_name ( ) ) ) {
/* Explicit request for a name in BUILTIN */
if ( lookup_builtin_name ( name , & rid ) ) {
sid_copy ( & sid , & global_sid_Builtin ) ;
sid_append_rid ( & sid , rid ) ;
type = SID_NAME_ALIAS ;
goto ok ;
2003-08-28 00:52:56 +04:00
}
2005-12-10 14:22:01 +03:00
goto failed ;
2003-08-28 00:52:56 +04:00
}
2005-12-03 21:34:13 +03:00
2006-02-04 01:19:41 +03:00
/* Try the explicit winbind lookup first, don't let it guess the
* domain yet at this point yet . This comes later . */
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 ;
}
goto failed ;
}
if ( strequal ( domain , unix_groups_domain_name ( ) ) ) {
if ( lookup_unix_group_name ( name , & sid ) ) {
type = SID_NAME_DOM_GRP ;
2005-12-03 21:34:13 +03:00
goto ok ;
}
2005-12-10 14:22:01 +03:00
goto failed ;
2005-12-03 21:34:13 +03:00
}
2006-02-04 01:19:41 +03:00
if ( ( domain [ 0 ] = = ' \0 ' ) & & ( ! ( flags & LOOKUP_NAME_ISOLATED ) ) ) {
2005-12-10 14:22:01 +03:00
goto failed ;
2005-12-03 21:34:13 +03:00
}
2006-02-25 01:26:53 +03:00
/*
* Nasty hack necessary for too common scenarios :
*
* For ' valid users = + users ' we know " users " is most probably not
* BUILTIN \ users but the unix group users . This hack requires the
* admin to explicitly qualify BUILTIN if BUILTIN \ users is meant .
*
* Please note that LOOKUP_NAME_GROUP can not be requested via for
* example lsa_lookupnames , it only comes into this routine via
* the expansion of group names coming in from smb . conf
*/
2006-06-07 00:18:11 +04:00
if ( ( flags & LOOKUP_NAME_GROUP ) & & ( ( grp = getgrnam ( name ) ) ! = NULL ) ) {
GROUP_MAP map ;
if ( pdb_getgrgid ( & map , grp - > gr_gid ) ) {
/* The hack gets worse. Handle the case where we have
* ' force group = + unixgroup ' but " unixgroup " has a
* group mapping */
if ( sid_check_is_in_builtin ( & map . sid ) ) {
domain = talloc_strdup (
tmp_ctx , builtin_domain_name ( ) ) ;
} else {
domain = talloc_strdup (
tmp_ctx , get_global_sam_name ( ) ) ;
}
sid_copy ( & sid , & map . sid ) ;
type = map . sid_name_use ;
goto ok ;
}
2006-04-30 18:34:30 +04:00
/* If we are using the smbpasswd backend, we need to use the
* algorithmic mapping for the unix group we find . This is
* necessary because when creating the NT token from the unix
* gid list we got from initgroups ( ) we use gid_to_sid ( ) that
* uses algorithmic mapping if pdb_rid_algorithm ( ) is true . */
2006-06-07 00:18:11 +04:00
if ( pdb_rid_algorithm ( ) & &
2006-04-30 18:34:30 +04:00
( grp - > gr_gid < max_algorithmic_gid ( ) ) ) {
domain = talloc_strdup ( tmp_ctx , get_global_sam_name ( ) ) ;
sid_compose ( & sid , get_global_sam_sid ( ) ,
pdb_gid_to_group_rid ( grp - > gr_gid ) ) ;
type = SID_NAME_DOM_GRP ;
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 ;
}
2006-02-25 01:26:53 +03:00
}
2005-12-03 21:34:13 +03:00
/* Now the guesswork begins, we haven't been given an explicit
* domain . Try the sequence as documented on
* http : //msdn.microsoft.com/library/en-us/secmgmt/security/lsalookupnames.asp
* November 27 , 2005 */
/* 1. well-known names */
2006-02-24 23:50:13 +03:00
if ( lookup_wellknown_name ( tmp_ctx , name , & sid , & domain ) ) {
type = SID_NAME_WKN_GRP ;
goto ok ;
2005-12-03 21:34:13 +03:00
}
/* 2. Builtin domain as such */
if ( strequal ( name , builtin_domain_name ( ) ) ) {
/* Swap domain and name */
tmp = name ; name = domain ; domain = tmp ;
sid_copy ( & sid , & global_sid_Builtin ) ;
type = SID_NAME_DOMAIN ;
goto ok ;
}
/* 3. Account domain */
if ( strequal ( name , get_global_sam_name ( ) ) ) {
if ( ! secrets_fetch_domain_sid ( name , & sid ) ) {
DEBUG ( 3 , ( " Could not fetch my SID \n " ) ) ;
2005-12-10 14:22:01 +03:00
goto failed ;
2005-12-03 21:34:13 +03:00
}
/* Swap domain and name */
tmp = name ; name = domain ; domain = tmp ;
type = SID_NAME_DOMAIN ;
goto ok ;
}
/* 4. Primary domain */
if ( ! IS_DC & & strequal ( name , lp_workgroup ( ) ) ) {
if ( ! secrets_fetch_domain_sid ( name , & sid ) ) {
DEBUG ( 3 , ( " Could not fetch the domain SID \n " ) ) ;
2005-12-10 14:22:01 +03:00
goto failed ;
2005-12-03 21:34:13 +03:00
}
/* Swap domain and name */
tmp = name ; name = domain ; domain = tmp ;
type = SID_NAME_DOMAIN ;
goto ok ;
}
/* 5. Trusted domains as such, to me it looks as if members don't do
this , tested an XP workstation in a NT domain - - vl */
if ( IS_DC & & ( secrets_fetch_trusted_domain_password ( name , NULL ,
& sid , NULL ) ) ) {
/* Swap domain and name */
tmp = name ; name = domain ; domain = tmp ;
type = SID_NAME_DOMAIN ;
goto ok ;
}
/* 6. Builtin aliases */
if ( lookup_builtin_name ( name , & rid ) ) {
2005-12-10 14:22:01 +03:00
domain = talloc_strdup ( tmp_ctx , builtin_domain_name ( ) ) ;
2005-12-03 21:34:13 +03:00
sid_copy ( & sid , & global_sid_Builtin ) ;
sid_append_rid ( & sid , rid ) ;
type = SID_NAME_ALIAS ;
goto ok ;
}
/* 7. Local systems' SAM (DCs don't have a local SAM) */
/* 8. Primary SAM (On members, this is the domain) */
/* Both cases are done by looking at our passdb */
2006-02-04 01:19:41 +03:00
if ( lookup_global_sam_name ( name , flags , & rid , & type ) ) {
2005-12-10 14:22:01 +03:00
domain = talloc_strdup ( tmp_ctx , get_global_sam_name ( ) ) ;
2005-12-03 21:34:13 +03:00
sid_copy ( & sid , get_global_sam_sid ( ) ) ;
sid_append_rid ( & sid , rid ) ;
goto ok ;
}
/* Now our local possibilities are exhausted. */
if ( ! ( flags & LOOKUP_NAME_REMOTE ) ) {
2005-12-10 14:22:01 +03:00
goto failed ;
2005-12-03 21:34:13 +03:00
}
/* If we are not a DC, we have to ask in our primary domain. Let
* winbind do that . */
if ( ! IS_DC & &
( winbind_lookup_name ( lp_workgroup ( ) , name , & sid , & type ) ) ) {
2005-12-10 14:22:01 +03:00
domain = talloc_strdup ( tmp_ctx , lp_workgroup ( ) ) ;
2005-12-03 21:34:13 +03:00
goto ok ;
}
/* 9. Trusted domains */
/* If we're a DC we have to ask all trusted DC's. Winbind does not do
* that ( yet ) , but give it a chance . */
if ( IS_DC & & winbind_lookup_name ( " " , name , & sid , & type ) ) {
DOM_SID dom_sid ;
uint32 tmp_rid ;
enum SID_NAME_USE domain_type ;
if ( type = = SID_NAME_DOMAIN ) {
/* Swap name and type */
tmp = name ; name = domain ; domain = tmp ;
goto ok ;
}
/* Here we have to cope with a little deficiency in the
* winbind API : We have to ask it again for the name of the
* domain it figured out itself . Maybe fix that later . . . */
sid_copy ( & dom_sid , & sid ) ;
sid_split_rid ( & dom_sid , & tmp_rid ) ;
2005-12-10 14:22:01 +03:00
if ( ! winbind_lookup_sid ( tmp_ctx , & dom_sid , & domain , NULL ,
2005-12-03 21:34:13 +03:00
& domain_type ) | |
( domain_type ! = SID_NAME_DOMAIN ) ) {
2005-12-10 14:22:01 +03:00
DEBUG ( 2 , ( " winbind could not find the domain's name "
" it just looked up for us \n " ) ) ;
goto failed ;
2005-12-03 21:34:13 +03:00
}
goto ok ;
}
/* 10. Don't translate */
2006-02-04 01:19:41 +03:00
/* 11. Ok, windows would end here. Samba has two more options:
Unmapped users and unmapped groups */
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 ;
}
2005-12-10 14:22:01 +03:00
failed :
2006-02-20 20:59:58 +03:00
TALLOC_FREE ( tmp_ctx ) ;
2003-08-28 00:52:56 +04:00
return False ;
2005-12-03 21:34:13 +03:00
ok :
if ( ( domain = = NULL ) | | ( name = = NULL ) ) {
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
2006-02-20 20:59:58 +03:00
TALLOC_FREE ( tmp_ctx ) ;
2005-12-03 21:34:13 +03:00
return False ;
}
if ( ret_name ! = NULL ) {
2005-12-10 14:22:01 +03:00
* ret_name = talloc_steal ( mem_ctx , name ) ;
2005-12-03 21:34:13 +03:00
}
if ( ret_domain ! = NULL ) {
2005-12-10 14:22:01 +03:00
char * tmp_dom = talloc_strdup ( tmp_ctx , domain ) ;
strupper_m ( tmp_dom ) ;
* ret_domain = talloc_steal ( mem_ctx , tmp_dom ) ;
2005-12-03 21:34:13 +03:00
}
if ( ret_sid ! = NULL ) {
sid_copy ( ret_sid , & sid ) ;
}
if ( ret_type ! = NULL ) {
* ret_type = type ;
}
2006-02-20 20:59:58 +03:00
TALLOC_FREE ( tmp_ctx ) ;
2005-12-03 21:34:13 +03:00
return True ;
2003-08-28 00:52:56 +04:00
}
2006-02-04 01:19:41 +03:00
static BOOL winbind_lookup_rids ( TALLOC_CTX * mem_ctx ,
const DOM_SID * domain_sid ,
int num_rids , uint32 * rids ,
const char * * domain_name ,
2006-06-29 21:03:19 +04:00
const char * * names , enum SID_NAME_USE * types )
2006-02-04 01:19:41 +03:00
{
/* Unless the winbind interface is upgraded, fall back to ask for
* individual sids . I imagine introducing a lookuprids operation that
* directly proxies to lsa_lookupsids to the correct DC . - - vl */
int i ;
for ( i = 0 ; i < num_rids ; i + + ) {
DOM_SID sid ;
sid_copy ( & sid , domain_sid ) ;
sid_append_rid ( & sid , rids [ i ] ) ;
if ( winbind_lookup_sid ( mem_ctx , & sid ,
* domain_name = = NULL ?
domain_name : NULL ,
& names [ i ] , & types [ i ] ) ) {
if ( ( names [ i ] = = NULL ) | | ( ( * domain_name ) = = NULL ) ) {
return False ;
}
} else {
types [ i ] = SID_NAME_UNKNOWN ;
}
}
return True ;
}
2003-08-28 00:52:56 +04:00
2006-02-04 01:19:41 +03:00
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 SID_NAME_USE * * types )
2003-08-28 00:52:56 +04:00
{
2006-02-04 01:19:41 +03:00
int i ;
2005-12-10 14:22:01 +03:00
2006-02-04 01:19:41 +03:00
* names = TALLOC_ARRAY ( mem_ctx , const char * , num_rids ) ;
* types = TALLOC_ARRAY ( mem_ctx , enum SID_NAME_USE , num_rids ) ;
2003-08-28 00:52:56 +04:00
2006-02-04 01:19:41 +03:00
if ( ( * names = = NULL ) | | ( * types = = NULL ) ) {
2005-12-10 14:22:01 +03:00
return False ;
}
2006-02-04 01:19:41 +03:00
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 ) ) ;
2004-11-19 16:26:17 +03:00
}
2006-02-04 01:19:41 +03:00
if ( sid_check_is_builtin ( domain_sid ) ) {
2005-11-27 00:02:48 +03:00
2006-02-04 01:19:41 +03:00
if ( * domain_name = = NULL ) {
* domain_name = talloc_strdup (
mem_ctx , builtin_domain_name ( ) ) ;
2005-12-03 21:34:13 +03:00
}
2006-02-04 01:19:41 +03:00
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 winbind_lookup_rids ( mem_ctx , domain_sid , num_rids , rids ,
domain_name , * names , * types ) ;
}
/*
* Is the SID a domain as such ? If yes , lookup its name .
*/
static BOOL lookup_as_domain ( const DOM_SID * sid , TALLOC_CTX * mem_ctx ,
const char * * name )
{
const char * tmp ;
enum SID_NAME_USE type ;
if ( sid_check_is_domain ( sid ) ) {
* name = talloc_strdup ( mem_ctx , get_global_sam_name ( ) ) ;
return True ;
2005-11-27 00:02:48 +03:00
}
2005-11-26 23:28:12 +03:00
if ( sid_check_is_builtin ( sid ) ) {
2006-02-04 01:19:41 +03:00
* name = talloc_strdup ( mem_ctx , builtin_domain_name ( ) ) ;
return True ;
}
2003-08-28 00:52:56 +04:00
2006-02-04 01:19:41 +03:00
if ( sid_check_is_wellknown_domain ( sid , & tmp ) ) {
* name = talloc_strdup ( mem_ctx , tmp ) ;
return True ;
}
2003-08-28 00:52:56 +04:00
2006-02-04 01:19:41 +03:00
if ( sid - > num_auths ! = 4 ) {
/* This can't be a domain */
return False ;
2005-11-26 23:28:12 +03:00
}
2006-02-04 01:19:41 +03:00
if ( IS_DC ) {
uint32 i , num_domains ;
struct trustdom_info * * domains ;
2005-11-27 00:02:48 +03:00
2006-02-04 01:19:41 +03:00
/* This is relatively expensive, but it happens only on DCs
* and for SIDs that have 4 sub - authorities and thus look like
* domains */
2005-11-26 23:28:12 +03:00
2006-02-04 01:19:41 +03:00
if ( ! NT_STATUS_IS_OK ( secrets_trusted_domains ( mem_ctx ,
& num_domains ,
& domains ) ) ) {
return False ;
2005-12-03 21:34:13 +03:00
}
2005-11-27 00:02:48 +03:00
2006-02-04 01:19:41 +03:00
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 ;
}
2005-11-27 00:02:48 +03:00
2006-02-04 01:19:41 +03:00
if ( winbind_lookup_sid ( mem_ctx , sid , & tmp , NULL , & type ) & &
( type = = SID_NAME_DOMAIN ) ) {
* name = tmp ;
return True ;
2003-08-28 00:52:56 +04:00
}
2006-02-04 01:19:41 +03:00
return False ;
}
/*
* This tries to implement the rather weird rules for the lsa_lookup level
* parameter .
*
* This is as close as we can get to what W2k3 does . With this we survive the
* RPC - LSALOOKUP samba4 test as of 2006 - 01 - 08. NT4 as a PDC is a bit more
* different , but I assume that ' s just being too liberal . For example , W2k3
* replies to everything else but the levels 1 - 6 with INVALID_PARAMETER
* whereas NT4 does the same as level 1 ( I think ) . I did not fully test that
* with NT4 , this is what w2k3 does .
*
* Level 1 : Ask everywhere
* Level 2 : Ask domain and trusted domains , no builtin and wkn
* Level 3 : Only ask domain
* Level 4 : W2k3ad : Only ask AD trusts
* Level 5 : Don ' t lookup anything
* Level 6 : Like 4
*/
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 ;
2005-09-30 21:13:37 +04:00
}
2003-08-28 00:52:56 +04:00
2006-02-04 01:19:41 +03:00
DEBUG ( 10 , ( " %s SID %s in level %d \n " ,
ret ? " Accepting " : " Rejecting " ,
sid_string_static ( sid ) , level ) ) ;
return ret ;
}
2003-08-28 00:52:56 +04:00
2006-02-04 01:19:41 +03:00
/*
* Lookup a bunch of SIDs . This is modeled after lsa_lookup_sids with
* references to domains , it is explicitly made for this .
*
* This attempts to be as efficient as possible : It collects all SIDs
* belonging to a domain and hands them in bulk to the appropriate lookup
* function . In particular pdb_lookup_rids with ldapsam_trusted benefits
* * hugely * from this . Winbind is going to be extended with a lookup_rids
* interface as well , so on a DC we can do a bulk lsa_lookuprids to the
* appropriate DC .
*/
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 ;
int i , j ;
tmp_ctx = talloc_new ( mem_ctx ) ;
if ( tmp_ctx = = NULL ) {
DEBUG ( 0 , ( " talloc_new failed \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
2003-08-28 00:52:56 +04:00
}
2005-09-30 21:13:37 +04:00
2006-02-04 01:19:41 +03:00
name_infos = TALLOC_ARRAY ( tmp_ctx , struct lsa_name_info , num_sids ) ;
dom_infos = TALLOC_ZERO_ARRAY ( tmp_ctx , struct lsa_dom_info ,
MAX_REF_DOMAINS ) ;
if ( ( name_infos = = NULL ) | | ( dom_infos = = NULL ) ) {
result = NT_STATUS_NO_MEMORY ;
goto done ;
}
/* First build up the data structures:
*
* dom_infos is a list of domains referenced in the list of
* SIDs . Later we will walk the list of domains and look up the RIDs
* in bulk .
*
* name_infos is a shadow - copy of the SIDs array to collect the real
* data .
*
* dom_info - > idxs is an index into the name_infos array . The
* difficulty we have here is that we need to keep the SIDs the client
* asked for in the same order for the reply
*/
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 ) ) {
/* We can't push that through the normal lookup
* process , as this would reference illegal
* domains .
*
* For example S - 1 - 5 - 32 would end up referencing
* domain S - 1 - 5 - with RID 32 which is clearly wrong .
*/
if ( domain_name = = NULL ) {
result = NT_STATUS_NO_MEMORY ;
goto done ;
}
name_infos [ i ] . rid = 0 ;
name_infos [ i ] . type = SID_NAME_DOMAIN ;
name_infos [ i ] . name = NULL ;
if ( sid_check_is_builtin ( & sid ) ) {
/* Yes, W2k3 returns "BUILTIN" both as domain
* and name here */
name_infos [ i ] . name = talloc_strdup (
name_infos , builtin_domain_name ( ) ) ;
if ( name_infos [ i ] . name = = NULL ) {
result = NT_STATUS_NO_MEMORY ;
goto done ;
}
}
} else {
/* This is a normal SID with rid component */
if ( ! sid_split_rid ( & sid , & rid ) ) {
result = NT_STATUS_INVALID_PARAMETER ;
goto done ;
}
}
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 ) {
/* TODO: What's the right error message here? */
result = NT_STATUS_NONE_MAPPED ;
goto done ;
}
if ( ! dom_infos [ j ] . valid ) {
/* We found a domain not yet referenced, create a new
* ref . */
dom_infos [ j ] . valid = True ;
sid_copy ( & dom_infos [ j ] . sid , & sid ) ;
if ( domain_name ! = NULL ) {
/* This name was being found above in the case
* when we found a domain SID */
dom_infos [ j ] . name =
talloc_steal ( dom_infos , domain_name ) ;
} else {
/* lookup_rids will take care of this */
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 done ;
}
}
}
/* Iterate over the domains found */
for ( i = 0 ; i < MAX_REF_DOMAINS ; i + + ) {
uint32_t * rids ;
const char * * names ;
enum SID_NAME_USE * types ;
struct lsa_dom_info * dom = & dom_infos [ i ] ;
if ( ! dom - > valid ) {
/* No domains left, we're done */
break ;
}
rids = TALLOC_ARRAY ( tmp_ctx , uint32 , dom - > num_idxs ) ;
if ( rids = = NULL ) {
result = NT_STATUS_NO_MEMORY ;
goto done ;
}
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 , & dom - > name ,
& names , & types ) ) {
result = NT_STATUS_NO_MEMORY ;
goto done ;
}
talloc_steal ( dom_infos , dom - > name ) ;
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_steal ( name_infos , names [ j ] ) ;
} else {
name_infos [ idx ] . name = NULL ;
}
}
}
* ret_domains = talloc_steal ( mem_ctx , dom_infos ) ;
* ret_names = talloc_steal ( mem_ctx , name_infos ) ;
result = NT_STATUS_OK ;
done :
2006-02-20 20:59:58 +03:00
TALLOC_FREE ( tmp_ctx ) ;
2006-02-04 01:19:41 +03:00
return result ;
}
2005-12-03 21:34:13 +03:00
2006-02-04 01:19:41 +03:00
/*****************************************************************
* THE CANONICAL * convert SID to name function .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-12-03 21:34:13 +03:00
2006-02-04 01:19:41 +03:00
BOOL lookup_sid ( TALLOC_CTX * mem_ctx , const DOM_SID * sid ,
const char * * ret_domain , const char * * ret_name ,
enum SID_NAME_USE * ret_type )
{
struct lsa_dom_info * domain ;
struct lsa_name_info * name ;
TALLOC_CTX * tmp_ctx ;
BOOL ret = False ;
tmp_ctx = talloc_new ( mem_ctx ) ;
if ( tmp_ctx = = NULL ) {
DEBUG ( 0 , ( " talloc_new failed \n " ) ) ;
2005-12-03 21:34:13 +03:00
return False ;
}
2006-02-04 01:19:41 +03:00
if ( ! NT_STATUS_IS_OK ( lookup_sids ( tmp_ctx , 1 , & sid , 1 ,
& domain , & name ) ) ) {
goto done ;
}
if ( name - > type = = SID_NAME_UNKNOWN ) {
goto done ;
}
2005-12-03 21:34:13 +03:00
if ( ret_domain ! = NULL ) {
2006-02-04 01:19:41 +03:00
* ret_domain = talloc_steal ( mem_ctx , domain - > name ) ;
2005-12-03 21:34:13 +03:00
}
if ( ret_name ! = NULL ) {
2006-02-04 01:19:41 +03:00
* ret_name = talloc_steal ( mem_ctx , name - > name ) ;
2005-12-03 21:34:13 +03:00
}
if ( ret_type ! = NULL ) {
2006-02-04 01:19:41 +03:00
* ret_type = name - > type ;
2005-12-03 21:34:13 +03:00
}
2006-02-04 01:19:41 +03:00
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 ) ) ) ;
}
2006-02-20 20:59:58 +03:00
TALLOC_FREE ( tmp_ctx ) ;
2006-02-04 01:19:41 +03:00
return ret ;
2003-08-28 00:52:56 +04:00
}
/*****************************************************************
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 ) {
* psid = pc - > sid ;
DEBUG ( 3 , ( " fetch sid from uid cache %u -> %s \n " ,
2005-12-03 21:34:13 +03:00
( unsigned int ) uid , sid_string_static ( psid ) ) ) ;
2003-08-28 00:52:56 +04:00
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 ) {
* puid = pc - > uid ;
DEBUG ( 3 , ( " fetch uid from cache %u -> %s \n " ,
2005-12-03 21:34:13 +03:00
( unsigned int ) * puid , sid_string_static ( psid ) ) ) ;
2003-08-28 00:52:56 +04:00
DLIST_PROMOTE ( uid_sid_cache_head , pc ) ;
return True ;
}
}
return False ;
}
/*****************************************************************
Store uid to SID mapping in cache .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-02-04 01:19:41 +03:00
void store_uid_sid_cache ( const DOM_SID * psid , uid_t uid )
2003-08-28 00:52:56 +04:00
{
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 - - ;
}
}
2004-12-07 21:25:53 +03:00
pc = SMB_MALLOC_P ( struct uid_sid_cache ) ;
2003-08-28 00:52:56 +04:00
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 ) {
* psid = pc - > sid ;
DEBUG ( 3 , ( " fetch sid from gid cache %u -> %s \n " ,
2005-12-03 21:34:13 +03:00
( unsigned int ) gid , sid_string_static ( psid ) ) ) ;
2003-08-28 00:52:56 +04:00
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 ) {
* pgid = pc - > gid ;
2005-06-09 02:10:34 +04:00
DEBUG ( 3 , ( " fetch gid from cache %u -> %s \n " ,
2005-12-03 21:34:13 +03:00
( unsigned int ) * pgid , sid_string_static ( psid ) ) ) ;
2003-08-28 00:52:56 +04:00
DLIST_PROMOTE ( gid_sid_cache_head , pc ) ;
return True ;
}
}
return False ;
}
/*****************************************************************
Store gid to SID mapping in cache .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-02-04 01:19:41 +03:00
void store_gid_sid_cache ( const DOM_SID * psid , gid_t gid )
2003-08-28 00:52:56 +04:00
{
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 - - ;
}
}
2004-12-07 21:25:53 +03:00
pc = SMB_MALLOC_P ( struct gid_sid_cache ) ;
2003-08-28 00:52:56 +04:00
if ( ! pc )
return ;
pc - > gid = gid ;
sid_copy ( & pc - > sid , psid ) ;
DLIST_ADD ( gid_sid_cache_head , pc ) ;
2006-06-03 03:58:02 +04:00
DEBUG ( 3 , ( " store_gid_sid_cache: gid %u in cache -> %s \n " , ( unsigned int ) gid ,
sid_string_static ( psid ) ) ) ;
2003-08-28 00:52:56 +04:00
n_gid_sid_cache + + ;
}
/*****************************************************************
* THE CANONICAL * convert uid_t to SID function .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-02-04 01:19:41 +03:00
void uid_to_sid ( DOM_SID * psid , uid_t uid )
2003-08-28 00:52:56 +04:00
{
2003-11-07 17:39:47 +03:00
uid_t low , high ;
2006-02-04 01:19:41 +03:00
uint32 rid ;
2003-08-28 00:52:56 +04:00
ZERO_STRUCTP ( psid ) ;
if ( fetch_sid_from_uid_cache ( psid , uid ) )
2006-02-04 01:19:41 +03:00
return ;
2003-08-28 00:52:56 +04:00
2006-02-04 01:19:41 +03:00
if ( lp_idmap_uid ( & low , & high ) & & ( uid > = low ) & & ( uid < = high ) & &
winbind_uid_to_sid ( psid , uid ) ) {
2003-11-07 17:39:47 +03:00
2006-02-04 01:19:41 +03:00
DEBUG ( 10 , ( " uid_to_sid: winbindd %u -> %s \n " ,
( unsigned int ) uid , sid_string_static ( psid ) ) ) ;
goto done ;
}
2003-08-28 00:52:56 +04:00
2006-02-04 01:19:41 +03:00
if ( pdb_uid_to_rid ( uid , & rid ) ) {
/* This is a mapped user */
sid_copy ( psid , get_global_sam_sid ( ) ) ;
sid_append_rid ( psid , rid ) ;
goto done ;
2003-08-28 00:52:56 +04:00
}
2006-02-04 01:19:41 +03:00
if ( pdb_rid_algorithm ( ) & & ( uid < max_algorithmic_uid ( ) ) ) {
sid_copy ( psid , get_global_sam_sid ( ) ) ;
sid_append_rid ( psid , algorithmic_pdb_uid_to_user_rid ( uid ) ) ;
goto done ;
} else {
2006-07-07 23:01:15 +04:00
uid_to_unix_users_sid ( uid , psid ) ;
2006-02-04 01:19:41 +03:00
goto done ;
2003-08-28 00:52:56 +04:00
}
2006-02-04 01:19:41 +03:00
done :
2005-12-03 21:34:13 +03:00
DEBUG ( 10 , ( " uid_to_sid: local %u -> %s \n " , ( unsigned int ) uid ,
sid_string_static ( psid ) ) ) ;
2003-08-28 00:52:56 +04:00
store_uid_sid_cache ( psid , uid ) ;
2006-02-04 01:19:41 +03:00
return ;
2003-08-28 00:52:56 +04:00
}
/*****************************************************************
* THE CANONICAL * convert gid_t to SID function .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-02-04 01:19:41 +03:00
void gid_to_sid ( DOM_SID * psid , gid_t gid )
2003-08-28 00:52:56 +04:00
{
2003-11-07 17:39:47 +03:00
gid_t low , high ;
2003-08-28 00:52:56 +04:00
ZERO_STRUCTP ( psid ) ;
if ( fetch_sid_from_gid_cache ( psid , gid ) )
2006-02-04 01:19:41 +03:00
return ;
2003-08-28 00:52:56 +04:00
2006-02-04 01:19:41 +03:00
if ( lp_idmap_gid ( & low , & high ) & & ( gid > = low ) & & ( gid < = high ) & &
winbind_gid_to_sid ( psid , gid ) ) {
2003-11-07 17:39:47 +03:00
2006-02-04 01:19:41 +03:00
DEBUG ( 10 , ( " gid_to_sid: winbindd %u -> %s \n " ,
( unsigned int ) gid , sid_string_static ( psid ) ) ) ;
goto done ;
}
2003-08-28 00:52:56 +04:00
2006-02-04 01:19:41 +03:00
if ( pdb_gid_to_sid ( gid , psid ) ) {
/* This is a mapped group */
goto done ;
2003-08-28 00:52:56 +04:00
}
2006-02-04 01:19:41 +03:00
if ( pdb_rid_algorithm ( ) & & ( gid < max_algorithmic_gid ( ) ) ) {
sid_copy ( psid , get_global_sam_sid ( ) ) ;
sid_append_rid ( psid , pdb_gid_to_group_rid ( gid ) ) ;
goto done ;
} else {
sid_copy ( psid , & global_sid_Unix_Groups ) ;
sid_append_rid ( psid , gid ) ;
goto done ;
2003-08-28 00:52:56 +04:00
}
2006-02-04 01:19:41 +03:00
done :
2005-12-03 21:34:13 +03:00
DEBUG ( 10 , ( " gid_to_sid: local %u -> %s \n " , ( unsigned int ) gid ,
sid_string_static ( psid ) ) ) ;
2003-08-28 00:52:56 +04:00
store_gid_sid_cache ( psid , gid ) ;
2006-02-04 01:19:41 +03:00
return ;
2003-08-28 00:52:56 +04:00
}
/*****************************************************************
* THE CANONICAL * convert SID to uid function .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-02-04 01:19:41 +03:00
BOOL sid_to_uid ( const DOM_SID * psid , uid_t * puid )
2003-08-28 00:52:56 +04:00
{
2006-02-04 01:19:41 +03:00
enum SID_NAME_USE type ;
uint32 rid ;
gid_t gid ;
2003-08-28 00:52:56 +04:00
if ( fetch_uid_from_cache ( puid , psid ) )
2006-02-04 01:19:41 +03:00
return True ;
2003-08-28 00:52:56 +04:00
2006-02-04 01:19:41 +03:00
if ( fetch_gid_from_cache ( & gid , psid ) ) {
return False ;
2003-08-28 00:52:56 +04:00
}
2006-02-04 01:19:41 +03:00
if ( sid_peek_check_rid ( & global_sid_Unix_Users , psid , & rid ) ) {
uid_t uid = rid ;
* puid = uid ;
goto done ;
2003-08-28 00:52:56 +04:00
}
2006-02-04 01:19:41 +03:00
if ( sid_peek_check_rid ( get_global_sam_sid ( ) , psid , & rid ) ) {
union unid_t id ;
if ( pdb_sid_to_id ( psid , & id , & type ) ) {
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 ;
}
if ( pdb_rid_algorithm ( ) & &
algorithmic_pdb_rid_is_user ( rid ) ) {
* puid = algorithmic_pdb_user_rid_to_uid ( rid ) ;
goto done ;
}
2003-08-28 00:52:56 +04:00
2006-02-04 01:19:41 +03:00
/* This was ours, but it was neither mapped nor
* algorithmic . Fail */
return False ;
2003-08-28 00:52:56 +04:00
}
2006-02-04 01:19:41 +03:00
if ( winbind_lookup_sid ( NULL , psid , NULL , NULL , & type ) ) {
if ( type ! = SID_NAME_USER ) {
DEBUG ( 10 , ( " sid_to_uid: sid %s is a %s \n " ,
sid_string_static ( psid ) ,
sid_type_lookup ( type ) ) ) ;
return False ;
}
2003-08-28 00:52:56 +04:00
2006-02-04 01:19:41 +03:00
if ( ! winbind_sid_to_uid ( puid , psid ) ) {
DEBUG ( 5 , ( " sid_to_uid: winbind failed to allocate a "
" new uid for sid %s \n " ,
sid_string_static ( psid ) ) ) ;
return False ;
}
goto done ;
2003-08-28 00:52:56 +04:00
}
2006-02-04 01:19:41 +03:00
/* TODO: Here would be the place to allocate both a gid and a uid for
* the SID in question */
return False ;
done :
2005-12-03 21:34:13 +03:00
DEBUG ( 10 , ( " sid_to_uid: %s -> %u \n " , sid_string_static ( psid ) ,
2003-08-28 00:52:56 +04:00
( unsigned int ) * puid ) ) ;
store_uid_sid_cache ( psid , * puid ) ;
2006-02-04 01:19:41 +03:00
return True ;
2003-08-28 00:52:56 +04:00
}
2006-02-04 01:19:41 +03:00
2003-08-28 00:52:56 +04:00
/*****************************************************************
* THE CANONICAL * convert SID to gid function .
Group mapping is used for gids that maps to Wellknown SIDs
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-02-04 01:19:41 +03:00
BOOL sid_to_gid ( const DOM_SID * psid , gid_t * pgid )
2003-08-28 00:52:56 +04:00
{
2006-02-04 01:19:41 +03:00
uint32 rid ;
GROUP_MAP map ;
union unid_t id ;
enum SID_NAME_USE type ;
uid_t uid ;
2003-08-28 00:52:56 +04:00
if ( fetch_gid_from_cache ( pgid , psid ) )
2006-02-04 01:19:41 +03:00
return True ;
2003-08-28 00:52:56 +04:00
2006-02-04 01:19:41 +03:00
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 ;
goto done ;
}
2006-03-02 21:33:43 +03:00
if ( ( sid_check_is_in_builtin ( psid ) | |
sid_check_is_in_wellknown_domain ( psid ) ) ) {
if ( pdb_getgrsid ( & map , * psid ) ) {
* pgid = map . gid ;
goto done ;
}
return False ;
2006-02-04 01:19:41 +03:00
}
2003-08-28 00:52:56 +04:00
2006-02-04 01:19:41 +03:00
if ( sid_peek_check_rid ( get_global_sam_sid ( ) , psid , & rid ) ) {
if ( pdb_sid_to_id ( psid , & id , & type ) ) {
if ( ( type ! = SID_NAME_DOM_GRP ) & &
( type ! = SID_NAME_ALIAS ) ) {
DEBUG ( 5 , ( " sid %s is a %s, expected a group \n " ,
sid_string_static ( psid ) ,
sid_type_lookup ( type ) ) ) ;
return False ;
}
* pgid = id . gid ;
goto done ;
}
if ( pdb_rid_algorithm ( ) & &
! algorithmic_pdb_rid_is_user ( rid ) ) {
/* This must be a group, presented as alias */
* pgid = pdb_group_rid_to_gid ( rid ) ;
goto done ;
}
/* This was ours, but it was neither mapped nor
* algorithmic . Fail . */
return False ;
}
2004-05-28 12:57:00 +04:00
2006-02-04 01:19:41 +03:00
if ( ! winbind_lookup_sid ( NULL , psid , NULL , NULL , & type ) ) {
DEBUG ( 11 , ( " sid_to_gid: no one knows the SID %s (tried local, "
" then winbind) \n " , sid_string_static ( psid ) ) ) ;
2003-08-28 00:52:56 +04:00
2006-02-04 01:19:41 +03:00
return False ;
2003-08-28 00:52:56 +04:00
}
/* winbindd knows it; Ensure this is a group sid */
2006-02-04 01:19:41 +03:00
if ( ( type ! = SID_NAME_DOM_GRP ) & & ( type ! = SID_NAME_ALIAS ) & &
( type ! = SID_NAME_WKN_GRP ) ) {
DEBUG ( 10 , ( " sid_to_gid: winbind lookup succeeded but SID is "
" a %s \n " , sid_type_lookup ( type ) ) ) ;
return False ;
2003-08-28 00:52:56 +04:00
}
/* 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 ) ) {
2006-02-04 01:19:41 +03:00
DEBUG ( 10 , ( " sid_to_gid: winbind failed to allocate a new gid "
" for sid %s \n " , sid_string_static ( psid ) ) ) ;
return False ;
2003-08-28 00:52:56 +04:00
}
2006-02-04 01:19:41 +03:00
done :
2005-12-03 21:34:13 +03:00
DEBUG ( 10 , ( " sid_to_gid: %s -> %u \n " , sid_string_static ( psid ) ,
( unsigned int ) * pgid ) ) ;
2003-08-28 00:52:56 +04:00
store_gid_sid_cache ( psid , * pgid ) ;
2006-02-04 01:19:41 +03:00
return True ;
2003-08-28 00:52:56 +04:00
}