compiles; not tested
authorJohn Kohl <jtkohl@mit.edu>
Tue, 27 Mar 1990 13:55:44 +0000 (13:55 +0000)
committerJohn Kohl <jtkohl@mit.edu>
Tue, 27 Mar 1990 13:55:44 +0000 (13:55 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@425 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/krb5/krb/gc_frm_kdc.c
src/lib/krb5/krb/gc_via_tgt.c

index 158e3f037f8c93f5b4ddc890417bc8ab7be06386..6c0d23b5885bdbcea61455863f50028989816e12 100644 (file)
@@ -19,6 +19,11 @@ static char rcsid_gcfkdc_c[] =
 #include <krb5/copyright.h>
 
 #include <krb5/krb5.h>
+#include <krb5/krb5_err.h>
+#include <errno.h>
+
+#include <krb5/ext-proto.h>
+#include "int-proto.h"
 
 /*
  * Retrieve credentials for principal creds->client,
@@ -29,7 +34,8 @@ static char rcsid_gcfkdc_c[] =
  * TGT credentials obtained in the process of contacting the KDC are
  * returned in an array of credentials; tgts is filled in to point to an
  * array of pointers to credential structures (if no TGT's were used, the
- * pointer is zeroed).
+ * pointer is zeroed).  TGT's may be returned even if no useful end ticket
+ * was obtained.
  * 
  * The returned credentials are NOT cached.
  *
@@ -43,6 +49,9 @@ static char rcsid_gcfkdc_c[] =
  * returns errors, system errors.
  */
 
+/* helper function: convert flags to necessary KDC options */
+#define flags2options(flags) (flags & KDC_TKT_COMMON_MASK)
+
 krb5_error_code
 krb5_get_cred_from_kdc (ccache, cred, tgts)
     krb5_ccache ccache;
@@ -50,15 +59,20 @@ krb5_get_cred_from_kdc (ccache, cred, tgts)
     krb5_creds ***tgts;
 {
     krb5_creds tgt, tgtq;
+    krb5_creds **ret_tgts = 0;
+    krb5_principal *tgs_list, next_server;
     krb5_error_code retval;
+    int nservers;
     
+    /* in case we never get a TGT, zero the return */
+    tgts = 0;
+
     /*
      * we know that the desired credentials aren't in the cache yet.
      *
      * To get them, we first need a tgt for the realm of the server.
+     * first, we see if we have such a TGT in cache.
      */
-
-    /* first, we see if we have a shortcut path to the server's realm. */
     
     /*
      * look for ticket with:
@@ -74,9 +88,10 @@ krb5_get_cred_from_kdc (ccache, cred, tgts)
 
     if (retval = krb5_tgtname(cred->server, cred->client, &tgtq.server))
        return retval;
-    /* go find it.. */
+
+    /* try to fetch it directly */
     retval = krb5_cc_retrieve_cred (ccache,
-                                   KRB5_CF_CLIENT|KRB5_CF_SERVER,
+                                   0,  /* default is client & server */
                                    &tgtq,
                                    &tgt);
     krb5_free_principal(tgtq.server);
@@ -84,11 +99,71 @@ krb5_get_cred_from_kdc (ccache, cred, tgts)
     if (retval != 0) {
        if (retval != KRB5_CC_NOTFOUND)
            goto out;
-       /* nope; attempt to get tgt */
+       /* don't have the right TGT in the cred cache.  Time to iterate
+          across realms to get the right TGT. */
+
+       /* get a list of realms to consult */
+       retval = krb5_walk_realm_tree(cred->client, cred->server, &tgs_list);
+       if (retval)
+           goto out;
+       /* 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[0]; next_server; next_server++);
+       nservers = next_server - tgs_list[0];
+       next_server--;
+
+       /* next_server now points to the last TGT */
+       for (; next_server >= tgs_list[0]; next_server--) {
+           tgtq.server = next_server;
+           retval = krb5_cc_retrieve_cred (ccache,
+                                           0, /* default is client & server */
+                                           &tgtq,
+                                           &tgt);
+           if (retval) {
+               if (retval != KRB5_CC_NOTFOUND) {
+                   krb5_free_realm_tree(tgs_list);
+                   goto out;
+               }
+               continue;
+           }
+           next_server++;
+           break;                      /* found one! */
+       }
+       /* allocate storage for TGT pointers. */
+       ret_tgts = (krb5_creds **)calloc(nservers+1, sizeof(krb5_creds));
+       if (!ret_tgts) {
+           retval = ENOMEM;
+           goto out;
+       }
+       for (nservers = 0; next_server; next_server++, nservers++) {
+           /* now get the TGTs */
+           tgtq.times = tgt.times;
+           tgtq.client = tgt.client;
+           tgtq.server = next_server;
+           tgtq.is_skey = FALSE;       
+           tgtq.ticket_flags = tgt.ticket_flags;
+           if (retval = krb5_get_cred_via_tgt(&tgt,
+                                              flags2options(tgtq.ticket_flags),
+                                              0, /* XXX etype */
+                                              0, /* XXX sumtype */
+                                              0, /* XXX addrs */
+                                              &tgtq))
+               goto out;
+           /* save tgt in return array */
+           if (retval = krb5_copy_cred(&tgtq, &ret_tgts[nservers]))
+               goto out;
+           /* XXX need to clean up stuff pointed to by tgtq? */
+           tgt = tgtq;
+       }
     }
-    /* got tgt! */
-    retval = krb5_get_cred_via_tgt(&tgt, cred);
+    /* got/finally have tgt! */
+    retval = krb5_get_cred_via_tgt(&tgt,
+                                  flags2options(tgtq.ticket_flags),
+                                  0, /* XXX etype */
+                                  0, /* XXX sumtype */
+                                  0, /* XXX addrs */
+                                  cred);
 out:
-    /* XXX what about tgts? */
     return retval;
 }
index e00c88c43e550617cb8fa143564c749cd8a88eba..c2dc04af2181eef1c145078bda8558776c859748 100644 (file)
@@ -24,28 +24,26 @@ static char rcsid_gcvtgt_c[] =
 #include <stdio.h>
 #include <krb5/libos-proto.h>
 #include <krb5/ext-proto.h>
-
-static krb5_flags
-creds_to_kdcoptions(creds)
-krb5_creds *creds;
-{
-    krb5_flags result;
-
-    /* XXX this is a hack; we don't necessarily want all these! */
-    result = creds->ticket_flags & KDC_TKT_COMMON_MASK;
-    result |= KDC_OPT_RENEWABLE_OK;
-    return result;
-}
+#include "int-proto.h"
 
 krb5_error_code
-krb5_get_cred_via_tgt (tgt, cred)
-    krb5_creds *tgt;           /* IN */
-    krb5_creds *cred;          /* IN OUT */
+krb5_get_cred_via_tgt (DECLARG(krb5_creds *, tgt),
+                      DECLARG(krb5_flags, kdcoptions),
+                      DECLARG(krb5_enctype, etype),
+                      DECLARG(krb5_cksumtype, sumtype),
+                      DECLARG(krb5_address **, addrs),
+                      DECLARG(krb5_creds *, cred))
+OLDDECLARG(krb5_creds *, tgt)
+OLDDECLARG(krb5_flags, kdcoptions)
+OLDDECLARG(krb5_enctype, etype)
+OLDDECLARG(krb5_cksumtype, sumtype)
+OLDDECLARG(krb5_address **, addrs)
+OLDDECLARG(krb5_creds *, cred)
 {
     krb5_tgs_req tgsreq;
     krb5_real_tgs_req realreq;
     krb5_error_code retval;
-    krb5f_principal tempprinc;
+    krb5_principal tempprinc;
     krb5_data *scratch, reply;
     krb5_checksum ap_checksum;
     krb5_kdc_rep *dec_rep;
@@ -71,35 +69,37 @@ krb5_get_cred_via_tgt (tgt, cred)
 
     bzero((char *)&realreq, sizeof(realreq));
 
-    realreq.kdc_options = creds_to_kdcoptions(cred);
+    realreq.kdc_options = kdcoptions;
     realreq.from = cred->times.starttime;
     realreq.till = cred->times.endtime;
     realreq.rtime = cred->times.renew_till;
     
     if (retval = krb5_timeofday(&realreq.ctime))
        return(retval);
-    realreq.etype = xxx;
+    realreq.etype = etype;
     realreq.server = cred->server;
-    realreq.addresses = xxx;
+    realreq.addresses = addrs;
     /* enc_part & enc_part2 are left blank for the moment. */
 
     if (retval = encode_krb5_real_tgs_req(&realreq, &scratch))
        return(retval);
 
     /* xxx choose a checksum type */
-    if (retval = (*(krb5_cksumarray[xxx]->sum_func))(scratch->data,
-                                                    0, /* XXX? */
-                                                    (krb5_pointer) cred->keyblock.contents,
-                                                    scratch->length,
-                                                    cred->keyblock.length,
-                                                    &ap_checksum)) {
+    if (retval = (*(krb5_cksumarray[sumtype]->
+                   sum_func))(scratch->data,
+                              0, /* XXX? */
+                              (krb5_pointer) cred->keyblock.contents,
+                              scratch->length,
+                              cred->keyblock.length,
+                              &ap_checksum)) {
        krb5_free_data(scratch);
        return retval;
     }
     tgsreq.tgs_request = *scratch;
     xfree(scratch);
 
-#define cleanup() {(void) free(tgsreq.tgs_request.data);}
+#define cleanup() {(void) free((char *)tgsreq.tgs_request.data); \
+                  (void) free((char *)ap_checksum.contents);}
 
     /*
      * Now get an ap_req.
@@ -138,7 +138,7 @@ krb5_get_cred_via_tgt (tgt, cred)
     /* we expect *reply to be either an error or a proper reply */
     if (retval = krb5_decode_kdc_rep(&reply,
                                     &tgt->keyblock,
-                                    xxx, /* enctype */
+                                    realreq.etype, /* enctype */
                                     &dec_rep)) {
        if (decode_krb5_error(&reply, &err_reply)) {
            cleanup();
@@ -160,11 +160,11 @@ krb5_get_cred_via_tgt (tgt, cred)
 
     if (!krb5_principal_compare(dec_rep->client, tgt->client)) {
        cleanup();
-       return XXX_MODIFIED;
+       return KRB5_KDCREP_MODIFIED;
     }
     /* put pieces into cred-> */
-    if (retval = xxx_copy_keyblock(dec_rep->enc_part2->session,
-                                  &cred->keyblock)) {
+    if (retval = krb5_copy_keyblock(dec_rep->enc_part2->session,
+                                   &cred->keyblock)) {
        cleanup();
        return retval;
     }
@@ -172,8 +172,12 @@ krb5_get_cred_via_tgt (tgt, cred)
     /* check compatibility here first ? XXX */
     cred->ticket_flags = dec_rep->enc_part2->flags;
     cred->is_skey = FALSE;
-    retval = xxx_copy_ticket(dec_rep->ticket, &cred->ticket);
 
+    retval = krb5_encode_ticket(dec_rep->ticket, &scratch);
+    if (!retval) {
+       cred->ticket = *scratch;
+       free((char *)scratch);
+    }
     cleanup();
     return retval;
 }