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 ,
2006-09-08 18:28:06 +04:00
DOM_SID * ret_sid , enum lsa_SidType * 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 ;
2006-09-08 18:28:06 +04:00
enum lsa_SidType type ;
2005-12-10 14:22:01 +03:00
TALLOC_CTX * tmp_ctx = talloc_new ( mem_ctx ) ;
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
}
2006-08-05 00:39:37 +04:00
DEBUG ( 10 , ( " lookup_name: %s => %s (domain), %s (name) \n " ,
full_name , domain , name ) ) ;
2005-12-03 21:34:13 +03:00
if ( ( domain = = NULL ) | | ( name = = NULL ) ) {
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
2006-07-11 22:01:26 +04:00
TALLOC_FREE ( tmp_ctx ) ;
2005-12-03 21:34:13 +03:00
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
}
2006-07-11 22:01:26 +04:00
TALLOC_FREE ( tmp_ctx ) ;
return False ;
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
}
2006-07-11 22:01:26 +04:00
TALLOC_FREE ( tmp_ctx ) ;
return False ;
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 ;
}
2006-07-11 22:01:26 +04:00
TALLOC_FREE ( tmp_ctx ) ;
return False ;
2006-02-04 01:19:41 +03:00
}
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 ;
}
2006-07-11 22:01:26 +04:00
TALLOC_FREE ( tmp_ctx ) ;
return False ;
2005-12-03 21:34:13 +03:00
}
2006-02-04 01:19:41 +03:00
if ( ( domain [ 0 ] = = ' \0 ' ) & & ( ! ( flags & LOOKUP_NAME_ISOLATED ) ) ) {
2006-07-11 22:01:26 +04:00
TALLOC_FREE ( tmp_ctx ) ;
return False ;
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 " ) ) ;
2006-07-11 22:01:26 +04:00
TALLOC_FREE ( tmp_ctx ) ;
return False ;
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 " ) ) ;
2006-07-11 22:01:26 +04:00
TALLOC_FREE ( tmp_ctx ) ;
return False ;
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 ) ) {
2006-07-11 22:01:26 +04:00
TALLOC_FREE ( tmp_ctx ) ;
return False ;
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 ;
2006-09-08 18:28:06 +04:00
enum lsa_SidType domain_type ;
2005-12-03 21:34:13 +03:00
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 " ) ) ;
2006-07-11 22:01:26 +04:00
TALLOC_FREE ( tmp_ctx ) ;
return False ;
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 ;
}
2006-07-11 22:01:26 +04:00
/*
* Ok , all possibilities tried . Fail .
*/
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 ;
}
2006-07-11 22:01:26 +04:00
/*
* Hand over the results to the talloc context we ' ve been given .
*/
if ( ( ret_name ! = NULL ) & &
! ( * ret_name = talloc_strdup ( mem_ctx , name ) ) ) {
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
TALLOC_FREE ( tmp_ctx ) ;
return False ;
2005-12-03 21:34:13 +03:00
}
if ( ret_domain ! = NULL ) {
2006-07-11 22:01:26 +04:00
char * tmp_dom ;
2006-07-16 00:39:00 +04:00
if ( ! ( tmp_dom = talloc_strdup ( mem_ctx , domain ) ) ) {
2006-07-11 22:01:26 +04:00
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
TALLOC_FREE ( tmp_ctx ) ;
return False ;
}
2005-12-10 14:22:01 +03:00
strupper_m ( tmp_dom ) ;
2006-07-11 22:01:26 +04:00
* ret_domain = 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-08-05 00:35:52 +04:00
/************************************************************************
Names from smb . conf can be unqualified . eg . valid users = foo
2006-08-05 00:43:21 +04:00
These names should never map to a remote name . Try global_sam_name ( ) \ foo ,
2006-08-05 00:35:52 +04:00
and then " Unix Users " \ foo ( or " Unix Groups " \ foo ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL lookup_name_smbconf ( TALLOC_CTX * mem_ctx ,
const char * full_name , int flags ,
const char * * ret_domain , const char * * ret_name ,
2006-09-08 18:28:06 +04:00
DOM_SID * ret_sid , enum lsa_SidType * ret_type )
2006-08-05 00:35:52 +04:00
{
char * qualified_name ;
2006-08-05 01:15:52 +04:00
const char * p ;
2006-08-05 00:35:52 +04:00
/* NB. No winbindd_separator here as lookup_name needs \\' */
2006-08-05 01:15:52 +04:00
if ( ( p = strchr_m ( full_name , * lp_winbind_separator ( ) ) ) ! = NULL ) {
2006-08-05 01:07:32 +04:00
2006-08-05 00:35:52 +04:00
/* The name is already qualified with a domain. */
2006-08-05 01:07:32 +04:00
if ( * lp_winbind_separator ( ) ! = ' \\ ' ) {
2006-08-05 01:15:52 +04:00
char * tmp ;
2006-08-05 01:07:32 +04:00
/* lookup_name() needs '\\' as a separator */
tmp = talloc_strdup ( mem_ctx , full_name ) ;
if ( ! tmp ) {
return False ;
}
2006-08-05 01:15:52 +04:00
tmp [ p - full_name ] = ' \\ ' ;
2006-08-05 01:07:32 +04:00
full_name = tmp ;
}
2006-08-05 00:35:52 +04:00
return lookup_name ( mem_ctx , full_name , flags ,
ret_domain , ret_name ,
ret_sid , ret_type ) ;
}
2006-08-05 00:43:21 +04:00
/* Try with our own SAM name. */
2006-08-05 00:35:52 +04:00
qualified_name = talloc_asprintf ( mem_ctx , " %s \\ %s " ,
2006-08-05 00:43:21 +04:00
get_global_sam_name ( ) ,
2006-08-05 00:35:52 +04:00
full_name ) ;
if ( ! qualified_name ) {
return False ;
}
if ( lookup_name ( mem_ctx , qualified_name , flags ,
ret_domain , ret_name ,
ret_sid , ret_type ) ) {
return True ;
}
/* Finally try with "Unix Users" or "Unix Group" */
qualified_name = talloc_asprintf ( mem_ctx , " %s \\ %s " ,
flags & LOOKUP_NAME_GROUP ?
unix_groups_domain_name ( ) :
unix_users_domain_name ( ) ,
full_name ) ;
if ( ! qualified_name ) {
return False ;
}
return lookup_name ( mem_ctx , qualified_name , flags ,
ret_domain , ret_name ,
ret_sid , ret_type ) ;
}
2006-07-11 22:01:26 +04:00
static BOOL wb_lookup_rids ( TALLOC_CTX * mem_ctx ,
const DOM_SID * domain_sid ,
int num_rids , uint32 * rids ,
const char * * domain_name ,
2006-09-08 18:28:06 +04:00
const char * * names , enum lsa_SidType * types )
2006-02-04 01:19:41 +03:00
{
int i ;
2006-07-11 22:01:26 +04:00
const char * * my_names ;
2006-09-08 18:28:06 +04:00
enum lsa_SidType * my_types ;
2006-07-11 22:01:26 +04:00
TALLOC_CTX * tmp_ctx ;
2006-02-04 01:19:41 +03:00
2006-07-11 22:01:26 +04:00
if ( ! ( tmp_ctx = talloc_init ( " wb_lookup_rids " ) ) ) {
return False ;
}
2006-02-04 01:19:41 +03:00
2006-07-11 22:01:26 +04:00
if ( ! winbind_lookup_rids ( tmp_ctx , domain_sid , num_rids , rids ,
domain_name , & my_names , & my_types ) ) {
for ( i = 0 ; i < num_rids ; i + + ) {
2006-02-04 01:19:41 +03:00
types [ i ] = SID_NAME_UNKNOWN ;
}
2006-07-11 22:01:26 +04:00
return True ;
}
/*
* winbind_lookup_rids allocates its own array . We ' ve been given the
* array , so copy it over
*/
for ( i = 0 ; i < num_rids ; i + + ) {
if ( my_names [ i ] = = NULL ) {
TALLOC_FREE ( tmp_ctx ) ;
return False ;
}
if ( ! ( names [ i ] = talloc_strdup ( names , my_names [ i ] ) ) ) {
TALLOC_FREE ( tmp_ctx ) ;
return False ;
}
types [ i ] = my_types [ i ] ;
2006-02-04 01:19:41 +03:00
}
2006-07-11 22:01:26 +04:00
TALLOC_FREE ( tmp_ctx ) ;
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
static BOOL lookup_rids ( TALLOC_CTX * mem_ctx , const DOM_SID * domain_sid ,
int num_rids , uint32_t * rids ,
const char * * domain_name ,
2006-09-08 18:28:06 +04:00
const char * * * names , enum lsa_SidType * * 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 ) ;
2006-09-08 18:28:06 +04:00
* types = TALLOC_ARRAY ( mem_ctx , enum lsa_SidType , 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 ;
}
2006-09-14 20:02:58 +04:00
become_root_uid_only ( ) ;
2006-02-04 01:19:41 +03:00
result = pdb_lookup_rids ( domain_sid , num_rids , rids ,
* names , * types ) ;
2006-09-14 20:02:58 +04:00
unbecome_root_uid_only ( ) ;
2006-02-04 01:19:41 +03:00
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 ;
}
2006-07-11 22:01:26 +04:00
return wb_lookup_rids ( mem_ctx , domain_sid , num_rids , rids ,
domain_name , * names , * types ) ;
2006-02-04 01:19:41 +03:00
}
/*
* 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 ;
2006-09-08 18:28:06 +04:00
enum lsa_SidType type ;
2006-02-04 01:19:41 +03:00
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 ;
2006-07-11 22:01:26 +04:00
if ( ! ( tmp_ctx = talloc_new ( mem_ctx ) ) ) {
2006-02-04 01:19:41 +03:00
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-07-11 22:01:26 +04:00
name_infos = TALLOC_ARRAY ( mem_ctx , struct lsa_name_info , num_sids ) ;
dom_infos = TALLOC_ZERO_ARRAY ( mem_ctx , struct lsa_dom_info ,
2006-02-04 01:19:41 +03:00
MAX_REF_DOMAINS ) ;
if ( ( name_infos = = NULL ) | | ( dom_infos = = NULL ) ) {
result = NT_STATUS_NO_MEMORY ;
2006-07-11 22:01:26 +04:00
goto fail ;
2006-02-04 01:19:41 +03:00
}
/* 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 ;
2006-07-11 22:01:26 +04:00
goto fail ;
2006-02-04 01:19:41 +03:00
}
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 ;
2006-07-11 22:01:26 +04:00
goto fail ;
2006-02-04 01:19:41 +03:00
}
}
} else {
/* This is a normal SID with rid component */
if ( ! sid_split_rid ( & sid , & rid ) ) {
result = NT_STATUS_INVALID_PARAMETER ;
2006-07-11 22:01:26 +04:00
goto fail ;
2006-02-04 01:19:41 +03:00
}
}
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 ;
2006-07-11 22:01:26 +04:00
goto fail ;
2006-02-04 01:19:41 +03:00
}
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 =
2006-07-11 22:01:26 +04:00
talloc_strdup ( dom_infos , domain_name ) ;
if ( dom_infos [ j ] . name = = NULL ) {
result = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2006-02-04 01:19:41 +03:00
} 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 ;
2006-07-11 22:01:26 +04:00
goto fail ;
2006-02-04 01:19:41 +03:00
}
}
}
/* Iterate over the domains found */
for ( i = 0 ; i < MAX_REF_DOMAINS ; i + + ) {
uint32_t * rids ;
2006-07-11 22:01:26 +04:00
const char * domain_name = NULL ;
2006-02-04 01:19:41 +03:00
const char * * names ;
2006-09-08 18:28:06 +04:00
enum lsa_SidType * types ;
2006-02-04 01:19:41 +03:00
struct lsa_dom_info * dom = & dom_infos [ i ] ;
if ( ! dom - > valid ) {
/* No domains left, we're done */
break ;
}
2006-07-11 22:01:26 +04:00
if ( ! ( rids = TALLOC_ARRAY ( tmp_ctx , uint32 , dom - > num_idxs ) ) ) {
2006-02-04 01:19:41 +03:00
result = NT_STATUS_NO_MEMORY ;
2006-07-11 22:01:26 +04:00
goto fail ;
2006-02-04 01:19:41 +03:00
}
for ( j = 0 ; j < dom - > num_idxs ; j + + ) {
rids [ j ] = name_infos [ dom - > idxs [ j ] ] . rid ;
}
if ( ! lookup_rids ( tmp_ctx , & dom - > sid ,
2006-07-11 22:01:26 +04:00
dom - > num_idxs , rids , & domain_name ,
2006-02-04 01:19:41 +03:00
& names , & types ) ) {
result = NT_STATUS_NO_MEMORY ;
2006-07-11 22:01:26 +04:00
goto fail ;
2006-02-04 01:19:41 +03:00
}
2006-07-11 22:01:26 +04:00
if ( ! ( dom - > name = talloc_strdup ( dom_infos , domain_name ) ) ) {
result = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2006-02-04 01:19:41 +03:00
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 =
2006-07-11 22:01:26 +04:00
talloc_strdup ( name_infos , names [ j ] ) ;
if ( name_infos [ idx ] . name = = NULL ) {
result = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2006-02-04 01:19:41 +03:00
} else {
name_infos [ idx ] . name = NULL ;
}
}
}
2006-07-11 22:01:26 +04:00
* ret_domains = dom_infos ;
* ret_names = name_infos ;
return NT_STATUS_OK ;
2006-02-04 01:19:41 +03:00
2006-07-11 22:01:26 +04:00
fail :
TALLOC_FREE ( dom_infos ) ;
TALLOC_FREE ( name_infos ) ;
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 ,
2006-09-08 18:28:06 +04:00
enum lsa_SidType * ret_type )
2006-02-04 01:19:41 +03:00
{
struct lsa_dom_info * domain ;
struct lsa_name_info * name ;
TALLOC_CTX * tmp_ctx ;
BOOL ret = False ;
2006-07-11 22:01:26 +04:00
if ( ! ( tmp_ctx = talloc_new ( mem_ctx ) ) ) {
2006-02-04 01:19:41 +03:00
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 ;
}
2006-07-11 22:01:26 +04:00
if ( ( ret_domain ! = NULL ) & &
! ( * ret_domain = talloc_strdup ( mem_ctx , domain - > name ) ) ) {
goto done ;
2005-12-03 21:34:13 +03:00
}
2006-07-11 22:01:26 +04:00
if ( ( ret_name ! = NULL ) & &
! ( * ret_name = talloc_strdup ( mem_ctx , name - > name ) ) ) {
goto done ;
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 ;
2006-09-08 18:28:06 +04:00
enum lsa_SidType sidtype ;
2003-08-28 00:52:56 +04:00
} * uid_sid_cache_head ;
static struct gid_sid_cache {
struct gid_sid_cache * next , * prev ;
gid_t gid ;
DOM_SID sid ;
2006-09-08 18:28:06 +04:00
enum lsa_SidType sidtype ;
2003-08-28 00:52:56 +04:00
} * 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 ;
2006-08-31 22:32:23 +04:00
/* do not store SIDs in the "Unix Group" domain */
if ( sid_check_is_in_unix_users ( psid ) )
return ;
2003-08-28 00:52:56 +04:00
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 ;
2006-08-31 22:32:23 +04:00
/* do not store SIDs in the "Unix Group" domain */
if ( sid_check_is_in_unix_groups ( psid ) )
return ;
2003-08-28 00:52:56 +04:00
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 ;
2006-09-13 20:30:40 +04:00
BOOL ret ;
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-11-06 22:46:50 +03:00
if ( ( lp_winbind_trusted_domains_only ( ) | |
( lp_idmap_uid ( & low , & high ) & & ( uid > = low ) & & ( uid < = high ) ) ) & &
2006-02-04 01:19:41 +03:00
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-09-14 20:02:58 +04:00
become_root_uid_only ( ) ;
2006-09-13 20:30:40 +04:00
ret = pdb_uid_to_rid ( uid , & rid ) ;
2006-09-14 20:02:58 +04:00
unbecome_root_uid_only ( ) ;
2006-09-13 20:30:40 +04:00
if ( ret ) {
2006-02-04 01:19:41 +03:00
/* 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-08-22 00:04:01 +04:00
/* This is an unmapped user */
uid_to_unix_users_sid ( uid , psid ) ;
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
{
2006-09-13 20:30:40 +04:00
BOOL ret ;
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-11-06 22:46:50 +03:00
if ( ( lp_winbind_trusted_domains_only ( ) | |
( lp_idmap_gid ( & low , & high ) & & ( gid > = low ) & & ( gid < = high ) ) ) & &
2006-02-04 01:19:41 +03:00
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-09-14 20:02:58 +04:00
become_root_uid_only ( ) ;
2006-09-13 20:30:40 +04:00
ret = pdb_gid_to_sid ( gid , psid ) ;
2006-09-14 20:02:58 +04:00
unbecome_root_uid_only ( ) ;
2006-09-13 20:30:40 +04:00
if ( ret ) {
2006-02-04 01:19:41 +03:00
/* This is a mapped group */
goto done ;
2003-08-28 00:52:56 +04:00
}
2006-08-22 00:04:01 +04:00
/* This is an unmapped group */
2003-08-28 00:52:56 +04:00
2006-08-22 19:18:13 +04:00
gid_to_unix_groups_sid ( gid , psid ) ;
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-09-08 18:28:06 +04:00
enum lsa_SidType type ;
2006-02-04 01:19:41 +03:00
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 ;
2006-09-13 20:30:40 +04:00
BOOL ret ;
2006-02-04 01:19:41 +03:00
2006-09-14 20:02:58 +04:00
become_root_uid_only ( ) ;
2006-09-13 20:30:40 +04:00
ret = pdb_sid_to_id ( psid , & id , & type ) ;
2006-09-14 20:02:58 +04:00
unbecome_root_uid_only ( ) ;
2006-09-13 20:30:40 +04:00
if ( ret ) {
2006-02-04 01:19:41 +03:00
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 ;
}
2003-08-28 00:52:56 +04:00
2006-08-22 00:04:01 +04:00
/* This was ours, but it was not mapped. Fail */
2006-02-04 01:19:41 +03:00
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 ;
2006-09-08 18:28:06 +04:00
enum lsa_SidType type ;
2006-02-04 01:19:41 +03:00
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 ) ) ) {
2006-09-13 20:30:40 +04:00
BOOL ret ;
2006-09-14 20:02:58 +04:00
become_root_uid_only ( ) ;
2006-09-13 20:30:40 +04:00
ret = pdb_getgrsid ( & map , * psid ) ;
2006-09-14 20:02:58 +04:00
unbecome_root_uid_only ( ) ;
2006-09-13 20:30:40 +04:00
if ( ret ) {
2006-03-02 21:33:43 +03:00
* 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 ) ) {
2006-09-13 20:30:40 +04:00
BOOL ret ;
2006-09-14 20:02:58 +04:00
become_root_uid_only ( ) ;
2006-09-13 20:30:40 +04:00
ret = pdb_sid_to_id ( psid , & id , & type ) ;
2006-09-14 20:02:58 +04:00
unbecome_root_uid_only ( ) ;
2006-09-13 20:30:40 +04:00
if ( ret ) {
2006-02-04 01:19:41 +03:00
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 ;
}
2006-08-22 00:04:01 +04:00
/* This was ours, but it was not mapped. Fail */
2006-02-04 01:19:41 +03:00
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
}