[3057] in Kerberos

home help back first fref pref prev next nref lref last post

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;


home help back first fref pref prev next nref lref last post