Add support for using the encrypted part of a krb5 ticket as an AFS token--
authorSam Hartman <hartmans@mit.edu>
Tue, 27 Aug 2002 17:50:07 +0000 (17:50 +0000)
committerSam Hartman <hartmans@mit.edu>
Tue, 27 Aug 2002 17:50:07 +0000 (17:50 +0000)
af krb5-encpart-only (kvno 213) and enable this support by default.

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@14777 dc483132-0cff-0310-8789-dd5450dbe970

src/krb524/ChangeLog
src/krb524/README
src/krb524/krb524d.c

index 9c299aa3750a02de4de81a21db77c6d3eab24d8b..d78c76c96f244b0a0e0a50f16f9da96651090502 100644 (file)
@@ -3,6 +3,27 @@
        * Makefile.in ($(KRB524_HDR), $(KRB524_ERR_HDR)): Quote target of
        copy on Windows.
 
+2002-08-27  Sam Hartman  <hartmans@mit.edu>
+
+       * README: Document  new afs_krb5 configuration information
+
+       * krb524d.c (afs_return_v4): New function  to determine if we have
+       been configured to return v4 tickets for afs or use the afs
+       krb5-encpart proposal
+       (do_connection):  Call afs_return_v4 and use its result
+
+       2002-08-26  Sam Hartman  <hartmans@mit.edu>
+
+       * RELEASE_NOTES: Delete OV release notes now with 100% incorrect
+       content 
+
+2002-08-22  Sam Hartman  <hartmans@mit.edu>
+
+       * krb524d.c (do_connection): Add support for  AFS
+       krb5-encpart-only per discussion with jhutz and lha
+       (handle_classic_v4): Split out code for handling v4 tickets since
+       it needs to be called multiple times
+
 2002-08-23  Ken Raeburn  <raeburn@mit.edu>
 
        * Makefile.in: Change $(S)=>/ and $(U)=>.. globally.
index 1531de0d96a5efaaac3f9c4c1328dd88826cdb98..dd7ca9c239d2a222b730b0e30e909ecb10d50921 100644 (file)
@@ -48,6 +48,16 @@ information in the V5 credential and {C,S}_4.
 Steps (2) through (4) are encapsulated in a single function call in
 the krb524 library.
 
+An alternate conversion is provided for AFS servers that support the
+encrypted part of a krb5 ticket as an AFS token.  If the krb524d is
+converting a principal whose first component is afs and if the
+encrypted part of the ticket fits in 344 bytes, then it will default
+to simply returning the encrypted part of the ticket as a token.  If
+it turns out that the AFS server does not support the ticket, then
+users will get an unknown key version error and the krb524d must be
+configured to use v4 tickets for this AFS service.
+
+
 Obviously, not all V5 credentials can be completely converted to V4
 credentials, since the former is a superset of the latter.  The
 precise semantics of the conversion function are still undecided.
@@ -82,6 +92,29 @@ default principal's realm if not specified.  The -n argument causes
 the new ticket to be added to the existing ticket file; otherwise, the
 ticket file is initialized.
 
+Configuring krb524d AFS Conversion
+======================================================================
+
+The krb524d looks in the appdefaults  section of krb5.conf for an
+application called afs_krb5 to determine whether  afs principals
+support encrypted ticket parts as tokens.  The following configuration
+fragment says that afs/sipb.mit.edu@ATHENA.MIT.EDU supports the new
+token format but afs@ATHENA.MIT.EDU and
+afs/athena.mit.edu@ATHENA.MIT.EDU do not.  Note that the default is to
+assume afs servers support the new format.
+
+[appdefaults]
+afs_krb5 = { 
+       ATHENA.MIT.EDU = {
+               # This stanza describes principals in the
+               #ATHENA.MIT.EDU realm
+               afs = false
+               afs/athena.mit.edu = false
+               afs/sipb.mit.edu = true
+       }
+}
+
+
 Using libkrb524.a
 ======================================================================
 
index ad7c43978ecc8a1b1306d78e1e24dba0c8fda75e..4995b515fc229978e6c9e181b85f1d8c4517df97 100644 (file)
@@ -1,4 +1,25 @@
 /*
+ * Copyright (C) 2002 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
  * Copyright 1994 by OpenVision Technologies, Inc.
  * 
  * Permission to use, copy, modify, distribute, and sell this software
@@ -26,6 +47,7 @@
 #include <com_err.h>
 #include <stdarg.h>
 
+#include <assert.h>
 #include <stdio.h>
 #ifdef HAVE_SYS_SELECT_H
 #include <sys/select.h>
@@ -68,6 +90,13 @@ krb5_error_code  kdc_get_server_key(krb5_context, krb5_principal,
                                    krb5_keyblock *, krb5_kvno *,
                                    krb5_enctype, krb5_kvno);
 
+static krb5_error_code
+handle_classic_v4 (krb5_context context, krb5_ticket *v5tkt,
+                  struct sockaddr_in *saddr,
+                  krb5_data *tktdata, krb5_kvno *v4kvno);
+static krb5_error_code 
+afs_return_v4(krb5_context, const krb5_principal , int *use_v5);
+
 static void usage(context)
      krb5_context context;
 {
@@ -276,20 +305,16 @@ krb5_error_code do_connection(s, context)
 {
      struct sockaddr saddr;
      krb5_ticket *v5tkt = 0;
-     KTEXT_ST v4tkt;
-     krb5_keyblock v5_service_key, v4_service_key;
      krb5_data msgdata, tktdata;
      char msgbuf[MSGSIZE], tktbuf[TKT_BUFSIZ], *p;
      int ret, saddrlen;
      krb5_int32 n; /* Must be 4 bytes */
      krb5_kvno v4kvno;
 
-     /* Clear out keyblock contents so we don't accidentally free the stack.*/
-     v5_service_key.contents = v4_service_key.contents = 0;
-
      msgdata.data = msgbuf;
      msgdata.length = MSGSIZE;
-
+     tktdata.data = tktbuf;
+     tktdata.length = TKT_BUFSIZ;
      saddrlen = sizeof(struct sockaddr);
      ret = recvfrom(s, msgdata.data, (int) msgdata.length, 0, &saddr, &saddrlen);
      if (ret < 0) {
@@ -321,51 +346,41 @@ krb5_error_code do_connection(s, context)
      if (debug)
          printf("V5 ticket decoded\n");
      
-     if ((ret = lookup_service_key(context, v5tkt->server,
-                                  v5tkt->enc_part.enctype,
-                                  v5tkt->enc_part.kvno,
-                                  &v5_service_key, NULL)))
-         goto error;
-
-     if ((ret = lookup_service_key(context, v5tkt->server,
-                                  ENCTYPE_DES3_CBC_RAW,
-                                  0, /* highest kvno */
-                                  &v4_service_key, &v4kvno)) &&
-        (ret = lookup_service_key(context, v5tkt->server,
-                                  ENCTYPE_LOCAL_DES3_HMAC_SHA1,
-                                  0,
-                                  &v4_service_key, &v4kvno)) &&
-        (ret = lookup_service_key(context, v5tkt->server,
-                                  ENCTYPE_DES3_CBC_SHA1,
-                                  0,
-                                  &v4_service_key, &v4kvno)) &&
-        (ret = lookup_service_key(context, v5tkt->server,
-                                  ENCTYPE_DES_CBC_CRC,
-                                  0,
-                                  &v4_service_key, &v4kvno)))
-        goto error;
-
-     if (debug)
-         printf("service key retrieved\n");
-
-     ret = krb524_convert_tkt_skey(context, v5tkt, &v4tkt, &v5_service_key,
-                                  &v4_service_key,
-                                  (struct sockaddr_in *)&saddr);
-     if (ret)
-         goto error;
-
-     if (debug)
-         printf("credentials converted\n");
-
-     tktdata.data = tktbuf;
-     tktdata.length = TKT_BUFSIZ;
-     ret = encode_v4tkt(&v4tkt, tktdata.data, &tktdata.length);
-     if (ret)
-         goto error;
-     if (debug)
-         printf("v4 credentials encoded\n");
-
-error:
+     if( v5tkt->server->length >= 1
+        &&krb5_princ_component(context, v5tkt->server, 0)->length == 3
+        &&strncmp(krb5_princ_component(context, v5tkt->server, 0)->data,
+                  "afs", 3) == 0) {
+        krb5_data *enc_part;
+        int use_v5;
+        if ((ret = afs_return_v4(context, v5tkt->server,
+                                 &use_v5)) != 0) 
+            goto error;
+        if ((ret = encode_krb5_enc_data( &v5tkt->enc_part, &enc_part)) != 0) 
+            goto error;
+        if (!(use_v5 )|| enc_part->length >= 344) {
+            krb5_free_data(context, enc_part);
+            if ((ret = handle_classic_v4(context, v5tkt,
+                                        (struct sockaddr_in *) &saddr, &tktdata,
+                                        &v4kvno)) != 0)
+                goto error;
+        } else {
+          KTEXT_ST fake_v4tkt;
+          fake_v4tkt.mbz = 0;
+          fake_v4tkt.length = enc_part->length;
+          memcpy(fake_v4tkt.dat, enc_part->data, enc_part->length);
+            v4kvno = (0x100-0x2b); /*protocol constant indicating  v5
+                                    * enc part only*/
+            krb5_free_data(context, enc_part);
+            ret = encode_v4tkt(&fake_v4tkt, tktdata.data, &tktdata.length);
+        }
+     } else {
+        if ((ret = handle_classic_v4(context, v5tkt,
+                                    (struct sockaddr_in *) &saddr, &tktdata,
+                                    &v4kvno)) != 0)
+            goto error;
+     }
+     
+       error:
      /* create the reply */
      p = msgdata.data;
      msgdata.length = 0;
@@ -395,11 +410,6 @@ write_msg:
               ret = errno;
      if (debug)
          printf("reply written\n");
-     /* If we have keys to clean up, do so.*/
-     if (v5_service_key.contents)
-       krb5_free_keyblock_contents(context, &v5_service_key);
-     if (v4_service_key.contents)
-       krb5_free_keyblock_contents(context, &v4_service_key);
      if (v5tkt)
        krb5_free_ticket(context, v5tkt);
      
@@ -488,3 +498,110 @@ krb5_error_code kdc_get_server_key(context, service, key, kvnop, ktype, kvno)
     kadm5_free_principal_ent(handle, &server);
     return ret;
 }
+
+/*
+ * We support two  kinds of v4 credentials.  There are real v4
+ *   credentials, and  a Kerberos v5 enc part masquerading as a krb4
+ *  credential to be used by modern AFS implementations; this function
+ *  handles the classic v4 case.
+ */
+
+static krb5_error_code
+handle_classic_v4 (krb5_context context, krb5_ticket *v5tkt,
+                  struct sockaddr_in *saddr,
+                  krb5_data *tktdata, krb5_kvno *v4kvno)
+{
+    krb5_error_code ret;
+    krb5_keyblock v5_service_key, v4_service_key;
+     KTEXT_ST v4tkt;
+
+    v5_service_key.contents = NULL;
+    v4_service_key.contents = NULL;
+    
+             if ((ret = lookup_service_key(context, v5tkt->server,
+                                  v5tkt->enc_part.enctype,
+                                  v5tkt->enc_part.kvno,
+                                  &v5_service_key, NULL)))
+         goto error;
+
+     if ((ret = lookup_service_key(context, v5tkt->server,
+                                  ENCTYPE_DES3_CBC_RAW,
+                                  0, /* highest kvno */
+                                  &v4_service_key, v4kvno)) &&
+        (ret = lookup_service_key(context, v5tkt->server,
+                                  ENCTYPE_LOCAL_DES3_HMAC_SHA1,
+                                  0,
+                                  &v4_service_key, v4kvno)) &&
+        (ret = lookup_service_key(context, v5tkt->server,
+                                  ENCTYPE_DES3_CBC_SHA1,
+                                  0,
+                                  &v4_service_key, v4kvno)) &&
+        (ret = lookup_service_key(context, v5tkt->server,
+                                  ENCTYPE_DES_CBC_CRC,
+                                  0,
+                                  &v4_service_key, v4kvno)))
+        goto error;
+
+     if (debug)
+         printf("service key retrieved\n");
+
+     ret = krb524_convert_tkt_skey(context, v5tkt, &v4tkt, &v5_service_key,
+                                  &v4_service_key,
+                                  (struct sockaddr_in *)saddr);
+     if (ret)
+         goto error;
+
+     if (debug)
+         printf("credentials converted\n");
+
+     ret = encode_v4tkt(&v4tkt, tktdata->data, &tktdata->length);
+     if (ret)
+         goto error;
+     if (debug)
+         printf("v4 credentials encoded\n");
+
+ error:
+     if(v5_service_key.contents)
+       krb5_free_keyblock_contents(context, &v5_service_key);
+     if (v4_service_key.contents)
+        krb5_free_keyblock_contents(context, &v4_service_key);
+     return ret;
+}
+
+/*
+ * afs_return_v4: a predicate to determine whether we want to try
+ * using the afs krb5 encrypted part encoding or whether we  just
+ * return krb4.  Takes a principal, and checks the configuration file.
+ */
+static krb5_error_code 
+afs_return_v4 (krb5_context context, const krb5_principal princ,
+              int *use_v5)
+{
+    krb5_error_code ret;
+    char *unparsed_name;
+    char *cp;
+    krb5_data realm;
+    assert(use_v5 != NULL);
+    ret = krb5_unparse_name(context, princ, &unparsed_name);
+        if (ret != 0)
+       return ret;
+/* Trim out trailing realm component into separate string.*/
+    for (cp = unparsed_name; *cp != '\0'; cp++) {
+       if (*cp == '\\') {
+           cp++; /* We trust unparse_name not to leave a singleton
+                  * backslash*/
+           continue;
+       }
+       if (*cp == '@') {
+           *cp = '\0';
+           realm.data = cp+1;
+           realm.length = strlen((char *) realm.data);
+                   break;
+       }
+    }
+     krb5_appdefault_boolean(context, "afs_krb5",
+                                 &realm, unparsed_name, 1,
+                                 use_v5);
+    krb5_free_unparsed_name(context, unparsed_name);
+    return ret;
+}