pull up r19062 from trunk
authorTom Yu <tlyu@mit.edu>
Tue, 13 Feb 2007 05:18:04 +0000 (05:18 +0000)
committerTom Yu <tlyu@mit.edu>
Tue, 13 Feb 2007 05:18:04 +0000 (05:18 +0000)
 r19062@cathode-dark-space:  jaltman | 2007-01-15 23:18:02 -0500
 ticket: 5349
 tags: pullup

   This commit adds two new functions, krb5_server_decrypt_ticket_keyblock
   (private) and krb5_server_decrypt_ticket_keytab (public).  These
   functions take a krb5_ticket as input and decrypt it using the provided
   key data.  The public function is useful for higher level application
   protocols such a TLS-KRB5 and AFS RX-KRB5 which exchange a service
   but do not use the AP-REQ/AP-REP messages.

   This commit also adds new functionality to kvno which permits kvno
   when provided a keytab as input to verify whether or not the keytab
   contains a key that can successfully decrypt the obtains service ticket.

ticket: 5349

git-svn-id: svn://anonsvn.mit.edu/krb5/branches/krb5-1-6@19160 dc483132-0cff-0310-8789-dd5450dbe970

src/clients/kvno/kvno.c
src/include/krb5/krb5.hin
src/lib/krb5/krb/Makefile.in
src/lib/krb5/krb/srv_dec_tkt.c [new file with mode: 0644]
src/lib/krb5/libkrb5.exports
src/lib/krb5_32.def

index a6620b9368ed250f3685897c7e34d1fae978f0c8..3b227474a46f123a57b367cbd80b0469344c56ac 100644 (file)
@@ -41,10 +41,10 @@ static void xusage()
 {
 #ifdef KRB5_KRB4_COMPAT
     fprintf(stderr, 
-            "usage: %s [-4 | [-c ccache] [-e etype]] service1 service2 ...\n", 
+            "usage: %s [-4 | [-c ccache] [-e etype] [-k keytab]] service1 service2 ...\n", 
             prog);
 #else
-    fprintf(stderr, "usage: %s [-c ccache] [-e etype] service1 service2 ...\n",
+    fprintf(stderr, "usage: %s [-c ccache] [-e etype] [-k keytab] service1 service2 ...\n",
             prog);
 #endif
     exit(1);
@@ -54,7 +54,7 @@ int quiet = 0;
 
 static void do_v4_kvno (int argc, char *argv[]);
 static void do_v5_kvno (int argc, char *argv[], 
-                        char *ccachestr, char *etypestr);
+                        char *ccachestr, char *etypestr, char *keytab_name);
 
 #include <com_err.h>
 static void extended_com_err_fn (const char *, errcode_t, const char *,
@@ -63,7 +63,7 @@ static void extended_com_err_fn (const char *, errcode_t, const char *,
 int main(int argc, char *argv[])
 {
     int option;
-    char *etypestr = 0, *ccachestr = 0;
+    char *etypestr = NULL, *ccachestr = NULL, *keytab_name = NULL;
     int v4 = 0;
 
     set_com_err_hook (extended_com_err_fn);
@@ -71,7 +71,7 @@ int main(int argc, char *argv[])
     prog = strrchr(argv[0], '/');
     prog = prog ? (prog + 1) : argv[0];
 
-    while ((option = getopt(argc, argv, "c:e:hq4")) != -1) {
+    while ((option = getopt(argc, argv, "c:e:hk:q4")) != -1) {
        switch (option) {
        case 'c':
            ccachestr = optarg;
@@ -82,6 +82,9 @@ int main(int argc, char *argv[])
        case 'h':
            xusage();
            break;
+       case 'k':
+           keytab_name = optarg;
+           break;
        case 'q':
            quiet = 1;
            break;
@@ -97,13 +100,13 @@ int main(int argc, char *argv[])
     if ((argc - optind) < 1)
        xusage();
 
-    if ((ccachestr != 0 || etypestr != 0) && v4)
+    if ((ccachestr != NULL || etypestr != NULL || keytab_name != NULL) && v4)
        xusage();
 
     if (v4)
        do_v4_kvno(argc - optind, argv + optind);
     else
-       do_v5_kvno(argc - optind, argv + optind, ccachestr, etypestr);
+       do_v5_kvno(argc - optind, argv + optind, ccachestr, etypestr, keytab_name);
     return 0;
 }
 
@@ -169,7 +172,7 @@ static void extended_com_err_fn (const char *myprog, errcode_t code,
 }
 
 static void do_v5_kvno (int count, char *names[], 
-                        char * ccachestr, char *etypestr)
+                        char * ccachestr, char *etypestr, char *keytab_name)
 {
     krb5_error_code ret;
     int i, errors;
@@ -179,6 +182,7 @@ static void do_v5_kvno (int count, char *names[],
     krb5_creds in_creds, *out_creds;
     krb5_ticket *ticket;
     char *princ;
+    krb5_keytab keytab = NULL;
 
     ret = krb5_init_context(&context);
     if (ret) {
@@ -205,6 +209,14 @@ static void do_v5_kvno (int count, char *names[],
        exit(1);
     }
 
+    if (keytab_name) {
+       ret = krb5_kt_resolve(context, keytab_name, &keytab);
+       if (ret) {
+           com_err(prog, ret, "resolving keytab %s", keytab_name);
+           exit(1);
+       }
+    }
+
     ret = krb5_cc_get_principal(context, ccache, &me);
     if (ret) {
        com_err(prog, ret, "while getting client principal name");
@@ -261,14 +273,32 @@ static void do_v5_kvno (int count, char *names[],
            continue;
        }
            
-       if (!quiet)
-           printf("%s: kvno = %d\n", princ, ticket->enc_part.kvno);
+       if (keytab) {
+           ret = krb5_server_decrypt_ticket_keytab(context, keytab, ticket);
+           if (ret) {
+               if (!quiet)
+                   printf("%s: kvno = %d, keytab entry invalid", princ, ticket->enc_part.kvno);
+               com_err(prog, ret, "while decrypting ticket for %s", princ);
+               krb5_free_ticket(context, ticket);
+               krb5_free_creds(context, out_creds);
+               krb5_free_unparsed_name(context, princ);
+
+               errors++;
+               continue;
+           }
+           if (!quiet)
+               printf("%s: kvno = %d, keytab entry valid\n", princ, ticket->enc_part.kvno);
+       } else {
+           if (!quiet)
+               printf("%s: kvno = %d\n", princ, ticket->enc_part.kvno);
+       }
 
-       krb5_free_ticket(context, ticket);
        krb5_free_creds(context, out_creds);
        krb5_free_unparsed_name(context, princ);
     }
 
+    if (keytab)
+       krb5_kt_close(context, keytab);
     krb5_free_principal(context, me);
     krb5_cc_close(context, ccache);
     krb5_free_context(context);
index d123773a18f6d06b57479195befb24cd2cf7fa75..5a12284c232c36295ecc08578a4877f22020f041 100644 (file)
@@ -1469,8 +1469,20 @@ krb5_error_code krb5_get_cred_from_kdc_renew
                krb5_creds *,
                krb5_creds **,
                krb5_creds *** );
+
+krb5_error_code KRB5_CALLCONV
+krb5_server_decrypt_ticket_keyblock
+       (krb5_context context,
+                const krb5_keyblock key,
+                krb5_ticket  *ticket);
 #endif
 
+krb5_error_code KRB5_CALLCONV
+krb5_server_decrypt_ticket_keytab
+       (krb5_context context,
+                const krb5_keytab kt,
+                krb5_ticket  *ticket);
+
 void KRB5_CALLCONV krb5_free_tgt_creds
        (krb5_context,
         krb5_creds **); /* XXX too hard to do with const */
index 84b1f27bbd4ed6a92f53747a483f1ead7d1432a7..ebb2e802061d2f9a029a038c13bc54af27fa1ba1 100644 (file)
@@ -89,6 +89,7 @@ STLIBOBJS= \
        ser_princ.o     \
        serialize.o     \
        set_realm.o     \
+       srv_dec_tkt.o   \
        srv_rcache.o    \
        str_conv.o      \
        tgtname.o       \
@@ -175,6 +176,7 @@ OBJS=       $(OUTPRE)addr_comp.$(OBJEXT)    \
        $(OUTPRE)ser_princ.$(OBJEXT)    \
        $(OUTPRE)serialize.$(OBJEXT)    \
        $(OUTPRE)set_realm.$(OBJEXT)    \
+       $(OUTPRE)srv_dec_tkt.$(OBJEXT)  \
        $(OUTPRE)srv_rcache.$(OBJEXT)   \
        $(OUTPRE)str_conv.$(OBJEXT)     \
        $(OUTPRE)tgtname.$(OBJEXT)      \
@@ -262,6 +264,7 @@ SRCS=       $(srcdir)/addr_comp.c   \
        $(srcdir)/ser_princ.c   \
        $(srcdir)/serialize.c   \
        $(srcdir)/set_realm.c   \
+       $(srcdir)/srv_dec_tkt.c \
        $(srcdir)/srv_rcache.c  \
        $(srcdir)/str_conv.c    \
        $(srcdir)/tgtname.c     \
@@ -1041,6 +1044,15 @@ set_realm.so set_realm.po $(OUTPRE)set_realm.$(OBJEXT): \
   $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
   $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
   set_realm.c
+srv_dec_tkt.so srv_dec_tkt.po $(OUTPRE)srv_dec_tkt.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+  $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+  $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+  $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+  $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+  $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+  $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+  srv_dec_tkt.c
 srv_rcache.so srv_rcache.po $(OUTPRE)srv_rcache.$(OBJEXT): \
   $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
   $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
diff --git a/src/lib/krb5/krb/srv_dec_tkt.c b/src/lib/krb5/krb/srv_dec_tkt.c
new file mode 100644 (file)
index 0000000..5fce58e
--- /dev/null
@@ -0,0 +1,93 @@
+/*\r
+ * lib/krb5/krb/srv_dec_tkt.c\r
+ *\r
+ * Copyright 2006 by the Massachusetts Institute of Technology.\r
+ * All Rights Reserved.\r
+ *\r
+ * Export of this software from the United States of America may\r
+ *   require a specific license from the United States Government.\r
+ *   It is the responsibility of any person or organization contemplating\r
+ *   export to obtain such a license before exporting.\r
+ *\r
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and\r
+ * distribute this software and its documentation for any purpose and\r
+ * without fee is hereby granted, provided that the above copyright\r
+ * notice appear in all copies and that both that copyright notice and\r
+ * this permission notice appear in supporting documentation, and that\r
+ * the name of M.I.T. not be used in advertising or publicity pertaining\r
+ * to distribution of the software without specific, written prior\r
+ * permission.  Furthermore if you modify this software you must label\r
+ * your software as modified software and not distribute it in such a\r
+ * fashion that it might be confused with the original M.I.T. software.\r
+ * M.I.T. makes no representations about the suitability of\r
+ * this software for any purpose.  It is provided "as is" without express\r
+ * or implied warranty.\r
+ *\r
+ *\r
+ * Server decrypt ticket via keytab or keyblock. \r
+ *\r
+ * Different from krb5_rd_req_decoded. (krb5/src/lib/krb5/krb/rd_req_dec.c)\r
+ *   - No krb5_principal_compare or KRB5KRB_AP_ERR_BADMATCH error.\r
+ *   - No replay cache processing.\r
+ *   - No skew checking or KRB5KRB_AP_ERR_SKEW error.\r
+ *   - No address checking or KRB5KRB_AP_ERR_BADADDR error.\r
+ *   - No time validation.\r
+ *   - No permitted enctype validation or KRB5_NOPERM_ETYPE error.\r
+ *   - Does not free ticket->enc_part2 on error. \r
+ */\r
+\r
+#include <k5-int.h>\r
+\r
+krb5_error_code KRB5_CALLCONV\r
+krb5_server_decrypt_ticket_keyblock(krb5_context context, \r
+                                   const krb5_keyblock *key,\r
+                                   krb5_ticket *ticket)\r
+{\r
+    krb5_error_code retval;\r
+    krb5_data *realm;\r
+    krb5_transited *trans;\r
+\r
+    retval = krb5_decrypt_tkt_part(context, key, ticket);\r
+    if (retval) \r
+       goto done;\r
+\r
+    trans = &ticket->enc_part2->transited;\r
+    realm = &ticket->enc_part2->client->realm;\r
+    if (trans->tr_contents.data && *trans->tr_contents.data) {\r
+       retval = krb5_check_transited_list(context, &trans->tr_contents,\r
+                                          realm, &ticket->server->realm);\r
+       goto done;\r
+    }\r
+\r
+    if (ticket->enc_part2->flags & TKT_FLG_INVALID) {  /* ie, KDC_OPT_POSTDATED */\r
+       retval = KRB5KRB_AP_ERR_TKT_INVALID;\r
+       goto done;\r
+    }\r
+\r
+  done:\r
+    return retval;\r
+}\r
+\r
+\r
+krb5_error_code        KRB5_CALLCONV\r
+krb5_server_decrypt_ticket_keytab(krb5_context context,\r
+                                 const krb5_keytab kt,\r
+                                 krb5_ticket *ticket)\r
+{\r
+    krb5_error_code       retval;\r
+    krb5_enctype          enctype;\r
+    krb5_keytab_entry     ktent;\r
+\r
+    enctype = ticket->enc_part.enctype;\r
+\r
+    if ((retval = krb5_kt_get_entry(context, kt, ticket->server,\r
+                                    ticket->enc_part.kvno,\r
+                                    enctype, &ktent)))\r
+        return retval;\r
+\r
+    retval = krb5_server_decrypt_ticket_keyblock(context, &ktent.key, ticket);\r
+    /* Upon error, Free keytab entry first, then return */\r
+\r
+    (void) krb5_kt_free_entry(context, &ktent);\r
+    return retval;\r
+}\r
index f9c4593045b59ec35038b2947b74488616816f0e..22d2b4272af19e475d1cd02ab12fc443b7a41bef 100644 (file)
@@ -619,6 +619,7 @@ krb5_ser_rcache_init
 krb5_ser_unpack_bytes
 krb5_ser_unpack_int32
 krb5_ser_unpack_int64
+krb5_server_decrypt_ticket_keytab
 krb5_set_config_files
 krb5_set_debugging_time
 krb5_set_default_in_tkt_ktypes
index c2a61482cd1d625c49d2c1c82a80afb6e7e92723..5b833f45ef9ba58933fdcea606e7b0ae3f1ca2a9 100644 (file)
@@ -224,6 +224,7 @@ krb5_c_string_to_key_with_params
        krb5_recvauth_version
        krb5_salttype_to_string
        krb5_sendauth
+       krb5_server_decrypt_ticket_keytab
        krb5_set_default_realm
        krb5_set_default_tgs_enctypes
         krb5_set_password