2001-12-03 09:04:18 +03:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
2001-12-03 09:04:18 +03:00
Winbind ADS backend functions
Copyright ( C ) Andrew Tridgell 2001
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 "winbindd.h"
# ifdef HAVE_ADS
2002-07-15 14:35:28 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_WINBIND
2001-12-19 11:44:23 +03:00
/* the realm of our primary LDAP server */
static char * primary_realm ;
2001-12-05 10:05:53 +03:00
/*
return our ads connections structure for a domain . We keep the connection
open to make things faster
*/
static ADS_STRUCT * ads_cached_connection ( struct winbindd_domain * domain )
{
ADS_STRUCT * ads ;
2001-12-19 15:21:12 +03:00
ADS_STATUS status ;
2001-12-11 01:10:16 +03:00
char * ccache ;
2001-12-05 10:05:53 +03:00
if ( domain - > private ) {
return ( ADS_STRUCT * ) domain - > private ;
}
2001-12-11 01:10:16 +03:00
/* we don't want this to affect the users ccache */
ccache = lock_path ( " winbindd_ccache " ) ;
2001-12-11 09:17:01 +03:00
SETENV ( " KRB5CCNAME " , ccache , 1 ) ;
2001-12-11 01:10:16 +03:00
unlink ( ccache ) ;
2002-08-17 21:00:51 +04:00
ads = ads_init ( domain - > alt_name , domain - > name , NULL ) ;
2001-12-05 10:05:53 +03:00
if ( ! ads ) {
DEBUG ( 1 , ( " ads_init for domain %s failed \n " , domain - > name ) ) ;
return NULL ;
}
2001-12-08 14:18:56 +03:00
/* the machine acct password might have change - fetch it every time */
2002-08-17 21:00:51 +04:00
SAFE_FREE ( ads - > auth . password ) ;
ads - > auth . password = secrets_fetch_machine_password ( ) ;
if ( primary_realm ) {
SAFE_FREE ( ads - > auth . realm ) ;
ads - > auth . realm = strdup ( primary_realm ) ;
}
2001-12-08 14:18:56 +03:00
2001-12-19 15:21:12 +03:00
status = ads_connect ( ads ) ;
2002-08-17 21:00:51 +04:00
if ( ! ADS_ERR_OK ( status ) | | ! ads - > config . realm ) {
2001-12-19 15:38:52 +03:00
extern struct winbindd_methods msrpc_methods ;
2001-12-19 15:21:12 +03:00
DEBUG ( 1 , ( " ads_connect for domain %s failed: %s \n " ,
domain - > name , ads_errstr ( status ) ) ) ;
2001-12-05 10:05:53 +03:00
ads_destroy ( & ads ) ;
2001-12-19 15:38:52 +03:00
/* if we get ECONNREFUSED then it might be a NT4
server , fall back to MSRPC */
if ( status . error_type = = ADS_ERROR_SYSTEM & &
2002-09-25 19:19:00 +04:00
status . err . rc = = ECONNREFUSED ) {
2001-12-19 15:38:52 +03:00
DEBUG ( 1 , ( " Trying MSRPC methods \n " ) ) ;
domain - > methods = & msrpc_methods ;
}
2001-12-05 10:05:53 +03:00
return NULL ;
}
2001-12-19 11:44:23 +03:00
/* remember our primary realm for trusted domain support */
if ( ! primary_realm ) {
2002-08-17 21:00:51 +04:00
primary_realm = strdup ( ads - > config . realm ) ;
2001-12-19 11:44:23 +03:00
}
2001-12-05 10:05:53 +03:00
domain - > private = ( void * ) ads ;
return ads ;
}
2001-12-05 07:48:51 +03:00
/* useful utility */
static void sid_from_rid ( struct winbindd_domain * domain , uint32 rid , DOM_SID * sid )
{
sid_copy ( sid , & domain - > sid ) ;
sid_append_rid ( sid , rid ) ;
}
2002-07-15 14:35:28 +04:00
2001-12-03 09:04:18 +03:00
/* Query display info for a realm. This is the basic user list fn */
2001-12-03 14:32:55 +03:00
static NTSTATUS query_user_list ( struct winbindd_domain * domain ,
2001-12-03 09:04:18 +03:00
TALLOC_CTX * mem_ctx ,
2001-12-11 03:03:58 +03:00
uint32 * num_entries ,
2001-12-03 14:32:55 +03:00
WINBIND_USERINFO * * info )
2001-12-03 09:04:18 +03:00
{
2001-12-05 09:16:33 +03:00
ADS_STRUCT * ads = NULL ;
2002-07-15 14:35:28 +04:00
const char * attrs [ ] = { " userPrincipalName " ,
" sAMAccountName " ,
" name " , " objectSid " , " primaryGroupID " ,
2001-12-09 09:10:02 +03:00
" sAMAccountType " , NULL } ;
2001-12-19 15:21:12 +03:00
int i , count ;
ADS_STATUS rc ;
2001-12-05 09:16:33 +03:00
void * res = NULL ;
void * msg = NULL ;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL ;
2001-12-03 09:04:18 +03:00
2001-12-11 01:10:16 +03:00
* num_entries = 0 ;
2001-12-03 14:32:55 +03:00
DEBUG ( 3 , ( " ads: query_user_list \n " ) ) ;
2001-12-03 09:04:18 +03:00
2001-12-05 10:05:53 +03:00
ads = ads_cached_connection ( domain ) ;
if ( ! ads ) goto done ;
2001-12-03 09:04:18 +03:00
2001-12-10 09:21:44 +03:00
rc = ads_search_retry ( ads , & res , " (objectCategory=user) " , attrs ) ;
2001-12-19 15:21:12 +03:00
if ( ! ADS_ERR_OK ( rc ) ) {
2001-12-03 14:32:55 +03:00
DEBUG ( 1 , ( " query_user_list ads_search: %s \n " , ads_errstr ( rc ) ) ) ;
2001-12-05 09:16:33 +03:00
goto done ;
2001-12-03 09:04:18 +03:00
}
count = ads_count_replies ( ads , res ) ;
if ( count = = 0 ) {
2001-12-03 14:32:55 +03:00
DEBUG ( 1 , ( " query_user_list: No users found \n " ) ) ;
2001-12-05 09:16:33 +03:00
goto done ;
2001-12-03 09:04:18 +03:00
}
2002-04-11 18:30:31 +04:00
( * info ) = talloc_zero ( mem_ctx , count * sizeof ( * * info ) ) ;
2001-12-05 09:16:33 +03:00
if ( ! * info ) {
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
2001-12-03 09:04:18 +03:00
i = 0 ;
for ( msg = ads_first_entry ( ads , res ) ; msg ; msg = ads_next_entry ( ads , msg ) ) {
char * name , * gecos ;
DOM_SID sid ;
uint32 rid , group ;
2001-12-09 09:10:02 +03:00
uint32 atype ;
2001-12-03 09:04:18 +03:00
2001-12-09 09:10:02 +03:00
if ( ! ads_pull_uint32 ( ads , msg , " sAMAccountType " , & atype ) | |
ads_atype_map ( atype ) ! = SID_NAME_USER ) {
DEBUG ( 1 , ( " Not a user account? atype=0x%x \n " , atype ) ) ;
continue ;
}
2001-12-03 09:04:18 +03:00
2002-10-01 22:26:00 +04:00
name = ads_pull_username ( ads , mem_ctx , msg ) ;
2001-12-03 09:04:18 +03:00
gecos = ads_pull_string ( ads , mem_ctx , msg , " name " ) ;
if ( ! ads_pull_sid ( ads , msg , " objectSid " , & sid ) ) {
DEBUG ( 1 , ( " No sid for %s !? \n " , name ) ) ;
continue ;
}
if ( ! ads_pull_uint32 ( ads , msg , " primaryGroupID " , & group ) ) {
DEBUG ( 1 , ( " No primary group for %s !? \n " , name ) ) ;
continue ;
}
2002-07-15 14:35:28 +04:00
if ( ! sid_peek_check_rid ( & domain - > sid , & sid , & rid ) ) {
2001-12-03 09:04:18 +03:00
DEBUG ( 1 , ( " No rid for %s !? \n " , name ) ) ;
continue ;
}
( * info ) [ i ] . acct_name = name ;
( * info ) [ i ] . full_name = gecos ;
( * info ) [ i ] . user_rid = rid ;
( * info ) [ i ] . group_rid = group ;
i + + ;
}
( * num_entries ) = i ;
2001-12-05 09:16:33 +03:00
status = NT_STATUS_OK ;
2001-12-03 09:04:18 +03:00
2001-12-09 09:10:02 +03:00
DEBUG ( 3 , ( " ads query_user_list gave %d entries \n " , ( * num_entries ) ) ) ;
2001-12-05 09:16:33 +03:00
done :
if ( res ) ads_msgfree ( ads , res ) ;
2001-12-03 09:04:18 +03:00
2001-12-05 09:16:33 +03:00
return status ;
2001-12-03 09:04:18 +03:00
}
/* list all domain groups */
static NTSTATUS enum_dom_groups ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
2001-12-11 04:04:13 +03:00
uint32 * num_entries ,
2001-12-03 09:04:18 +03:00
struct acct_info * * info )
{
2001-12-05 09:16:33 +03:00
ADS_STRUCT * ads = NULL ;
2002-07-15 14:35:28 +04:00
const char * attrs [ ] = { " userPrincipalName " , " sAMAccountName " ,
" name " , " objectSid " ,
2001-12-03 09:04:18 +03:00
" sAMAccountType " , NULL } ;
2001-12-19 15:21:12 +03:00
int i , count ;
ADS_STATUS rc ;
2001-12-05 09:16:33 +03:00
void * res = NULL ;
void * msg = NULL ;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL ;
2002-11-15 20:57:21 +03:00
uint32 group_flags ;
2001-12-03 09:04:18 +03:00
2001-12-11 01:10:16 +03:00
* num_entries = 0 ;
2001-12-03 09:04:18 +03:00
DEBUG ( 3 , ( " ads: enum_dom_groups \n " ) ) ;
2001-12-05 10:05:53 +03:00
ads = ads_cached_connection ( domain ) ;
if ( ! ads ) goto done ;
2001-12-03 09:04:18 +03:00
2001-12-10 09:21:44 +03:00
rc = ads_search_retry ( ads , & res , " (objectCategory=group) " , attrs ) ;
2001-12-19 15:21:12 +03:00
if ( ! ADS_ERR_OK ( rc ) ) {
2002-07-15 14:35:28 +04:00
DEBUG ( 1 , ( " enum_dom_groups ads_search: %s \n " , ads_errstr ( rc ) ) ) ;
2001-12-05 09:16:33 +03:00
goto done ;
2001-12-03 09:04:18 +03:00
}
count = ads_count_replies ( ads , res ) ;
if ( count = = 0 ) {
2002-07-15 14:35:28 +04:00
DEBUG ( 1 , ( " enum_dom_groups: No groups found \n " ) ) ;
2001-12-05 09:16:33 +03:00
goto done ;
2001-12-03 09:04:18 +03:00
}
2002-04-11 18:30:31 +04:00
( * info ) = talloc_zero ( mem_ctx , count * sizeof ( * * info ) ) ;
2001-12-05 09:16:33 +03:00
if ( ! * info ) {
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
2001-12-03 09:04:18 +03:00
i = 0 ;
2002-11-15 20:57:21 +03:00
group_flags = ATYPE_GLOBAL_GROUP ;
if ( domain - > native_mode )
group_flags | = ATYPE_LOCAL_GROUP ;
2001-12-03 09:04:18 +03:00
for ( msg = ads_first_entry ( ads , res ) ; msg ; msg = ads_next_entry ( ads , msg ) ) {
char * name , * gecos ;
DOM_SID sid ;
uint32 rid ;
uint32 account_type ;
2002-11-15 20:57:21 +03:00
if ( ! ads_pull_uint32 ( ads , msg , " sAMAccountType " , & account_type ) | | ! ( account_type & group_flags ) )
continue ;
2002-10-01 22:26:00 +04:00
name = ads_pull_username ( ads , mem_ctx , msg ) ;
2001-12-03 09:04:18 +03:00
gecos = ads_pull_string ( ads , mem_ctx , msg , " name " ) ;
if ( ! ads_pull_sid ( ads , msg , " objectSid " , & sid ) ) {
DEBUG ( 1 , ( " No sid for %s !? \n " , name ) ) ;
continue ;
}
2002-07-15 14:35:28 +04:00
if ( ! sid_peek_check_rid ( & domain - > sid , & sid , & rid ) ) {
2001-12-03 09:04:18 +03:00
DEBUG ( 1 , ( " No rid for %s !? \n " , name ) ) ;
continue ;
}
fstrcpy ( ( * info ) [ i ] . acct_name , name ) ;
fstrcpy ( ( * info ) [ i ] . acct_desc , gecos ) ;
( * info ) [ i ] . rid = rid ;
i + + ;
}
( * num_entries ) = i ;
2001-12-05 09:16:33 +03:00
status = NT_STATUS_OK ;
2001-12-09 09:10:02 +03:00
DEBUG ( 3 , ( " ads enum_dom_groups gave %d entries \n " , ( * num_entries ) ) ) ;
2001-12-05 09:16:33 +03:00
done :
if ( res ) ads_msgfree ( ads , res ) ;
2001-12-03 09:04:18 +03:00
2001-12-05 09:16:33 +03:00
return status ;
2001-12-03 09:04:18 +03:00
}
2002-11-15 20:57:21 +03:00
/* list all domain local groups */
static NTSTATUS enum_local_groups ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
uint32 * num_entries ,
struct acct_info * * info )
{
/*
* This is a stub function only as we returned the domain
* ocal groups in enum_dom_groups ( ) if the domain - > native field
* was true . This is a simple performance optimization when
* using LDAP .
*
* if we ever need to enumerate domain local groups separately ,
* then this the optimization in enum_dom_groups ( ) will need
* to be split out
*/
* num_entries = 0 ;
return NT_STATUS_OK ;
}
2001-12-03 11:17:46 +03:00
/* convert a single name to a sid in a domain */
static NTSTATUS name_to_sid ( struct winbindd_domain * domain ,
const char * name ,
DOM_SID * sid ,
enum SID_NAME_USE * type )
{
2002-10-01 22:26:00 +04:00
ADS_STRUCT * ads ;
2001-12-05 09:16:33 +03:00
2001-12-03 11:17:46 +03:00
DEBUG ( 3 , ( " ads: name_to_sid \n " ) ) ;
2001-12-05 10:05:53 +03:00
ads = ads_cached_connection ( domain ) ;
2002-10-01 22:26:00 +04:00
if ( ! ads )
return NT_STATUS_UNSUCCESSFUL ;
2001-12-03 11:17:46 +03:00
2002-10-01 22:26:00 +04:00
return ads_name_to_sid ( ads , name , sid , type ) ;
2001-12-05 07:48:51 +03:00
}
/* convert a sid to a user or group name */
static NTSTATUS sid_to_name ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
DOM_SID * sid ,
char * * name ,
enum SID_NAME_USE * type )
{
2001-12-05 09:16:33 +03:00
ADS_STRUCT * ads = NULL ;
2001-12-05 07:48:51 +03:00
DEBUG ( 3 , ( " ads: sid_to_name \n " ) ) ;
2001-12-05 10:05:53 +03:00
ads = ads_cached_connection ( domain ) ;
2002-10-01 22:26:00 +04:00
if ( ! ads )
return NT_STATUS_UNSUCCESSFUL ;
2001-12-05 07:48:51 +03:00
2002-10-01 22:26:00 +04:00
return ads_sid_to_name ( ads , mem_ctx , sid , name , type ) ;
2001-12-03 11:17:46 +03:00
}
2001-12-05 07:48:51 +03:00
2002-07-15 14:35:28 +04:00
/* convert a DN to a name, rid and name type
this might become a major speed bottleneck if groups have
lots of users , in which case we could cache the results
*/
static BOOL dn_lookup ( ADS_STRUCT * ads , TALLOC_CTX * mem_ctx ,
const char * dn ,
char * * name , uint32 * name_type , uint32 * rid )
{
char * exp ;
void * res = NULL ;
const char * attrs [ ] = { " userPrincipalName " , " sAMAccountName " ,
" objectSid " , " sAMAccountType " , NULL } ;
ADS_STATUS rc ;
uint32 atype ;
DOM_SID sid ;
asprintf ( & exp , " (distinguishedName=%s) " , dn ) ;
rc = ads_search_retry ( ads , & res , exp , attrs ) ;
free ( exp ) ;
if ( ! ADS_ERR_OK ( rc ) ) {
goto failed ;
}
2002-10-01 22:26:00 +04:00
( * name ) = ads_pull_username ( ads , mem_ctx , res ) ;
2002-07-15 14:35:28 +04:00
if ( ! ads_pull_uint32 ( ads , res , " sAMAccountType " , & atype ) ) {
goto failed ;
}
( * name_type ) = ads_atype_map ( atype ) ;
if ( ! ads_pull_sid ( ads , res , " objectSid " , & sid ) | |
! sid_peek_rid ( & sid , rid ) ) {
goto failed ;
}
if ( res ) ads_msgfree ( ads , res ) ;
return True ;
failed :
if ( res ) ads_msgfree ( ads , res ) ;
return False ;
}
2001-12-05 07:48:51 +03:00
/* Lookup user information from a rid */
2001-12-04 09:17:39 +03:00
static NTSTATUS query_user ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
2001-12-05 07:48:51 +03:00
uint32 user_rid ,
2001-12-04 09:17:39 +03:00
WINBIND_USERINFO * info )
{
2001-12-05 09:16:33 +03:00
ADS_STRUCT * ads = NULL ;
2002-07-15 14:35:28 +04:00
const char * attrs [ ] = { " userPrincipalName " ,
" sAMAccountName " ,
" name " , " objectSid " ,
2001-12-09 09:10:02 +03:00
" primaryGroupID " , NULL } ;
2001-12-19 15:21:12 +03:00
ADS_STATUS rc ;
int count ;
2001-12-05 09:16:33 +03:00
void * msg = NULL ;
2001-12-04 09:17:39 +03:00
char * exp ;
DOM_SID sid ;
2001-12-05 07:48:51 +03:00
char * sidstr ;
2001-12-05 09:16:33 +03:00
NTSTATUS status = NT_STATUS_UNSUCCESSFUL ;
2001-12-04 09:17:39 +03:00
DEBUG ( 3 , ( " ads: query_user \n " ) ) ;
2001-12-05 07:48:51 +03:00
sid_from_rid ( domain , user_rid , & sid ) ;
2001-12-05 10:05:53 +03:00
ads = ads_cached_connection ( domain ) ;
if ( ! ads ) goto done ;
2001-12-04 09:17:39 +03:00
2001-12-10 03:39:01 +03:00
sidstr = sid_binstring ( & sid ) ;
2001-12-05 07:48:51 +03:00
asprintf ( & exp , " (objectSid=%s) " , sidstr ) ;
2001-12-08 14:18:56 +03:00
rc = ads_search_retry ( ads , & msg , exp , attrs ) ;
2001-12-04 09:17:39 +03:00
free ( exp ) ;
2001-12-05 07:48:51 +03:00
free ( sidstr ) ;
2001-12-19 15:21:12 +03:00
if ( ! ADS_ERR_OK ( rc ) ) {
2001-12-05 07:48:51 +03:00
DEBUG ( 1 , ( " query_user(rid=%d) ads_search: %s \n " , user_rid , ads_errstr ( rc ) ) ) ;
2001-12-05 09:16:33 +03:00
goto done ;
2001-12-04 09:17:39 +03:00
}
count = ads_count_replies ( ads , msg ) ;
if ( count ! = 1 ) {
2001-12-05 07:48:51 +03:00
DEBUG ( 1 , ( " query_user(rid=%d): Not found \n " , user_rid ) ) ;
2001-12-05 09:16:33 +03:00
goto done ;
2001-12-04 09:17:39 +03:00
}
2002-10-01 22:26:00 +04:00
info - > acct_name = ads_pull_username ( ads , mem_ctx , msg ) ;
2001-12-04 09:17:39 +03:00
info - > full_name = ads_pull_string ( ads , mem_ctx , msg , " name " ) ;
if ( ! ads_pull_sid ( ads , msg , " objectSid " , & sid ) ) {
2001-12-05 07:48:51 +03:00
DEBUG ( 1 , ( " No sid for %d !? \n " , user_rid ) ) ;
2001-12-05 09:16:33 +03:00
goto done ;
2001-12-04 09:17:39 +03:00
}
if ( ! ads_pull_uint32 ( ads , msg , " primaryGroupID " , & info - > group_rid ) ) {
2001-12-05 07:48:51 +03:00
DEBUG ( 1 , ( " No primary group for %d !? \n " , user_rid ) ) ;
2001-12-05 09:16:33 +03:00
goto done ;
2001-12-04 09:17:39 +03:00
}
2002-07-15 14:35:28 +04:00
if ( ! sid_peek_check_rid ( & domain - > sid , & sid , & info - > user_rid ) ) {
2001-12-05 07:48:51 +03:00
DEBUG ( 1 , ( " No rid for %d !? \n " , user_rid ) ) ;
2001-12-05 09:16:33 +03:00
goto done ;
2001-12-04 09:17:39 +03:00
}
2001-12-05 09:16:33 +03:00
status = NT_STATUS_OK ;
2001-12-09 09:10:02 +03:00
DEBUG ( 3 , ( " ads query_user gave %s \n " , info - > acct_name ) ) ;
2001-12-05 09:16:33 +03:00
done :
if ( msg ) ads_msgfree ( ads , msg ) ;
2001-12-04 09:17:39 +03:00
2001-12-05 09:16:33 +03:00
return status ;
2001-12-04 09:17:39 +03:00
}
2001-12-05 09:16:33 +03:00
2001-12-04 09:46:53 +03:00
/* Lookup groups a user is a member of. */
static NTSTATUS lookup_usergroups ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
2001-12-05 07:48:51 +03:00
uint32 user_rid ,
2001-12-04 15:10:05 +03:00
uint32 * num_groups , uint32 * * user_gids )
2001-12-04 09:46:53 +03:00
{
2001-12-05 09:16:33 +03:00
ADS_STRUCT * ads = NULL ;
2001-12-04 15:10:05 +03:00
const char * attrs [ ] = { " distinguishedName " , NULL } ;
const char * attrs2 [ ] = { " tokenGroups " , " primaryGroupID " , NULL } ;
2001-12-19 15:21:12 +03:00
ADS_STATUS rc ;
int count ;
2001-12-05 09:16:33 +03:00
void * msg = NULL ;
2001-12-04 15:10:05 +03:00
char * exp ;
char * user_dn ;
DOM_SID * sids ;
int i ;
uint32 primary_group ;
2001-12-05 07:48:51 +03:00
DOM_SID sid ;
char * sidstr ;
2001-12-05 09:16:33 +03:00
NTSTATUS status = NT_STATUS_UNSUCCESSFUL ;
2001-12-04 15:10:05 +03:00
2001-12-11 01:10:16 +03:00
* num_groups = 0 ;
2001-12-04 15:10:05 +03:00
DEBUG ( 3 , ( " ads: lookup_usergroups \n " ) ) ;
( * num_groups ) = 0 ;
2001-12-05 07:48:51 +03:00
sid_from_rid ( domain , user_rid , & sid ) ;
2001-12-05 10:05:53 +03:00
ads = ads_cached_connection ( domain ) ;
if ( ! ads ) goto done ;
2001-12-04 15:10:05 +03:00
2001-12-10 03:39:01 +03:00
sidstr = sid_binstring ( & sid ) ;
2001-12-05 07:48:51 +03:00
asprintf ( & exp , " (objectSid=%s) " , sidstr ) ;
2001-12-08 14:18:56 +03:00
rc = ads_search_retry ( ads , & msg , exp , attrs ) ;
2001-12-04 15:10:05 +03:00
free ( exp ) ;
2001-12-05 07:48:51 +03:00
free ( sidstr ) ;
2001-12-19 15:21:12 +03:00
if ( ! ADS_ERR_OK ( rc ) ) {
2001-12-05 07:48:51 +03:00
DEBUG ( 1 , ( " lookup_usergroups(rid=%d) ads_search: %s \n " , user_rid , ads_errstr ( rc ) ) ) ;
2001-12-05 09:16:33 +03:00
goto done ;
2001-12-04 15:10:05 +03:00
}
user_dn = ads_pull_string ( ads , mem_ctx , msg , " distinguishedName " ) ;
2001-12-05 10:11:26 +03:00
if ( msg ) ads_msgfree ( ads , msg ) ;
2001-12-08 14:18:56 +03:00
rc = ads_search_retry_dn ( ads , & msg , user_dn , attrs2 ) ;
2001-12-19 15:21:12 +03:00
if ( ! ADS_ERR_OK ( rc ) ) {
2001-12-05 07:48:51 +03:00
DEBUG ( 1 , ( " lookup_usergroups(rid=%d) ads_search tokenGroups: %s \n " , user_rid , ads_errstr ( rc ) ) ) ;
2001-12-05 09:16:33 +03:00
goto done ;
2001-12-04 15:10:05 +03:00
}
if ( ! ads_pull_uint32 ( ads , msg , " primaryGroupID " , & primary_group ) ) {
2001-12-19 11:44:23 +03:00
DEBUG ( 1 , ( " %s: No primary group for rid=%d !? \n " , domain - > name , user_rid ) ) ;
2001-12-05 09:16:33 +03:00
goto done ;
2001-12-04 15:10:05 +03:00
}
count = ads_pull_sids ( ads , mem_ctx , msg , " tokenGroups " , & sids ) + 1 ;
2002-04-11 18:30:31 +04:00
( * user_gids ) = ( uint32 * ) talloc_zero ( mem_ctx , sizeof ( uint32 ) * count ) ;
2001-12-04 15:10:05 +03:00
( * user_gids ) [ ( * num_groups ) + + ] = primary_group ;
for ( i = 1 ; i < count ; i + + ) {
uint32 rid ;
2002-07-15 14:35:28 +04:00
if ( ! sid_peek_check_rid ( & domain - > sid , & sids [ i - 1 ] , & rid ) ) continue ;
2001-12-04 15:10:05 +03:00
( * user_gids ) [ * num_groups ] = rid ;
( * num_groups ) + + ;
}
2001-12-05 09:16:33 +03:00
status = NT_STATUS_OK ;
2001-12-09 09:10:02 +03:00
DEBUG ( 3 , ( " ads lookup_usergroups for rid=%d \n " , user_rid ) ) ;
2001-12-05 09:16:33 +03:00
done :
if ( msg ) ads_msgfree ( ads , msg ) ;
return status ;
2001-12-04 09:46:53 +03:00
}
2002-07-15 14:35:28 +04:00
/*
find the members of a group , given a group rid and domain
*/
2001-12-05 07:48:51 +03:00
static NTSTATUS lookup_groupmem ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
uint32 group_rid , uint32 * num_names ,
uint32 * * rid_mem , char * * * names ,
uint32 * * name_types )
{
2001-12-05 08:35:45 +03:00
DOM_SID group_sid ;
2001-12-19 15:21:12 +03:00
ADS_STATUS rc ;
int count ;
2002-07-15 14:35:28 +04:00
void * res = NULL ;
2001-12-05 09:16:33 +03:00
ADS_STRUCT * ads = NULL ;
2002-07-15 14:35:28 +04:00
char * exp ;
2001-12-05 09:16:33 +03:00
NTSTATUS status = NT_STATUS_UNSUCCESSFUL ;
2002-07-15 14:35:28 +04:00
char * sidstr ;
const char * attrs [ ] = { " member " , NULL } ;
char * * members ;
int i , num_members ;
2001-12-05 08:35:45 +03:00
* num_names = 0 ;
2001-12-05 10:05:53 +03:00
ads = ads_cached_connection ( domain ) ;
if ( ! ads ) goto done ;
2001-12-05 08:35:45 +03:00
sid_from_rid ( domain , group_rid , & group_sid ) ;
2002-07-15 14:35:28 +04:00
sidstr = sid_binstring ( & group_sid ) ;
2002-03-21 05:28:23 +03:00
2002-07-15 14:35:28 +04:00
/* search for all members of the group */
asprintf ( & exp , " (objectSid=%s) " , sidstr ) ;
2001-12-08 14:18:56 +03:00
rc = ads_search_retry ( ads , & res , exp , attrs ) ;
2001-12-05 09:16:33 +03:00
free ( exp ) ;
2002-07-15 14:35:28 +04:00
free ( sidstr ) ;
2001-12-19 15:21:12 +03:00
if ( ! ADS_ERR_OK ( rc ) ) {
2001-12-05 08:35:45 +03:00
DEBUG ( 1 , ( " query_user_list ads_search: %s \n " , ads_errstr ( rc ) ) ) ;
2001-12-05 09:16:33 +03:00
goto done ;
2001-12-05 08:35:45 +03:00
}
count = ads_count_replies ( ads , res ) ;
if ( count = = 0 ) {
2001-12-05 09:16:33 +03:00
status = NT_STATUS_OK ;
goto done ;
2001-12-05 08:35:45 +03:00
}
2002-07-15 14:35:28 +04:00
members = ads_pull_strings ( ads , mem_ctx , res , " member " ) ;
if ( ! members ) {
/* no members? ok ... */
status = NT_STATUS_OK ;
goto done ;
}
2001-12-05 08:35:45 +03:00
2002-07-15 14:35:28 +04:00
/* now we need to turn a list of members into rids, names and name types
the problem is that the members are in the form of distinguised names
*/
for ( i = 0 ; members [ i ] ; i + + ) /* noop */ ;
num_members = i ;
2001-12-05 08:35:45 +03:00
2002-07-15 14:35:28 +04:00
( * rid_mem ) = talloc_zero ( mem_ctx , sizeof ( uint32 ) * num_members ) ;
( * name_types ) = talloc_zero ( mem_ctx , sizeof ( uint32 ) * num_members ) ;
( * names ) = talloc_zero ( mem_ctx , sizeof ( char * ) * num_members ) ;
for ( i = 0 ; i < num_members ; i + + ) {
uint32 name_type , rid ;
char * name ;
if ( dn_lookup ( ads , mem_ctx , members [ i ] , & name , & name_type , & rid ) ) {
( * names ) [ * num_names ] = name ;
( * name_types ) [ * num_names ] = name_type ;
( * rid_mem ) [ * num_names ] = rid ;
( * num_names ) + + ;
2001-12-05 08:35:45 +03:00
}
}
2001-12-05 09:16:33 +03:00
status = NT_STATUS_OK ;
2001-12-09 09:10:02 +03:00
DEBUG ( 3 , ( " ads lookup_groupmem for rid=%d \n " , group_rid ) ) ;
2001-12-05 09:16:33 +03:00
done :
if ( res ) ads_msgfree ( ads , res ) ;
2001-12-05 08:35:45 +03:00
2001-12-05 09:16:33 +03:00
return status ;
2001-12-05 07:48:51 +03:00
}
2002-07-15 14:35:28 +04:00
2001-12-05 10:52:44 +03:00
/* find the sequence number for a domain */
2001-12-10 02:59:42 +03:00
static NTSTATUS sequence_number ( struct winbindd_domain * domain , uint32 * seq )
2001-12-05 10:52:44 +03:00
{
ADS_STRUCT * ads = NULL ;
2001-12-19 15:21:12 +03:00
ADS_STATUS rc ;
2001-12-05 10:52:44 +03:00
2001-12-10 02:59:42 +03:00
* seq = DOM_SEQUENCE_NONE ;
2001-12-05 10:52:44 +03:00
ads = ads_cached_connection ( domain ) ;
2001-12-10 02:59:42 +03:00
if ( ! ads ) return NT_STATUS_UNSUCCESSFUL ;
2001-12-05 10:52:44 +03:00
2001-12-19 15:21:12 +03:00
rc = ads_USN ( ads , seq ) ;
2002-03-21 05:28:23 +03:00
if ( ! ADS_ERR_OK ( rc ) ) {
/* its a dead connection */
ads_destroy ( & ads ) ;
domain - > private = NULL ;
}
2001-12-19 15:21:12 +03:00
return ads_ntstatus ( rc ) ;
2001-12-05 10:52:44 +03:00
}
2001-12-10 05:25:19 +03:00
/* get a list of trusted domains */
static NTSTATUS trusted_domains ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
uint32 * num_domains ,
char * * * names ,
2002-08-17 21:00:51 +04:00
char * * * alt_names ,
2001-12-10 05:25:19 +03:00
DOM_SID * * dom_sids )
{
2001-12-21 02:35:14 +03:00
ADS_STRUCT * ads ;
2001-12-19 15:21:12 +03:00
ADS_STATUS rc ;
2001-12-19 11:44:23 +03:00
2001-12-10 05:25:19 +03:00
* num_domains = 0 ;
2001-12-19 11:44:23 +03:00
* names = NULL ;
ads = ads_cached_connection ( domain ) ;
if ( ! ads ) return NT_STATUS_UNSUCCESSFUL ;
2002-08-17 21:00:51 +04:00
rc = ads_trusted_domains ( ads , mem_ctx , num_domains , names , alt_names , dom_sids ) ;
2001-12-19 11:44:23 +03:00
2001-12-19 15:21:12 +03:00
return ads_ntstatus ( rc ) ;
2001-12-10 05:25:19 +03:00
}
/* find the domain sid for a domain */
static NTSTATUS domain_sid ( struct winbindd_domain * domain , DOM_SID * sid )
{
2001-12-21 02:35:14 +03:00
ADS_STRUCT * ads ;
2001-12-19 15:21:12 +03:00
ADS_STATUS rc ;
2001-12-10 05:25:19 +03:00
ads = ads_cached_connection ( domain ) ;
2001-12-21 02:35:14 +03:00
if ( ! ads ) return NT_STATUS_UNSUCCESSFUL ;
2001-12-10 05:25:19 +03:00
2001-12-21 02:35:14 +03:00
rc = ads_domain_sid ( ads , sid ) ;
2001-12-10 05:25:19 +03:00
2002-03-09 22:36:53 +03:00
if ( ! ADS_ERR_OK ( rc ) ) {
/* its a dead connection */
2002-03-12 23:17:34 +03:00
ads_destroy ( & ads ) ;
2002-03-09 22:36:53 +03:00
domain - > private = NULL ;
}
2001-12-21 02:35:14 +03:00
return ads_ntstatus ( rc ) ;
2001-12-10 05:25:19 +03:00
}
2002-08-17 21:00:51 +04:00
/* find alternate names list for the domain - for ADS this is the
netbios name */
static NTSTATUS alternate_name ( struct winbindd_domain * domain )
{
ADS_STRUCT * ads ;
ADS_STATUS rc ;
TALLOC_CTX * ctx ;
char * workgroup ;
ads = ads_cached_connection ( domain ) ;
if ( ! ads ) return NT_STATUS_UNSUCCESSFUL ;
2002-12-20 23:21:31 +03:00
if ( ! ( ctx = talloc_init ( " alternate_name " ) ) ) {
2002-08-17 21:00:51 +04:00
return NT_STATUS_NO_MEMORY ;
}
rc = ads_workgroup_name ( ads , ctx , & workgroup ) ;
if ( ADS_ERR_OK ( rc ) ) {
fstrcpy ( domain - > name , workgroup ) ;
fstrcpy ( domain - > alt_name , ads - > config . realm ) ;
strupper ( domain - > alt_name ) ;
strupper ( domain - > name ) ;
}
talloc_destroy ( ctx ) ;
return ads_ntstatus ( rc ) ;
}
2001-12-03 14:11:14 +03:00
/* the ADS backend methods are exposed via this structure */
2001-12-03 09:04:18 +03:00
struct winbindd_methods ads_methods = {
2001-12-10 09:05:21 +03:00
True ,
2001-12-03 14:32:55 +03:00
query_user_list ,
2001-12-03 11:17:46 +03:00
enum_dom_groups ,
2002-11-15 20:57:21 +03:00
enum_local_groups ,
2001-12-03 14:11:14 +03:00
name_to_sid ,
2001-12-05 07:48:51 +03:00
sid_to_name ,
2001-12-04 09:46:53 +03:00
query_user ,
2001-12-05 07:48:51 +03:00
lookup_usergroups ,
2001-12-05 10:52:44 +03:00
lookup_groupmem ,
2001-12-10 05:25:19 +03:00
sequence_number ,
trusted_domains ,
2002-08-17 21:00:51 +04:00
domain_sid ,
alternate_name
2001-12-03 09:04:18 +03:00
} ;
# endif