Refresh default kerberos keytab (usually /etc/krb5.keytab) on each machine password change. Without it machine password changes break non-samba krb5 auth. Index: samba-4.1.7+dfsg/source3/winbindd/winbindd_dual.c =================================================================== --- samba-4.1.7+dfsg.orig/source3/winbindd/winbindd_dual.c +++ samba-4.1.7+dfsg/source3/winbindd/winbindd_dual.c @@ -37,6 +37,7 @@ #include "messages.h" #include "../lib/util/tevent_unix.h" #include "lib/param/loadparm.h" +#include "ads.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND @@ -1050,6 +1051,32 @@ static void machine_password_change_hand "trust_pw_find_change_and_store_it returned %s\n", nt_errstr(result))); + /** + * Refresh kerberos keytab to not break other applications + * Run from under the machine account, like 'net ads keytab create -P' + */ + if (NT_STATUS_IS_OK(result) && USE_KERBEROS_KEYTAB) { + ADS_STRUCT *ads = ads_init(lp_realm(), child->domain->name, NULL); + if (ads) { + ADS_STATUS status; + ads->auth.user_name = NULL; + asprintf(&ads->auth.user_name, "%s$@%s", lp_netbios_name(), lp_realm()); + ads->auth.realm = smb_xstrdup(lp_realm()); + ads->auth.password = secrets_fetch_machine_password(child->domain->name, NULL, NULL); + status = ads_connect(ads); + if (ADS_ERR_OK(status)) { + if (ads_keytab_create_default(ads)) { + DEBUG(0,("failed to refresh keytab - raise log level to see details\n")); + } + } else { + DEBUG(0,("failed to refresh keytab - ads_connect() returned %s\n", ads_errstr(status))); + } + ads_destroy(&ads); + } else { + DEBUG(0,("failed to refresh keytab - ads_init() failed\n")); + } + } + if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) ) { DEBUG(3,("machine_password_change_handler: password set returned " "ACCESS_DENIED. Maybe the trust account " @@ -1529,7 +1556,6 @@ static bool fork_domain_child(struct win } if (child->domain && child->domain->primary && - !USE_KERBEROS_KEYTAB && lp_server_role() == ROLE_DOMAIN_MEMBER) { struct timeval next_change;