2004-04-07 16:43:44 +04:00
/*
Unix SMB / CIFS implementation .
Winbind rpc backend functions
Copyright ( C ) Tim Potter 2000 - 2001 , 2003
Copyright ( C ) Simo Sorce 2003
Copyright ( C ) Volker Lendecke 2004
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
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2004-04-07 16:43:44 +04:00
( 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
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2004-04-07 16:43:44 +04:00
*/
# include "includes.h"
# include "winbindd.h"
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_WINBIND
/* Query display info for a domain. This returns enough information plus a
bit extra to give an overview of domain users for the User Manager
application . */
static NTSTATUS query_user_list ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
uint32 * num_entries ,
WINBIND_USERINFO * * info )
{
/* We don't have users */
* num_entries = 0 ;
* info = NULL ;
return NT_STATUS_OK ;
}
/* list all domain groups */
static NTSTATUS enum_dom_groups ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
uint32 * num_entries ,
struct acct_info * * info )
{
/* We don't have domain groups */
* num_entries = 0 ;
* info = NULL ;
return NT_STATUS_OK ;
}
/* List all domain groups */
static NTSTATUS enum_local_groups ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
uint32 * num_entries ,
struct acct_info * * info )
{
2005-04-15 17:41:49 +04:00
struct pdb_search * search ;
struct samr_displayentry * aliases ;
int i ;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL ;
2004-04-07 16:43:44 +04:00
2005-04-15 17:41:49 +04:00
search = pdb_search_aliases ( & domain - > sid ) ;
if ( search = = NULL ) goto done ;
2004-04-07 16:43:44 +04:00
2005-04-15 17:41:49 +04:00
* num_entries = pdb_search_entries ( search , 0 , 0xffffffff , & aliases ) ;
if ( * num_entries = = 0 ) goto done ;
2004-04-07 16:43:44 +04:00
2005-04-15 17:41:49 +04:00
* info = TALLOC_ARRAY ( mem_ctx , struct acct_info , * num_entries ) ;
if ( * info = = NULL ) {
result = NT_STATUS_NO_MEMORY ;
goto done ;
}
2004-04-07 16:43:44 +04:00
2005-04-15 17:41:49 +04:00
for ( i = 0 ; i < * num_entries ; i + + ) {
fstrcpy ( ( * info ) [ i ] . acct_name , aliases [ i ] . account_name ) ;
fstrcpy ( ( * info ) [ i ] . acct_desc , aliases [ i ] . description ) ;
( * info ) [ i ] . rid = aliases [ i ] . rid ;
}
2004-04-07 16:43:44 +04:00
2005-04-15 17:41:49 +04:00
result = NT_STATUS_OK ;
done :
pdb_search_destroy ( search ) ;
return result ;
2004-04-07 16:43:44 +04:00
}
/* convert a single name to a sid in a domain */
static NTSTATUS name_to_sid ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
2007-05-30 23:47:35 +04:00
enum winbindd_cmd original_cmd ,
2004-04-20 06:37:49 +04:00
const char * domain_name ,
2004-04-07 16:43:44 +04:00
const char * name ,
DOM_SID * sid ,
2006-09-08 18:28:06 +04:00
enum lsa_SidType * type )
2004-04-07 16:43:44 +04:00
{
2007-05-30 23:47:35 +04:00
uint32 flags = LOOKUP_NAME_ALL ;
switch ( original_cmd ) {
case WINBINDD_LOOKUPNAME :
/* This call is ok */
break ;
default :
/* Avoid any NSS calls in the lookup_name by default */
flags | = LOOKUP_NAME_EXPLICIT ;
DEBUG ( 10 , ( " winbindd_passdb: limiting name_to_sid() to explicit mappings \n " ) ) ;
break ;
}
2004-04-07 16:43:44 +04:00
DEBUG ( 10 , ( " Finding name %s \n " , name ) ) ;
2007-05-30 23:47:35 +04:00
if ( ! lookup_name ( mem_ctx , name , flags , NULL , NULL , sid , type ) ) {
2004-04-07 16:43:44 +04:00
return NT_STATUS_NONE_MAPPED ;
2006-03-15 06:46:20 +03:00
}
2004-05-26 22:52:45 +04:00
2004-04-07 16:43:44 +04:00
return NT_STATUS_OK ;
}
/*
convert a domain SID to a user or group name
*/
static NTSTATUS sid_to_name ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
const DOM_SID * sid ,
2004-04-20 06:37:49 +04:00
char * * domain_name ,
2004-04-07 16:43:44 +04:00
char * * name ,
2006-09-08 18:28:06 +04:00
enum lsa_SidType * type )
2004-04-07 16:43:44 +04:00
{
2006-02-04 01:19:41 +03:00
const char * dom , * nam ;
2004-04-07 16:43:44 +04:00
DEBUG ( 10 , ( " Converting SID %s \n " , sid_string_static ( sid ) ) ) ;
2006-02-04 01:19:41 +03:00
/* Paranoia check */
if ( ! sid_check_is_in_builtin ( sid ) & &
2007-05-22 00:36:22 +04:00
! sid_check_is_in_our_domain ( sid ) & &
! sid_check_is_in_unix_users ( sid ) & &
! sid_check_is_unix_users ( sid ) & &
! sid_check_is_in_unix_groups ( sid ) & &
! sid_check_is_unix_groups ( sid ) )
{
2006-02-04 01:19:41 +03:00
DEBUG ( 0 , ( " Possible deadlock: Trying to lookup SID %s with "
" passdb backend \n " , sid_string_static ( sid ) ) ) ;
2004-04-07 16:43:44 +04:00
return NT_STATUS_NONE_MAPPED ;
2006-02-04 01:19:41 +03:00
}
2004-04-07 16:43:44 +04:00
2006-02-04 01:19:41 +03:00
if ( ! lookup_sid ( mem_ctx , sid , & dom , & nam , type ) ) {
return NT_STATUS_NONE_MAPPED ;
}
* domain_name = talloc_strdup ( mem_ctx , dom ) ;
* name = talloc_strdup ( mem_ctx , nam ) ;
2004-04-07 16:43:44 +04:00
return NT_STATUS_OK ;
}
2006-07-11 22:01:26 +04:00
static NTSTATUS rids_to_names ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
const DOM_SID * sid ,
uint32 * rids ,
size_t num_rids ,
char * * domain_name ,
char * * * names ,
2006-09-08 18:28:06 +04:00
enum lsa_SidType * * types )
2006-07-11 22:01:26 +04:00
{
return NT_STATUS_UNSUCCESSFUL ;
}
2004-04-07 16:43:44 +04:00
/* Lookup user information from a rid or username. */
static NTSTATUS query_user ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
const DOM_SID * user_sid ,
WINBIND_USERINFO * user_info )
{
return NT_STATUS_NO_SUCH_USER ;
}
/* Lookup groups a user is a member of. I wish Unix had a call like this! */
static NTSTATUS lookup_usergroups ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
const DOM_SID * user_sid ,
2005-06-09 02:10:34 +04:00
uint32 * num_groups , DOM_SID * * user_gids )
2004-04-07 16:43:44 +04:00
{
2006-04-02 10:25:11 +04:00
NTSTATUS result ;
DOM_SID * groups = NULL ;
gid_t * gids = NULL ;
size_t ngroups = 0 ;
struct samu * user ;
if ( ( user = samu_new ( mem_ctx ) ) = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
if ( ! pdb_getsampwsid ( user , user_sid ) ) {
return NT_STATUS_NO_SUCH_USER ;
}
result = pdb_enum_group_memberships ( mem_ctx , user , & groups , & gids , & ngroups ) ;
TALLOC_FREE ( user ) ;
* num_groups = ( uint32 ) ngroups ;
* user_gids = groups ;
return result ;
2004-04-07 16:43:44 +04:00
}
2005-01-15 22:00:18 +03:00
static NTSTATUS lookup_useraliases ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
2005-06-09 02:10:34 +04:00
uint32 num_sids , const DOM_SID * sids ,
2005-10-18 07:24:00 +04:00
uint32 * p_num_aliases , uint32 * * rids )
2005-01-15 22:00:18 +03:00
{
2006-02-04 01:19:41 +03:00
NTSTATUS result ;
2005-11-08 21:22:32 +03:00
size_t num_aliases = 0 ;
2005-06-09 02:10:34 +04:00
result = pdb_enum_alias_memberships ( mem_ctx , & domain - > sid ,
2005-10-18 07:24:00 +04:00
sids , num_sids , rids , & num_aliases ) ;
2005-06-09 02:10:34 +04:00
2005-10-18 07:24:00 +04:00
* p_num_aliases = num_aliases ;
2006-02-04 01:19:41 +03:00
return result ;
2005-01-15 22:00:18 +03:00
}
2004-04-07 16:43:44 +04:00
/* Lookup group membership given a rid. */
static NTSTATUS lookup_groupmem ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
const DOM_SID * group_sid , uint32 * num_names ,
2005-06-09 02:10:34 +04:00
DOM_SID * * sid_mem , char * * * names ,
2004-04-07 16:43:44 +04:00
uint32 * * name_types )
{
2006-02-04 01:19:41 +03:00
size_t i , num_members , num_mapped ;
uint32 * rids ;
NTSTATUS result ;
const DOM_SID * * sids ;
struct lsa_dom_info * lsa_domains ;
struct lsa_name_info * lsa_names ;
2006-07-11 22:01:26 +04:00
TALLOC_CTX * tmp_ctx ;
2006-02-04 01:19:41 +03:00
if ( ! sid_check_is_in_our_domain ( group_sid ) ) {
/* There's no groups, only aliases in BUILTIN */
return NT_STATUS_NO_SUCH_GROUP ;
}
2006-07-11 22:01:26 +04:00
if ( ! ( tmp_ctx = talloc_init ( " lookup_groupmem " ) ) ) {
return NT_STATUS_NO_MEMORY ;
}
result = pdb_enum_group_members ( tmp_ctx , group_sid , & rids ,
2006-02-04 01:19:41 +03:00
& num_members ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
2006-07-11 22:01:26 +04:00
TALLOC_FREE ( tmp_ctx ) ;
2006-02-04 01:19:41 +03:00
return result ;
}
if ( num_members = = 0 ) {
* num_names = 0 ;
* sid_mem = NULL ;
* names = NULL ;
* name_types = NULL ;
2006-07-11 22:01:26 +04:00
TALLOC_FREE ( tmp_ctx ) ;
2006-02-04 01:19:41 +03:00
return NT_STATUS_OK ;
}
* sid_mem = TALLOC_ARRAY ( mem_ctx , DOM_SID , num_members ) ;
* names = TALLOC_ARRAY ( mem_ctx , char * , num_members ) ;
* name_types = TALLOC_ARRAY ( mem_ctx , uint32 , num_members ) ;
2006-07-11 22:01:26 +04:00
sids = TALLOC_ARRAY ( tmp_ctx , const DOM_SID * , num_members ) ;
2006-02-04 01:19:41 +03:00
if ( ( ( * sid_mem ) = = NULL ) | | ( ( * names ) = = NULL ) | |
( ( * name_types ) = = NULL ) | | ( sids = = NULL ) ) {
2006-07-11 22:01:26 +04:00
TALLOC_FREE ( tmp_ctx ) ;
2006-02-04 01:19:41 +03:00
return NT_STATUS_NO_MEMORY ;
}
2006-07-11 22:01:26 +04:00
/*
* Prepare an array of sid pointers for the lookup_sids calling
* convention .
*/
2006-02-04 01:19:41 +03:00
for ( i = 0 ; i < num_members ; i + + ) {
DOM_SID * sid = & ( ( * sid_mem ) [ i ] ) ;
2006-07-11 22:01:26 +04:00
if ( ! sid_compose ( sid , & domain - > sid , rids [ i ] ) ) {
TALLOC_FREE ( tmp_ctx ) ;
return NT_STATUS_INTERNAL_ERROR ;
}
2006-02-04 01:19:41 +03:00
sids [ i ] = sid ;
}
2006-07-11 22:01:26 +04:00
result = lookup_sids ( tmp_ctx , num_members , sids , 1 ,
2006-02-04 01:19:41 +03:00
& lsa_domains , & lsa_names ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
2006-07-11 22:01:26 +04:00
TALLOC_FREE ( tmp_ctx ) ;
2006-02-04 01:19:41 +03:00
return result ;
}
num_mapped = 0 ;
for ( i = 0 ; i < num_members ; i + + ) {
if ( lsa_names [ i ] . type ! = SID_NAME_USER ) {
DEBUG ( 2 , ( " Got %s as group member -- ignoring \n " ,
sid_type_lookup ( lsa_names [ i ] . type ) ) ) ;
continue ;
}
2006-07-11 22:01:26 +04:00
if ( ! ( ( * names ) [ i ] = talloc_strdup ( ( * names ) ,
lsa_names [ i ] . name ) ) ) {
TALLOC_FREE ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
2006-02-04 01:19:41 +03:00
( * name_types ) [ i ] = lsa_names [ i ] . type ;
num_mapped + = 1 ;
}
* num_names = num_mapped ;
2006-07-11 22:01:26 +04:00
TALLOC_FREE ( tmp_ctx ) ;
2004-04-07 16:43:44 +04:00
return NT_STATUS_OK ;
}
/* find the sequence number for a domain */
static NTSTATUS sequence_number ( struct winbindd_domain * domain , uint32 * seq )
{
2006-02-04 01:19:41 +03:00
BOOL result ;
time_t seq_num ;
result = pdb_get_seq_num ( & seq_num ) ;
if ( ! result ) {
* seq = 1 ;
}
* seq = ( int ) seq_num ;
/* *seq = 1; */
2004-04-07 16:43:44 +04:00
return NT_STATUS_OK ;
}
2006-02-04 01:19:41 +03:00
static NTSTATUS lockout_policy ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
2006-04-13 14:14:07 +04:00
SAM_UNK_INFO_12 * policy )
2006-02-04 01:19:41 +03:00
{
/* actually we have that */
return NT_STATUS_NOT_IMPLEMENTED ;
}
static NTSTATUS password_policy ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
2006-04-13 14:14:07 +04:00
SAM_UNK_INFO_1 * policy )
2006-02-04 01:19:41 +03:00
{
2006-05-31 14:09:31 +04:00
uint32 min_pass_len , pass_hist , password_properties ;
time_t u_expire , u_min_age ;
NTTIME nt_expire , nt_min_age ;
uint32 account_policy_temp ;
if ( ( policy = TALLOC_ZERO_P ( mem_ctx , SAM_UNK_INFO_1 ) ) = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
if ( ! pdb_get_account_policy ( AP_MIN_PASSWORD_LEN , & account_policy_temp ) ) {
return NT_STATUS_ACCESS_DENIED ;
}
min_pass_len = account_policy_temp ;
if ( ! pdb_get_account_policy ( AP_PASSWORD_HISTORY , & account_policy_temp ) ) {
return NT_STATUS_ACCESS_DENIED ;
}
pass_hist = account_policy_temp ;
if ( ! pdb_get_account_policy ( AP_USER_MUST_LOGON_TO_CHG_PASS , & account_policy_temp ) ) {
return NT_STATUS_ACCESS_DENIED ;
}
password_properties = account_policy_temp ;
if ( ! pdb_get_account_policy ( AP_MAX_PASSWORD_AGE , & account_policy_temp ) ) {
return NT_STATUS_ACCESS_DENIED ;
}
u_expire = account_policy_temp ;
if ( ! pdb_get_account_policy ( AP_MIN_PASSWORD_AGE , & account_policy_temp ) ) {
return NT_STATUS_ACCESS_DENIED ;
}
u_min_age = account_policy_temp ;
unix_to_nt_time_abs ( & nt_expire , u_expire ) ;
unix_to_nt_time_abs ( & nt_min_age , u_min_age ) ;
init_unk_info1 ( policy , ( uint16 ) min_pass_len , ( uint16 ) pass_hist ,
password_properties , nt_expire , nt_min_age ) ;
return NT_STATUS_OK ;
2006-02-04 01:19:41 +03:00
}
2004-04-07 16:43:44 +04:00
/* get a list of trusted domains */
static NTSTATUS trusted_domains ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
uint32 * num_domains ,
char * * * names ,
char * * * alt_names ,
DOM_SID * * dom_sids )
{
2004-04-20 06:37:49 +04:00
NTSTATUS nt_status ;
2006-02-04 01:19:41 +03:00
struct trustdom_info * * domains ;
int i ;
2006-07-11 22:01:26 +04:00
TALLOC_CTX * tmp_ctx ;
2006-02-04 01:19:41 +03:00
2004-04-20 06:37:49 +04:00
* num_domains = 0 ;
* names = NULL ;
* alt_names = NULL ;
* dom_sids = NULL ;
2006-07-11 22:01:26 +04:00
if ( ! ( tmp_ctx = talloc_init ( " trusted_domains " ) ) ) {
return NT_STATUS_NO_MEMORY ;
}
2007-01-16 11:17:26 +03:00
nt_status = pdb_enum_trusteddoms ( tmp_ctx , num_domains , & domains ) ;
2006-02-04 01:19:41 +03:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
2006-07-11 22:01:26 +04:00
TALLOC_FREE ( tmp_ctx ) ;
2006-02-04 01:19:41 +03:00
return nt_status ;
}
2004-04-20 06:37:49 +04:00
2007-04-30 06:39:34 +04:00
if ( * num_domains ) {
* names = TALLOC_ARRAY ( mem_ctx , char * , * num_domains ) ;
* alt_names = TALLOC_ARRAY ( mem_ctx , char * , * num_domains ) ;
* dom_sids = TALLOC_ARRAY ( mem_ctx , DOM_SID , * num_domains ) ;
2006-02-04 01:19:41 +03:00
2007-04-30 06:39:34 +04:00
if ( ( * alt_names = = NULL ) | | ( * names = = NULL ) | | ( * dom_sids = = NULL ) ) {
TALLOC_FREE ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
} else {
* names = NULL ;
* alt_names = NULL ;
* dom_sids = NULL ;
2004-04-20 06:37:49 +04:00
}
2006-02-04 01:19:41 +03:00
for ( i = 0 ; i < * num_domains ; i + + ) {
( * alt_names ) [ i ] = NULL ;
2006-07-11 22:01:26 +04:00
if ( ! ( ( * names ) [ i ] = talloc_strdup ( ( * names ) ,
domains [ i ] - > name ) ) ) {
TALLOC_FREE ( tmp_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
2006-02-04 01:19:41 +03:00
sid_copy ( & ( * dom_sids ) [ i ] , & domains [ i ] - > sid ) ;
}
2006-07-11 22:01:26 +04:00
TALLOC_FREE ( tmp_ctx ) ;
2006-02-04 01:19:41 +03:00
return NT_STATUS_OK ;
2004-04-07 16:43:44 +04:00
}
/* the rpc backend methods are exposed via this structure */
struct winbindd_methods passdb_methods = {
False ,
query_user_list ,
enum_dom_groups ,
enum_local_groups ,
name_to_sid ,
sid_to_name ,
2006-07-11 22:01:26 +04:00
rids_to_names ,
2004-04-07 16:43:44 +04:00
query_user ,
lookup_usergroups ,
2005-01-15 22:00:18 +03:00
lookup_useraliases ,
2004-04-07 16:43:44 +04:00
lookup_groupmem ,
sequence_number ,
2006-02-04 01:19:41 +03:00
lockout_policy ,
password_policy ,
2004-04-07 16:43:44 +04:00
trusted_domains ,
} ;