Author: Tukaram Laxmeshwar Subject: winbindd can't resolve usernames from trusted domains Bugzilla: bnc#5699 Index: source/libads/kerberos.c =================================================================== --- source/libads/kerberos.c.orig 2008-08-16 15:50:46.000000000 +0530 +++ source/libads/kerberos.c 2008-08-16 15:50:50.000000000 +0530 @@ -231,6 +231,155 @@ return ret; } +int kerberos_kinit(const char *principal, + int time_offset, + time_t *expire_time, + time_t *renew_till_time, + const char *cache_name, + BOOL request_pac, + BOOL add_netbios_addr, + time_t renewable_time) + +{ + krb5_context ctx = NULL; + krb5_error_code code = 0; + krb5_ccache cc = NULL; + krb5_principal me; + krb5_creds my_creds; + krb5_get_init_creds_opt *opt = NULL; + smb_krb5_addresses *addr = NULL; + + initialize_krb5_error_table(); + if ((code = krb5_init_context(&ctx))) + return code; + + if (time_offset != 0) { + krb5_set_real_time(ctx, time(NULL) + time_offset, 0); + } + + DEBUG(10,("kerberos_kinit_password: using [%s] as ccache and config [%s]\n", + cache_name ? cache_name: krb5_cc_default_name(ctx), + getenv("KRB5_CONFIG"))); + + if ((code = krb5_cc_resolve(ctx, cache_name ? cache_name : krb5_cc_default_name(ctx), &cc))) { + krb5_free_context(ctx); + return code; + } + + if ((code = smb_krb5_parse_name(ctx, principal, &me))) { + krb5_cc_close(ctx, cc); + krb5_free_context(ctx); + return code; + } + + code = smb_krb5_get_init_creds_opt_alloc(ctx, &opt); + if (code) { + krb5_cc_close(ctx, cc); + krb5_free_context(ctx); + return code; + } + + krb5_get_init_creds_opt_set_renew_life(opt, renewable_time); + krb5_get_init_creds_opt_set_forwardable(opt, True); +#if 0 + /* insane testing */ + krb5_get_init_creds_opt_set_tkt_life(opt, 60); +#endif + +#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_PAC_REQUEST + if (request_pac) { + code = krb5_get_init_creds_opt_set_pac_request(ctx, opt, (krb5_boolean)request_pac); + if (code) { + krb5_cc_close(ctx, cc); + krb5_free_principal(ctx, me); + krb5_free_context(ctx); + return code; + } + } +#endif + if (add_netbios_addr) { + code = smb_krb5_gen_netbios_krb5_address(&addr); + if (code) { + krb5_cc_close(ctx, cc); + krb5_free_principal(ctx, me); + krb5_free_context(ctx); + return code; + } + krb5_get_init_creds_opt_set_address_list(opt, addr->addrs); + } + + if ((code = krb5_get_init_creds_keytab(ctx,&my_creds, me, NULL, 0, NULL, opt))) { + smb_krb5_get_init_creds_opt_free(ctx, opt); + smb_krb5_free_addresses(ctx, addr); + krb5_cc_close(ctx, cc); + krb5_free_principal(ctx, me); + krb5_free_context(ctx); + return code; + } + + smb_krb5_get_init_creds_opt_free(ctx, opt); + + if ((code = krb5_cc_initialize(ctx, cc, me))) { + smb_krb5_free_addresses(ctx, addr); + krb5_free_cred_contents(ctx, &my_creds); + krb5_cc_close(ctx, cc); + krb5_free_principal(ctx, me); + krb5_free_context(ctx); + return code; + } + + if ((code = krb5_cc_store_cred(ctx, cc, &my_creds))) { + krb5_cc_close(ctx, cc); + smb_krb5_free_addresses(ctx, addr); + krb5_free_cred_contents(ctx, &my_creds); + krb5_free_principal(ctx, me); + krb5_free_context(ctx); + return code; + } + + if (expire_time) { + *expire_time = (time_t) my_creds.times.endtime; + } + + if (renew_till_time) { + *renew_till_time = (time_t) my_creds.times.renew_till; + } + + krb5_cc_close(ctx, cc); + smb_krb5_free_addresses(ctx, addr); + krb5_free_cred_contents(ctx, &my_creds); + krb5_free_principal(ctx, me); + krb5_free_context(ctx); + + return 0; + +} + +/* Get Kerberos initial ticket for domain controller */ +int ads_kinit(ADS_STRUCT *ads) +{ + char *s; + int ret; + fstring acct_name; + fstring my_domname; + + get_mydnsdomname(my_domname); + if (asprintf(&s, "%s$@%s", global_myname(), my_domname) == -1) { + return KRB5_CC_NOMEM; + } + + ret = kerberos_kinit(s, ads->auth.time_offset, + &ads->auth.tgt_expire, NULL, NULL, False, False, ads->auth.renewable); + + if (ret) { + DEBUG(0,("kerberos_kinit_password %s failed: %s\n", + s, error_message(ret))); + } + SAFE_FREE(s); + return ret; + +} + int ads_kdestroy(const char *cc_name) { krb5_error_code code; Index: source/libads/sasl.c =================================================================== --- source/libads/sasl.c.orig 2008-08-16 15:50:50.000000000 +0530 +++ source/libads/sasl.c 2008-08-16 15:50:50.000000000 +0530 @@ -261,7 +261,11 @@ DEBUG(10,("ads_sasl_spnego_krb5_bind failed with: %s, " "calling kinit\n", ads_errstr(status))); - status = ADS_ERROR_KRB5(ads_kinit_password(ads)); + /* There won't be any password in the tdb files in DSfW */ + if (ads->auth.password == NULL) + status = ADS_ERROR_KRB5(ads_kinit(ads)); + else + status = ADS_ERROR_KRB5(ads_kinit_password(ads)); if (ADS_ERR_OK(status)) { status = ads_sasl_spnego_krb5_bind(ads, principal); Index: source/nsswitch/winbindd_ads.c =================================================================== --- source/nsswitch/winbindd_ads.c.orig 2008-08-16 15:50:50.000000000 +0530 +++ source/nsswitch/winbindd_ads.c 2008-08-16 15:50:50.000000000 +0530 @@ -94,6 +94,9 @@ DOM_SID sid; time_t last_set_time; + // We don't need a password for GSSAPI bind or SPNEGO in DSfW. + // We can get ticket using keytab. + if(ads->auth.flags & ADS_AUTH_SIMPLE_BIND) if ( !secrets_fetch_trusted_domain_password( domain->name, &ads->auth.password, &sid, &last_set_time ) ) { ads_destroy( &ads ); return NULL;