2008-02-17 03:47:01 +03:00
/*
2005-11-10 23:28:23 +03:00
Unix SMB / CIFS implementation .
Net_sam_logon info3 helpers
Copyright ( C ) Alexander Bokovoy 2002.
Copyright ( C ) Andrew Bartlett 2002.
Copyright ( C ) Gerald Carter 2003.
Copyright ( C ) Tim Potter 2003.
2008-02-27 21:38:48 +03:00
Copyright ( C ) Guenther Deschner 2008.
2008-02-17 03:47:01 +03:00
2005-11-10 23:28:23 +03: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
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2005-11-10 23:28:23 +03:00
( at your option ) any later version .
2008-02-17 03:47:01 +03:00
2005-11-10 23:28:23 +03:00
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 .
2008-02-17 03:47:01 +03:00
2005-11-10 23:28:23 +03:00
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/>.
2005-11-10 23:28:23 +03:00
*/
# include "includes.h"
2011-02-26 01:20:06 +03:00
# include "system/filesys.h"
2008-10-20 21:21:10 +04:00
# include "librpc/gen_ndr/ndr_krb5pac.h"
2010-10-12 08:27:50 +04:00
# include "../libcli/security/security.h"
2011-05-05 13:25:29 +04:00
# include "util_tdb.h"
2005-11-10 23:28:23 +03:00
# define NETSAMLOGON_TDB "netsamlogon_cache.tdb"
static TDB_CONTEXT * netsamlogon_tdb = NULL ;
/***********************************************************************
open the tdb
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-02-17 03:47:01 +03:00
2007-10-19 04:40:25 +04:00
bool netsamlogon_cache_init ( void )
2005-11-10 23:28:23 +03:00
{
2009-12-04 18:34:08 +03:00
bool first_try = true ;
const char * path = NULL ;
int ret ;
struct tdb_context * tdb ;
if ( netsamlogon_tdb ) {
return true ;
}
path = cache_path ( NETSAMLOGON_TDB ) ;
again :
2010-09-27 16:46:07 +04:00
tdb = tdb_open_log ( path , 0 , TDB_DEFAULT | TDB_INCOMPATIBLE_HASH ,
2009-12-04 18:34:08 +03:00
O_RDWR | O_CREAT , 0600 ) ;
if ( tdb = = NULL ) {
DEBUG ( 0 , ( " tdb_open_log('%s') - failed \n " , path ) ) ;
goto clear ;
}
ret = tdb_check ( tdb , NULL , NULL ) ;
if ( ret ! = 0 ) {
tdb_close ( tdb ) ;
DEBUG ( 0 , ( " tdb_check('%s') - failed \n " , path ) ) ;
goto clear ;
}
netsamlogon_tdb = tdb ;
return true ;
clear :
if ( ! first_try ) {
return false ;
}
first_try = false ;
2011-04-19 06:36:05 +04:00
DEBUG ( 0 , ( " retry after truncate for '%s' \n " , path ) ) ;
truncate ( path , 0 ) ;
goto again ;
2005-11-10 23:28:23 +03:00
}
/***********************************************************************
Shutdown samlogon_cache database
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
bool netsamlogon_cache_shutdown ( void )
2005-11-10 23:28:23 +03:00
{
2008-02-17 03:47:01 +03:00
if ( netsamlogon_tdb ) {
2005-11-10 23:28:23 +03:00
return ( tdb_close ( netsamlogon_tdb ) = = 0 ) ;
2008-02-17 03:47:01 +03:00
}
return true ;
2005-11-10 23:28:23 +03:00
}
/***********************************************************************
Clear cache getpwnam and getgroups entries from the winbindd cache
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-02-17 03:47:01 +03:00
2010-12-11 16:19:50 +03:00
void netsamlogon_clear_cached_user ( const struct dom_sid * user_sid )
2005-11-10 23:28:23 +03:00
{
2010-12-11 16:16:51 +03:00
fstring keystr ;
2005-11-10 23:28:23 +03:00
2008-08-28 04:28:34 +04:00
if ( ! netsamlogon_cache_init ( ) ) {
DEBUG ( 0 , ( " netsamlogon_clear_cached_user: cannot open "
" %s for write! \n " ,
NETSAMLOGON_TDB ) ) ;
return ;
}
2005-11-10 23:28:23 +03:00
2008-08-28 04:28:34 +04:00
/* Prepare key as DOMAIN-SID/USER-RID string */
2010-12-11 16:19:50 +03:00
sid_to_fstring ( keystr , user_sid ) ;
2005-11-10 23:28:23 +03:00
2008-08-28 04:28:34 +04:00
DEBUG ( 10 , ( " netsamlogon_clear_cached_user: SID [%s] \n " , keystr ) ) ;
2005-11-10 23:28:23 +03:00
2008-08-28 04:28:34 +04:00
tdb_delete_bystring ( netsamlogon_tdb , keystr ) ;
2005-11-10 23:28:23 +03:00
}
/***********************************************************************
2008-02-17 03:47:01 +03:00
Store a netr_SamInfo3 structure in a tdb for later user
2005-11-10 23:28:23 +03:00
username should be in UTF - 8 format
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-02-17 03:47:01 +03:00
bool netsamlogon_cache_store ( const char * username , struct netr_SamInfo3 * info3 )
2005-11-10 23:28:23 +03:00
{
2008-02-17 03:47:01 +03:00
TDB_DATA data ;
2010-12-11 16:16:51 +03:00
fstring keystr ;
2008-02-17 03:47:01 +03:00
bool result = false ;
2010-05-21 05:25:01 +04:00
struct dom_sid user_sid ;
2008-02-17 03:47:01 +03:00
time_t t = time ( NULL ) ;
TALLOC_CTX * mem_ctx ;
DATA_BLOB blob ;
enum ndr_err_code ndr_err ;
struct netsamlogoncache_entry r ;
if ( ! info3 ) {
return false ;
}
2005-11-10 23:28:23 +03:00
if ( ! netsamlogon_cache_init ( ) ) {
2008-02-17 03:47:01 +03:00
DEBUG ( 0 , ( " netsamlogon_cache_store: cannot open %s for write! \n " ,
NETSAMLOGON_TDB ) ) ;
return false ;
2005-11-10 23:28:23 +03:00
}
2010-01-10 19:39:27 +03:00
sid_compose ( & user_sid , info3 - > base . domain_sid , info3 - > base . rid ) ;
2005-11-10 23:28:23 +03:00
/* Prepare key as DOMAIN-SID/USER-RID string */
2010-12-11 16:16:51 +03:00
sid_to_fstring ( keystr , & user_sid ) ;
2005-11-10 23:28:23 +03:00
DEBUG ( 10 , ( " netsamlogon_cache_store: SID [%s] \n " , keystr ) ) ;
2008-02-17 03:47:01 +03:00
/* Prepare data */
2011-06-07 05:38:41 +04:00
if ( ! ( mem_ctx = talloc ( NULL , int ) ) ) {
2008-02-17 03:47:01 +03:00
DEBUG ( 0 , ( " netsamlogon_cache_store: talloc() failed! \n " ) ) ;
return false ;
}
2005-11-10 23:28:23 +03:00
/* only Samba fills in the username, not sure why NT doesn't */
/* so we fill it in since winbindd_getpwnam() makes use of it */
2008-02-17 03:47:01 +03:00
if ( ! info3 - > base . account_name . string ) {
2008-03-26 00:35:20 +03:00
info3 - > base . account_name . string = talloc_strdup ( info3 , username ) ;
2005-11-10 23:28:23 +03:00
}
2008-02-17 03:47:01 +03:00
r . timestamp = t ;
r . info3 = * info3 ;
if ( DEBUGLEVEL > = 10 ) {
NDR_PRINT_DEBUG ( netsamlogoncache_entry , & r ) ;
2005-11-11 06:03:41 +03:00
}
2010-05-10 02:42:06 +04:00
ndr_err = ndr_push_struct_blob ( & blob , mem_ctx , & r ,
2008-02-17 03:47:01 +03:00
( ndr_push_flags_fn_t ) ndr_push_netsamlogoncache_entry ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
DEBUG ( 0 , ( " netsamlogon_cache_store: failed to push entry to cache \n " ) ) ;
TALLOC_FREE ( mem_ctx ) ;
return false ;
2005-12-03 09:46:46 +03:00
}
2005-11-10 23:28:23 +03:00
2008-02-17 03:47:01 +03:00
data . dsize = blob . length ;
data . dptr = blob . data ;
2011-06-20 13:10:31 +04:00
if ( tdb_store_bystring ( netsamlogon_tdb , keystr , data , TDB_REPLACE ) = = 0 ) {
2008-02-17 03:47:01 +03:00
result = true ;
2005-11-10 23:28:23 +03:00
}
2005-11-11 06:03:41 +03:00
2008-02-17 03:47:01 +03:00
TALLOC_FREE ( mem_ctx ) ;
2005-11-10 23:28:23 +03:00
return result ;
}
/***********************************************************************
2008-02-17 03:47:01 +03:00
Retrieves a netr_SamInfo3 structure from a tdb . Caller must
2005-11-10 23:28:23 +03:00
free the user_info struct ( malloc ( ) ' d memory )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-05-21 05:25:01 +04:00
struct netr_SamInfo3 * netsamlogon_cache_get ( TALLOC_CTX * mem_ctx , const struct dom_sid * user_sid )
2005-11-10 23:28:23 +03:00
{
2008-02-17 03:47:01 +03:00
struct netr_SamInfo3 * info3 = NULL ;
TDB_DATA data ;
fstring keystr , tmp ;
enum ndr_err_code ndr_err ;
DATA_BLOB blob ;
struct netsamlogoncache_entry r ;
2005-11-10 23:28:23 +03:00
if ( ! netsamlogon_cache_init ( ) ) {
2008-02-17 03:47:01 +03:00
DEBUG ( 0 , ( " netsamlogon_cache_get: cannot open %s for write! \n " ,
NETSAMLOGON_TDB ) ) ;
2011-12-20 13:25:05 +04:00
return NULL ;
2005-11-10 23:28:23 +03:00
}
/* Prepare key as DOMAIN-SID/USER-RID string */
2007-12-16 00:47:30 +03:00
slprintf ( keystr , sizeof ( keystr ) , " %s " , sid_to_fstring ( tmp , user_sid ) ) ;
2005-11-10 23:28:23 +03:00
DEBUG ( 10 , ( " netsamlogon_cache_get: SID [%s] \n " , keystr ) ) ;
2007-03-27 13:30:40 +04:00
data = tdb_fetch_bystring ( netsamlogon_tdb , keystr ) ;
2007-05-03 16:29:32 +04:00
2008-02-17 03:47:01 +03:00
if ( ! data . dptr ) {
return NULL ;
}
2007-05-03 16:29:32 +04:00
2011-06-07 05:44:43 +04:00
info3 = talloc_zero ( mem_ctx , struct netr_SamInfo3 ) ;
2008-02-17 03:47:01 +03:00
if ( ! info3 ) {
goto done ;
}
2008-04-21 12:25:28 +04:00
blob = data_blob_const ( data . dptr , data . dsize ) ;
2008-02-17 03:47:01 +03:00
2010-05-10 02:42:06 +04:00
ndr_err = ndr_pull_struct_blob ( & blob , mem_ctx , & r ,
2008-02-17 03:47:01 +03:00
( ndr_pull_flags_fn_t ) ndr_pull_netsamlogoncache_entry ) ;
2005-11-10 23:28:23 +03:00
2008-02-17 03:47:01 +03:00
if ( DEBUGLEVEL > = 10 ) {
NDR_PRINT_DEBUG ( netsamlogoncache_entry , & r ) ;
}
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
DEBUG ( 0 , ( " netsamlogon_cache_get: failed to pull entry from cache \n " ) ) ;
tdb_delete ( netsamlogon_tdb , data ) ;
2008-02-29 01:15:11 +03:00
TALLOC_FREE ( info3 ) ;
2008-02-17 03:47:01 +03:00
goto done ;
}
2008-02-23 12:50:12 +03:00
info3 = ( struct netr_SamInfo3 * ) talloc_memdup ( mem_ctx , & r . info3 ,
sizeof ( r . info3 ) ) ;
2008-02-17 03:47:01 +03:00
done :
SAFE_FREE ( data . dptr ) ;
return info3 ;
#if 0 /* The netsamlogon cache needs to hang around. Something about
2005-11-10 23:28:23 +03:00
this feels wrong , but it is the only way we can get all of the
groups . The old universal groups cache didn ' t expire either .
- - jerry */
{
time_t now = time ( NULL ) ;
uint32 time_diff ;
2008-02-17 03:47:01 +03:00
2005-11-10 23:28:23 +03:00
/* is the entry expired? */
time_diff = now - t ;
2008-02-17 03:47:01 +03:00
2005-11-10 23:28:23 +03:00
if ( ( time_diff < 0 ) | | ( time_diff > lp_winbind_cache_time ( ) ) ) {
DEBUG ( 10 , ( " netsamlogon_cache_get: cache entry expired \n " ) ) ;
tdb_delete ( netsamlogon_tdb , key ) ;
2007-05-04 00:12:00 +04:00
TALLOC_FREE ( user ) ;
2005-11-10 23:28:23 +03:00
}
}
2008-02-17 03:47:01 +03:00
# endif
2005-11-10 23:28:23 +03:00
}
2010-05-21 05:25:01 +04:00
bool netsamlogon_cache_have ( const struct dom_sid * user_sid )
2005-11-10 23:28:23 +03:00
{
TALLOC_CTX * mem_ctx = talloc_init ( " netsamlogon_cache_have " ) ;
2008-02-17 03:47:01 +03:00
struct netr_SamInfo3 * info3 = NULL ;
2007-10-19 04:40:25 +04:00
bool result ;
2005-11-10 23:28:23 +03:00
if ( ! mem_ctx )
return False ;
2008-02-17 03:47:01 +03:00
info3 = netsamlogon_cache_get ( mem_ctx , user_sid ) ;
2005-11-10 23:28:23 +03:00
2008-02-17 03:47:01 +03:00
result = ( info3 ! = NULL ) ;
2005-11-10 23:28:23 +03:00
talloc_destroy ( mem_ctx ) ;
return result ;
}