2006-02-04 01:19:41 +03:00
/*
Unix SMB / CIFS implementation .
2006-09-23 10:36:22 +04:00
Winbind daemon - krb5 credential cache functions
2006-08-26 06:53:45 +04:00
and in - memory cache functions .
2006-02-04 01:19:41 +03:00
2006-09-08 04:19:32 +04:00
Copyright ( C ) Guenther Deschner 2005 - 2006
2006-08-26 06:53:45 +04:00
Copyright ( C ) Jeremy Allison 2006
2007-09-03 16:23:45 +04:00
2006-02-04 01:19:41 +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
2006-02-04 01:19:41 +03:00
( at your option ) any later version .
2007-09-03 16:23:45 +04:00
2006-02-04 01:19:41 +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 .
2007-09-03 16:23:45 +04:00
2006-02-04 01:19:41 +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/>.
2006-02-04 01:19:41 +03:00
*/
# include "includes.h"
# include "winbindd.h"
2009-03-16 13:27:58 +03:00
# include "../libcli/auth/libcli_auth.h"
2009-11-27 17:52:57 +03:00
# include "smb_krb5.h"
2010-07-02 02:32:52 +04:00
# include "libads/kerberos_proto.h"
2009-11-27 17:52:57 +03:00
2006-02-04 01:19:41 +03:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_WINBIND
2007-09-03 16:23:45 +04:00
/* uncomment this to do fast debugging on the krb5 ticket renewal event */
2007-04-03 22:32:25 +04:00
# ifdef DEBUG_KRB5_TKT_RENEWAL
# undef DEBUG_KRB5_TKT_RENEWAL
# endif
2006-08-26 06:53:45 +04:00
# define MAX_CCACHES 100
2006-02-04 01:19:41 +03:00
static struct WINBINDD_CCACHE_ENTRY * ccache_list ;
2009-01-04 11:45:30 +03:00
static void krb5_ticket_gain_handler ( struct event_context * ,
struct timed_event * ,
2009-01-05 12:22:50 +03:00
struct timeval ,
2009-01-04 11:45:30 +03:00
void * ) ;
2009-01-07 00:16:46 +03:00
static void add_krb5_ticket_gain_handler_event ( struct WINBINDD_CCACHE_ENTRY * ,
struct timeval ) ;
2006-02-04 01:19:41 +03:00
2007-09-03 16:23:45 +04:00
/* The Krb5 ticket refresh handler should be scheduled
at one - half of the period from now till the tkt
2007-04-03 22:32:25 +04:00
expiration */
2010-03-29 18:13:14 +04:00
static time_t krb5_event_refresh_time ( time_t end_time )
{
time_t rest = end_time - time ( NULL ) ;
return end_time - rest / 2 ;
}
2007-04-03 22:32:25 +04:00
2006-08-26 06:53:45 +04:00
/****************************************************************
Find an entry by name .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-02-04 01:19:41 +03:00
2006-08-29 03:01:30 +04:00
static struct WINBINDD_CCACHE_ENTRY * get_ccache_by_username ( const char * username )
2006-02-04 01:19:41 +03:00
{
struct WINBINDD_CCACHE_ENTRY * entry ;
for ( entry = ccache_list ; entry ; entry = entry - > next ) {
if ( strequal ( entry - > username , username ) ) {
return entry ;
}
}
return NULL ;
}
2006-08-26 06:53:45 +04:00
/****************************************************************
How many do we have ?
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-02-04 01:19:41 +03:00
static int ccache_entry_count ( void )
{
struct WINBINDD_CCACHE_ENTRY * entry ;
int i = 0 ;
for ( entry = ccache_list ; entry ; entry = entry - > next ) {
i + + ;
}
return i ;
}
2008-12-30 11:17:20 +03:00
void ccache_remove_all_after_fork ( void )
{
struct WINBINDD_CCACHE_ENTRY * cur , * next ;
for ( cur = ccache_list ; cur ; cur = next ) {
next = cur - > next ;
DLIST_REMOVE ( ccache_list , cur ) ;
TALLOC_FREE ( cur - > event ) ;
TALLOC_FREE ( cur ) ;
}
return ;
}
2006-08-26 06:53:45 +04:00
/****************************************************************
Do the work of refreshing the ticket .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-02-04 01:19:41 +03:00
2007-01-17 15:59:14 +03:00
static void krb5_ticket_refresh_handler ( struct event_context * event_ctx ,
struct timed_event * te ,
2009-01-05 12:22:50 +03:00
struct timeval now ,
2006-02-04 01:19:41 +03:00
void * private_data )
{
struct WINBINDD_CCACHE_ENTRY * entry =
talloc_get_type_abort ( private_data , struct WINBINDD_CCACHE_ENTRY ) ;
2006-09-04 13:29:50 +04:00
# ifdef HAVE_KRB5
2006-02-04 01:19:41 +03:00
int ret ;
time_t new_start ;
2009-01-04 11:45:30 +03:00
time_t expire_time = 0 ;
2006-08-26 06:53:45 +04:00
struct WINBINDD_MEMORY_CREDS * cred_ptr = entry - > cred_ptr ;
2006-09-04 13:29:50 +04:00
# endif
2006-02-04 01:19:41 +03:00
DEBUG ( 10 , ( " krb5_ticket_refresh_handler called \n " ) ) ;
2007-09-03 16:23:45 +04:00
DEBUGADD ( 10 , ( " event called for: %s, %s \n " ,
entry - > ccname , entry - > username ) ) ;
2006-02-04 01:19:41 +03:00
2006-02-20 20:59:58 +03:00
TALLOC_FREE ( entry - > event ) ;
2006-02-04 01:19:41 +03:00
# ifdef HAVE_KRB5
/* Kinit again if we have the user password and we can't renew the old
2009-01-04 11:45:30 +03:00
* tgt anymore
* NB
* This happens when machine are put to sleep for a very long time . */
if ( entry - > renew_until < time ( NULL ) ) {
rekinit :
if ( cred_ptr & & cred_ptr - > pass ) {
set_effective_uid ( entry - > uid ) ;
ret = kerberos_kinit_password_ext ( entry - > principal_name ,
cred_ptr - > pass ,
0 , /* hm, can we do time correction here ? */
& entry - > refresh_time ,
& entry - > renew_until ,
entry - > ccname ,
False , /* no PAC required anymore */
True ,
WINBINDD_PAM_AUTH_KRB5_RENEW_TIME ,
NULL ) ;
gain_root_privilege ( ) ;
if ( ret ) {
DEBUG ( 3 , ( " krb5_ticket_refresh_handler: "
" could not re-kinit: %s \n " ,
error_message ( ret ) ) ) ;
/* destroy the ticket because we cannot rekinit
* it , ignore error here */
ads_kdestroy ( entry - > ccname ) ;
/* Don't break the ticket refresh chain: retry
* refreshing ticket sometime later when KDC is
2009-01-06 07:49:59 +03:00
* unreachable - - BoYang . More error code handling
* here ?
2009-01-04 11:45:30 +03:00
* */
if ( ( ret = = KRB5_KDC_UNREACH )
| | ( ret = = KRB5_REALM_CANT_RESOLVE ) ) {
# if defined(DEBUG_KRB5_TKT_RENEWAL)
new_start = time ( NULL ) + 30 ;
# else
new_start = time ( NULL ) +
MAX ( 30 , lp_winbind_cache_time ( ) ) ;
# endif
2009-01-07 00:16:46 +03:00
add_krb5_ticket_gain_handler_event ( entry ,
timeval_set ( new_start , 0 ) ) ;
2009-01-04 11:45:30 +03:00
return ;
}
TALLOC_FREE ( entry - > event ) ;
return ;
}
DEBUG ( 10 , ( " krb5_ticket_refresh_handler: successful re-kinit "
" for: %s in ccache: %s \n " ,
entry - > principal_name , entry - > ccname ) ) ;
2006-02-04 01:19:41 +03:00
2007-04-03 22:32:25 +04:00
# if defined(DEBUG_KRB5_TKT_RENEWAL)
2009-01-04 11:45:30 +03:00
new_start = time ( NULL ) + 30 ;
2007-04-03 22:32:25 +04:00
# else
2009-01-04 11:45:30 +03:00
/* The tkt should be refreshed at one-half the period
from now to the expiration time */
expire_time = entry - > refresh_time ;
2010-03-29 18:13:14 +04:00
new_start = krb5_event_refresh_time ( entry - > refresh_time ) ;
2007-04-03 22:32:25 +04:00
# endif
2009-01-04 11:45:30 +03:00
goto done ;
} else {
/* can this happen?
* No cached credentials
* destroy ticket and refresh chain
* */
ads_kdestroy ( entry - > ccname ) ;
TALLOC_FREE ( entry - > event ) ;
return ;
}
2006-02-04 01:19:41 +03:00
}
2006-05-12 02:47:28 +04:00
set_effective_uid ( entry - > uid ) ;
2006-02-04 01:19:41 +03:00
2007-09-03 16:23:45 +04:00
ret = smb_krb5_renew_ticket ( entry - > ccname ,
2006-02-04 01:19:41 +03:00
entry - > principal_name ,
entry - > service ,
& new_start ) ;
2007-04-03 22:32:25 +04:00
# if defined(DEBUG_KRB5_TKT_RENEWAL)
new_start = time ( NULL ) + 30 ;
# else
2009-01-04 11:45:30 +03:00
expire_time = new_start ;
2010-03-29 18:13:14 +04:00
new_start = krb5_event_refresh_time ( new_start ) ;
2007-04-03 22:32:25 +04:00
# endif
2006-05-12 02:47:28 +04:00
gain_root_privilege ( ) ;
2006-02-04 01:19:41 +03:00
if ( ret ) {
2007-09-03 16:23:45 +04:00
DEBUG ( 3 , ( " krb5_ticket_refresh_handler: "
" could not renew tickets: %s \n " ,
2006-09-08 04:19:32 +04:00
error_message ( ret ) ) ) ;
2006-02-04 01:19:41 +03:00
/* maybe we are beyond the renewing window */
2006-09-08 04:19:32 +04:00
2009-01-04 11:45:30 +03:00
/* evil rises here, we refresh ticket failed,
* but the ticket might be expired . Therefore ,
* When we refresh ticket failed , destory the
* ticket */
ads_kdestroy ( entry - > ccname ) ;
2007-09-03 16:23:45 +04:00
/* avoid breaking the renewal chain: retry in
* lp_winbind_cache_time ( ) seconds when the KDC was not
2009-01-04 11:45:30 +03:00
* available right now .
2009-01-06 07:49:59 +03:00
* the return code can be KRB5_REALM_CANT_RESOLVE .
* More error code handling here ? */
2006-09-08 04:19:32 +04:00
2009-01-04 11:45:30 +03:00
if ( ( ret = = KRB5_KDC_UNREACH )
| | ( ret = = KRB5_REALM_CANT_RESOLVE ) ) {
# if defined(DEBUG_KRB5_TKT_RENEWAL)
new_start = time ( NULL ) + 30 ;
# else
2007-09-03 16:23:45 +04:00
new_start = time ( NULL ) +
MAX ( 30 , lp_winbind_cache_time ( ) ) ;
2009-01-04 11:45:30 +03:00
# endif
/* ticket is destroyed here, we have to regain it
* if it is possible */
2009-01-07 00:16:46 +03:00
add_krb5_ticket_gain_handler_event ( entry ,
timeval_set ( new_start , 0 ) ) ;
2009-01-04 11:45:30 +03:00
return ;
2006-09-08 04:19:32 +04:00
}
2009-01-04 11:45:30 +03:00
/* This is evil, if the ticket was already expired.
* renew ticket function returns KRB5KRB_AP_ERR_TKT_EXPIRED .
* But there is still a chance that we can rekinit it .
*
* This happens when user login in online mode , and then network
* down or something cause winbind goes offline for a very long time ,
* and then goes online again . ticket expired , renew failed .
* This happens when machine are put to sleep for a long time ,
* but shorter than entry - > renew_util .
* NB
* Looks like the KDC is reachable , we want to rekinit as soon as
* possible instead of waiting some time later . */
if ( ( ret = = KRB5KRB_AP_ERR_TKT_EXPIRED )
| | ( ret = = KRB5_FCC_NOFILE ) ) goto rekinit ;
2006-02-04 01:19:41 +03:00
return ;
}
done :
2009-01-04 11:45:30 +03:00
/* in cases that ticket will be unrenewable soon, we don't try to renew ticket
* but try to regain ticket if it is possible */
if ( entry - > renew_until & & expire_time
& & ( entry - > renew_until < = expire_time ) ) {
2010-05-01 16:39:01 +04:00
/* try to regain ticket 10 seconds before expiration */
2009-01-04 11:45:30 +03:00
expire_time - = 10 ;
2009-01-07 00:16:46 +03:00
add_krb5_ticket_gain_handler_event ( entry ,
timeval_set ( expire_time , 0 ) ) ;
2009-01-04 11:45:30 +03:00
return ;
}
2006-02-04 01:19:41 +03:00
2008-12-30 11:56:36 +03:00
if ( entry - > refresh_time = = 0 ) {
entry - > refresh_time = new_start ;
}
2007-09-03 16:23:45 +04:00
entry - > event = event_add_timed ( winbind_event_context ( ) , entry ,
2006-09-08 04:19:32 +04:00
timeval_set ( new_start , 0 ) ,
2006-02-04 01:19:41 +03:00
krb5_ticket_refresh_handler ,
entry ) ;
# endif
}
2006-09-08 04:19:32 +04:00
/****************************************************************
Do the work of regaining a ticket when coming from offline auth .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-01-17 15:59:14 +03:00
static void krb5_ticket_gain_handler ( struct event_context * event_ctx ,
struct timed_event * te ,
2009-01-05 12:22:50 +03:00
struct timeval now ,
2007-09-03 16:23:45 +04:00
void * private_data )
2006-09-08 04:19:32 +04:00
{
struct WINBINDD_CCACHE_ENTRY * entry =
talloc_get_type_abort ( private_data , struct WINBINDD_CCACHE_ENTRY ) ;
# ifdef HAVE_KRB5
int ret ;
struct timeval t ;
struct WINBINDD_MEMORY_CREDS * cred_ptr = entry - > cred_ptr ;
struct winbindd_domain * domain = NULL ;
# endif
DEBUG ( 10 , ( " krb5_ticket_gain_handler called \n " ) ) ;
2007-09-03 16:23:45 +04:00
DEBUGADD ( 10 , ( " event called for: %s, %s \n " ,
entry - > ccname , entry - > username ) ) ;
2006-09-08 04:19:32 +04:00
TALLOC_FREE ( entry - > event ) ;
# ifdef HAVE_KRB5
if ( ! cred_ptr | | ! cred_ptr - > pass ) {
DEBUG ( 10 , ( " krb5_ticket_gain_handler: no memory creds \n " ) ) ;
return ;
}
if ( ( domain = find_domain_from_name ( entry - > realm ) ) = = NULL ) {
DEBUG ( 0 , ( " krb5_ticket_gain_handler: unknown domain \n " ) ) ;
return ;
}
2007-09-03 16:23:45 +04:00
if ( ! domain - > online ) {
goto retry_later ;
}
2006-09-08 04:19:32 +04:00
2007-09-03 16:23:45 +04:00
set_effective_uid ( entry - > uid ) ;
2006-09-08 04:19:32 +04:00
2007-09-03 16:23:45 +04:00
ret = kerberos_kinit_password_ext ( entry - > principal_name ,
cred_ptr - > pass ,
0 , /* hm, can we do time correction here ? */
& entry - > refresh_time ,
& entry - > renew_until ,
entry - > ccname ,
False , /* no PAC required anymore */
True ,
WINBINDD_PAM_AUTH_KRB5_RENEW_TIME ,
NULL ) ;
gain_root_privilege ( ) ;
2006-09-08 04:19:32 +04:00
2007-09-03 16:23:45 +04:00
if ( ret ) {
DEBUG ( 3 , ( " krb5_ticket_gain_handler: "
" could not kinit: %s \n " ,
error_message ( ret ) ) ) ;
2009-01-04 11:45:30 +03:00
/* evil. If we cannot do it, destroy any the __maybe__
* __existing__ ticket */
ads_kdestroy ( entry - > ccname ) ;
2007-09-03 16:23:45 +04:00
goto retry_later ;
}
2006-09-08 04:19:32 +04:00
2007-09-03 16:23:45 +04:00
DEBUG ( 10 , ( " krb5_ticket_gain_handler: "
" successful kinit for: %s in ccache: %s \n " ,
entry - > principal_name , entry - > ccname ) ) ;
2006-09-08 04:19:32 +04:00
2007-09-03 16:23:45 +04:00
goto got_ticket ;
2006-09-08 04:19:32 +04:00
retry_later :
2009-01-04 11:45:30 +03:00
2010-05-01 16:51:15 +04:00
# if defined(DEBUG_KRB5_TKT_RENEWAL)
2009-01-04 11:45:30 +03:00
t = timeval_set ( time ( NULL ) + 30 , 0 ) ;
# else
2007-09-03 16:23:45 +04:00
t = timeval_current_ofs ( MAX ( 30 , lp_winbind_cache_time ( ) ) , 0 ) ;
2009-01-04 11:45:30 +03:00
# endif
2007-09-03 16:23:45 +04:00
2009-01-07 00:16:46 +03:00
add_krb5_ticket_gain_handler_event ( entry , t ) ;
2006-09-08 04:19:32 +04:00
return ;
got_ticket :
2007-04-03 22:32:25 +04:00
# if defined(DEBUG_KRB5_TKT_RENEWAL)
2006-09-08 04:19:32 +04:00
t = timeval_set ( time ( NULL ) + 30 , 0 ) ;
# else
2010-03-29 18:13:14 +04:00
t = timeval_set ( krb5_event_refresh_time ( entry - > refresh_time ) , 0 ) ;
2007-04-03 22:32:25 +04:00
# endif
2006-09-08 04:19:32 +04:00
2008-12-30 11:56:36 +03:00
if ( entry - > refresh_time = = 0 ) {
entry - > refresh_time = t . tv_sec ;
}
2007-09-03 16:23:45 +04:00
entry - > event = event_add_timed ( winbind_event_context ( ) ,
entry ,
t ,
krb5_ticket_refresh_handler ,
entry ) ;
2006-09-08 04:19:32 +04:00
return ;
# endif
}
2009-01-07 00:16:46 +03:00
/**************************************************************
The gain initial ticket case is recognised as entry - > refresh_time
is always zero .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void add_krb5_ticket_gain_handler_event ( struct WINBINDD_CCACHE_ENTRY * entry ,
struct timeval t )
{
entry - > refresh_time = 0 ;
entry - > event = event_add_timed ( winbind_event_context ( ) ,
entry ,
t ,
krb5_ticket_gain_handler ,
entry ) ;
}
2008-12-30 11:56:36 +03:00
void ccache_regain_all_now ( void )
{
struct WINBINDD_CCACHE_ENTRY * cur ;
struct timeval t = timeval_current ( ) ;
for ( cur = ccache_list ; cur ; cur = cur - > next ) {
struct timed_event * new_event ;
/*
* if refresh_time is 0 , we know that the
* the event has the krb5_ticket_gain_handler
*/
if ( cur - > refresh_time = = 0 ) {
new_event = event_add_timed ( winbind_event_context ( ) ,
cur ,
t ,
krb5_ticket_gain_handler ,
cur ) ;
} else {
new_event = event_add_timed ( winbind_event_context ( ) ,
cur ,
t ,
krb5_ticket_refresh_handler ,
cur ) ;
}
if ( ! new_event ) {
continue ;
}
TALLOC_FREE ( cur - > event ) ;
cur - > event = new_event ;
}
return ;
}
2007-02-26 12:53:35 +03:00
/****************************************************************
Check if an ccache entry exists .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
bool ccache_entry_exists ( const char * username )
2007-02-26 12:53:35 +03:00
{
struct WINBINDD_CCACHE_ENTRY * entry = get_ccache_by_username ( username ) ;
return ( entry ! = NULL ) ;
}
2006-08-26 06:53:45 +04:00
/****************************************************************
Ensure we ' re changing the correct entry .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
bool ccache_entry_identical ( const char * username ,
2007-09-03 16:23:45 +04:00
uid_t uid ,
const char * ccname )
2006-08-26 06:53:45 +04:00
{
struct WINBINDD_CCACHE_ENTRY * entry = get_ccache_by_username ( username ) ;
if ( ! entry ) {
return False ;
}
if ( entry - > uid ! = uid ) {
DEBUG ( 0 , ( " cache_entry_identical: uid's differ: %u != %u \n " ,
2007-09-03 16:23:45 +04:00
( unsigned int ) entry - > uid , ( unsigned int ) uid ) ) ;
2006-08-26 06:53:45 +04:00
return False ;
}
if ( ! strcsequal ( entry - > ccname , ccname ) ) {
2007-09-03 16:23:45 +04:00
DEBUG ( 0 , ( " cache_entry_identical: "
" ccnames differ: (cache) %s != (client) %s \n " ,
2006-08-26 06:53:45 +04:00
entry - > ccname , ccname ) ) ;
return False ;
}
return True ;
}
2006-02-04 01:19:41 +03:00
NTSTATUS add_ccache_to_list ( const char * princ_name ,
const char * ccname ,
const char * service ,
2007-09-03 16:23:45 +04:00
const char * username ,
2006-09-08 04:19:32 +04:00
const char * realm ,
2006-02-04 01:19:41 +03:00
uid_t uid ,
2007-09-03 16:23:45 +04:00
time_t create_time ,
time_t ticket_end ,
time_t renew_until ,
2007-10-19 04:40:25 +04:00
bool postponed_request )
2006-02-04 01:19:41 +03:00
{
2006-08-26 06:53:45 +04:00
struct WINBINDD_CCACHE_ENTRY * entry = NULL ;
2007-09-03 16:23:45 +04:00
struct timeval t ;
2009-01-04 11:45:30 +03:00
NTSTATUS ntret ;
# ifdef HAVE_KRB5
int ret ;
# endif
2006-02-04 01:19:41 +03:00
2007-09-03 16:23:45 +04:00
if ( ( username = = NULL & & princ_name = = NULL ) | |
ccname = = NULL | | uid < 0 ) {
2006-02-04 01:19:41 +03:00
return NT_STATUS_INVALID_PARAMETER ;
}
if ( ccache_entry_count ( ) + 1 > MAX_CCACHES ) {
2007-09-03 16:23:45 +04:00
DEBUG ( 10 , ( " add_ccache_to_list: "
" max number of ccaches reached \n " ) ) ;
2006-02-04 01:19:41 +03:00
return NT_STATUS_NO_MORE_ENTRIES ;
}
2009-01-04 11:45:30 +03:00
/* If it is cached login, destroy krb5 ticket
* to avoid surprise . */
# ifdef HAVE_KRB5
if ( postponed_request ) {
/* ignore KRB5_FCC_NOFILE error here */
ret = ads_kdestroy ( ccname ) ;
if ( ret = = KRB5_FCC_NOFILE ) {
ret = 0 ;
}
if ( ret ) {
DEBUG ( 0 , ( " add_ccache_to_list: failed to destroy "
" user krb5 ccache %s with %s \n " , ccname ,
error_message ( ret ) ) ) ;
return krb5_to_nt_status ( ret ) ;
}
2010-01-09 20:43:38 +03:00
DEBUG ( 10 , ( " add_ccache_to_list: successfully destroyed "
" krb5 ccache %s for user %s \n " , ccname ,
username ) ) ;
2009-01-04 11:45:30 +03:00
}
# endif
2006-08-26 06:53:45 +04:00
/* Reference count old entries */
entry = get_ccache_by_username ( username ) ;
if ( entry ) {
/* Check cached entries are identical. */
if ( ! ccache_entry_identical ( username , uid , ccname ) ) {
return NT_STATUS_INVALID_PARAMETER ;
2006-05-02 23:15:14 +04:00
}
2006-08-26 06:53:45 +04:00
entry - > ref_count + + ;
2007-09-03 16:23:45 +04:00
DEBUG ( 10 , ( " add_ccache_to_list: "
" ref count on entry %s is now %d \n " ,
2006-08-26 06:53:45 +04:00
username , entry - > ref_count ) ) ;
2007-02-26 12:53:35 +03:00
/* FIXME: in this case we still might want to have a krb5 cred
2009-01-04 11:45:30 +03:00
* event handler created - gd
* Add ticket refresh handler here */
2010-01-09 22:26:46 +03:00
2009-01-04 11:45:30 +03:00
if ( ! lp_winbind_refresh_tickets ( ) | | renew_until < = 0 ) {
return NT_STATUS_OK ;
}
2010-01-09 22:26:46 +03:00
2009-01-04 11:45:30 +03:00
if ( ! entry - > event ) {
if ( postponed_request ) {
t = timeval_current_ofs ( MAX ( 30 , lp_winbind_cache_time ( ) ) , 0 ) ;
2009-01-07 00:16:46 +03:00
add_krb5_ticket_gain_handler_event ( entry , t ) ;
2009-01-04 11:45:30 +03:00
} else {
/* Renew at 1/2 the ticket expiration time */
# if defined(DEBUG_KRB5_TKT_RENEWAL)
t = timeval_set ( time ( NULL ) + 30 , 0 ) ;
# else
2010-03-29 18:13:14 +04:00
t = timeval_set ( krb5_event_refresh_time ( ticket_end ) ,
0 ) ;
2009-01-04 11:45:30 +03:00
# endif
2009-01-06 07:49:59 +03:00
if ( ! entry - > refresh_time ) {
entry - > refresh_time = t . tv_sec ;
}
2009-01-04 11:45:30 +03:00
entry - > event = event_add_timed ( winbind_event_context ( ) ,
entry ,
t ,
krb5_ticket_refresh_handler ,
entry ) ;
}
if ( ! entry - > event ) {
ntret = remove_ccache ( username ) ;
if ( ! NT_STATUS_IS_OK ( ntret ) ) {
DEBUG ( 0 , ( " add_ccache_to_list: Failed to remove krb5 "
" ccache %s for user %s \n " , entry - > ccname ,
entry - > username ) ) ;
DEBUG ( 0 , ( " add_ccache_to_list: error is %s \n " ,
nt_errstr ( ntret ) ) ) ;
return ntret ;
}
return NT_STATUS_NO_MEMORY ;
}
DEBUG ( 10 , ( " add_ccache_to_list: added krb5_ticket handler \n " ) ) ;
}
2010-01-09 22:26:46 +03:00
2006-08-26 06:53:45 +04:00
return NT_STATUS_OK ;
2006-05-02 23:15:14 +04:00
}
2007-09-03 16:23:45 +04:00
2011-06-07 05:38:41 +04:00
entry = talloc ( NULL , struct WINBINDD_CCACHE_ENTRY ) ;
2006-08-26 06:53:45 +04:00
if ( ! entry ) {
2006-02-04 01:19:41 +03:00
return NT_STATUS_NO_MEMORY ;
}
2006-08-26 06:53:45 +04:00
ZERO_STRUCTP ( entry ) ;
2006-02-04 01:19:41 +03:00
if ( username ) {
2006-08-26 06:53:45 +04:00
entry - > username = talloc_strdup ( entry , username ) ;
if ( ! entry - > username ) {
goto no_mem ;
}
2006-02-04 01:19:41 +03:00
}
if ( princ_name ) {
2006-08-26 06:53:45 +04:00
entry - > principal_name = talloc_strdup ( entry , princ_name ) ;
if ( ! entry - > principal_name ) {
goto no_mem ;
}
2006-02-04 01:19:41 +03:00
}
if ( service ) {
2006-08-26 06:53:45 +04:00
entry - > service = talloc_strdup ( entry , service ) ;
if ( ! entry - > service ) {
goto no_mem ;
}
2006-02-04 01:19:41 +03:00
}
2006-05-16 18:29:39 +04:00
2006-08-26 06:53:45 +04:00
entry - > ccname = talloc_strdup ( entry , ccname ) ;
if ( ! entry - > ccname ) {
goto no_mem ;
}
2006-08-20 05:25:26 +04:00
2006-09-08 04:19:32 +04:00
entry - > realm = talloc_strdup ( entry , realm ) ;
if ( ! entry - > realm ) {
goto no_mem ;
}
2006-08-26 06:53:45 +04:00
entry - > create_time = create_time ;
entry - > renew_until = renew_until ;
entry - > uid = uid ;
2006-09-06 08:41:43 +04:00
entry - > ref_count = 1 ;
2006-08-20 05:25:26 +04:00
2007-09-03 16:23:45 +04:00
if ( ! lp_winbind_refresh_tickets ( ) | | renew_until < = 0 ) {
goto add_entry ;
}
if ( postponed_request ) {
t = timeval_current_ofs ( MAX ( 30 , lp_winbind_cache_time ( ) ) , 0 ) ;
2009-01-07 00:16:46 +03:00
add_krb5_ticket_gain_handler_event ( entry , t ) ;
2007-09-03 16:23:45 +04:00
} else {
/* Renew at 1/2 the ticket expiration time */
2007-04-03 22:32:25 +04:00
# if defined(DEBUG_KRB5_TKT_RENEWAL)
2007-09-03 16:23:45 +04:00
t = timeval_set ( time ( NULL ) + 30 , 0 ) ;
2007-04-03 22:32:25 +04:00
# else
2010-03-29 18:13:14 +04:00
t = timeval_set ( krb5_event_refresh_time ( ticket_end ) , 0 ) ;
2007-04-03 22:32:25 +04:00
# endif
2008-12-30 11:56:36 +03:00
if ( entry - > refresh_time = = 0 ) {
entry - > refresh_time = t . tv_sec ;
}
2007-09-03 16:23:45 +04:00
entry - > event = event_add_timed ( winbind_event_context ( ) ,
entry ,
t ,
krb5_ticket_refresh_handler ,
entry ) ;
}
2006-08-20 05:25:26 +04:00
2007-09-03 16:23:45 +04:00
if ( ! entry - > event ) {
goto no_mem ;
2006-08-26 06:53:45 +04:00
}
2007-09-03 16:23:45 +04:00
DEBUG ( 10 , ( " add_ccache_to_list: added krb5_ticket handler \n " ) ) ;
add_entry :
2006-08-26 06:53:45 +04:00
DLIST_ADD ( ccache_list , entry ) ;
2007-09-03 16:23:45 +04:00
DEBUG ( 10 , ( " add_ccache_to_list: "
" added ccache [%s] for user [%s] to the list \n " ,
ccname , username ) ) ;
2006-08-20 05:25:26 +04:00
2006-08-26 06:53:45 +04:00
return NT_STATUS_OK ;
no_mem :
TALLOC_FREE ( entry ) ;
return NT_STATUS_NO_MEMORY ;
}
2006-12-14 19:34:24 +03:00
/*******************************************************************
2007-09-03 16:23:45 +04:00
Remove a WINBINDD_CCACHE_ENTRY entry and the krb5 ccache if no longer
referenced .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-12-14 19:34:24 +03:00
2006-08-26 06:53:45 +04:00
NTSTATUS remove_ccache ( const char * username )
{
struct WINBINDD_CCACHE_ENTRY * entry = get_ccache_by_username ( username ) ;
2007-08-20 16:29:07 +04:00
NTSTATUS status = NT_STATUS_OK ;
2010-04-17 23:39:09 +04:00
# ifdef HAVE_KRB5
2006-12-14 19:34:24 +03:00
krb5_error_code ret ;
# endif
2006-08-26 06:53:45 +04:00
if ( ! entry ) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
}
if ( entry - > ref_count < = 0 ) {
2007-09-03 16:23:45 +04:00
DEBUG ( 0 , ( " remove_ccache: logic error. "
" ref count for user %s = %d \n " ,
2006-08-26 06:53:45 +04:00
username , entry - > ref_count ) ) ;
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
entry - > ref_count - - ;
2006-12-14 19:34:24 +03:00
if ( entry - > ref_count > 0 ) {
2006-08-26 06:53:45 +04:00
DEBUG ( 10 , ( " remove_ccache: entry %s ref count now %d \n " ,
2007-09-03 16:23:45 +04:00
username , entry - > ref_count ) ) ;
2006-12-14 19:34:24 +03:00
return NT_STATUS_OK ;
2006-08-26 06:53:45 +04:00
}
2006-12-14 19:34:24 +03:00
/* no references any more */
DLIST_REMOVE ( ccache_list , entry ) ;
TALLOC_FREE ( entry - > event ) ; /* unregisters events */
# ifdef HAVE_KRB5
ret = ads_kdestroy ( entry - > ccname ) ;
2007-01-05 02:41:16 +03:00
/* we ignore the error when there has been no credential cache */
if ( ret = = KRB5_FCC_NOFILE ) {
ret = 0 ;
} else if ( ret ) {
2007-09-03 16:23:45 +04:00
DEBUG ( 0 , ( " remove_ccache: "
" failed to destroy user krb5 ccache %s with: %s \n " ,
2006-12-14 19:34:24 +03:00
entry - > ccname , error_message ( ret ) ) ) ;
} else {
2007-09-03 16:23:45 +04:00
DEBUG ( 10 , ( " remove_ccache: "
" successfully destroyed krb5 ccache %s for user %s \n " ,
2006-12-14 19:34:24 +03:00
entry - > ccname , username ) ) ;
}
status = krb5_to_nt_status ( ret ) ;
# endif
TALLOC_FREE ( entry ) ;
DEBUG ( 10 , ( " remove_ccache: removed ccache for user %s \n " , username ) ) ;
return status ;
2006-08-26 06:53:45 +04:00
}
/*******************************************************************
In memory credentials cache code .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static struct WINBINDD_MEMORY_CREDS * memory_creds_list ;
/***********************************************************
Find an entry on the list by name .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-08-29 03:01:30 +04:00
struct WINBINDD_MEMORY_CREDS * find_memory_creds_by_name ( const char * username )
2006-08-26 06:53:45 +04:00
{
struct WINBINDD_MEMORY_CREDS * p ;
2006-08-20 05:25:26 +04:00
2006-08-26 06:53:45 +04:00
for ( p = memory_creds_list ; p ; p = p - > next ) {
if ( strequal ( p - > username , username ) ) {
return p ;
2006-08-20 05:25:26 +04:00
}
2006-02-04 01:19:41 +03:00
}
2006-08-26 06:53:45 +04:00
return NULL ;
}
2006-02-04 01:19:41 +03:00
2006-08-26 06:53:45 +04:00
/***********************************************************
Store the required creds and mlock them .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-09-03 16:23:45 +04:00
static NTSTATUS store_memory_creds ( struct WINBINDD_MEMORY_CREDS * memcredp ,
const char * pass )
2006-08-26 06:53:45 +04:00
{
# if !defined(HAVE_MLOCK)
return NT_STATUS_OK ;
# else
/* new_entry->nt_hash is the base pointer for the block
of memory pointed into by new_entry - > lm_hash and
new_entry - > pass ( if we ' re storing plaintext ) . */
memcredp - > len = NT_HASH_LEN + LM_HASH_LEN ;
2006-09-08 04:19:32 +04:00
if ( pass ) {
2006-08-26 06:53:45 +04:00
memcredp - > len + = strlen ( pass ) + 1 ;
2006-02-04 01:19:41 +03:00
}
2007-04-03 22:32:25 +04:00
2007-03-01 06:14:20 +03:00
# if defined(LINUX)
2007-09-03 16:23:45 +04:00
/* aligning the memory on on x86_64 and compiling
with gcc 4.1 using - O2 causes a segv in the
2007-03-01 06:14:20 +03:00
next memset ( ) - - jerry */
memcredp - > nt_hash = SMB_MALLOC_ARRAY ( unsigned char , memcredp - > len ) ;
# else
/* On non-linux platforms, mlock()'d memory must be aligned */
2007-09-03 16:23:45 +04:00
memcredp - > nt_hash = SMB_MEMALIGN_ARRAY ( unsigned char ,
2007-03-01 06:14:20 +03:00
getpagesize ( ) , memcredp - > len ) ;
# endif
2007-02-24 15:40:43 +03:00
if ( ! memcredp - > nt_hash ) {
2006-08-26 06:53:45 +04:00
return NT_STATUS_NO_MEMORY ;
}
2007-09-03 16:23:45 +04:00
memset ( memcredp - > nt_hash , 0x0 , memcredp - > len ) ;
2006-02-04 01:19:41 +03:00
2006-08-26 06:53:45 +04:00
memcredp - > lm_hash = memcredp - > nt_hash + NT_HASH_LEN ;
2007-02-22 20:21:27 +03:00
2006-08-26 06:53:45 +04:00
# ifdef DEBUG_PASSWORD
DEBUG ( 10 , ( " mlocking memory: %p \n " , memcredp - > nt_hash ) ) ;
2007-09-03 16:23:45 +04:00
# endif
2007-02-24 15:40:43 +03:00
if ( ( mlock ( memcredp - > nt_hash , memcredp - > len ) ) = = - 1 ) {
2007-09-03 16:23:45 +04:00
DEBUG ( 0 , ( " failed to mlock memory: %s (%d) \n " ,
2006-08-26 06:53:45 +04:00
strerror ( errno ) , errno ) ) ;
2007-03-01 08:52:38 +03:00
SAFE_FREE ( memcredp - > nt_hash ) ;
2006-08-26 06:53:45 +04:00
return map_nt_error_from_unix ( errno ) ;
2006-02-04 01:19:41 +03:00
}
2006-08-26 06:53:45 +04:00
# ifdef DEBUG_PASSWORD
DEBUG ( 10 , ( " mlocked memory: %p \n " , memcredp - > nt_hash ) ) ;
2007-09-03 16:23:45 +04:00
# endif
2006-02-04 01:19:41 +03:00
2006-08-26 06:53:45 +04:00
/* Create and store the password hashes. */
E_md4hash ( pass , memcredp - > nt_hash ) ;
E_deshash ( pass , memcredp - > lm_hash ) ;
2006-09-08 04:19:32 +04:00
if ( pass ) {
2006-08-26 06:53:45 +04:00
memcredp - > pass = ( char * ) memcredp - > lm_hash + LM_HASH_LEN ;
2007-09-03 16:23:45 +04:00
memcpy ( memcredp - > pass , pass ,
memcredp - > len - NT_HASH_LEN - LM_HASH_LEN ) ;
2006-08-26 06:53:45 +04:00
}
2006-02-04 01:19:41 +03:00
return NT_STATUS_OK ;
2006-08-26 06:53:45 +04:00
# endif
2006-02-04 01:19:41 +03:00
}
2006-08-26 06:53:45 +04:00
/***********************************************************
Destroy existing creds .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS delete_memory_creds ( struct WINBINDD_MEMORY_CREDS * memcredp )
2006-02-04 01:19:41 +03:00
{
2006-08-26 06:53:45 +04:00
# if !defined(HAVE_MUNLOCK)
return NT_STATUS_OK ;
# else
2007-02-24 15:40:43 +03:00
if ( munlock ( memcredp - > nt_hash , memcredp - > len ) = = - 1 ) {
2007-09-03 16:23:45 +04:00
DEBUG ( 0 , ( " failed to munlock memory: %s (%d) \n " ,
2006-05-16 18:29:39 +04:00
strerror ( errno ) , errno ) ) ;
return map_nt_error_from_unix ( errno ) ;
}
2007-02-24 15:40:43 +03:00
memset ( memcredp - > nt_hash , ' \0 ' , memcredp - > len ) ;
SAFE_FREE ( memcredp - > nt_hash ) ;
2007-02-22 20:21:27 +03:00
memcredp - > nt_hash = NULL ;
2006-08-26 06:53:45 +04:00
memcredp - > lm_hash = NULL ;
memcredp - > pass = NULL ;
memcredp - > len = 0 ;
return NT_STATUS_OK ;
# endif
2006-02-04 01:19:41 +03:00
}
2006-08-26 06:53:45 +04:00
/***********************************************************
Replace the required creds with new ones ( password change ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS winbindd_replace_memory_creds_internal ( struct WINBINDD_MEMORY_CREDS * memcredp ,
2007-09-03 16:23:45 +04:00
const char * pass )
2006-02-04 01:19:41 +03:00
{
2006-08-26 06:53:45 +04:00
NTSTATUS status = delete_memory_creds ( memcredp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2006-09-08 04:19:32 +04:00
return store_memory_creds ( memcredp , pass ) ;
2006-08-26 06:53:45 +04:00
}
/*************************************************************
Store credentials in memory in a list .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-09-03 16:23:45 +04:00
static NTSTATUS winbindd_add_memory_creds_internal ( const char * username ,
uid_t uid ,
const char * pass )
2006-08-26 06:53:45 +04:00
{
/* Shortcut to ensure we don't store if no mlock. */
# if !defined(HAVE_MLOCK) || !defined(HAVE_MUNLOCK)
return NT_STATUS_OK ;
# else
NTSTATUS status ;
2007-09-03 16:23:45 +04:00
struct WINBINDD_MEMORY_CREDS * memcredp = NULL ;
2006-08-26 06:53:45 +04:00
2007-09-03 16:23:45 +04:00
memcredp = find_memory_creds_by_name ( username ) ;
2006-08-29 03:01:30 +04:00
if ( uid = = ( uid_t ) - 1 ) {
2007-09-03 16:23:45 +04:00
DEBUG ( 0 , ( " winbindd_add_memory_creds_internal: "
" invalid uid for user %s. \n " , username ) ) ;
2006-08-29 03:01:30 +04:00
return NT_STATUS_INVALID_PARAMETER ;
}
2006-08-26 06:53:45 +04:00
if ( memcredp ) {
/* Already exists. Increment the reference count and replace stored creds. */
2006-08-29 03:01:30 +04:00
if ( uid ! = memcredp - > uid ) {
2007-09-03 16:23:45 +04:00
DEBUG ( 0 , ( " winbindd_add_memory_creds_internal: "
" uid %u for user %s doesn't "
2006-08-29 03:01:30 +04:00
" match stored uid %u. Replacing. \n " ,
2007-09-03 16:23:45 +04:00
( unsigned int ) uid , username ,
( unsigned int ) memcredp - > uid ) ) ;
2006-08-29 03:01:30 +04:00
memcredp - > uid = uid ;
}
2006-08-26 06:53:45 +04:00
memcredp - > ref_count + + ;
2007-09-03 16:23:45 +04:00
DEBUG ( 10 , ( " winbindd_add_memory_creds_internal: "
" ref count for user %s is now %d \n " ,
username , memcredp - > ref_count ) ) ;
2006-09-08 04:19:32 +04:00
return winbindd_replace_memory_creds_internal ( memcredp , pass ) ;
2006-02-04 01:19:41 +03:00
}
2011-06-07 05:44:43 +04:00
memcredp = talloc_zero ( NULL , struct WINBINDD_MEMORY_CREDS ) ;
2006-08-26 06:53:45 +04:00
if ( ! memcredp ) {
return NT_STATUS_NO_MEMORY ;
}
memcredp - > username = talloc_strdup ( memcredp , username ) ;
if ( ! memcredp - > username ) {
talloc_destroy ( memcredp ) ;
2006-02-04 01:19:41 +03:00
return NT_STATUS_NO_MEMORY ;
}
2006-09-08 04:19:32 +04:00
status = store_memory_creds ( memcredp , pass ) ;
2006-08-26 06:53:45 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2006-08-29 03:01:30 +04:00
talloc_destroy ( memcredp ) ;
2006-08-26 06:53:45 +04:00
return status ;
}
2006-08-29 03:01:30 +04:00
memcredp - > uid = uid ;
2006-08-26 06:53:45 +04:00
memcredp - > ref_count = 1 ;
DLIST_ADD ( memory_creds_list , memcredp ) ;
2007-09-03 16:23:45 +04:00
DEBUG ( 10 , ( " winbindd_add_memory_creds_internal: "
" added entry for user %s \n " , username ) ) ;
2006-02-04 01:19:41 +03:00
return NT_STATUS_OK ;
2006-08-26 06:53:45 +04:00
# endif
}
/*************************************************************
2007-09-03 16:23:45 +04:00
Store users credentials in memory . If we also have a
2006-08-26 06:53:45 +04:00
struct WINBINDD_CCACHE_ENTRY for this username with a
refresh timer , then store the plaintext of the password
and associate the new credentials with the struct WINBINDD_CCACHE_ENTRY .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-09-03 16:23:45 +04:00
NTSTATUS winbindd_add_memory_creds ( const char * username ,
uid_t uid ,
const char * pass )
2006-08-26 06:53:45 +04:00
{
struct WINBINDD_CCACHE_ENTRY * entry = get_ccache_by_username ( username ) ;
NTSTATUS status ;
2006-09-08 04:19:32 +04:00
status = winbindd_add_memory_creds_internal ( username , uid , pass ) ;
2006-08-26 06:53:45 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2006-09-08 04:19:32 +04:00
if ( entry ) {
2007-09-03 16:23:45 +04:00
struct WINBINDD_MEMORY_CREDS * memcredp = NULL ;
memcredp = find_memory_creds_by_name ( username ) ;
2006-08-26 06:53:45 +04:00
if ( memcredp ) {
entry - > cred_ptr = memcredp ;
}
}
return status ;
}
/*************************************************************
Decrement the in - memory ref count - delete if zero .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS winbindd_delete_memory_creds ( const char * username )
{
2007-09-03 16:23:45 +04:00
struct WINBINDD_MEMORY_CREDS * memcredp = NULL ;
struct WINBINDD_CCACHE_ENTRY * entry = NULL ;
2006-08-26 06:53:45 +04:00
NTSTATUS status = NT_STATUS_OK ;
2007-09-03 16:23:45 +04:00
memcredp = find_memory_creds_by_name ( username ) ;
entry = get_ccache_by_username ( username ) ;
2006-08-26 06:53:45 +04:00
if ( ! memcredp ) {
DEBUG ( 10 , ( " winbindd_delete_memory_creds: unknown user %s \n " ,
2007-09-03 16:23:45 +04:00
username ) ) ;
2006-08-26 06:53:45 +04:00
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
}
if ( memcredp - > ref_count < = 0 ) {
2007-09-03 16:23:45 +04:00
DEBUG ( 0 , ( " winbindd_delete_memory_creds: logic error. "
" ref count for user %s = %d \n " ,
2006-08-26 06:53:45 +04:00
username , memcredp - > ref_count ) ) ;
status = NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
memcredp - > ref_count - - ;
if ( memcredp - > ref_count < = 0 ) {
delete_memory_creds ( memcredp ) ;
DLIST_REMOVE ( memory_creds_list , memcredp ) ;
talloc_destroy ( memcredp ) ;
2007-09-03 16:23:45 +04:00
DEBUG ( 10 , ( " winbindd_delete_memory_creds: "
" deleted entry for user %s \n " ,
2006-08-26 06:53:45 +04:00
username ) ) ;
} else {
2007-09-03 16:23:45 +04:00
DEBUG ( 10 , ( " winbindd_delete_memory_creds: "
" entry for user %s ref_count now %d \n " ,
2006-08-26 06:53:45 +04:00
username , memcredp - > ref_count ) ) ;
}
2006-09-08 04:19:32 +04:00
if ( entry ) {
2007-09-03 16:23:45 +04:00
/* Ensure we have no dangling references to this. */
entry - > cred_ptr = NULL ;
2006-09-08 04:19:32 +04:00
}
2007-09-03 16:23:45 +04:00
2006-08-26 06:53:45 +04:00
return status ;
}
/***********************************************************
Replace the required creds with new ones ( password change ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-09-03 16:23:45 +04:00
NTSTATUS winbindd_replace_memory_creds ( const char * username ,
const char * pass )
2006-08-26 06:53:45 +04:00
{
2007-09-03 16:23:45 +04:00
struct WINBINDD_MEMORY_CREDS * memcredp = NULL ;
2006-08-26 06:53:45 +04:00
2007-09-03 16:23:45 +04:00
memcredp = find_memory_creds_by_name ( username ) ;
2006-08-26 06:53:45 +04:00
if ( ! memcredp ) {
DEBUG ( 10 , ( " winbindd_replace_memory_creds: unknown user %s \n " ,
2007-09-03 16:23:45 +04:00
username ) ) ;
2006-08-26 06:53:45 +04:00
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
}
DEBUG ( 10 , ( " winbindd_replace_memory_creds: replaced creds for user %s \n " ,
2007-09-03 16:23:45 +04:00
username ) ) ;
2006-08-26 06:53:45 +04:00
2006-09-08 04:19:32 +04:00
return winbindd_replace_memory_creds_internal ( memcredp , pass ) ;
2006-02-04 01:19:41 +03:00
}