commit 3b2a695c2455a17b4788bf010d7537fbb1654f23 Author: David Mulder Date: Mon Dec 3 11:02:50 2018 -0700 winbind: account locked when using winbind refresh tickets Users were being locked out by machines they hadn't recently authenticated to. The source of the problem is in krb5_ticket_refresh_handler(), when users are password kinit'd after a period of being offline using invalid passwords. Signed-off-by: David Mulder diff --git a/docs-xml/smbdotconf/winbind/winbindcachedpasswdrenew.xml b/docs-xml/smbdotconf/winbind/winbindcachedpasswdrenew.xml new file mode 100644 index 00000000000..d5be937494d --- /dev/null +++ b/docs-xml/smbdotconf/winbind/winbindcachedpasswdrenew.xml @@ -0,0 +1,16 @@ + + + This is a list of user principal names which should be re-kinited + by winbind if their creds have expired, and the renew time has passed. + This is useful for service accounts. This option can potentially lock + out accounts which have their password changed between the period of + expiration and kinit renewal, therefore this option should be used with + care. This applies to all principal names by default. + + +* +fred@example.com tux@example.com + diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index d8be520dc51..fd0d4adefd7 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -820,6 +820,8 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals) Globals.winbind_refresh_tickets = false; Globals.winbind_offline_logon = false; Globals.winbind_scan_trusted_domains = true; + Globals.winbind_cached_passwd_renew = + str_list_make_v3_const(NULL, "*", NULL); Globals.idmap_cache_time = 86400 * 7; /* a week by default */ Globals.idmap_negative_cache_time = 120; /* 2 minutes by default */ diff --git a/source3/winbindd/winbindd_cred_cache.c b/source3/winbindd/winbindd_cred_cache.c index 85ad426446a..b46875584cf 100644 --- a/source3/winbindd/winbindd_cred_cache.c +++ b/source3/winbindd/winbindd_cred_cache.c @@ -101,6 +101,30 @@ void ccache_remove_all_after_fork(void) return; } +static bool cached_passwd_renew(const char *principal_name) +{ + const char **renew_users; + bool ret = false; + renew_users = lp_winbind_cached_passwd_renew(); + + if (renew_users != NULL && renew_users[0] != NULL) { + if (strcmp(renew_users[0], "*") == 0) { + ret = true; + goto out; + } + while (*renew_users != NULL) { + if (strcmp(renew_users[0], principal_name) == 0) { + ret = true; + goto out; + } + renew_users++; + } + } + +out: + return ret; +} + /**************************************************************** Do the work of refreshing the ticket. ****************************************************************/ @@ -134,20 +158,29 @@ static void krb5_ticket_refresh_handler(struct tevent_context *event_ctx, 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 (cached_passwd_renew(entry->principal_name)) { + set_effective_uid(entry->uid); + + ret = kerberos_kinit_password_ext( + entry->principal_name, + cred_ptr->pass, + 0, /* 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(); + } else { + ret = KRB5KDC_ERR_PREAUTH_FAILED; + DBG_NOTICE("Skipping re-kinit for %s. " + "Set winbind cached passwd renew in" + "smb.conf to override.", + entry->principal_name); + } if (ret) { DEBUG(3,("krb5_ticket_refresh_handler: "