2002-09-28 12:27:04 +00:00
/*
Unix SMB / CIFS implementation .
Active Directory SAM backend , for simulate a W2K DC in mixed mode .
Copyright ( C ) Stefan ( metze ) Metzmacher 2002
Copyright ( C ) Andrew Bartlett 2002
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"
# ifdef HAVE_LDAP
static int sam_ads_debug_level = DBGC_SAM ;
# undef DBGC_CLASS
# define DBGC_CLASS sam_ads_debug_level
2002-10-21 15:36:51 +00:00
# ifndef FIXME
# define FIXME( body ) { DEBUG(0,("FIXME: "));\
DEBUGADD ( 0 , ( body ) ) ; }
# endif
2002-09-28 12:27:04 +00:00
# define ADS_STATUS_OK ADS_ERROR(0)
# define ADS_STATUS_UNSUCCESSFUL ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL)
# define ADS_STATUS_NOT_IMPLEMENTED ADS_ERROR_NT(NT_STATUS_NOT_IMPLEMENTED)
# define ADS_SUBTREE_BUILTIN "CN=Builtin,"
# define ADS_SUBTREE_COMPUTERS "CN=Computers,"
# define ADS_SUBTREE_DC "CN=Domain Controllers,"
# define ADS_SUBTREE_USERS "CN=Users,"
# define ADS_ROOT_TREE ""
/* Here are private module structs and functions */
2002-10-21 15:36:51 +00:00
typedef struct sam_ads_privates {
2002-09-28 12:27:04 +00:00
ADS_STRUCT * ads_struct ;
TALLOC_CTX * mem_ctx ;
BOOL bind_plaintext ;
char * ads_bind_dn ;
char * ads_bind_pw ;
char * ldap_uri ;
/* did we need something more? */
2002-10-21 15:36:51 +00:00
} SAM_ADS_PRIVATES ;
2002-09-28 12:27:04 +00:00
/* get only these LDAP attributes, witch we really need for an account */
const char * account_attrs [ ] = { " objectSid " ,
" objectGUID " ,
" sAMAccountType " ,
" sAMAcountName " ,
" userPrincipalName " ,
" accountExpires " ,
" badPasswordTime " ,
" badPwdCount " ,
" lastLogoff " ,
" lastLogon " ,
" userWorkstations " ,
" dBCSPwd " ,
" unicodePwd " ,
" pwdLastSet " ,
" userAccountControl " ,
" profilePath " ,
" homeDrive " ,
" scriptPath " ,
" homeDirectory " ,
" cn " ,
" primaryGroupID " , /* 513 */
" nsNPAllowDialIn " , /* TRUE */
" userParameters " , /* Dial Back number ...*/
" codePage " , /* 0 */
" countryCode " , /* 0 */
" adminCount " , /* 1 or 0 */
" logonCount " , /* 0 */
" managedObjects " ,
" memberOf " , /* dn */
" instanceType " , /* 4 */
" name " , /* sync with cn */
" description " ,
/* "nTSecurityDescriptor", */
NULL } ;
/* get only these LDAP attributes, witch we really need for a group */
const char * group_attrs [ ] = { " objectSid " ,
/* "objectGUID", */
" sAMAccountType " ,
" sAMAcountName " ,
" groupType " ,
/* "member", */
" description " ,
" name " , /* sync with cn */
/* "nTSecurityDescriptor", */
NULL } ;
/***************************************************
return our ads connection . We keep the connection
open to make things faster
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-10-21 15:36:51 +00:00
static ADS_STATUS sam_ads_cached_connection ( SAM_ADS_PRIVATES * privates )
2002-09-28 12:27:04 +00:00
{
ADS_STRUCT * ads_struct ;
ADS_STATUS ads_status ;
2002-10-21 15:36:51 +00:00
if ( ! privates - > ads_struct ) {
privates - > ads_struct = ads_init_simple ( ) ;
ads_struct = privates - > ads_struct ;
ads_struct - > server . ldap_uri = smb_xstrdup ( privates - > ldap_uri ) ;
if ( ( ! privates - > ads_bind_dn ) | | ( ! * privates - > ads_bind_dn ) ) {
2002-09-28 12:27:04 +00:00
ads_struct - > auth . flags | = ADS_AUTH_ANON_BIND ;
} else {
ads_struct - > auth . user_name
2002-10-21 15:36:51 +00:00
= smb_xstrdup ( privates - > ads_bind_dn ) ;
if ( privates - > ads_bind_pw ) {
2002-09-28 12:27:04 +00:00
ads_struct - > auth . password
2002-10-21 15:36:51 +00:00
= smb_xstrdup ( privates - > ads_bind_pw ) ;
2002-09-28 12:27:04 +00:00
}
}
2002-10-21 15:36:51 +00:00
if ( privates - > bind_plaintext ) {
2002-09-28 12:27:04 +00:00
ads_struct - > auth . flags | = ADS_AUTH_SIMPLE_BIND ;
}
} else {
2002-10-21 15:36:51 +00:00
ads_struct = privates - > ads_struct ;
2002-09-28 12:27:04 +00:00
}
if ( ads_struct - > ld ! = NULL ) {
/* connection has been opened. ping server. */
struct sockaddr_un addr ;
socklen_t len ;
int sd ;
if ( ldap_get_option ( ads_struct - > ld , LDAP_OPT_DESC , & sd ) = = 0 & &
getpeername ( sd , ( struct sockaddr * ) & addr , & len ) < 0 ) {
/* the other end has died. reopen. */
ldap_unbind_ext ( ads_struct - > ld , NULL , NULL ) ;
ads_struct - > ld = NULL ;
}
}
if ( ads_struct - > ld ! = NULL ) {
DEBUG ( 5 , ( " sam_ads_cached_connection: allready connected to the LDAP server \n " ) ) ;
return ADS_SUCCESS ;
}
ads_status = ads_connect ( ads_struct ) ;
ads_status = ads_server_info ( ads_struct ) ;
if ( ! ADS_ERR_OK ( ads_status ) ) {
DEBUG ( 0 , ( " Can't set server info: %s \n " , ads_errstr ( ads_status ) ) ) ;
2002-10-21 15:36:51 +00:00
/* return ads_status; */ FIXME ( " for now we only warn! \n " ) ;
2002-09-28 12:27:04 +00:00
}
DEBUG ( 2 , ( " sam_ads_cached_connection: succesful connection to the LDAP server \n " ) ) ;
return ADS_SUCCESS ;
}
2002-10-21 15:36:51 +00:00
static ADS_STATUS sam_ads_do_search ( SAM_ADS_PRIVATES * privates , const char * bind_path , int scope , const char * exp , const char * * attrs , void * * res )
2002-09-28 12:27:04 +00:00
{
ADS_STATUS ads_status = ADS_ERROR_NT ( NT_STATUS_UNSUCCESSFUL ) ;
2002-10-21 15:36:51 +00:00
ads_status = sam_ads_cached_connection ( privates ) ;
2002-09-28 12:27:04 +00:00
if ( ! ADS_ERR_OK ( ads_status ) )
return ads_status ;
2002-10-21 15:36:51 +00:00
return ads_do_search_retry ( privates - > ads_struct , bind_path , scope , exp , attrs , res ) ;
2002-09-28 12:27:04 +00:00
}
2002-09-29 01:01:44 +00:00
/*********************************************
here we have to check the update serial number
- this is the core of the ldap cache
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-10-21 15:36:51 +00:00
static ADS_STATUS sam_ads_usn_is_valid ( SAM_ADS_PRIVATES * privates , uint32 usn_in , uint32 * usn_out )
2002-09-29 01:01:44 +00:00
{
ADS_STATUS ads_status = ADS_ERROR_NT ( NT_STATUS_UNSUCCESSFUL ) ;
2002-10-21 15:36:51 +00:00
SAM_ASSERT ( privates & & privates - > ads_struct & & usn_out ) ;
2002-09-29 01:01:44 +00:00
2002-10-21 15:36:51 +00:00
ads_status = ads_USN ( privates - > ads_struct , usn_out ) ;
2002-09-29 01:01:44 +00:00
if ( ! ADS_ERR_OK ( ads_status ) )
return ads_status ;
if ( * usn_out = = usn_in )
return ADS_SUCCESS ;
return ads_status ;
}
2002-09-28 12:27:04 +00:00
/***********************************************
Initialize SAM_ACCOUNT_HANDLE from an ADS query
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* not ready :-( */
2002-10-21 15:36:51 +00:00
static ADS_STATUS ads_entry2sam_account_handle ( SAM_ADS_PRIVATES * privates , SAM_ACCOUNT_HANDLE * account , void * msg )
2002-09-28 12:27:04 +00:00
{
2002-10-21 15:36:51 +00:00
ADS_STATUS ads_status = ADS_ERROR_NT ( NT_STATUS_NO_SUCH_USER ) ;
NTSTATUS nt_status = NT_STATUS_NO_SUCH_USER ;
ADS_STRUCT * ads_struct = privates - > ads_struct ;
TALLOC_CTX * mem_ctx = account - > mem_ctx ;
char * tmp_str = NULL ;
SAM_ASSERT ( privates & & ads_struct & & account & & mem_ctx & & msg ) ;
2002-09-28 12:27:04 +00:00
2002-10-21 15:36:51 +00:00
FIXME ( " should we really use ads_pull_username()(or ads_pull_string())? \n " ) ;
if ( ( account - > private . account_name = ads_pull_username ( ads_struct , mem_ctx , msg ) ) = = NULL ) {
DEBUG ( 0 , ( " ads_pull_username failed \n " ) ) ;
return ADS_ERROR_NT ( NT_STATUS_NO_SUCH_USER ) ;
}
if ( ( account - > private . full_name = ads_pull_string ( ads_struct , mem_ctx , msg , " name " ) ) = = NULL ) {
DEBUG ( 3 , ( " ads_pull_string for 'name' failed - skip \n " ) ) ;
}
if ( ( account - > private . acct_desc = ads_pull_string ( ads_struct , mem_ctx , msg , " description " ) ) ! = NULL ) {
DEBUG ( 3 , ( " ads_pull_string for 'acct_desc' failed - skip \n " ) ) ;
}
if ( ( account - > private . home_dir = ads_pull_string ( ads_struct , mem_ctx , msg , " homeDirectory " ) ) ! = NULL ) {
DEBUG ( 3 , ( " ads_pull_string for 'homeDirectory' failed - skip \n " ) ) ;
}
if ( ( account - > private . dir_drive = ads_pull_string ( ads_struct , mem_ctx , msg , " homeDrive " ) ) ! = NULL ) {
DEBUG ( 3 , ( " ads_pull_string for 'homeDrive' failed - skip \n " ) ) ;
}
if ( ( account - > private . profile_path = ads_pull_string ( ads_struct , mem_ctx , msg , " profilePath " ) ) ! = NULL ) {
DEBUG ( 3 , ( " ads_pull_string for 'profilePath' failed - skip \n " ) ) ;
}
if ( ( account - > private . logon_script = ads_pull_string ( ads_struct , mem_ctx , msg , " scriptPath " ) ) ! = NULL ) {
DEBUG ( 3 , ( " ads_pull_string for 'scriptPath' failed - skip \n " ) ) ;
}
FIXME ( " check 'nsNPAllowDialIn' for munged_dial! \n " ) ;
if ( ( account - > private . munged_dial = ads_pull_string ( ads_struct , mem_ctx , msg , " userParameters " ) ) ! = NULL ) {
DEBUG ( 3 , ( " ads_pull_string for 'userParameters' failed - skip \n " ) ) ;
}
if ( ( account - > private . unix_home_dir = ads_pull_string ( ads_struct , mem_ctx , msg , " msSFUHomeDrirectory " ) ) ! = NULL ) {
DEBUG ( 3 , ( " ads_pull_string for 'msSFUHomeDrirectory' failed - skip \n " ) ) ;
}
2002-09-28 12:27:04 +00:00
2002-10-21 15:36:51 +00:00
#if 0
FIXME ( " use function intern mem_ctx for pwdLastSet \n " ) ;
if ( ( tmp_str = ads_pull_string ( ads_struct , mem_ctx , msg , " pwdLastSet " ) ) ! = NULL ) {
DEBUG ( 3 , ( " ads_pull_string for 'pwdLastSet' failed - skip \n " ) ) ;
} else {
account - > private . pass_last_set_time = ads_parse_nttime ( tmp_str ) ;
tmp_str = NULL ;
}
# endif
#if 0
typedef struct sam_account_handle {
TALLOC_CTX * mem_ctx ;
uint32 access_granted ;
const struct sam_methods * current_sam_methods ; /* sam_methods creating this handle */
void ( * free_fn ) ( struct sam_account_handle * * ) ;
struct sam_account_data {
uint32 init_flag ;
NTTIME logon_time ; /* logon time */
NTTIME logoff_time ; /* logoff time */
NTTIME kickoff_time ; /* kickoff time */
NTTIME pass_last_set_time ; /* password last set time */
NTTIME pass_can_change_time ; /* password can change time */
NTTIME pass_must_change_time ; /* password must change time */
char * account_name ; /* account_name string */
SAM_DOMAIN_HANDLE * domain ; /* domain of account */
char * full_name ; /* account's full name string */
char * unix_home_dir ; /* UNIX home directory string */
char * home_dir ; /* home directory string */
char * dir_drive ; /* home directory drive string */
char * logon_script ; /* logon script string */
char * profile_path ; /* profile path string */
char * acct_desc ; /* account description string */
char * workstations ; /* login from workstations string */
char * unknown_str ; /* don't know what this is, yet. */
char * munged_dial ; /* munged path name and dial-back tel number */
DOM_SID account_sid ; /* Primary Account SID */
DOM_SID group_sid ; /* Primary Group SID */
DATA_BLOB lm_pw ; /* .data is Null if no password */
DATA_BLOB nt_pw ; /* .data is Null if no password */
char * plaintext_pw ; /* if Null not available */
uint16 acct_ctrl ; /* account info (ACB_xxxx bit-mask) */
uint32 unknown_1 ; /* 0x00ff ffff */
uint16 logon_divs ; /* 168 - number of hours in a week */
uint32 hours_len ; /* normally 21 bytes */
uint8 hours [ MAX_HOURS_LEN ] ;
uint32 unknown_2 ; /* 0x0002 0000 */
uint32 unknown_3 ; /* 0x0000 04ec */
} private ;
} SAM_ACCOUNT_HANDLE ;
# endif
2002-09-28 12:27:04 +00:00
return ads_status ;
}
/***********************************************
Initialize SAM_GROUP_ENUM from an ads entry
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* not ready :-( */
2002-10-21 15:36:51 +00:00
static ADS_STATUS ads_entry2sam_group_enum ( SAM_ADS_PRIVATES * privates , TALLOC_CTX * mem_ctx , SAM_GROUP_ENUM * * group_enum , const void * entry )
2002-09-28 12:27:04 +00:00
{
ADS_STATUS ads_status = ADS_STATUS_UNSUCCESSFUL ;
2002-10-21 15:36:51 +00:00
ADS_STRUCT * ads_struct = privates - > ads_struct ;
2002-09-28 12:27:04 +00:00
SAM_GROUP_ENUM __group_enum ;
SAM_GROUP_ENUM * _group_enum = & __group_enum ;
2002-10-21 15:36:51 +00:00
SAM_ASSERT ( privates & & ads_struct & & mem_ctx & & group_enum & & entry ) ;
2002-09-28 12:27:04 +00:00
* group_enum = _group_enum ;
DEBUG ( 3 , ( " sam_ads: ads_entry2sam_account_handle \n " ) ) ;
2002-10-21 15:36:51 +00:00
if ( ! ads_pull_sid ( ads_struct , & entry , " objectSid " , & ( _group_enum - > sid ) ) ) {
2002-09-28 12:27:04 +00:00
DEBUG ( 0 , ( " No sid for!? \n " ) ) ;
return ADS_STATUS_UNSUCCESSFUL ;
}
2002-10-21 15:36:51 +00:00
if ( ! ( _group_enum - > group_name = ads_pull_string ( ads_struct , mem_ctx , & entry , " sAMAccountName " ) ) ) {
2002-09-28 12:27:04 +00:00
DEBUG ( 0 , ( " No groupname found " ) ) ;
return ADS_STATUS_UNSUCCESSFUL ;
}
2002-10-21 15:36:51 +00:00
if ( ! ( _group_enum - > group_desc = ads_pull_string ( ads_struct , mem_ctx , & entry , " desciption " ) ) ) {
2002-09-28 12:27:04 +00:00
DEBUG ( 0 , ( " No description found " ) ) ;
return ADS_STATUS_UNSUCCESSFUL ;
}
DEBUG ( 0 , ( " sAMAccountName: %s \n description: %s \n objectSid: %s \n " ,
_group_enum - > group_name ,
_group_enum - > group_desc ,
sid_string_static ( & ( _group_enum - > sid ) )
) ) ;
return ads_status ;
}
2002-10-21 15:36:51 +00:00
static ADS_STATUS sam_ads_access_check ( SAM_ADS_PRIVATES * privates , const SEC_DESC * sd , const NT_USER_TOKEN * access_token , uint32 access_desired , uint32 * acc_granted )
2002-09-28 12:27:04 +00:00
{
ADS_STATUS ads_status = ADS_ERROR_NT ( NT_STATUS_ACCESS_DENIED ) ;
NTSTATUS nt_status ;
2002-10-21 15:36:51 +00:00
uint32 my_acc_granted ;
2002-09-28 12:27:04 +00:00
2002-10-21 15:36:51 +00:00
SAM_ASSERT ( privates & & sd & & access_token ) ;
/* acc_granted can be set to NULL */
2002-09-28 12:27:04 +00:00
/* the steps you need are:
1. get_sec_desc for sid
2. se_map_generic ( accessdesired , generic_mapping )
3. se_access_check ( ) */
2002-10-21 15:36:51 +00:00
if ( ! se_access_check ( sd , access_token , access_desired , ( acc_granted ) ? acc_granted : & my_acc_granted , & nt_status ) ) {
2002-09-28 12:27:04 +00:00
DEBUG ( 3 , ( " sam_ads_access_check: ACCESS DENIED \n " ) ) ;
ads_status = ADS_ERROR_NT ( nt_status ) ;
return ads_status ;
}
ads_status = ADS_ERROR_NT ( nt_status ) ;
return ads_status ;
}
2002-10-21 15:36:51 +00:00
static ADS_STATUS sam_ads_get_tree_sec_desc ( SAM_ADS_PRIVATES * privates , const char * subtree , SEC_DESC * * sd )
2002-09-28 12:27:04 +00:00
{
ADS_STATUS ads_status = ADS_ERROR_NT ( NT_STATUS_INVALID_PARAMETER ) ;
ADS_STRUCT * ads_struct = privates - > ads_struct ;
TALLOC_CTX * mem_ctx = privates - > mem_ctx ;
char * search_path ;
void * sec_desc_res ;
void * sec_desc_msg ;
const char * sec_desc_attrs [ ] = { " nTSecurityDescriptor " , NULL } ;
2002-10-21 15:36:51 +00:00
SAM_ASSERT ( privates & & ads_struct & & mem_ctx & & sd ) ;
2002-09-28 12:27:04 +00:00
* sd = NULL ;
if ( subtree ) {
asprintf ( & search_path , " %s%s " , subtree , ads_struct - > config . bind_path ) ;
} else {
asprintf ( & search_path , " %s " , " " ) ;
}
ads_status = sam_ads_do_search ( privates , search_path , LDAP_SCOPE_BASE , " (objectClass=*) " , sec_desc_attrs , & sec_desc_res ) ;
SAFE_FREE ( search_path ) ;
if ( ! ADS_ERR_OK ( ads_status ) )
return ads_status ;
if ( ( sec_desc_msg = ads_first_entry ( ads_struct , sec_desc_res ) ) = = NULL ) {
ads_status = ADS_ERROR_NT ( NT_STATUS_INVALID_PARAMETER ) ;
return ads_status ;
}
if ( ! ads_pull_sd ( ads_struct , mem_ctx , sec_desc_msg , sec_desc_attrs [ 0 ] , sd ) ) {
* sd = NULL ;
ads_status = ADS_ERROR_NT ( NT_STATUS_INVALID_PARAMETER ) ;
return ads_status ;
}
return ads_status ;
}
2002-10-21 15:36:51 +00:00
static ADS_STATUS sam_ads_account_policy_get ( SAM_ADS_PRIVATES * privates , int field , uint32 * value )
2002-09-28 12:27:04 +00:00
{
2002-09-29 01:01:44 +00:00
ADS_STATUS ads_status = ADS_ERROR_NT ( NT_STATUS_INVALID_PARAMETER ) ;
ADS_STRUCT * ads_struct = privates - > ads_struct ;
void * ap_res ;
void * ap_msg ;
2002-10-21 15:36:51 +00:00
const char * ap_attrs [ ] = { " minPwdLength " , /* AP_MIN_PASSWORD_LEN */
" pwdHistoryLength " , /* AP_PASSWORD_HISTORY */
" AP_USER_MUST_LOGON_TO_CHG_PASS " , /* AP_USER_MUST_LOGON_TO_CHG_PASS */
" maxPwdAge " , /* AP_MAX_PASSWORD_AGE */
" minPwdAge " , /* AP_MIN_PASSWORD_AGE */
" lockoutDuration " , /* AP_LOCK_ACCOUNT_DURATION */
" AP_RESET_COUNT_TIME " , /* AP_RESET_COUNT_TIME */
" AP_BAD_ATTEMPT_LOCKOUT " , /* AP_BAD_ATTEMPT_LOCKOUT */
" AP_TIME_TO_LOGOUT " , /* AP_TIME_TO_LOGOUT */
NULL } ;
2002-09-29 01:01:44 +00:00
/*lockOutObservationWindow
lockoutThreshold $ pwdProperties */
static uint32 ap [ 9 ] ;
static uint32 ap_usn = 0 ;
uint32 tmp_usn = 0 ;
2002-09-28 12:27:04 +00:00
2002-10-21 15:36:51 +00:00
SAM_ASSERT ( privates & & ads_struct & & value ) ;
FIXME ( " We need to decode all account_policy attributes! \n " ) ;
2002-09-28 12:27:04 +00:00
2002-10-21 15:36:51 +00:00
ads_status = sam_ads_usn_is_valid ( privates , ap_usn , & tmp_usn ) ;
2002-09-29 01:01:44 +00:00
if ( ! ADS_ERR_OK ( ads_status ) ) {
ads_status = sam_ads_do_search ( privates , ads_struct - > config . bind_path , LDAP_SCOPE_BASE , " (objectClass=*) " , ap_attrs , & ap_res ) ;
if ( ! ADS_ERR_OK ( ads_status ) )
return ads_status ;
if ( ads_count_replies ( ads_struct , ap_res ) ! = 1 ) {
ads_msgfree ( ads_struct , ap_res ) ;
return ADS_ERROR ( LDAP_NO_RESULTS_RETURNED ) ;
}
if ( ! ( ap_msg = ads_first_entry ( ads_struct , ap_res ) ) ) {
ads_msgfree ( ads_struct , ap_res ) ;
return ADS_ERROR ( LDAP_NO_RESULTS_RETURNED ) ;
}
if ( ! ads_pull_uint32 ( ads_struct , ap_msg , ap_attrs [ 0 ] , & ap [ 0 ] ) ) {
/* AP_MIN_PASSWORD_LEN */
ap [ 0 ] = MINPASSWDLENGTH ; /* 5 chars minimum */
}
if ( ! ads_pull_uint32 ( ads_struct , ap_msg , ap_attrs [ 1 ] , & ap [ 1 ] ) ) {
/* AP_PASSWORD_HISTORY */
ap [ 1 ] = 0 ; /* don't keep any old password */
}
if ( ! ads_pull_uint32 ( ads_struct , ap_msg , ap_attrs [ 2 ] , & ap [ 2 ] ) ) {
/* AP_USER_MUST_LOGON_TO_CHG_PASS */
ap [ 2 ] = 0 ; /* don't force user to logon */
}
if ( ! ads_pull_uint32 ( ads_struct , ap_msg , ap_attrs [ 3 ] , & ap [ 3 ] ) ) {
/* AP_MAX_PASSWORD_AGE */
ap [ 3 ] = MAX_PASSWORD_AGE ; /* 21 days */
}
if ( ! ads_pull_uint32 ( ads_struct , ap_msg , ap_attrs [ 4 ] , & ap [ 4 ] ) ) {
/* AP_MIN_PASSWORD_AGE */
ap [ 4 ] = 0 ; /* 0 days */
}
if ( ! ads_pull_uint32 ( ads_struct , ap_msg , ap_attrs [ 5 ] , & ap [ 5 ] ) ) {
/* AP_LOCK_ACCOUNT_DURATION */
ap [ 5 ] = 0 ; /* lockout for 0 minutes */
}
if ( ! ads_pull_uint32 ( ads_struct , ap_msg , ap_attrs [ 6 ] , & ap [ 6 ] ) ) {
/* AP_RESET_COUNT_TIME */
ap [ 6 ] = 0 ; /* reset immediatly */
}
if ( ! ads_pull_uint32 ( ads_struct , ap_msg , ap_attrs [ 7 ] , & ap [ 7 ] ) ) {
/* AP_BAD_ATTEMPT_LOCKOUT */
ap [ 7 ] = 0 ; /* don't lockout */
}
if ( ! ads_pull_uint32 ( ads_struct , ap_msg , ap_attrs [ 8 ] , & ap [ 8 ] ) ) {
/* AP_TIME_TO_LOGOUT */
ap [ 8 ] = - 1 ; /* don't force logout */
}
ads_msgfree ( ads_struct , ap_res ) ;
ap_usn = tmp_usn ;
}
2002-09-28 12:27:04 +00:00
switch ( field ) {
2002-09-29 01:01:44 +00:00
case AP_MIN_PASSWORD_LEN :
* value = ap [ 0 ] ;
ads_status = ADS_ERROR_NT ( NT_STATUS_OK ) ;
break ;
case AP_PASSWORD_HISTORY :
* value = ap [ 1 ] ;
ads_status = ADS_ERROR_NT ( NT_STATUS_OK ) ;
break ;
case AP_USER_MUST_LOGON_TO_CHG_PASS :
* value = ap [ 2 ] ;
ads_status = ADS_ERROR_NT ( NT_STATUS_OK ) ;
break ;
case AP_MAX_PASSWORD_AGE :
* value = ap [ 3 ] ;
ads_status = ADS_ERROR_NT ( NT_STATUS_OK ) ;
break ;
case AP_MIN_PASSWORD_AGE :
* value = ap [ 4 ] ;
ads_status = ADS_ERROR_NT ( NT_STATUS_OK ) ;
break ;
case AP_LOCK_ACCOUNT_DURATION :
* value = ap [ 5 ] ;
ads_status = ADS_ERROR_NT ( NT_STATUS_OK ) ;
break ;
case AP_RESET_COUNT_TIME :
* value = ap [ 6 ] ;
ads_status = ADS_ERROR_NT ( NT_STATUS_OK ) ;
break ;
case AP_BAD_ATTEMPT_LOCKOUT :
* value = ap [ 7 ] ;
ads_status = ADS_ERROR_NT ( NT_STATUS_OK ) ;
break ;
case AP_TIME_TO_LOGOUT :
* value = ap [ 8 ] ;
ads_status = ADS_ERROR_NT ( NT_STATUS_OK ) ;
break ;
2002-09-28 12:27:04 +00:00
default : * value = 0 ; break ;
}
return ads_status ;
}
2002-10-21 15:36:51 +00:00
2002-09-28 12:27:04 +00:00
/**********************************
Now the functions off the SAM API
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* General API */
static NTSTATUS sam_ads_get_sec_desc ( const SAM_METHODS * sam_method , const NT_USER_TOKEN * access_token ,
const DOM_SID * sid , SEC_DESC * * sd )
{
ADS_STATUS ads_status = ADS_ERROR_NT ( NT_STATUS_UNSUCCESSFUL ) ;
2002-10-21 15:36:51 +00:00
SAM_ADS_PRIVATES * privates = ( struct sam_ads_privates * ) sam_method - > private_data ;
2002-09-28 12:27:04 +00:00
ADS_STRUCT * ads_struct = privates - > ads_struct ;
TALLOC_CTX * mem_ctx ;
char * sidstr , * filter ;
void * sec_desc_res ;
void * sec_desc_msg ;
const char * sec_desc_attrs [ ] = { " nTSecurityDescriptor " , NULL } ;
fstring sid_str ;
SEC_DESC * my_sd ;
SAM_ASSERT ( sam_method & & access_token & & sid & & sd ) ;
2002-10-21 15:36:51 +00:00
ads_status = sam_ads_get_tree_sec_desc ( privates , ADS_ROOT_TREE , & my_sd ) ;
2002-09-28 12:27:04 +00:00
if ( ! ADS_ERR_OK ( ads_status ) )
return ads_ntstatus ( ads_status ) ;
2002-10-21 15:36:51 +00:00
ads_status = sam_ads_access_check ( privates , my_sd , access_token , GENERIC_RIGHTS_DOMAIN_READ , NULL ) ;
2002-09-28 12:27:04 +00:00
if ( ! ADS_ERR_OK ( ads_status ) )
return ads_ntstatus ( ads_status ) ;
sidstr = sid_binstring ( sid ) ;
if ( asprintf ( & filter , " (objectSid=%s) " , sidstr ) = = - 1 ) {
SAFE_FREE ( sidstr ) ;
return NT_STATUS_NO_MEMORY ;
}
SAFE_FREE ( sidstr ) ;
ads_status = sam_ads_do_search ( privates , ads_struct - > config . bind_path ,
LDAP_SCOPE_SUBTREE , filter , sec_desc_attrs ,
& sec_desc_res ) ;
SAFE_FREE ( filter ) ;
if ( ! ADS_ERR_OK ( ads_status ) ) {
return ads_ntstatus ( ads_status ) ;
}
if ( ! ( mem_ctx = talloc_init_named ( " sec_desc parse in sam_ads " ) ) ) {
DEBUG ( 1 , ( " talloc_init_named() failed for sec_desc parse context in sam_ads " ) ) ;
ads_msgfree ( ads_struct , sec_desc_res ) ;
return NT_STATUS_NO_MEMORY ;
}
if ( ads_count_replies ( ads_struct , sec_desc_res ) ! = 1 ) {
DEBUG ( 1 , ( " sam_ads_get_sec_desc: duplicate or 0 results for sid %s \n " ,
sid_to_string ( sid_str , sid ) ) ) ;
talloc_destroy ( mem_ctx ) ;
ads_msgfree ( ads_struct , sec_desc_res ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
if ( ! ( sec_desc_msg = ads_first_entry ( ads_struct , sec_desc_res ) ) ) {
talloc_destroy ( mem_ctx ) ;
ads_msgfree ( ads_struct , sec_desc_res ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
if ( ! ads_pull_sd ( ads_struct , mem_ctx , sec_desc_msg , sec_desc_attrs [ 0 ] , sd ) ) {
ads_status = ADS_ERROR_NT ( NT_STATUS_INVALID_PARAMETER ) ;
talloc_destroy ( mem_ctx ) ;
ads_msgfree ( ads_struct , sec_desc_res ) ;
return ads_ntstatus ( ads_status ) ;
}
/* now, were we allowed to see the SD we just got? */
ads_msgfree ( ads_struct , sec_desc_res ) ;
talloc_destroy ( mem_ctx ) ;
return ads_ntstatus ( ads_status ) ;
}
static NTSTATUS sam_ads_set_sec_desc ( const SAM_METHODS * sam_method , const NT_USER_TOKEN * access_token ,
const DOM_SID * sid , const SEC_DESC * sd )
{
ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED ;
DEBUG ( 0 , ( " sam_ads: %s was called! \n " , __FUNCTION__ ) ) ;
SAM_ASSERT ( sam_method ) ;
return ads_ntstatus ( ads_status ) ;
}
static NTSTATUS sam_ads_lookup_sid ( const SAM_METHODS * sam_method , const NT_USER_TOKEN * access_token ,
TALLOC_CTX * mem_ctx , const DOM_SID * sid , char * * name ,
enum SID_NAME_USE * type )
{
2002-09-29 01:01:44 +00:00
ADS_STATUS ads_status = ADS_ERROR_NT ( NT_STATUS_UNSUCCESSFUL ) ;
2002-10-21 15:36:51 +00:00
SAM_ADS_PRIVATES * privates = ( struct sam_ads_privates * ) sam_method - > private_data ;
2002-09-28 12:27:04 +00:00
ADS_STRUCT * ads_struct = privates - > ads_struct ;
2002-09-29 01:01:44 +00:00
SEC_DESC * my_sd ;
SAM_ASSERT ( sam_method & & access_token & & mem_ctx & & sid & & name & & type ) ;
2002-10-21 15:36:51 +00:00
ads_status = sam_ads_get_tree_sec_desc ( privates , ADS_ROOT_TREE , & my_sd ) ;
2002-09-29 01:01:44 +00:00
if ( ! ADS_ERR_OK ( ads_status ) )
return ads_ntstatus ( ads_status ) ;
2002-09-28 12:27:04 +00:00
2002-10-21 15:36:51 +00:00
ads_status = sam_ads_access_check ( privates , my_sd , access_token , GENERIC_RIGHTS_DOMAIN_READ , NULL ) ;
2002-09-29 01:01:44 +00:00
if ( ! ADS_ERR_OK ( ads_status ) )
return ads_ntstatus ( ads_status ) ;
2002-09-28 12:27:04 +00:00
return ads_sid_to_name ( ads_struct , mem_ctx , sid , name , type ) ;
}
static NTSTATUS sam_ads_lookup_name ( const SAM_METHODS * sam_method , const NT_USER_TOKEN * access_token ,
const char * name , DOM_SID * sid , enum SID_NAME_USE * type )
{
2002-09-29 01:01:44 +00:00
ADS_STATUS ads_status = ADS_ERROR_NT ( NT_STATUS_UNSUCCESSFUL ) ;
2002-10-21 15:36:51 +00:00
SAM_ADS_PRIVATES * privates = ( struct sam_ads_privates * ) sam_method - > private_data ;
2002-09-28 12:27:04 +00:00
ADS_STRUCT * ads_struct = privates - > ads_struct ;
2002-09-29 01:01:44 +00:00
SEC_DESC * my_sd ;
2002-09-28 12:27:04 +00:00
2002-09-29 01:01:44 +00:00
SAM_ASSERT ( sam_method & & access_token & & name & & sid & & type ) ;
2002-10-21 15:36:51 +00:00
ads_status = sam_ads_get_tree_sec_desc ( privates , ADS_ROOT_TREE , & my_sd ) ;
2002-09-29 01:01:44 +00:00
if ( ! ADS_ERR_OK ( ads_status ) )
return ads_ntstatus ( ads_status ) ;
2002-10-21 15:36:51 +00:00
ads_status = sam_ads_access_check ( privates , my_sd , access_token , GENERIC_RIGHTS_DOMAIN_READ , NULL ) ;
2002-09-29 01:01:44 +00:00
if ( ! ADS_ERR_OK ( ads_status ) )
return ads_ntstatus ( ads_status ) ;
2002-09-28 12:27:04 +00:00
return ads_name_to_sid ( ads_struct , name , sid , type ) ;
}
/* Domain API */
static NTSTATUS sam_ads_update_domain ( const SAM_METHODS * sam_method , const SAM_DOMAIN_HANDLE * domain )
{
ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED ;
DEBUG ( 0 , ( " sam_ads: %s was called! \n " , __FUNCTION__ ) ) ;
SAM_ASSERT ( sam_method ) ;
return ads_ntstatus ( ads_status ) ;
}
static NTSTATUS sam_ads_get_domain_handle ( const SAM_METHODS * sam_method , const NT_USER_TOKEN * access_token ,
const uint32 access_desired , SAM_DOMAIN_HANDLE * * domain )
{
ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED ;
2002-10-21 15:36:51 +00:00
SAM_ADS_PRIVATES * privates = ( struct sam_ads_privates * ) sam_method - > private_data ;
2002-09-28 12:27:04 +00:00
TALLOC_CTX * mem_ctx = privates - > mem_ctx ; /*Fix me is this right??? */
SAM_DOMAIN_HANDLE * dom_handle = NULL ;
SEC_DESC * sd ;
uint32 acc_granted ;
uint32 tmp_value ;
DEBUG ( 5 , ( " sam_ads_get_domain_handle: %d \n " , __LINE__ ) ) ;
2002-09-29 01:01:44 +00:00
SAM_ASSERT ( sam_method & & access_token & & domain ) ;
2002-09-28 12:27:04 +00:00
( * domain ) = NULL ;
if ( ( dom_handle = talloc ( mem_ctx , sizeof ( SAM_DOMAIN_HANDLE ) ) ) = = NULL ) {
DEBUG ( 0 , ( " failed to talloc dom_handle \n " ) ) ;
ads_status = ADS_ERROR_NT ( NT_STATUS_NO_MEMORY ) ;
return ads_ntstatus ( ads_status ) ;
}
ZERO_STRUCTP ( dom_handle ) ;
dom_handle - > mem_ctx = mem_ctx ; /*Fix me is this right??? */
dom_handle - > free_fn = NULL ;
dom_handle - > current_sam_methods = sam_method ;
/* check if access can be granted as requested */
2002-10-21 15:36:51 +00:00
ads_status = sam_ads_get_tree_sec_desc ( privates , ADS_ROOT_TREE , & sd ) ;
2002-09-28 12:27:04 +00:00
if ( ! ADS_ERR_OK ( ads_status ) )
return ads_ntstatus ( ads_status ) ;
2002-10-21 15:36:51 +00:00
ads_status = sam_ads_access_check ( privates , sd , access_token , access_desired , & acc_granted ) ;
2002-09-28 12:27:04 +00:00
if ( ! ADS_ERR_OK ( ads_status ) )
return ads_ntstatus ( ads_status ) ;
dom_handle - > access_granted = acc_granted ;
/* fill all the values of dom_handle */
sid_copy ( & dom_handle - > private . sid , & sam_method - > domain_sid ) ;
dom_handle - > private . name = smb_xstrdup ( sam_method - > domain_name ) ;
dom_handle - > private . servername = " WHOKNOWS " ; /* what is the servername */
/*Fix me: sam_ads_account_policy_get() return ADS_STATUS! */
2002-10-21 15:36:51 +00:00
ads_status = sam_ads_account_policy_get ( privates , AP_MAX_PASSWORD_AGE , & tmp_value ) ;
2002-09-28 12:27:04 +00:00
if ( ! ADS_ERR_OK ( ads_status ) ) {
DEBUG ( 4 , ( " sam_ads_account_policy_get failed for max password age. Useing default \n " ) ) ;
tmp_value = MAX_PASSWORD_AGE ;
}
unix_to_nt_time_abs ( & dom_handle - > private . max_passwordage , tmp_value ) ;
2002-10-21 15:36:51 +00:00
ads_status = sam_ads_account_policy_get ( privates , AP_MIN_PASSWORD_AGE , & tmp_value ) ;
2002-09-28 12:27:04 +00:00
if ( ! ADS_ERR_OK ( ads_status ) ) {
DEBUG ( 4 , ( " sam_ads_account_policy_get failed for min password age. Useing default \n " ) ) ;
tmp_value = 0 ;
}
unix_to_nt_time_abs ( & dom_handle - > private . min_passwordage , tmp_value ) ;
2002-10-21 15:36:51 +00:00
ads_status = sam_ads_account_policy_get ( privates , AP_LOCK_ACCOUNT_DURATION , & tmp_value ) ;
2002-09-28 12:27:04 +00:00
if ( ! ADS_ERR_OK ( ads_status ) ) {
DEBUG ( 4 , ( " sam_ads_account_policy_get failed for lockout duration. Useing default \n " ) ) ;
tmp_value = 0 ;
}
unix_to_nt_time_abs ( & dom_handle - > private . lockout_duration , tmp_value ) ;
2002-10-21 15:36:51 +00:00
ads_status = sam_ads_account_policy_get ( privates , AP_RESET_COUNT_TIME , & tmp_value ) ;
2002-09-28 12:27:04 +00:00
if ( ! ADS_ERR_OK ( ads_status ) ) {
DEBUG ( 4 , ( " sam_ads_account_policy_get failed for time till locout count is reset. Useing default \n " ) ) ;
tmp_value = 0 ;
}
unix_to_nt_time_abs ( & dom_handle - > private . reset_count , tmp_value ) ;
2002-10-21 15:36:51 +00:00
ads_status = sam_ads_account_policy_get ( privates , AP_MIN_PASSWORD_LEN , & tmp_value ) ;
2002-09-28 12:27:04 +00:00
if ( ! ADS_ERR_OK ( ads_status ) ) {
DEBUG ( 4 , ( " sam_ads_account_policy_get failed for min password length. Useing default \n " ) ) ;
tmp_value = 0 ;
}
dom_handle - > private . min_passwordlength = ( uint16 ) tmp_value ;
2002-10-21 15:36:51 +00:00
ads_status = sam_ads_account_policy_get ( privates , AP_PASSWORD_HISTORY , & tmp_value ) ;
2002-09-28 12:27:04 +00:00
if ( ! ADS_ERR_OK ( ads_status ) ) {
DEBUG ( 4 , ( " sam_ads_account_policy_get failed password history. Useing default \n " ) ) ;
tmp_value = 0 ;
}
dom_handle - > private . password_history = ( uint16 ) tmp_value ;
2002-10-21 15:36:51 +00:00
ads_status = sam_ads_account_policy_get ( privates , AP_BAD_ATTEMPT_LOCKOUT , & tmp_value ) ;
2002-09-28 12:27:04 +00:00
if ( ! ADS_ERR_OK ( ads_status ) ) {
DEBUG ( 4 , ( " sam_ads_account_policy_get failed for bad attempts till lockout. Useing default \n " ) ) ;
tmp_value = 0 ;
}
dom_handle - > private . lockout_count = ( uint16 ) tmp_value ;
2002-10-21 15:36:51 +00:00
ads_status = sam_ads_account_policy_get ( privates , AP_TIME_TO_LOGOUT , & tmp_value ) ;
2002-09-28 12:27:04 +00:00
if ( ! ADS_ERR_OK ( ads_status ) ) {
DEBUG ( 4 , ( " sam_ads_account_policy_get failed for force logout. Useing default \n " ) ) ;
tmp_value = - 1 ;
}
2002-10-21 15:36:51 +00:00
ads_status = sam_ads_account_policy_get ( privates , AP_USER_MUST_LOGON_TO_CHG_PASS , & tmp_value ) ;
2002-09-28 12:27:04 +00:00
if ( ! ADS_ERR_OK ( ads_status ) ) {
DEBUG ( 4 , ( " sam_ads_account_policy_get failed for user must login to change password. Useing default \n " ) ) ;
tmp_value = 0 ;
}
/* should the real values of num_accounts, num_groups and num_aliases be retreved?
* I think it is to expensive to bother
*/
dom_handle - > private . num_accounts = 3 ;
dom_handle - > private . num_groups = 4 ;
dom_handle - > private . num_aliases = 5 ;
* domain = dom_handle ;
ads_status = ADS_ERROR_NT ( NT_STATUS_OK ) ;
return ads_ntstatus ( ads_status ) ;
}
/* Account API */
static NTSTATUS sam_ads_create_account ( const SAM_METHODS * sam_method ,
const NT_USER_TOKEN * access_token , uint32 access_desired ,
const char * account_name , uint16 acct_ctrl , SAM_ACCOUNT_HANDLE * * account )
{
ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED ;
2002-10-21 15:36:51 +00:00
SAM_ADS_PRIVATES * privates = ( struct sam_ads_privates * ) sam_method - > private_data ;
2002-09-28 12:27:04 +00:00
SEC_DESC * sd = NULL ;
2002-10-21 15:36:51 +00:00
uint32 acc_granted ;
2002-09-28 12:27:04 +00:00
2002-10-21 15:36:51 +00:00
SAM_ASSERT ( sam_method & & privates & & access_token & & account_name & & account ) ;
2002-09-28 12:27:04 +00:00
2002-10-21 15:36:51 +00:00
ads_status = sam_ads_get_tree_sec_desc ( privates , ADS_SUBTREE_USERS , & sd ) ;
2002-09-28 12:27:04 +00:00
if ( ! ADS_ERR_OK ( ads_status ) )
return ads_ntstatus ( ads_status ) ;
2002-10-21 15:36:51 +00:00
ads_status = sam_ads_access_check ( privates , sd , access_token , access_desired , & acc_granted ) ;
2002-09-28 12:27:04 +00:00
if ( ! ADS_ERR_OK ( ads_status ) )
return ads_ntstatus ( ads_status ) ;
2002-09-28 14:26:19 +00:00
ads_status = ADS_ERROR_NT ( sam_init_account ( account ) ) ;
2002-09-28 12:27:04 +00:00
if ( ! ADS_ERR_OK ( ads_status ) )
return ads_ntstatus ( ads_status ) ;
2002-10-21 15:36:51 +00:00
( * account ) - > access_granted = acc_granted ;
2002-09-28 12:27:04 +00:00
return ads_ntstatus ( ads_status ) ;
}
static NTSTATUS sam_ads_add_account ( const SAM_METHODS * sam_method , const SAM_ACCOUNT_HANDLE * account )
{
ADS_STATUS ads_status = ADS_ERROR ( LDAP_NO_MEMORY ) ;
2002-10-21 15:36:51 +00:00
SAM_ADS_PRIVATES * privates = ( struct sam_ads_privates * ) sam_method - > private_data ;
2002-09-28 12:27:04 +00:00
ADS_STRUCT * ads_struct = privates - > ads_struct ;
TALLOC_CTX * mem_ctx = privates - > mem_ctx ;
ADS_MODLIST mods ;
uint16 acct_ctrl ;
char * new_dn ;
2002-10-21 15:36:51 +00:00
SEC_DESC * sd ;
uint32 acc_granted ;
2002-09-28 12:27:04 +00:00
SAM_ASSERT ( sam_method & & account ) ;
2002-10-21 15:36:51 +00:00
2002-09-28 12:27:04 +00:00
ads_status = ADS_ERROR_NT ( sam_get_account_acct_ctrl ( account , & acct_ctrl ) ) ;
if ( ! ADS_ERR_OK ( ads_status ) )
goto done ;
if ( ( acct_ctrl & ACB_WSTRUST ) | | ( acct_ctrl & ACB_SVRTRUST ) ) {
/* Computer account */
char * name , * controlstr ;
char * hostname , * host_upn , * host_spn ;
const char * objectClass [ ] = { " top " , " person " , " organizationalPerson " ,
" user " , " computer " , NULL } ;
ads_status = ADS_ERROR_NT ( sam_get_account_name ( account , & name ) ) ;
if ( ! ADS_ERR_OK ( ads_status ) )
goto done ;
if ( ! ( host_upn = talloc_asprintf ( mem_ctx , " %s@%s " , name , ads_struct - > config . realm ) ) ) {
ads_status = ADS_ERROR_NT ( NT_STATUS_NO_MEMORY ) ;
goto done ;
}
if ( ! ( new_dn = talloc_asprintf ( mem_ctx , " CN=%s,CN=Computers,%s " , hostname ,
ads_struct - > config . bind_path ) ) ) {
ads_status = ADS_ERROR_NT ( NT_STATUS_NO_MEMORY ) ;
goto done ;
}
if ( ! ( controlstr = talloc_asprintf ( mem_ctx , " %u " , ads_acb2uf ( acct_ctrl ) ) ) ) {
ads_status = ADS_ERROR_NT ( NT_STATUS_NO_MEMORY ) ;
goto done ;
}
if ( ! ( mods = ads_init_mods ( mem_ctx ) ) ) {
ads_status = ADS_ERROR_NT ( NT_STATUS_NO_MEMORY ) ;
goto done ;
}
ads_status = ads_mod_str ( mem_ctx , & mods , " cn " , hostname ) ;
if ( ! ADS_ERR_OK ( ads_status ) )
goto done ;
ads_status = ads_mod_strlist ( mem_ctx , & mods , " objectClass " , objectClass ) ;
if ( ! ADS_ERR_OK ( ads_status ) )
goto done ;
ads_status = ads_mod_str ( mem_ctx , & mods , " userPrincipalName " , host_upn ) ;
if ( ! ADS_ERR_OK ( ads_status ) )
goto done ;
ads_status = ads_mod_str ( mem_ctx , & mods , " displayName " , hostname ) ;
if ( ! ADS_ERR_OK ( ads_status ) )
goto done ;
ads_status = ads_mod_str ( mem_ctx , & mods , " sAMAccountName " , name ) ;
if ( ! ADS_ERR_OK ( ads_status ) )
goto done ;
ads_status = ads_mod_str ( mem_ctx , & mods , " userAccountControl " , controlstr ) ;
if ( ! ADS_ERR_OK ( ads_status ) )
goto done ;
ads_status = ads_mod_str ( mem_ctx , & mods , " servicePrincipalName " , host_spn ) ;
if ( ! ADS_ERR_OK ( ads_status ) )
goto done ;
ads_status = ads_mod_str ( mem_ctx , & mods , " dNSHostName " , hostname ) ;
if ( ! ADS_ERR_OK ( ads_status ) )
goto done ;
ads_status = ads_mod_str ( mem_ctx , & mods , " userAccountControl " , controlstr ) ;
if ( ! ADS_ERR_OK ( ads_status ) )
goto done ;
/* ads_status = ads_mod_str(mem_ctx, &mods, "operatingSystem", "Samba");
if ( ! ADS_ERR_OK ( ads_status ) )
goto done ;
*/ /* ads_status = ads_mod_str(mem_ctx, &mods, "operatingSystemVersion", VERSION);
if ( ! ADS_ERR_OK ( ads_status ) )
goto done ;
*/
/* End Computer account */
} else {
/* User account*/
char * upn , * controlstr ;
char * name , * fullname ;
const char * objectClass [ ] = { " top " , " person " , " organizationalPerson " ,
" user " , NULL } ;
ads_status = ADS_ERROR_NT ( sam_get_account_name ( account , & name ) ) ;
if ( ! ADS_ERR_OK ( ads_status ) )
goto done ;
ads_status = ADS_ERROR_NT ( sam_get_account_fullname ( account , & fullname ) ) ;
if ( ! ADS_ERR_OK ( ads_status ) )
goto done ;
if ( ! ( upn = talloc_asprintf ( mem_ctx , " %s@%s " , name , ads_struct - > config . realm ) ) ) {
ads_status = ADS_ERROR_NT ( NT_STATUS_NO_MEMORY ) ;
goto done ;
}
if ( ! ( new_dn = talloc_asprintf ( mem_ctx , " CN=%s,CN=Users,%s " , fullname ,
ads_struct - > config . bind_path ) ) ) {
ads_status = ADS_ERROR_NT ( NT_STATUS_NO_MEMORY ) ;
goto done ;
}
if ( ! ( controlstr = talloc_asprintf ( mem_ctx , " %u " , ads_acb2uf ( acct_ctrl ) ) ) ) {
ads_status = ADS_ERROR_NT ( NT_STATUS_NO_MEMORY ) ;
goto done ;
}
if ( ! ( mods = ads_init_mods ( mem_ctx ) ) ) {
ads_status = ADS_ERROR_NT ( NT_STATUS_NO_MEMORY ) ;
goto done ;
}
ads_status = ads_mod_str ( mem_ctx , & mods , " cn " , fullname ) ;
if ( ! ADS_ERR_OK ( ads_status ) )
goto done ;
ads_status = ads_mod_strlist ( mem_ctx , & mods , " objectClass " , objectClass ) ;
if ( ! ADS_ERR_OK ( ads_status ) )
goto done ;
ads_status = ads_mod_str ( mem_ctx , & mods , " userPrincipalName " , upn ) ;
if ( ! ADS_ERR_OK ( ads_status ) )
goto done ;
ads_status = ads_mod_str ( mem_ctx , & mods , " displayName " , fullname ) ;
if ( ! ADS_ERR_OK ( ads_status ) )
goto done ;
ads_status = ads_mod_str ( mem_ctx , & mods , " sAMAccountName " , name ) ;
if ( ! ADS_ERR_OK ( ads_status ) )
goto done ;
ads_status = ads_mod_str ( mem_ctx , & mods , " userAccountControl " , controlstr ) ;
if ( ! ADS_ERR_OK ( ads_status ) )
goto done ;
} /* End User account */
/* Finally at the account */
ads_status = ads_gen_add ( ads_struct , new_dn , mods ) ;
done :
return ads_ntstatus ( ads_status ) ;
}
static NTSTATUS sam_ads_update_account ( const SAM_METHODS * sam_method , const SAM_ACCOUNT_HANDLE * account )
{
ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED ;
DEBUG ( 0 , ( " sam_ads: %s was called! \n " , __FUNCTION__ ) ) ;
SAM_ASSERT ( sam_method ) ;
return ads_ntstatus ( ads_status ) ;
}
static NTSTATUS sam_ads_delete_account ( const SAM_METHODS * sam_method , const SAM_ACCOUNT_HANDLE * account )
{
ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED ;
DEBUG ( 0 , ( " sam_ads: %s was called! \n " , __FUNCTION__ ) ) ;
SAM_ASSERT ( sam_method ) ;
return ads_ntstatus ( ads_status ) ;
}
static NTSTATUS sam_ads_enum_accounts ( const SAM_METHODS * sam_method , const NT_USER_TOKEN * access_token , uint16 acct_ctrl , uint32 * account_count , SAM_ACCOUNT_ENUM * * accounts )
{
ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED ;
DEBUG ( 0 , ( " sam_ads: %s was called! \n " , __FUNCTION__ ) ) ;
SAM_ASSERT ( sam_method ) ;
return ads_ntstatus ( ads_status ) ;
}
2002-10-21 15:36:51 +00:00
#if 0
static NTSTATUS sam_ads_get_account_by_sid ( const SAM_METHODS * sam_method , const NT_USER_TOKEN * access_token , const uint32 access_desired , const DOM_SID * account_sid , SAM_ACCOUNT_HANDLE * * account )
{
ADS_STATUS ads_status = ADS_ERROR_NT ( NT_STATUS_UNSUCCESSFUL ) ;
SAM_ADS_PRIVATES * privates = ( struct sam_ads_privates * ) sam_method - > private_data ;
ADS_STRUCT * ads_struct = privates - > ads_struct ;
TALLOC_CTX * mem_ctx = privates - > mem_ctx ;
SEC_DESC * sd = NULL ;
uint32 acc_granted ;
SAM_ASSERT ( sam_method & & privates & & ads_struct & & access_token & & account_sid & & account ) ;
ads_status = ADS_ERROR_NT ( sam_ads_get_sec_desc ( sam_method , access_token , account_sid , & my_sd ) ) ;
if ( ! ADS_ERR_OK ( ads_status ) )
return ads_ntstatus ( ads_status ) ;
ads_status = sam_ads_access_check ( privates , sd , access_token , access_desired , & acc_granted ) ;
if ( ! ADS_ERR_OK ( ads_status ) )
return ads_ntstatus ( ads_status ) ;
ads_status = ADS_ERROR_NT ( sam_init_account ( account ) ) ;
if ( ! ADS_ERR_OK ( ads_status ) )
return ads_ntstatus ( ads_status ) ;
( * account ) - > access_granted = acc_granted ;
return ads_ntstatus ( ads_status ) ;
}
# else
static NTSTATUS sam_ads_get_account_by_sid ( const SAM_METHODS * sam_method , const NT_USER_TOKEN * access_token , const uint32 access_desired , const DOM_SID * account_sid , SAM_ACCOUNT_HANDLE * * account )
2002-09-28 12:27:04 +00:00
{
ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED ;
DEBUG ( 0 , ( " sam_ads: %s was called! \n " , __FUNCTION__ ) ) ;
SAM_ASSERT ( sam_method ) ;
return ads_ntstatus ( ads_status ) ;
}
2002-10-21 15:36:51 +00:00
# endif
2002-09-28 12:27:04 +00:00
2002-10-21 15:36:51 +00:00
#if 0
static NTSTATUS sam_ads_get_account_by_name ( const SAM_METHODS * sam_method , const NT_USER_TOKEN * access_token , const uint32 access_desired , const char * account_name , SAM_ACCOUNT_HANDLE * * account )
{
ADS_STATUS ads_status = ADS_ERROR_NT ( NT_STATUS_UNSUCCESSFUL ) ;
SAM_ADS_PRIVATES * privates = ( struct sam_ads_privates * ) sam_method - > private_data ;
ADS_STRUCT * ads_struct = privates - > ads_struct ;
TALLOC_CTX * mem_ctx = privates - > mem_ctx ;
SEC_DESC * sd = NULL ;
uint32 acc_granted ;
SAM_ASSERT ( sam_method & & privates & & ads_struct & & access_token & & account_name & & account ) ;
ads_status = sam_ads_get_tree_sec_desc ( privates , ADS_ROOT_TREE , & sd ) ;
if ( ! ADS_ERR_OK ( ads_status ) )
return ads_ntstatus ( ads_status ) ;
ads_status = sam_ads_access_check ( privates , sd , access_token , access_desired , & acc_granted ) ;
if ( ! ADS_ERR_OK ( ads_status ) )
return ads_ntstatus ( ads_status ) ;
ads_status = ADS_ERROR_NT ( sam_init_account ( account ) ) ;
if ( ! ADS_ERR_OK ( ads_status ) )
return ads_ntstatus ( ads_status ) ;
( * account ) - > access_granted = acc_granted ;
return ads_ntstatus ( ads_status ) ;
}
# else
static NTSTATUS sam_ads_get_account_by_name ( const SAM_METHODS * sam_method , const NT_USER_TOKEN * access_token , const uint32 access_desired , const char * account_name , SAM_ACCOUNT_HANDLE * * account )
2002-09-28 12:27:04 +00:00
{
ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED ;
DEBUG ( 0 , ( " sam_ads: %s was called! \n " , __FUNCTION__ ) ) ;
SAM_ASSERT ( sam_method ) ;
return ads_ntstatus ( ads_status ) ;
}
2002-10-21 15:36:51 +00:00
# endif
2002-09-28 12:27:04 +00:00
/* Group API */
static NTSTATUS sam_ads_create_group ( const SAM_METHODS * sam_method , const NT_USER_TOKEN * access_token , uint32 access_desired , const char * group_name , uint16 group_ctrl , SAM_GROUP_HANDLE * * group )
{
ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED ;
DEBUG ( 0 , ( " sam_ads: %s was called! \n " , __FUNCTION__ ) ) ;
SAM_ASSERT ( sam_method ) ;
return ads_ntstatus ( ads_status ) ;
}
static NTSTATUS sam_ads_add_group ( const SAM_METHODS * sam_method , const SAM_GROUP_HANDLE * group )
{
ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED ;
DEBUG ( 0 , ( " sam_ads: %s was called! \n " , __FUNCTION__ ) ) ;
SAM_ASSERT ( sam_method ) ;
return ads_ntstatus ( ads_status ) ;
}
static NTSTATUS sam_ads_update_group ( const SAM_METHODS * sam_method , const SAM_GROUP_HANDLE * group )
{
ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED ;
DEBUG ( 0 , ( " sam_ads: %s was called! \n " , __FUNCTION__ ) ) ;
SAM_ASSERT ( sam_method ) ;
return ads_ntstatus ( ads_status ) ;
}
static NTSTATUS sam_ads_delete_group ( const SAM_METHODS * sam_method , const SAM_GROUP_HANDLE * group )
{
ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED ;
DEBUG ( 0 , ( " sam_ads: %s was called! \n " , __FUNCTION__ ) ) ;
SAM_ASSERT ( sam_method ) ;
return ads_ntstatus ( ads_status ) ;
}
static NTSTATUS sam_ads_enum_groups ( const SAM_METHODS * sam_method , const NT_USER_TOKEN * access_token , const uint16 group_ctrl , uint32 * groups_count , SAM_GROUP_ENUM * * groups )
{
ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED ;
2002-10-21 15:36:51 +00:00
SAM_ADS_PRIVATES * privates = ( struct sam_ads_privates * ) sam_method - > private_data ;
2002-09-28 12:27:04 +00:00
ADS_STRUCT * ads_struct = privates - > ads_struct ;
TALLOC_CTX * mem_ctx = privates - > mem_ctx ;
void * res = NULL ;
void * msg = NULL ;
char * filter = NULL ;
int i = 0 ;
/* get only these LDAP attributes, witch we really need for a group */
const char * group_enum_attrs [ ] = { " objectSid " ,
" description " ,
" sAMAcountName " ,
NULL } ;
SAM_ASSERT ( sam_method & & access_token & & groups_count & & groups ) ;
* groups_count = 0 ;
DEBUG ( 3 , ( " ads: enum_dom_groups \n " ) ) ;
2002-10-21 15:36:51 +00:00
FIXME ( " get only group from the wanted Type! \n " ) ;
2002-09-28 12:27:04 +00:00
asprintf ( & filter , " (&(objectClass=group)(groupType=%s)) " , " * " ) ;
ads_status = sam_ads_do_search ( privates , ads_struct - > config . bind_path , LDAP_SCOPE_SUBTREE , filter , group_enum_attrs , & res ) ;
if ( ! ADS_ERR_OK ( ads_status ) ) {
DEBUG ( 1 , ( " enum_groups ads_search: %s \n " , ads_errstr ( ads_status ) ) ) ;
}
* groups_count = ads_count_replies ( ads_struct , res ) ;
if ( * groups_count = = 0 ) {
DEBUG ( 1 , ( " enum_groups: No groups found \n " ) ) ;
}
( * groups ) = talloc_zero ( mem_ctx , ( * groups_count ) * sizeof ( * * groups ) ) ;
if ( ! * groups ) {
ads_status = ADS_ERROR_NT ( NT_STATUS_NO_MEMORY ) ;
}
for ( msg = ads_first_entry ( ads_struct , res ) ; msg ; msg = ads_next_entry ( ads_struct , msg ) ) {
uint32 grouptype ;
if ( ! ads_pull_uint32 ( ads_struct , msg , " groupType " , & grouptype ) ) {
;
} else {
( * groups ) - > group_ctrl = ads_gtype2gcb ( grouptype ) ;
}
if ( ! ( ( * groups ) - > group_name = ads_pull_string ( ads_struct , mem_ctx , msg , " sAMAccountName " ) ) ) {
;
}
if ( ! ( ( * groups ) - > group_desc = ads_pull_string ( ads_struct , mem_ctx , msg , " description " ) ) ) {
;
}
if ( ! ads_pull_sid ( ads_struct , msg , " objectSid " , & ( ( * groups ) - > sid ) ) ) {
DEBUG ( 1 , ( " No sid for group %s !? \n " , ( * groups ) - > group_name ) ) ;
continue ;
}
i + + ;
}
( * groups_count ) = i ;
ads_status = ADS_ERROR_NT ( NT_STATUS_OK ) ;
DEBUG ( 3 , ( " ads enum_dom_groups gave %d entries \n " , ( * groups_count ) ) ) ;
if ( res ) ads_msgfree ( ads_struct , res ) ;
return ads_ntstatus ( ads_status ) ;
}
static NTSTATUS sam_ads_get_group_by_sid ( const SAM_METHODS * sam_method , const NT_USER_TOKEN * access_token , const uint32 access_desired , const DOM_SID * groupsid , SAM_GROUP_HANDLE * * group )
{
ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED ;
DEBUG ( 0 , ( " sam_ads: %s was called! \n " , __FUNCTION__ ) ) ;
SAM_ASSERT ( sam_method ) ;
return ads_ntstatus ( ads_status ) ;
}
static NTSTATUS sam_ads_get_group_by_name ( const SAM_METHODS * sam_method , const NT_USER_TOKEN * access_token , const uint32 access_desired , const char * name , SAM_GROUP_HANDLE * * group )
{
ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED ;
DEBUG ( 0 , ( " sam_ads: %s was called! \n " , __FUNCTION__ ) ) ;
SAM_ASSERT ( sam_method ) ;
return ads_ntstatus ( ads_status ) ;
}
static NTSTATUS sam_ads_add_member_to_group ( const SAM_METHODS * sam_method , const SAM_GROUP_HANDLE * group , const SAM_GROUP_MEMBER * member )
{
ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED ;
DEBUG ( 0 , ( " sam_ads: %s was called! \n " , __FUNCTION__ ) ) ;
SAM_ASSERT ( sam_method ) ;
return ads_ntstatus ( ads_status ) ;
}
static NTSTATUS sam_ads_delete_member_from_group ( const SAM_METHODS * sam_method , const SAM_GROUP_HANDLE * group , const SAM_GROUP_MEMBER * member )
{
ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED ;
DEBUG ( 0 , ( " sam_ads: %s was called! \n " , __FUNCTION__ ) ) ;
SAM_ASSERT ( sam_method ) ;
return ads_ntstatus ( ads_status ) ;
}
static NTSTATUS sam_ads_enum_groupmembers ( const SAM_METHODS * sam_method , const SAM_GROUP_HANDLE * group , uint32 * members_count , SAM_GROUP_MEMBER * * members )
{
ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED ;
DEBUG ( 0 , ( " sam_ads: %s was called! \n " , __FUNCTION__ ) ) ;
SAM_ASSERT ( sam_method ) ;
return ads_ntstatus ( ads_status ) ;
}
static NTSTATUS sam_ads_get_groups_of_sid ( const SAM_METHODS * sam_method , const NT_USER_TOKEN * access_token , const DOM_SID * * sids , const uint16 group_ctrl , uint32 * group_count , SAM_GROUP_ENUM * * groups )
{
ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED ;
DEBUG ( 0 , ( " sam_ads: %s was called! \n " , __FUNCTION__ ) ) ;
SAM_ASSERT ( sam_method ) ;
return ads_ntstatus ( ads_status ) ;
}
/**********************************
Free our private data
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void sam_ads_free_private_data ( void * * vp )
{
2002-10-21 15:36:51 +00:00
SAM_ADS_PRIVATES * * sam_ads_state = ( SAM_ADS_PRIVATES * * ) vp ;
2002-09-28 12:27:04 +00:00
if ( ( * sam_ads_state ) - > ads_struct - > ld ) {
ldap_unbind ( ( * sam_ads_state ) - > ads_struct - > ld ) ;
}
ads_destroy ( & ( ( * sam_ads_state ) - > ads_struct ) ) ;
talloc_destroy ( ( * sam_ads_state ) - > mem_ctx ) ;
2002-10-21 15:36:51 +00:00
FIXME ( " maybe we must free some other stuff here \n " ) ;
2002-09-28 12:27:04 +00:00
* sam_ads_state = NULL ;
}
/*****************************************************
Init the ADS SAM backend
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS sam_init_ads ( SAM_METHODS * sam_method , const char * module_params )
{
ADS_STATUS ads_status ;
2002-10-21 15:36:51 +00:00
SAM_ADS_PRIVATES * sam_ads_state ;
2002-09-28 12:27:04 +00:00
TALLOC_CTX * mem_ctx ;
SAM_ASSERT ( sam_method & & sam_method - > parent ) ;
mem_ctx = sam_method - > parent - > mem_ctx ;
/* Here the SAM API functions of the sam_ads module */
/* General API */
sam_method - > sam_get_sec_desc = sam_ads_get_sec_desc ;
sam_method - > sam_set_sec_desc = sam_ads_set_sec_desc ;
sam_method - > sam_lookup_sid = sam_ads_lookup_sid ;
sam_method - > sam_lookup_name = sam_ads_lookup_name ;
/* Domain API */
sam_method - > sam_update_domain = sam_ads_update_domain ;
sam_method - > sam_get_domain_handle = sam_ads_get_domain_handle ;
/* Account API */
sam_method - > sam_create_account = sam_ads_create_account ;
sam_method - > sam_add_account = sam_ads_add_account ;
sam_method - > sam_update_account = sam_ads_update_account ;
sam_method - > sam_delete_account = sam_ads_delete_account ;
sam_method - > sam_enum_accounts = sam_ads_enum_accounts ;
sam_method - > sam_get_account_by_sid = sam_ads_get_account_by_sid ;
sam_method - > sam_get_account_by_name = sam_ads_get_account_by_name ;
/* Group API */
sam_method - > sam_create_group = sam_ads_create_group ;
sam_method - > sam_add_group = sam_ads_add_group ;
sam_method - > sam_update_group = sam_ads_update_group ;
sam_method - > sam_delete_group = sam_ads_delete_group ;
sam_method - > sam_enum_groups = sam_ads_enum_groups ;
sam_method - > sam_get_group_by_sid = sam_ads_get_group_by_sid ;
sam_method - > sam_get_group_by_name = sam_ads_get_group_by_name ;
sam_method - > sam_add_member_to_group = sam_ads_add_member_to_group ;
sam_method - > sam_delete_member_from_group = sam_ads_delete_member_from_group ;
sam_method - > sam_enum_groupmembers = sam_ads_enum_groupmembers ;
sam_method - > sam_get_groups_of_sid = sam_ads_get_groups_of_sid ;
2002-10-21 15:36:51 +00:00
sam_ads_state = talloc_zero ( mem_ctx , sizeof ( SAM_ADS_PRIVATES ) ) ;
2002-09-28 12:27:04 +00:00
if ( ! sam_ads_state ) {
DEBUG ( 0 , ( " talloc() failed for sam_ads private_data! \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
if ( ! ( sam_ads_state - > mem_ctx = talloc_init_named ( " sam_ads_method " ) ) ) {
DEBUG ( 0 , ( " talloc_init_named() failed for sam_ads_state->mem_ctx \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
sam_ads_state - > ads_bind_dn = talloc_strdup ( sam_ads_state - > mem_ctx , lp_parm_string ( NULL , " sam_ads " , " bind as " ) ) ;
sam_ads_state - > ads_bind_pw = talloc_strdup ( sam_ads_state - > mem_ctx , lp_parm_string ( NULL , " sam_ads " , " bind pw " ) ) ;
sam_ads_state - > bind_plaintext = strequal ( lp_parm_string ( NULL , " sam_ads " , " plaintext bind " ) , " yes " ) ;
if ( ! sam_ads_state - > ads_bind_dn | | ! sam_ads_state - > ads_bind_pw ) {
DEBUG ( 0 , ( " talloc_strdup() failed for bind dn or password \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
/* Maybe we should not check the result here? Server down on startup? */
if ( module_params & & * module_params ) {
sam_ads_state - > ldap_uri = talloc_strdup ( sam_ads_state - > mem_ctx , module_params ) ;
if ( ! sam_ads_state - > ldap_uri ) {
DEBUG ( 0 , ( " talloc_strdup() failed for bind dn or password \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
} else {
sam_ads_state - > ldap_uri = " ldapi:// " ;
}
ads_status = sam_ads_cached_connection ( sam_ads_state ) ;
if ( ! ADS_ERR_OK ( ads_status ) ) {
return ads_ntstatus ( ads_status ) ;
}
sam_method - > private_data = sam_ads_state ;
sam_method - > free_private_data = sam_ads_free_private_data ;
sam_ads_debug_level = debug_add_class ( " sam_ads " ) ;
if ( sam_ads_debug_level = = - 1 ) {
sam_ads_debug_level = DBGC_ALL ;
DEBUG ( 0 , ( " sam_ads: Couldn't register custom debugging class! \n " ) ) ;
} else DEBUG ( 2 , ( " sam_ads: Debug class number of 'sam_ads': %d \n " , sam_ads_debug_level ) ) ;
DEBUG ( 5 , ( " Initializing sam_ads \n " ) ) ;
if ( module_params )
DEBUG ( 10 , ( " Module Parameters for Domain %s[%s]: %s \n " , sam_method - > domain_name , sam_method - > domain_name , module_params ) ) ;
return NT_STATUS_OK ;
}
# else /* HAVE_LDAP */
void sam_ads_dummy ( void )
{
DEBUG ( 0 , ( " sam_ads: not supported! \n " ) ) ;
}
# endif /* HAVE_LDAP */