diff -ruN krb5-1.7-alpha1/src/include/krb5/krb5.hin krb5-1.7-alpha1-new/src/include/krb5/krb5.hin --- krb5-1.7-alpha1/src/include/krb5/krb5.hin 2009-01-04 00:19:42.000000000 +0100 +++ krb5-1.7-alpha1-new/src/include/krb5/krb5.hin 2009-02-11 11:38:07.671182683 +0100 @@ -1488,6 +1488,9 @@ krb5_error_code KRB5_CALLCONV krb5_kt_end_seq_get(krb5_context context, krb5_keytab keytab, krb5_kt_cursor *cursor); +krb5_error_code +krb5_kt_find_realm(krb5_context context, krb5_keytab keytab, + krb5_principal princ, krb5_data *realm); /* * end "keytab.h" diff -ruN krb5-1.7-alpha1/src/lib/krb5/keytab/Makefile.in krb5-1.7-alpha1-new/src/lib/krb5/keytab/Makefile.in --- krb5-1.7-alpha1/src/lib/krb5/keytab/Makefile.in 2009-01-05 21:27:53.000000000 +0100 +++ krb5-1.7-alpha1-new/src/lib/krb5/keytab/Makefile.in 2009-02-11 11:32:30.403802035 +0100 @@ -20,6 +20,7 @@ ktremove.o \ ktfns.o \ kt_file.o \ + kt_findrealm.o \ kt_memory.o \ kt_srvtab.o \ read_servi.o @@ -32,6 +33,7 @@ $(OUTPRE)ktremove.$(OBJEXT) \ $(OUTPRE)ktfns.$(OBJEXT) \ $(OUTPRE)kt_file.$(OBJEXT) \ + $(OUTPRE)kt_findrealm.$(OBJEXT) \ $(OUTPRE)kt_memory.$(OBJEXT) \ $(OUTPRE)kt_srvtab.$(OBJEXT) \ $(OUTPRE)read_servi.$(OBJEXT) @@ -44,6 +46,7 @@ $(srcdir)/ktremove.c \ $(srcdir)/ktfns.c \ $(srcdir)/kt_file.c \ + $(srcdir)/kt_findrealm.c \ $(srcdir)/kt_memory.c \ $(srcdir)/kt_srvtab.c \ $(srcdir)/read_servi.c diff -ruN krb5-1.7-alpha1/src/lib/krb5/keytab/kt_findrealm.c krb5-1.7-alpha1-new/src/lib/krb5/keytab/kt_findrealm.c --- krb5-1.7-alpha1/src/lib/krb5/keytab/kt_findrealm.c 1970-01-01 01:00:00.000000000 +0100 +++ krb5-1.7-alpha1-new/src/lib/krb5/keytab/kt_findrealm.c 2009-02-11 11:31:38.853361905 +0100 @@ -0,0 +1,68 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Solaris Kerberos: + * Iterate through a keytab (keytab) looking for an entry which matches + * the components of a principal (princ) but match on any realm. When a + * suitable entry is found return the entry's realm. + */ + +#include "k5-int.h" + +krb5_error_code krb5_kt_find_realm(krb5_context context, krb5_keytab keytab, + krb5_principal princ, krb5_data *realm) { + + krb5_kt_cursor cur; + krb5_keytab_entry ent; + krb5_boolean match; + krb5_data tmp_realm; + krb5_error_code ret, ret2; + + ret = krb5_kt_start_seq_get(context, keytab, &cur); + if (ret != 0) { + return (ret); + } + + while ((ret = krb5_kt_next_entry(context, keytab, &ent, &cur)) == 0) { + /* For the comparison the realms should be the same. */ + memcpy(&tmp_realm, &ent.principal->realm, sizeof (krb5_data)); + memcpy(&ent.principal->realm, &princ->realm, + sizeof (krb5_data)); + + match = krb5_principal_compare(context, ent.principal, princ); + + /* Copy the realm back */ + memcpy(&ent.principal->realm, &tmp_realm, sizeof (krb5_data)); + + if (match) { + /* + * A suitable entry was found in the keytab. + * Copy its realm + */ + ret = krb5int_copy_data_contents(context, + &ent.principal->realm, realm); + if (ret) { + krb5_kt_free_entry(context, &ent); + krb5_kt_end_seq_get(context, keytab, &cur); + return (ret); + } + + krb5_kt_free_entry(context, &ent); + break; + } + + krb5_kt_free_entry(context, &ent); + } + + ret2 = krb5_kt_end_seq_get(context, keytab, &cur); + + if (ret == KRB5_KT_END) { + return (KRB5_KT_NOTFOUND); + } + + return (ret ? ret : ret2); +} + diff -ruN krb5-1.7-alpha1/src/lib/krb5/krb/gic_keytab.c krb5-1.7-alpha1-new/src/lib/krb5/krb/gic_keytab.c --- krb5-1.7-alpha1/src/lib/krb5/krb/gic_keytab.c 2009-01-28 01:04:15.000000000 +0100 +++ krb5-1.7-alpha1-new/src/lib/krb5/krb/gic_keytab.c 2009-02-11 11:34:36.979850913 +0100 @@ -23,6 +23,12 @@ * this software for any purpose. It is provided "as is" without express * or implied warranty. */ + +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + #ifndef LEAN_CLIENT #include "k5-int.h" @@ -102,6 +108,39 @@ if (ret) return ret; + + /* + * If "client" was constructed from krb5_sname_to_princ() it may + * have a referral realm. This happens when there is no applicable + * domain-to-realm mapping in the Kerberos configuration file. + * If that is the case then the realm of the first principal found + * in the keytab which matches the client is used for the client's + * realm. + */ + if (krb5_is_referral_realm(&client->realm)) { + krb5_data realm; + ret = krb5_kt_find_realm(context, keytab, client, &realm); + if (ret == 0) { + krb5_free_data_contents(context, &client->realm); + client->realm.length = realm.length; + client->realm.data = realm.data; + } else { + /* Try to set a useful error message */ + char *princ = NULL; + krb5_unparse_name(context, client, &princ); + + krb5_set_error_message(context, ret, + "Failed to find realm for %s in keytab", + princ ? princ : ""); + if (princ) + krb5_free_unparsed_name(context, princ); + } + } + + if (ret != 0) + goto cleanup; + + use_master = 0; /* first try: get the requested tkt from any kdc */ diff -ruN krb5-1.7-alpha1/src/lib/krb5/os/locate_kdc.c krb5-1.7-alpha1-new/src/lib/krb5/os/locate_kdc.c --- krb5-1.7-alpha1/src/lib/krb5/os/locate_kdc.c 2009-01-28 01:04:15.000000000 +0100 +++ krb5-1.7-alpha1-new/src/lib/krb5/os/locate_kdc.c 2009-02-11 11:36:27.559391766 +0100 @@ -818,7 +818,12 @@ code = prof_locate_server(context, realm, &al, svc, socktype, family); #ifdef KRB5_DNS_LOOKUP - if (code) { /* Try DNS for all profile errors? */ + /* + * There is no point in trying to locate the KDC in DNS is "relam" + * is empty. + */ + /* Try DNS for all profile errors? */ + if (code && !krb5_is_referral_realm(realm)) { krb5_error_code code2; code2 = dns_locate_server(context, realm, &al, svc, socktype, family);