[3057] in Kerberos
Cross Realm Authentication in Kerberos 5.3
daemon@ATHENA.MIT.EDU (Doug Engert)
Thu Mar 31 13:07:40 1994
Date: Thu, 31 Mar 94 11:28:01 CST
From: "Doug Engert" <DEEngert@anl.gov>
To: <kerberos@MIT.EDU>
I have been testing Cross realm authentication with Kerberos 5.3
SunOS 4.1.2 and have got it working after changing three
files as listed below.
I also have some questions about Cross Realm Authentication.
With a configuration of realms "z" "a.z" "b.z" and trying to go
from "a.z" to "b.z"
(1) As the realms are traversed, tickets are gotten for:
krbtgt/a.z@a.z (kinit did this)
krbtgt/z@a.z (from a.z)
krbtgt/b.z@z (from z)
host/xxx@b.z (from b.z)
Why does it not do one more for krbtgt/b.z@b.z ?
Without this requires changes to gc_frm_tkt.c
(2) What about forwarding tickets, can I forward tickets
across realms? How do I set that.
To get cross realm to work required changes to the following modules:
lib/krb5/krb/gc_frm_kdc.c
Change all references to "tgt" to be referenced by "tgtp" which
is a pointer which starts out pointing to "tgt". tgtp is
then changed to point to the most recent obtained credential
as the module contacts the KDCs in each of the next realms.
The previous code only worked when contacting one
KDC, i.e. you could get one step farther each time you
called rlogin, and as the next credential was cached.
This allows all the KDCs to be contacted in a loop in this module.
Fixed a problem with the next_server pointer being used twice,
and being incremented in a loop so as to cause a segmentation
fault in some cases.
Fixed a problem with tgt.server being used where tgtq.server
should be used.
lib/krb5/krb/gc_frm_tkt.c
Commented out two test which checked to see if the client
and server are in the same realm. With cross realm this is not
the case. Both tests returned KRB5_PRINC_NOMATCH.
krb/do_tgs_req.c
It looked like the code for cross realm was never updated
from some previous version. There is a test to see of there
are 3 components to the name field rather then two. The
realm is now treated separately in the principal. The if
test at line 180 was changed to check for 2 components,
and the compare for length and data was also changed.
The parameters to krb5_walk_realm_tree were also changed
in the call at line 675 to pass the realm and component 1
rather then component 0 and 2. The form of the cross realm
entry is krbtgt/remote@local.
Attached is a diff file for the changes.
Douglas E. Engert
Systems Programming
Argonne National Laboratory
9700 South Cass Avenue
Argonne, Illinois 60439
(708) 252-5444
Internet: DEEngert@anl.gov
----- ------ ----- ----- ----- ----- ----- ----- ----- -----
*** lib/krb5/krb/,gc_frm_kdc.c Mon Mar 7 14:56:12 1994
--- lib/krb5/krb/gc_frm_kdc.c Thu Mar 31 09:39:32 1994
***************
*** 72,77 ****
--- 72,78 ----
krb5_creds ***tgts;
{
krb5_creds tgt, tgtq;
+ krb5_creds *tgtp; /* ANL needed for cross realm */
krb5_creds **ret_tgts = 0;
krb5_principal *tgs_list = 0, *next_server;
krb5_principal final_server;
***************
*** 86,91 ****
--- 87,98 ----
memset((char *)&tgtq, 0, sizeof(tgtq));
memset((char *)&tgt, 0, sizeof(tgt));
+ /* ANL - set tgtp to point at tgt. If we are doing cross realm
+ * authentication, we will be steping through creds and changing
+ * tgtp to point to the next creds. DEE 03/29/94
+ */
+ tgtp = &tgt;
+
/*
* we know that the desired credentials aren't in the cache yet.
*
***************
*** 113,119 ****
retval = krb5_cc_retrieve_cred (ccache,
KRB5_TC_MATCH_SRV_NAMEONLY,
&tgtq,
! &tgt);
if (retval != 0) {
if (retval != KRB5_CC_NOTFOUND)
--- 120,126 ----
retval = krb5_cc_retrieve_cred (ccache,
KRB5_TC_MATCH_SRV_NAMEONLY,
&tgtq,
! tgtp);
if (retval != 0) {
if (retval != KRB5_CC_NOTFOUND)
***************
*** 130,149 ****
/* walk the list BACKWARDS until we find a cached
TGT, then move forward obtaining TGTs until we get the last
TGT needed */
! for (next_server = tgs_list; *next_server;)
next_server++;
! nservers = next_server - tgs_list;
next_server--;
/* next_server now points to the last TGT */
for (; next_server >= tgs_list; next_server--) {
! krb5_free_principal(tgtq.server);
! if (retval = krb5_copy_principal(*next_server, &tgt.server))
goto errout;
retval = krb5_cc_retrieve_cred (ccache,
KRB5_TC_MATCH_SRV_NAMEONLY,
&tgtq,
! &tgt);
if (retval) {
if (retval != KRB5_CC_NOTFOUND)
goto errout;
--- 137,164 ----
/* walk the list BACKWARDS until we find a cached
TGT, then move forward obtaining TGTs until we get the last
TGT needed */
!
! /* ANL - With gcc 2.5.7 and tgs_list having 3 elements, nserver
! * should be 2, but xdbx shows 8 i.e.size of two pointers.
! * this is an error. So we will do it another way.
! */
! for (next_server = tgs_list,nservers=0; *next_server;){
! nservers++;
next_server++;
! }
! /* nservers = next_server - tgs_list; */
! nservers--;
next_server--;
/* next_server now points to the last TGT */
for (; next_server >= tgs_list; next_server--) {
! krb5_free_principal(tgtq.server);
! if (retval = krb5_copy_principal(*next_server, &tgtq.server))
goto errout;
retval = krb5_cc_retrieve_cred (ccache,
KRB5_TC_MATCH_SRV_NAMEONLY,
&tgtq,
! tgtp);
if (retval) {
if (retval != KRB5_CC_NOTFOUND)
goto errout;
***************
*** 167,173 ****
for (nservers = 0; *next_server; next_server++, nservers++) {
krb5_data *tmpdata;
! if (!valid_keytype(tgt.keyblock.keytype)) {
retval = KRB5_PROG_KEYTYPE_NOSUPP;
goto errout;
}
--- 182,188 ----
for (nservers = 0; *next_server; next_server++, nservers++) {
krb5_data *tmpdata;
! if (!valid_keytype(tgtp->keyblock.keytype)) {
retval = KRB5_PROG_KEYTYPE_NOSUPP;
goto errout;
}
***************
*** 174,181 ****
/* now get the TGTs */
krb5_free_cred_contents(&tgtq);
memset((char *)&tgtq, 0, sizeof(tgtq));
! tgtq.times = tgt.times;
! if (retval = krb5_copy_principal(tgt.client, &tgtq.client))
goto errout;
/* ask each realm for a tgt to the end */
--- 189,196 ----
/* now get the TGTs */
krb5_free_cred_contents(&tgtq);
memset((char *)&tgtq, 0, sizeof(tgtq));
! tgtq.times = tgtp->times;
! if (retval = krb5_copy_principal(tgtp->client, &tgtq.client))
goto errout;
/* ask each realm for a tgt to the end */
***************
*** 189,199 ****
goto errout;
tgtq.is_skey = FALSE;
! tgtq.ticket_flags = tgt.ticket_flags;
! etype = krb5_keytype_array[tgt.keyblock.keytype]->system->proto_enctype;
! if (retval = krb5_get_cred_via_tgt(&tgt,
! flags2options(tgtq.ticket_flags),
etype,
krb5_kdc_req_sumtype,
&tgtq))
--- 204,215 ----
goto errout;
tgtq.is_skey = FALSE;
! tgtq.ticket_flags = tgtp->ticket_flags;
! etype = krb5_keytype_array[tgtp->keyblock.keytype]->system->proto_enctype;
!
! if (retval = krb5_get_cred_via_tgt(tgtp,
! flags2options(tgtp->ticket_flags),
etype,
krb5_kdc_req_sumtype,
&tgtq))
***************
*** 201,242 ****
/* make sure the returned ticket is somewhere in the remaining
list, but we can tolerate different expected issuing realms */
! while (*++next_server &&
! !krb5_principal_compare(&(next_server[0])[1],
&(tgtq.server[1])));
! if (!next_server) {
/* what we got back wasn't in the list! */
retval = KRB5_KDCREP_MODIFIED;
goto errout;
! }
/* save tgt in return array */
if (retval = krb5_copy_creds(&tgtq, &ret_tgts[nservers]))
goto errout;
! tgt = *ret_tgts[nservers];
! returning_tgt = 1; /* don't free it below... */
}
}
/* got/finally have tgt! */
! if (!valid_keytype(tgt.keyblock.keytype)) {
retval = KRB5_PROG_KEYTYPE_NOSUPP;
goto errout;
}
! etype = krb5_keytype_array[tgt.keyblock.keytype]->system->proto_enctype;
if (cred->second_ticket.length)
! retval = krb5_get_cred_via_2tgt(&tgt,
! KDC_OPT_ENC_TKT_IN_SKEY | flags2options(tgt.ticket_flags),
etype, krb5_kdc_req_sumtype, cred);
else
! retval = krb5_get_cred_via_tgt(&tgt,
! flags2options(tgt.ticket_flags),
etype,
krb5_kdc_req_sumtype,
cred);
errout:
! if (!returning_tgt)
krb5_free_cred_contents(&tgt);
if (final_server)
krb5_free_principal(final_server);
--- 217,270 ----
/* make sure the returned ticket is somewhere in the remaining
list, but we can tolerate different expected issuing realms */
! /* ANL - looks like we need to have another next_server so we dont
! * loose our place
! */
! {
! krb5_principal *next_serverx = next_server;
! while (*++next_serverx &&
! !krb5_principal_compare(&(next_serverx[0])[1],
&(tgtq.server[1])));
! if (!next_serverx) {
/* what we got back wasn't in the list! */
retval = KRB5_KDCREP_MODIFIED;
goto errout;
! }
! } /* ANL - end of temp next_server */
/* save tgt in return array */
if (retval = krb5_copy_creds(&tgtq, &ret_tgts[nservers]))
goto errout;
!
! /* ANL set tgtp to point to the new creds so we can use it
! * when we look at next server or when we exit the loop
! * returning_tgt does not mean anything any more.
! */
! tgtp = ret_tgts[nservers];
! /* returning_tgt = 1; */ /* don't free it below... */
}
}
+
/* got/finally have tgt! */
! if (!valid_keytype(tgtp->keyblock.keytype)) {
retval = KRB5_PROG_KEYTYPE_NOSUPP;
goto errout;
}
! etype = krb5_keytype_array[tgtp->keyblock.keytype]->system->proto_enctype;
if (cred->second_ticket.length)
! retval = krb5_get_cred_via_2tgt(tgtp,
! KDC_OPT_ENC_TKT_IN_SKEY | flags2options(tgtp->ticket_flags),
etype, krb5_kdc_req_sumtype, cred);
else
! retval = krb5_get_cred_via_tgt(tgtp,
! flags2options(tgtp->ticket_flags),
etype,
krb5_kdc_req_sumtype,
cred);
errout:
! /* if (!returning_tgt) */
krb5_free_cred_contents(&tgt);
if (final_server)
krb5_free_principal(final_server);
*** lib/krb5/krb/,gc_via_tgt.c Mon Mar 7 14:56:13 1994
--- lib/krb5/krb/gc_via_tgt.c Wed Mar 30 06:39:35 1994
***************
*** 59,66 ****
/* tgt->client must be equal to cred->client */
/* tgt->server must be equal to krbtgt/realmof(cred->client) */
! if (!krb5_principal_compare(tgt->client, cred->client))
! return KRB5_PRINC_NOMATCH;
if (!tgt->ticket.length)
return(KRB5_NO_TKT_SUPPLIED);
--- 59,69 ----
/* tgt->client must be equal to cred->client */
/* tgt->server must be equal to krbtgt/realmof(cred->client) */
! /* ANL for cross realm this is not true so coment it out for now */
! /* this should be a better test, and commenting this out may */
! /* open up some hole. DEE 03/29/94 */
! /* if (!krb5_principal_compare(tgt->client, cred->client)) */
! /* return KRB5_PRINC_NOMATCH; */
if (!tgt->ticket.length)
return(KRB5_NO_TKT_SUPPLIED);
***************
*** 69,78 ****
krb5_princ_realm(cred->client), &tempprinc))
return(retval);
! if (!krb5_principal_compare(tempprinc, tgt->server)) {
! krb5_free_principal(tempprinc);
! return KRB5_PRINC_NOMATCH;
! }
krb5_free_principal(tempprinc);
--- 72,82 ----
krb5_princ_realm(cred->client), &tempprinc))
return(retval);
! /* ANL for cross realm this is not true */
! /* if (!krb5_principal_compare(tempprinc, tgt->server)) { */
! /* krb5_free_principal(tempprinc); */
! /* return KRB5_PRINC_NOMATCH; */
! /* } */
krb5_free_principal(tempprinc);
*** kdc/,do_tgs_req.c Mon Mar 7 14:53:34 1994
--- kdc/do_tgs_req.c Wed Mar 30 07:31:18 1994
***************
*** 172,185 ****
the following statement is undefined? Only length 3 is valid
here, but can a length 1 ticket pass through all prior tests? */
krb5_data *server_1 = krb5_princ_component(request->server, 1);
krb5_data *tgs_1 = krb5_princ_component(tgs_server, 1);
/* might be a request for a TGT for some other realm; we should
do our best to find such a TGS in this db */
! if (firstpass && krb5_princ_size(request->server) == 3 &&
! server_1->length == tgs_1->length &&
! !memcmp(server_1->data, tgs_1->data, tgs_1->length)) {
krb5_db_free_principal(&server, nprincs);
find_alternate_tgs(request, &server, &more, &nprincs);
firstpass = 0;
--- 172,199 ----
the following statement is undefined? Only length 3 is valid
here, but can a length 1 ticket pass through all prior tests? */
+ /* ANL the requests I see are length 2 not 3 , i.e. we are looking
+ * for a krbtgt/remote@local DEE 03/29/94
+ */
+
krb5_data *server_1 = krb5_princ_component(request->server, 1);
krb5_data *tgs_1 = krb5_princ_component(tgs_server, 1);
+
/* might be a request for a TGT for some other realm; we should
do our best to find such a TGS in this db */
!
! /* ANL - The cross realm request is looking for a length 2
! * and the test for the lengths is wrong DEE 03/29/94
! */
!
! /* if (firstpass && krb5_princ_size(request->server) == 3 && */
! /* server_1->length == tgs_1->length && */
! /* !memcmp(server_1->data, tgs_1->data, tgs_1->length)) {*/
!
! if (firstpass && krb5_princ_size(request->server) == 2 &&
! (server_1->length != tgs_1->length ||
! !memcmp(server_1->data, tgs_1->data, tgs_1->length))) {
krb5_db_free_principal(&server, nprincs);
find_alternate_tgs(request, &server, &more, &nprincs);
firstpass = 0;
***************
*** 672,679 ****
*nprincs = 0;
*more = FALSE;
! if (retval = krb5_walk_realm_tree(krb5_princ_component(request->server, 0),
! krb5_princ_component(request->server, 2),
&plist, KRB5_REALM_BRANCH_CHAR))
return;
--- 686,694 ----
*nprincs = 0;
*more = FALSE;
! /* ANL changed to use request 1 and realm DEE 03/29/94*/
! if (retval = krb5_walk_realm_tree(krb5_princ_realm(request->server),
! krb5_princ_component(request->server,1),
&plist, KRB5_REALM_BRANCH_CHAR))
return;