2000-05-08 22:14:25 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
2001-11-24 17:16:41 +03:00
Copyright ( C ) Andrew Tridgell 1992 - 2001
2002-07-15 14:35:28 +04:00
Copyright ( C ) Andrew Bartlett 2002
Copyright ( C ) Rafal Szczesniak 2002
2004-01-07 13:11:24 +03:00
Copyright ( C ) Tim Potter 2001
2000-05-08 22:14:25 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
2000-05-15 21:13:50 +04:00
/* the Samba secrets database stores any generated, private information
2000-05-08 22:14:25 +04:00
such as the local SID and machine trust password */
# include "includes.h"
2002-07-15 14:35:28 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_PASSDB
2000-05-08 22:14:25 +04:00
static TDB_CONTEXT * tdb ;
2004-07-14 08:36:01 +04:00
/**
* Use a TDB to store an incrementing random seed .
*
* Initialised to the current pid , the very first time Samba starts ,
* and incremented by one each time it is needed .
*
* @ note Not called by systems with a working / dev / urandom .
*/
static void get_rand_seed ( int * new_seed )
{
* new_seed = sys_getpid ( ) ;
if ( tdb ) {
tdb_change_int32_atomic ( tdb , " INFO/random_seed " , new_seed , 1 ) ;
}
}
2000-05-08 22:14:25 +04:00
/* open up the secrets database */
BOOL secrets_init ( void )
{
pstring fname ;
2004-11-25 03:25:53 +03:00
unsigned char dummy ;
2000-05-08 22:14:25 +04:00
2001-11-17 06:19:17 +03:00
if ( tdb )
return True ;
2000-05-08 22:14:25 +04:00
2000-11-21 08:55:16 +03:00
pstrcpy ( fname , lp_private_dir ( ) ) ;
2000-05-08 22:14:25 +04:00
pstrcat ( fname , " /secrets.tdb " ) ;
2001-09-07 02:08:19 +04:00
tdb = tdb_open_log ( fname , 0 , TDB_DEFAULT , O_RDWR | O_CREAT , 0600 ) ;
2000-05-08 22:14:25 +04:00
if ( ! tdb ) {
DEBUG ( 0 , ( " Failed to open %s \n " , fname ) ) ;
return False ;
}
2004-07-14 08:36:01 +04:00
/**
* Set a reseed function for the crypto random generator
*
* This avoids a problem where systems without / dev / urandom
* could send the same challenge to multiple clients
*/
set_rand_reseed_callback ( get_rand_seed ) ;
/* Ensure that the reseed is done now, while we are root, etc */
generate_random_buffer ( & dummy , sizeof ( dummy ) ) ;
2000-05-08 22:14:25 +04:00
return True ;
}
/* read a entry from the secrets database - the caller must free the result
if size is non - null then the size of the entry is put in there
*/
2002-07-15 14:35:28 +04:00
void * secrets_fetch ( const char * key , size_t * size )
2000-05-08 22:14:25 +04:00
{
2005-03-12 12:49:23 +03:00
TDB_DATA dbuf ;
2001-12-05 12:45:00 +03:00
secrets_init ( ) ;
2001-11-17 06:19:17 +03:00
if ( ! tdb )
2001-11-24 17:16:41 +03:00
return NULL ;
2005-03-12 12:49:23 +03:00
dbuf = tdb_fetch ( tdb , string_tdb_data ( key ) ) ;
2001-11-17 06:19:17 +03:00
if ( size )
* size = dbuf . dsize ;
2000-05-08 22:14:25 +04:00
return dbuf . dptr ;
}
/* store a secrets entry
*/
2002-09-25 19:19:00 +04:00
BOOL secrets_store ( const char * key , const void * data , size_t size )
2000-05-08 22:14:25 +04:00
{
2001-12-05 12:45:00 +03:00
secrets_init ( ) ;
2001-11-17 06:19:17 +03:00
if ( ! tdb )
return False ;
2005-03-12 12:49:23 +03:00
return tdb_store ( tdb , string_tdb_data ( key ) , make_tdb_data ( data , size ) ,
TDB_REPLACE ) = = 0 ;
2000-05-08 22:14:25 +04:00
}
/* delete a secets database entry
*/
2002-07-15 14:35:28 +04:00
BOOL secrets_delete ( const char * key )
2000-05-08 22:14:25 +04:00
{
2001-12-05 12:45:00 +03:00
secrets_init ( ) ;
2001-11-17 06:19:17 +03:00
if ( ! tdb )
return False ;
2005-03-12 12:49:23 +03:00
return tdb_delete ( tdb , string_tdb_data ( key ) ) = = 0 ;
2000-05-08 22:14:25 +04:00
}
2000-05-29 05:23:48 +04:00
2002-10-01 17:10:57 +04:00
BOOL secrets_store_domain_sid ( const char * domain , const DOM_SID * sid )
2000-05-29 05:23:48 +04:00
{
fstring key ;
2004-02-08 14:05:34 +03:00
BOOL ret ;
2000-05-29 05:23:48 +04:00
2001-04-09 00:22:39 +04:00
slprintf ( key , sizeof ( key ) - 1 , " %s/%s " , SECRETS_DOMAIN_SID , domain ) ;
2003-07-03 23:11:31 +04:00
strupper_m ( key ) ;
2004-02-08 14:05:34 +03:00
ret = secrets_store ( key , sid , sizeof ( DOM_SID ) ) ;
/* Force a re-query, in case we modified our domain */
if ( ret )
reset_global_sam_sid ( ) ;
return ret ;
2000-05-29 05:23:48 +04:00
}
2002-10-01 17:10:57 +04:00
BOOL secrets_fetch_domain_sid ( const char * domain , DOM_SID * sid )
2000-05-29 05:23:48 +04:00
{
DOM_SID * dyn_sid ;
fstring key ;
2000-07-10 10:41:04 +04:00
size_t size ;
2000-05-29 05:23:48 +04:00
2001-04-09 00:22:39 +04:00
slprintf ( key , sizeof ( key ) - 1 , " %s/%s " , SECRETS_DOMAIN_SID , domain ) ;
2003-07-03 23:11:31 +04:00
strupper_m ( key ) ;
2000-05-29 05:23:48 +04:00
dyn_sid = ( DOM_SID * ) secrets_fetch ( key , & size ) ;
if ( dyn_sid = = NULL )
return False ;
if ( size ! = sizeof ( DOM_SID ) )
{
2001-09-17 09:04:17 +04:00
SAFE_FREE ( dyn_sid ) ;
2000-05-29 05:23:48 +04:00
return False ;
}
* sid = * dyn_sid ;
2001-09-17 09:04:17 +04:00
SAFE_FREE ( dyn_sid ) ;
2000-05-29 05:23:48 +04:00
return True ;
}
2004-04-13 18:39:48 +04:00
BOOL secrets_store_domain_guid ( const char * domain , struct uuid * guid )
2002-08-17 21:00:51 +04:00
{
fstring key ;
slprintf ( key , sizeof ( key ) - 1 , " %s/%s " , SECRETS_DOMAIN_GUID , domain ) ;
2003-07-03 23:11:31 +04:00
strupper_m ( key ) ;
2004-04-13 18:39:48 +04:00
return secrets_store ( key , guid , sizeof ( struct uuid ) ) ;
2002-08-17 21:00:51 +04:00
}
2004-04-13 18:39:48 +04:00
BOOL secrets_fetch_domain_guid ( const char * domain , struct uuid * guid )
2002-08-17 21:00:51 +04:00
{
2004-04-13 18:39:48 +04:00
struct uuid * dyn_guid ;
2002-08-17 21:00:51 +04:00
fstring key ;
size_t size ;
2004-04-13 18:39:48 +04:00
struct uuid new_guid ;
2002-08-17 21:00:51 +04:00
slprintf ( key , sizeof ( key ) - 1 , " %s/%s " , SECRETS_DOMAIN_GUID , domain ) ;
2003-07-03 23:11:31 +04:00
strupper_m ( key ) ;
2004-04-13 18:39:48 +04:00
dyn_guid = ( struct uuid * ) secrets_fetch ( key , & size ) ;
2002-08-17 21:00:51 +04:00
2004-04-13 18:39:48 +04:00
if ( ( ! dyn_guid ) & & ( lp_server_role ( ) = = ROLE_DOMAIN_PDC ) ) {
2003-06-13 08:35:53 +04:00
smb_uuid_generate_random ( & new_guid ) ;
2002-08-17 21:00:51 +04:00
if ( ! secrets_store_domain_guid ( domain , & new_guid ) )
return False ;
2004-04-13 18:39:48 +04:00
dyn_guid = ( struct uuid * ) secrets_fetch ( key , & size ) ;
2002-08-17 21:00:51 +04:00
if ( dyn_guid = = NULL )
return False ;
}
2004-04-13 18:39:48 +04:00
if ( size ! = sizeof ( struct uuid ) )
2002-08-17 21:00:51 +04:00
{
2004-04-13 18:39:48 +04:00
DEBUG ( 1 , ( " UUID size %d is wrong! \n " , ( int ) size ) ) ;
2002-08-17 21:00:51 +04:00
SAFE_FREE ( dyn_guid ) ;
return False ;
}
* guid = * dyn_guid ;
SAFE_FREE ( dyn_guid ) ;
return True ;
}
2000-06-03 10:16:11 +04:00
2002-07-15 14:35:28 +04:00
/**
* Form a key for fetching the machine trust account password
*
* @ param domain domain name
*
* @ return stored password ' s key
* */
const char * trust_keystr ( const char * domain )
2000-06-03 10:16:11 +04:00
{
static fstring keystr ;
2001-02-14 08:34:50 +03:00
2001-04-09 00:22:39 +04:00
slprintf ( keystr , sizeof ( keystr ) - 1 , " %s/%s " ,
2001-07-04 11:15:53 +04:00
SECRETS_MACHINE_ACCT_PASS , domain ) ;
2003-07-03 23:11:31 +04:00
strupper_m ( keystr ) ;
2001-02-14 08:34:50 +03:00
2000-06-03 10:16:11 +04:00
return keystr ;
}
2002-03-01 05:56:35 +03:00
/**
* Form a key for fetching a trusted domain password
*
2002-07-15 14:35:28 +04:00
* @ param domain trusted domain name
2002-03-01 05:56:35 +03:00
*
* @ return stored password ' s key
* */
2003-07-19 15:28:15 +04:00
static char * trustdom_keystr ( const char * domain )
2002-03-01 05:56:35 +03:00
{
2003-07-19 15:28:15 +04:00
static pstring keystr ;
2002-03-01 05:56:35 +03:00
2003-07-19 15:28:15 +04:00
pstr_sprintf ( keystr , " %s/%s " , SECRETS_DOMTRUST_ACCT_PASS , domain ) ;
2003-07-03 23:11:31 +04:00
strupper_m ( keystr ) ;
2002-03-01 05:56:35 +03:00
return keystr ;
}
2000-06-03 10:16:11 +04:00
/************************************************************************
2002-09-25 19:19:00 +04:00
Lock the trust password entry .
2000-06-03 10:16:11 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2002-11-09 02:08:59 +03:00
BOOL secrets_lock_trust_account_password ( const char * domain , BOOL dolock )
2002-09-25 19:19:00 +04:00
{
if ( ! tdb )
return False ;
if ( dolock )
2002-10-05 02:53:18 +04:00
return ( tdb_lock_bystring ( tdb , trust_keystr ( domain ) , 0 ) = = 0 ) ;
2002-09-25 19:19:00 +04:00
else
tdb_unlock_bystring ( tdb , trust_keystr ( domain ) ) ;
return True ;
}
2003-04-21 18:09:03 +04:00
/************************************************************************
Routine to get the default secure channel type for trust accounts
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 get_default_sec_channel ( void )
{
if ( lp_server_role ( ) = = ROLE_DOMAIN_BDC | |
lp_server_role ( ) = = ROLE_DOMAIN_PDC ) {
return SEC_CHAN_BDC ;
} else {
return SEC_CHAN_WKSTA ;
}
}
2002-09-25 19:19:00 +04:00
/************************************************************************
Routine to get the trust account password for a domain .
The user of this function must have locked the trust password file using
2004-04-13 18:39:48 +04:00
the above secrets_lock_trust_account_password ( ) .
2002-09-25 19:19:00 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-10-01 17:10:57 +04:00
BOOL secrets_fetch_trust_account_password ( const char * domain , uint8 ret_pwd [ 16 ] ,
2003-04-21 18:09:03 +04:00
time_t * pass_last_set_time ,
uint32 * channel )
2000-06-03 10:16:11 +04:00
{
struct machine_acct_pass * pass ;
2001-11-24 17:16:41 +03:00
char * plaintext ;
2000-06-03 10:16:11 +04:00
size_t size ;
2003-04-21 18:09:03 +04:00
plaintext = secrets_fetch_machine_password ( domain , pass_last_set_time ,
channel ) ;
2001-11-24 17:16:41 +03:00
if ( plaintext ) {
2003-06-25 21:41:05 +04:00
DEBUG ( 4 , ( " Using cleartext machine password \n " ) ) ;
2002-08-17 21:00:51 +04:00
E_md4hash ( plaintext , ret_pwd ) ;
2001-11-24 17:16:41 +03:00
SAFE_FREE ( plaintext ) ;
return True ;
}
2001-12-05 13:52:13 +03:00
if ( ! ( pass = secrets_fetch ( trust_keystr ( domain ) , & size ) ) ) {
DEBUG ( 5 , ( " secrets_fetch failed! \n " ) ) ;
2000-11-28 02:59:42 +03:00
return False ;
2001-12-05 13:52:13 +03:00
}
if ( size ! = sizeof ( * pass ) ) {
DEBUG ( 0 , ( " secrets were of incorrect size! \n " ) ) ;
return False ;
}
2000-06-03 10:16:11 +04:00
if ( pass_last_set_time ) * pass_last_set_time = pass - > mod_time ;
memcpy ( ret_pwd , pass - > hash , 16 ) ;
2001-09-17 09:04:17 +04:00
SAFE_FREE ( pass ) ;
2003-04-21 18:09:03 +04:00
if ( channel )
* channel = get_default_sec_channel ( ) ;
2000-06-03 10:16:11 +04:00
return True ;
}
2002-03-01 05:56:35 +03:00
/************************************************************************
Routine to get account password to trusted domain
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2002-11-09 02:08:59 +03:00
BOOL secrets_fetch_trusted_domain_password ( const char * domain , char * * pwd ,
2003-04-22 17:10:02 +04:00
DOM_SID * sid , time_t * pass_last_set_time )
2002-03-01 05:56:35 +03:00
{
2003-04-22 17:10:02 +04:00
struct trusted_dom_pass pass ;
2002-03-01 05:56:35 +03:00
size_t size ;
2003-04-22 17:10:02 +04:00
/* unpacking structures */
char * pass_buf ;
int pass_len = 0 ;
ZERO_STRUCT ( pass ) ;
2002-03-01 05:56:35 +03:00
2002-07-15 14:35:28 +04:00
/* fetching trusted domain password structure */
2003-04-22 17:10:02 +04:00
if ( ! ( pass_buf = secrets_fetch ( trustdom_keystr ( domain ) , & size ) ) ) {
2002-03-01 05:56:35 +03:00
DEBUG ( 5 , ( " secrets_fetch failed! \n " ) ) ;
return False ;
}
2002-07-15 14:35:28 +04:00
2003-04-22 17:10:02 +04:00
/* unpack trusted domain password */
pass_len = tdb_trusted_dom_pass_unpack ( pass_buf , size , & pass ) ;
SAFE_FREE ( pass_buf ) ;
if ( pass_len ! = size ) {
DEBUG ( 5 , ( " Invalid secrets size. Unpacked data doesn't match trusted_dom_pass structure. \n " ) ) ;
2002-03-01 05:56:35 +03:00
return False ;
}
2003-04-22 17:10:02 +04:00
2002-07-15 14:35:28 +04:00
/* the trust's password */
2002-03-02 07:45:29 +03:00
if ( pwd ) {
2004-12-07 21:25:53 +03:00
* pwd = SMB_STRDUP ( pass . pass ) ;
2002-03-02 07:45:29 +03:00
if ( ! * pwd ) {
return False ;
}
}
2002-03-01 05:56:35 +03:00
2002-07-15 14:35:28 +04:00
/* last change time */
2003-04-22 17:10:02 +04:00
if ( pass_last_set_time ) * pass_last_set_time = pass . mod_time ;
2002-03-01 05:56:35 +03:00
2002-07-15 14:35:28 +04:00
/* domain sid */
2003-04-22 17:10:02 +04:00
sid_copy ( sid , & pass . domain_sid ) ;
2002-03-01 05:56:35 +03:00
return True ;
}
2000-06-03 10:16:11 +04:00
/************************************************************************
Routine to set the trust account password for a domain .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-11-09 02:08:59 +03:00
BOOL secrets_store_trust_account_password ( const char * domain , uint8 new_pwd [ 16 ] )
2000-06-03 10:16:11 +04:00
{
struct machine_acct_pass pass ;
pass . mod_time = time ( NULL ) ;
memcpy ( pass . hash , new_pwd , 16 ) ;
return secrets_store ( trust_keystr ( domain ) , ( void * ) & pass , sizeof ( pass ) ) ;
}
2000-11-28 02:59:42 +03:00
2002-03-01 05:56:35 +03:00
/**
2003-04-22 17:10:02 +04:00
* Routine to store the password for trusted domain
2002-03-01 05:56:35 +03:00
*
* @ param domain remote domain name
* @ param pwd plain text password of trust relationship
* @ param sid remote domain sid
*
* @ return true if succeeded
* */
2002-11-09 02:08:59 +03:00
BOOL secrets_store_trusted_domain_password ( const char * domain , smb_ucs2_t * uni_dom_name ,
2003-04-22 17:10:02 +04:00
size_t uni_name_len , const char * pwd ,
DOM_SID sid )
{
/* packing structures */
pstring pass_buf ;
int pass_len = 0 ;
int pass_buf_len = sizeof ( pass_buf ) ;
2002-03-01 05:56:35 +03:00
struct trusted_dom_pass pass ;
2002-03-02 07:45:29 +03:00
ZERO_STRUCT ( pass ) ;
2003-04-22 17:10:02 +04:00
2002-07-15 14:35:28 +04:00
/* unicode domain name and its length */
if ( ! uni_dom_name )
return False ;
strncpy_w ( pass . uni_name , uni_dom_name , sizeof ( pass . uni_name ) - 1 ) ;
pass . uni_name_len = uni_name_len ;
/* last change time */
2002-03-01 05:56:35 +03:00
pass . mod_time = time ( NULL ) ;
2002-07-15 14:35:28 +04:00
/* password of the trust */
2002-03-01 05:56:35 +03:00
pass . pass_len = strlen ( pwd ) ;
2002-03-02 07:45:29 +03:00
fstrcpy ( pass . pass , pwd ) ;
2002-03-01 05:56:35 +03:00
2002-07-15 14:35:28 +04:00
/* domain sid */
2003-04-22 17:10:02 +04:00
sid_copy ( & pass . domain_sid , & sid ) ;
pass_len = tdb_trusted_dom_pass_pack ( pass_buf , pass_buf_len , & pass ) ;
2002-07-15 14:35:28 +04:00
2003-04-22 17:10:02 +04:00
return secrets_store ( trustdom_keystr ( domain ) , ( void * ) & pass_buf , pass_len ) ;
2002-03-01 05:56:35 +03:00
}
2001-11-24 17:16:41 +03:00
/************************************************************************
Routine to set the plaintext machine account password for a realm
the password is assumed to be a null terminated ascii string
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-11-09 02:08:59 +03:00
2003-04-21 18:09:03 +04:00
BOOL secrets_store_machine_password ( const char * pass , const char * domain , uint32 sec_channel )
2001-11-24 17:16:41 +03:00
{
2003-04-21 18:09:03 +04:00
char * key = NULL ;
2002-02-22 06:18:37 +03:00
BOOL ret ;
2003-04-21 18:09:03 +04:00
uint32 last_change_time ;
uint32 sec_channel_type ;
asprintf ( & key , " %s/%s " , SECRETS_MACHINE_PASSWORD , domain ) ;
if ( ! key )
return False ;
2003-07-03 23:11:31 +04:00
strupper_m ( key ) ;
2003-04-21 18:09:03 +04:00
2002-02-22 06:18:37 +03:00
ret = secrets_store ( key , pass , strlen ( pass ) + 1 ) ;
2003-04-21 18:09:03 +04:00
SAFE_FREE ( key ) ;
if ( ! ret )
return ret ;
asprintf ( & key , " %s/%s " , SECRETS_MACHINE_LAST_CHANGE_TIME , domain ) ;
if ( ! key )
return False ;
2003-07-03 23:11:31 +04:00
strupper_m ( key ) ;
2003-04-21 18:09:03 +04:00
SIVAL ( & last_change_time , 0 , time ( NULL ) ) ;
ret = secrets_store ( key , & last_change_time , sizeof ( last_change_time ) ) ;
SAFE_FREE ( key ) ;
asprintf ( & key , " %s/%s " , SECRETS_MACHINE_SEC_CHANNEL_TYPE , domain ) ;
if ( ! key )
return False ;
2003-07-03 23:11:31 +04:00
strupper_m ( key ) ;
2003-04-21 18:09:03 +04:00
SIVAL ( & sec_channel_type , 0 , sec_channel ) ;
ret = secrets_store ( key , & sec_channel_type , sizeof ( sec_channel_type ) ) ;
SAFE_FREE ( key ) ;
2002-02-22 06:18:37 +03:00
return ret ;
2001-11-24 17:16:41 +03:00
}
/************************************************************************
Routine to fetch the plaintext machine account password for a realm
the password is assumed to be a null terminated ascii string
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-04-21 18:09:03 +04:00
char * secrets_fetch_machine_password ( const char * domain ,
time_t * pass_last_set_time ,
uint32 * channel )
2001-11-24 17:16:41 +03:00
{
2003-04-21 18:09:03 +04:00
char * key = NULL ;
2002-02-22 06:18:37 +03:00
char * ret ;
2003-04-21 18:09:03 +04:00
asprintf ( & key , " %s/%s " , SECRETS_MACHINE_PASSWORD , domain ) ;
2003-07-03 23:11:31 +04:00
strupper_m ( key ) ;
2002-02-22 06:18:37 +03:00
ret = ( char * ) secrets_fetch ( key , NULL ) ;
2003-04-21 18:09:03 +04:00
SAFE_FREE ( key ) ;
if ( pass_last_set_time ) {
size_t size ;
uint32 * last_set_time ;
asprintf ( & key , " %s/%s " , SECRETS_MACHINE_LAST_CHANGE_TIME , domain ) ;
2003-07-03 23:11:31 +04:00
strupper_m ( key ) ;
2003-04-21 18:09:03 +04:00
last_set_time = secrets_fetch ( key , & size ) ;
if ( last_set_time ) {
* pass_last_set_time = IVAL ( last_set_time , 0 ) ;
2003-06-21 18:28:18 +04:00
SAFE_FREE ( last_set_time ) ;
2003-04-21 18:09:03 +04:00
} else {
* pass_last_set_time = 0 ;
}
SAFE_FREE ( key ) ;
}
if ( channel ) {
size_t size ;
uint32 * channel_type ;
asprintf ( & key , " %s/%s " , SECRETS_MACHINE_SEC_CHANNEL_TYPE , domain ) ;
2003-07-03 23:11:31 +04:00
strupper_m ( key ) ;
2003-04-21 18:09:03 +04:00
channel_type = secrets_fetch ( key , & size ) ;
if ( channel_type ) {
* channel = IVAL ( channel_type , 0 ) ;
2003-06-21 18:28:18 +04:00
SAFE_FREE ( channel_type ) ;
2003-04-21 18:09:03 +04:00
} else {
* channel = get_default_sec_channel ( ) ;
}
SAFE_FREE ( key ) ;
}
2002-02-22 06:18:37 +03:00
return ret ;
2001-11-24 17:16:41 +03:00
}
2000-11-28 02:59:42 +03:00
/************************************************************************
2002-03-01 05:56:35 +03:00
Routine to delete the machine trust account password file for a domain .
2000-11-28 02:59:42 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
BOOL trust_password_delete ( const char * domain )
2000-11-28 02:59:42 +03:00
{
return secrets_delete ( trust_keystr ( domain ) ) ;
}
2001-06-07 02:04:26 +04:00
2002-03-01 05:56:35 +03:00
/************************************************************************
Routine to delete the password for trusted domain
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-11-09 02:08:59 +03:00
2002-07-15 14:35:28 +04:00
BOOL trusted_domain_password_delete ( const char * domain )
2002-03-01 05:56:35 +03:00
{
return secrets_delete ( trustdom_keystr ( domain ) ) ;
}
2002-07-15 14:35:28 +04:00
BOOL secrets_store_ldap_pw ( const char * dn , char * pw )
2001-12-13 21:09:29 +03:00
{
2002-07-15 14:35:28 +04:00
char * key = NULL ;
BOOL ret ;
2001-12-13 21:09:29 +03:00
2002-07-15 14:35:28 +04:00
if ( asprintf ( & key , " %s/%s " , SECRETS_LDAP_BIND_PW , dn ) < 0 ) {
DEBUG ( 0 , ( " secrets_store_ldap_pw: asprintf failed! \n " ) ) ;
return False ;
}
ret = secrets_store ( key , pw , strlen ( pw ) + 1 ) ;
SAFE_FREE ( key ) ;
return ret ;
}
/**
2002-08-17 21:00:51 +04:00
* Get trusted domains info from secrets . tdb .
*
* The linked list is allocated on the supplied talloc context , caller gets to destroy
2002-07-15 14:35:28 +04:00
* when done .
*
* @ param ctx Allocation context
* @ param enum_ctx Starting index , eg . we can start fetching at third
* or sixth trusted domain entry . Zero is the first index .
* Value it is set to is the enum context for the next enumeration .
* @ param num_domains Number of domain entries to fetch at one call
* @ param domains Pointer to array of trusted domain structs to be filled up
*
* @ return nt status code of rpc response
* */
2004-04-13 18:39:48 +04:00
NTSTATUS secrets_get_trusted_domains ( TALLOC_CTX * ctx , int * enum_ctx , unsigned int max_num_domains ,
int * num_domains , TRUSTDOM * * * domains )
2002-07-15 14:35:28 +04:00
{
TDB_LIST_NODE * keys , * k ;
TRUSTDOM * dom = NULL ;
char * pattern ;
2003-02-01 10:25:53 +03:00
unsigned int start_idx ;
2002-07-15 14:35:28 +04:00
uint32 idx = 0 ;
2003-04-22 17:10:02 +04:00
size_t size , packed_size = 0 ;
2002-08-17 21:00:51 +04:00
fstring dom_name ;
2003-04-22 17:10:02 +04:00
char * packed_pass ;
2004-12-07 21:25:53 +03:00
struct trusted_dom_pass * pass = TALLOC_ZERO_P ( ctx , struct trusted_dom_pass ) ;
2002-07-15 14:35:28 +04:00
NTSTATUS status ;
2002-08-17 21:00:51 +04:00
if ( ! secrets_init ( ) ) return NT_STATUS_ACCESS_DENIED ;
2003-04-22 17:10:02 +04:00
if ( ! pass ) {
DEBUG ( 0 , ( " talloc_zero failed! \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
2002-07-15 14:35:28 +04:00
* num_domains = 0 ;
start_idx = * enum_ctx ;
/* generate searching pattern */
if ( ! ( pattern = talloc_asprintf ( ctx , " %s/* " , SECRETS_DOMTRUST_ACCT_PASS ) ) ) {
DEBUG ( 0 , ( " secrets_get_trusted_domains: talloc_asprintf() failed! \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
DEBUG ( 5 , ( " secrets_get_trusted_domains: looking for %d domains, starting at index %d \n " ,
max_num_domains , * enum_ctx ) ) ;
2004-12-07 21:25:53 +03:00
* domains = TALLOC_ZERO_ARRAY ( ctx , TRUSTDOM * , max_num_domains ) ;
2002-07-15 14:35:28 +04:00
/* fetching trusted domains' data and collecting them in a list */
keys = tdb_search_keys ( tdb , pattern ) ;
/*
* if there ' s no keys returned ie . no trusted domain ,
* return " no more entries " code
*/
status = NT_STATUS_NO_MORE_ENTRIES ;
2003-04-22 17:10:02 +04:00
/* searching for keys in secrets db -- way to go ... */
2002-07-15 14:35:28 +04:00
for ( k = keys ; k ; k = k - > next ) {
char * secrets_key ;
/* important: ensure null-termination of the key string */
2004-12-07 21:25:53 +03:00
secrets_key = SMB_STRNDUP ( k - > node_key . dptr , k - > node_key . dsize ) ;
2002-07-15 14:35:28 +04:00
if ( ! secrets_key ) {
DEBUG ( 0 , ( " strndup failed! \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
2003-07-01 16:40:52 +04:00
2003-04-22 17:10:02 +04:00
packed_pass = secrets_fetch ( secrets_key , & size ) ;
packed_size = tdb_trusted_dom_pass_unpack ( packed_pass , size , pass ) ;
/* packed representation isn't needed anymore */
SAFE_FREE ( packed_pass ) ;
2002-07-15 14:35:28 +04:00
2003-04-22 17:10:02 +04:00
if ( size ! = packed_size ) {
2002-07-15 14:35:28 +04:00
DEBUG ( 2 , ( " Secrets record %s is invalid! \n " , secrets_key ) ) ;
continue ;
}
2002-08-17 21:00:51 +04:00
pull_ucs2_fstring ( dom_name , pass - > uni_name ) ;
DEBUG ( 18 , ( " Fetched secret record num %d. \n Domain name: %s, SID: %s \n " ,
idx , dom_name , sid_string_static ( & pass - > domain_sid ) ) ) ;
2002-07-15 14:35:28 +04:00
SAFE_FREE ( secrets_key ) ;
if ( idx > = start_idx & & idx < start_idx + max_num_domains ) {
2004-12-07 21:25:53 +03:00
dom = TALLOC_ZERO_P ( ctx , TRUSTDOM ) ;
2002-07-15 14:35:28 +04:00
if ( ! dom ) {
/* free returned tdb record */
return NT_STATUS_NO_MEMORY ;
}
/* copy domain sid */
SMB_ASSERT ( sizeof ( dom - > sid ) = = sizeof ( pass - > domain_sid ) ) ;
memcpy ( & ( dom - > sid ) , & ( pass - > domain_sid ) , sizeof ( dom - > sid ) ) ;
/* copy unicode domain name */
dom - > name = talloc_strdup_w ( ctx , pass - > uni_name ) ;
( * domains ) [ idx - start_idx ] = dom ;
2002-08-17 21:00:51 +04:00
DEBUG ( 18 , ( " Secret record is in required range. \n \
start_idx = % d , max_num_domains = % d . Added to returned array . \ n " ,
start_idx , max_num_domains ) ) ;
2002-07-15 14:35:28 +04:00
* enum_ctx = idx + 1 ;
( * num_domains ) + + ;
/* set proper status code to return */
if ( k - > next ) {
/* there are yet some entries to enumerate */
status = STATUS_MORE_ENTRIES ;
} else {
/* this is the last entry in the whole enumeration */
status = NT_STATUS_OK ;
}
2002-08-17 21:00:51 +04:00
} else {
DEBUG ( 18 , ( " Secret is outside the required range. \n \
start_idx = % d , max_num_domains = % d . Not added to returned array \ n " ,
start_idx , max_num_domains ) ) ;
2002-07-15 14:35:28 +04:00
}
2003-04-22 17:10:02 +04:00
idx + + ;
2002-07-15 14:35:28 +04:00
}
2001-12-13 21:09:29 +03:00
2002-07-15 14:35:28 +04:00
DEBUG ( 5 , ( " secrets_get_trusted_domains: got %d domains \n " , * num_domains ) ) ;
/* free the results of searching the keys */
tdb_search_list_free ( keys ) ;
return status ;
2001-12-13 21:09:29 +03:00
}
2002-10-05 02:53:18 +04:00
/*******************************************************************************
Lock the secrets tdb based on a string - this is used as a primitive form of mutex
between smbd instances .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2003-03-18 02:06:12 +03:00
BOOL secrets_named_mutex ( const char * name , unsigned int timeout )
2002-09-25 19:19:00 +04:00
{
2003-01-16 23:08:26 +03:00
int ret = 0 ;
2002-09-25 19:19:00 +04:00
if ( ! message_init ( ) )
return False ;
2003-04-22 17:10:02 +04:00
ret = tdb_lock_bystring ( tdb , name , timeout ) ;
if ( ret = = 0 )
DEBUG ( 10 , ( " secrets_named_mutex: got mutex for %s \n " , name ) ) ;
2002-09-25 19:19:00 +04:00
return ( ret = = 0 ) ;
}
2002-10-05 02:53:18 +04:00
/*******************************************************************************
Unlock a named mutex .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-03-18 02:06:12 +03:00
void secrets_named_mutex_release ( const char * name )
2002-09-25 19:19:00 +04:00
{
2003-04-22 17:10:02 +04:00
tdb_unlock_bystring ( tdb , name ) ;
DEBUG ( 10 , ( " secrets_named_mutex: released mutex for %s \n " , name ) ) ;
2002-09-25 19:19:00 +04:00
}
2002-12-13 05:07:05 +03:00
/*********************************************************
Check to see if we must talk to the PDC to avoid sam
sync delays
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL must_use_pdc ( const char * domain )
{
time_t now = time ( NULL ) ;
time_t last_change_time ;
unsigned char passwd [ 16 ] ;
2003-04-21 18:09:03 +04:00
if ( ! secrets_fetch_trust_account_password ( domain , passwd , & last_change_time , NULL ) )
2002-12-13 05:07:05 +03:00
return False ;
/*
* If the time the machine password has changed
* was less than about 15 minutes then we need to contact
* the PDC only , as we cannot be sure domain replication
* has yet taken place . Bug found by Gerald ( way to go
* Gerald ! ) . JRA .
*/
if ( now - last_change_time < SAM_SYNC_WINDOW )
return True ;
return False ;
}
2003-09-07 20:36:13 +04:00
/*******************************************************************************
Store a complete AFS keyfile into secrets . tdb .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL secrets_store_afs_keyfile ( const char * cell , const struct afs_keyfile * keyfile )
{
fstring key ;
if ( ( cell = = NULL ) | | ( keyfile = = NULL ) )
return False ;
if ( ntohl ( keyfile - > nkeys ) > SECRETS_AFS_MAXKEYS )
return False ;
slprintf ( key , sizeof ( key ) - 1 , " %s/%s " , SECRETS_AFS_KEYFILE , cell ) ;
return secrets_store ( key , keyfile , sizeof ( struct afs_keyfile ) ) ;
}
/*******************************************************************************
Fetch the current ( highest ) AFS key from secrets . tdb
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL secrets_fetch_afs_key ( const char * cell , struct afs_key * result )
{
fstring key ;
struct afs_keyfile * keyfile ;
size_t size ;
uint32 i ;
slprintf ( key , sizeof ( key ) - 1 , " %s/%s " , SECRETS_AFS_KEYFILE , cell ) ;
keyfile = ( struct afs_keyfile * ) secrets_fetch ( key , & size ) ;
if ( keyfile = = NULL )
return False ;
if ( size ! = sizeof ( struct afs_keyfile ) ) {
SAFE_FREE ( keyfile ) ;
return False ;
}
i = ntohl ( keyfile - > nkeys ) ;
if ( i > SECRETS_AFS_MAXKEYS ) {
SAFE_FREE ( keyfile ) ;
return False ;
}
* result = keyfile - > entry [ i - 1 ] ;
result - > kvno = ntohl ( result - > kvno ) ;
return True ;
}
2004-01-07 13:11:24 +03:00
/******************************************************************************
When kerberos is not available , choose between anonymous or
authenticated connections .
We need to use an authenticated connection if DCs have the
RestrictAnonymous registry entry set > 0 , or the " Additional
restrictions for anonymous connections " set in the win2k Local
Security Policy .
Caller to free ( ) result in domain , username , password
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void secrets_fetch_ipc_userpass ( char * * username , char * * domain , char * * password )
{
* username = secrets_fetch ( SECRETS_AUTH_USER , NULL ) ;
* domain = secrets_fetch ( SECRETS_AUTH_DOMAIN , NULL ) ;
* password = secrets_fetch ( SECRETS_AUTH_PASSWORD , NULL ) ;
if ( * username & & * * username ) {
if ( ! * domain | | ! * * domain )
* domain = smb_xstrdup ( lp_workgroup ( ) ) ;
if ( ! * password | | ! * * password )
* password = smb_xstrdup ( " " ) ;
DEBUG ( 3 , ( " IPC$ connections done by user %s \\ %s \n " ,
* domain , * username ) ) ;
} else {
DEBUG ( 3 , ( " IPC$ connections done anonymously \n " ) ) ;
* username = smb_xstrdup ( " " ) ;
* domain = smb_xstrdup ( " " ) ;
* password = smb_xstrdup ( " " ) ;
}
}