svn rev #21723: trunk/src/ include/ kdc/ lib/krb5/ lib/krb5/krb/ lib/krb5/rcache/ ...

ghudson@MIT.EDU ghudson at MIT.EDU
Mon Jan 12 13:29:45 EST 2009


http://src.mit.edu/fisheye/changelog/krb5/?cs=21723
Commit By: ghudson
Log Message:
ticket: 1201

Add message hash support to the replay interface, using extension
records (with an empty client string) to retain compatibility with old
code.  For rd_req, the ciphertext of the authenticator (with no ASN.1
wrapping) is hashed; for other uses of the replay cache, no message
hash is used at this time.

This commit adds a command-line tool for testing the replay cache but
does not add any automated tests.



Changed Files:
U   trunk/src/include/k5-int.h
U   trunk/src/kdc/kdc_preauth.c
U   trunk/src/lib/krb5/krb/mk_cred.c
U   trunk/src/lib/krb5/krb/mk_priv.c
U   trunk/src/lib/krb5/krb/mk_safe.c
U   trunk/src/lib/krb5/krb/rd_cred.c
U   trunk/src/lib/krb5/krb/rd_priv.c
U   trunk/src/lib/krb5/krb/rd_req_dec.c
U   trunk/src/lib/krb5/krb/rd_safe.c
U   trunk/src/lib/krb5/libkrb5.exports
U   trunk/src/lib/krb5/rcache/Makefile.in
U   trunk/src/lib/krb5/rcache/rc_conv.c
U   trunk/src/lib/krb5/rcache/rc_dfl.c
A   trunk/src/lib/krb5/rcache/t_replay.c
U   trunk/src/tests/threads/t_rcache.c
Modified: trunk/src/include/k5-int.h
===================================================================
--- trunk/src/include/k5-int.h	2009-01-10 01:06:45 UTC (rev 21722)
+++ trunk/src/include/k5-int.h	2009-01-12 18:29:42 UTC (rev 21723)
@@ -2177,6 +2177,7 @@
     krb5_ui_4 hash;
     char *server;			/* null-terminated */
     char *client;			/* null-terminated */
+    char *msghash;			/* null-terminated */
     krb5_int32 cusec;
     krb5_timestamp ctime;
 } krb5_donot_replay;
@@ -2201,6 +2202,9 @@
 	(krb5_context,
 		krb5_tkt_authent *,
 		krb5_donot_replay *);
+krb5_error_code krb5_rc_hash_message
+	(krb5_context context,
+		const krb5_data *message, char **out);
 
 
 krb5_error_code KRB5_CALLCONV krb5_rc_initialize

Modified: trunk/src/kdc/kdc_preauth.c
===================================================================
--- trunk/src/kdc/kdc_preauth.c	2009-01-10 01:06:45 UTC (rev 21722)
+++ trunk/src/kdc/kdc_preauth.c	2009-01-12 18:29:42 UTC (rev 21723)
@@ -2396,6 +2396,7 @@
 	/* Now check the replay cache. */
 	rep.client = princ_psr;
 	rep.server = "SAM/rc";  /* Should not match any principal name. */
+	rep.msghash = NULL;
 	rep.ctime = psr->stime;
 	rep.cusec = psr->susec;
 	retval = krb5_rc_store(kdc_context, kdc_rcache, &rep);

Modified: trunk/src/lib/krb5/krb/mk_cred.c
===================================================================
--- trunk/src/lib/krb5/krb/mk_cred.c	2009-01-10 01:06:45 UTC (rev 21722)
+++ trunk/src/lib/krb5/krb/mk_cred.c	2009-01-12 18:29:42 UTC (rev 21723)
@@ -258,6 +258,7 @@
             goto error;
 
         replay.server = "";             /* XXX */
+        replay.msghash = NULL;
         replay.cusec = replaydata.usec;
         replay.ctime = replaydata.timestamp;
         if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) {

Modified: trunk/src/lib/krb5/krb/mk_priv.c
===================================================================
--- trunk/src/lib/krb5/krb/mk_priv.c	2009-01-10 01:06:45 UTC (rev 21722)
+++ trunk/src/lib/krb5/krb/mk_priv.c	2009-01-12 18:29:42 UTC (rev 21723)
@@ -214,6 +214,7 @@
 	}
 
 	replay.server = "";		/* XXX */
+	replay.msghash = NULL;
 	replay.cusec = replaydata.usec;
 	replay.ctime = replaydata.timestamp;
 	if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) {

Modified: trunk/src/lib/krb5/krb/mk_safe.c
===================================================================
--- trunk/src/lib/krb5/krb/mk_safe.c	2009-01-10 01:06:45 UTC (rev 21722)
+++ trunk/src/lib/krb5/krb/mk_safe.c	2009-01-12 18:29:42 UTC (rev 21723)
@@ -239,6 +239,7 @@
 	}
 
 	replay.server = "";		/* XXX */
+	replay.msghash = NULL;
 	replay.cusec = replaydata.usec;
 	replay.ctime = replaydata.timestamp;
 	if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) {

Modified: trunk/src/lib/krb5/krb/rd_cred.c
===================================================================
--- trunk/src/lib/krb5/krb/rd_cred.c	2009-01-10 01:06:45 UTC (rev 21722)
+++ trunk/src/lib/krb5/krb/rd_cred.c	2009-01-12 18:29:42 UTC (rev 21723)
@@ -210,6 +210,7 @@
             goto error;
 
         replay.server = "";             /* XXX */
+        replay.msghash = NULL;
         replay.cusec = replaydata.usec;
         replay.ctime = replaydata.timestamp;
         if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) {

Modified: trunk/src/lib/krb5/krb/rd_priv.c
===================================================================
--- trunk/src/lib/krb5/krb/rd_priv.c	2009-01-10 01:06:45 UTC (rev 21722)
+++ trunk/src/lib/krb5/krb/rd_priv.c	2009-01-12 18:29:42 UTC (rev 21723)
@@ -235,6 +235,7 @@
 	    goto error;
 
 	replay.server = "";		/* XXX */
+	replay.msghash = NULL;
 	replay.cusec = replaydata.usec;
 	replay.ctime = replaydata.timestamp;
 	if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) {

Modified: trunk/src/lib/krb5/krb/rd_req_dec.c
===================================================================
--- trunk/src/lib/krb5/krb/rd_req_dec.c	2009-01-10 01:06:45 UTC (rev 21722)
+++ trunk/src/lib/krb5/krb/rd_req_dec.c	2009-01-12 18:29:42 UTC (rev 21723)
@@ -349,7 +349,13 @@
 	tktauthent.ticket = req->ticket;	
 	tktauthent.authenticator = (*auth_context)->authentp;
 	if (!(retval = krb5_auth_to_rep(context, &tktauthent, &rep))) {
-	    retval = krb5_rc_store(context, (*auth_context)->rcache, &rep);
+	    retval = krb5_rc_hash_message(context,
+					  &req->authenticator.ciphertext,
+					  &rep.msghash);
+	    if (!retval) {
+		retval = krb5_rc_store(context, (*auth_context)->rcache, &rep);
+		krb5_xfree(rep.msghash);
+	    }
 	    krb5_xfree(rep.server);
 	    krb5_xfree(rep.client);
 	}

Modified: trunk/src/lib/krb5/krb/rd_safe.c
===================================================================
--- trunk/src/lib/krb5/krb/rd_safe.c	2009-01-10 01:06:45 UTC (rev 21722)
+++ trunk/src/lib/krb5/krb/rd_safe.c	2009-01-12 18:29:42 UTC (rev 21723)
@@ -241,6 +241,7 @@
 	    goto error;
 
 	replay.server = "";		/* XXX */
+	replay.msghash = NULL;
 	replay.cusec = replaydata.usec;
 	replay.ctime = replaydata.timestamp;
 	if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) {

Modified: trunk/src/lib/krb5/libkrb5.exports
===================================================================
--- trunk/src/lib/krb5/libkrb5.exports	2009-01-10 01:06:45 UTC (rev 21722)
+++ trunk/src/lib/krb5/libkrb5.exports	2009-01-12 18:29:42 UTC (rev 21723)
@@ -400,6 +400,7 @@
 krb5_rc_get_lifespan
 krb5_rc_get_name
 krb5_rc_get_type
+krb5_rc_hash_message
 krb5_rc_initialize
 krb5_rc_io_close
 krb5_rc_io_creat
@@ -413,6 +414,7 @@
 krb5_rc_io_unmark
 krb5_rc_io_write
 krb5_rc_recover
+krb5_rc_recover_or_initialize
 krb5_rc_register_type
 krb5_rc_resolve
 krb5_rc_resolve_full

Modified: trunk/src/lib/krb5/rcache/Makefile.in
===================================================================
--- trunk/src/lib/krb5/rcache/Makefile.in	2009-01-10 01:06:45 UTC (rev 21722)
+++ trunk/src/lib/krb5/rcache/Makefile.in	2009-01-12 18:29:42 UTC (rev 21723)
@@ -2,6 +2,8 @@
 myfulldir=lib/krb5/rcache
 mydir=lib/krb5/rcache
 BUILDTOP=$(REL)..$(S)..$(S)..
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
 DEFS=
 
 ##DOS##BUILDTOP = ..\..\..
@@ -36,12 +38,18 @@
 	$(srcdir)/rc_none.c	\
 	$(srcdir)/rc_conv.c	\
 	$(srcdir)/ser_rc.c	\
-	$(srcdir)/rcfns.c
+	$(srcdir)/rcfns.c	\
+	$(srcdir)/t_replay.c
 
 ##DOS##LIBOBJS = $(OBJS)
 
 all-unix:: all-libobjs
 clean-unix:: clean-libobjs
 
+T_REPLAY_OBJS= t_replay.o
+
+t_replay: $(T_REPLAY_OBJS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o t_replay $(T_REPLAY_OBJS) $(KRB5_BASE_LIBS)
+
 @libobj_frag@
 

Modified: trunk/src/lib/krb5/rcache/rc_conv.c
===================================================================
--- trunk/src/lib/krb5/rcache/rc_conv.c	2009-01-10 01:06:45 UTC (rev 21722)
+++ trunk/src/lib/krb5/rcache/rc_conv.c	2009-01-12 18:29:42 UTC (rev 21723)
@@ -36,3 +36,44 @@
     }
     return 0;
 }
+
+/*
+ * Generate a printable hash value for a message for use in a replay
+ * record.  It is not necessary for this hash function to be
+ * collision-proof (the only thing you can do with a second preimage
+ * is produce a false replay error) but it is necessary for the
+ * function to be consistent across implementations.  We do an unkeyed
+ * MD5 hash of the message and convert it into uppercase hex
+ * representation.
+ */
+krb5_error_code
+krb5_rc_hash_message(krb5_context context, const krb5_data *message,
+                     char **out)
+{
+    krb5_error_code retval;
+    krb5_checksum cksum;
+    char *hash, *ptr;
+    unsigned int i;
+
+    *out = NULL;
+
+    /* Calculate the binary checksum. */
+    retval = krb5_c_make_checksum(context, CKSUMTYPE_RSA_MD5, 0, 0,
+                                  message, &cksum);
+    if (retval)
+        return retval;
+
+    /* Convert the checksum into printable form. */
+    hash = malloc(cksum.length * 2 + 1);
+    if (!hash) {
+        krb5_free_checksum_contents(context, &cksum);
+        return KRB5_RC_MALLOC;
+    }
+    ptr = hash;
+    for (i = 0, ptr = hash; i < cksum.length; i++, ptr += 2)
+        snprintf(ptr, 3, "%02X", cksum.contents[i]);
+    *ptr = '\0';
+    *out = hash;
+    krb5_free_checksum_contents(context, &cksum);
+    return 0;
+}

Modified: trunk/src/lib/krb5/rcache/rc_dfl.c
===================================================================
--- trunk/src/lib/krb5/rcache/rc_dfl.c	2009-01-10 01:06:45 UTC (rev 21722)
+++ trunk/src/lib/krb5/rcache/rc_dfl.c	2009-01-12 18:29:42 UTC (rev 21723)
@@ -85,8 +85,12 @@
     if ((old->cusec == new1->cusec) && /* most likely to distinguish */
         (old->ctime == new1->ctime) &&
         (strcmp(old->client, new1->client) == 0) &&
-        (strcmp(old->server, new1->server) == 0)) /* always true */
-        return CMP_REPLAY;
+        (strcmp(old->server, new1->server) == 0)) { /* always true */
+        /* If both records include message hashes, compare them as well. */
+        if (old->msghash == NULL || new1->msghash == NULL ||
+            strcmp(old->msghash, new1->msghash) == 0)
+            return CMP_REPLAY;
+    }
     return CMP_HOHUM;
 }
 
@@ -157,17 +161,22 @@
     ta->na = t->a; t->a = ta;
     ta->nh = t->h[rephash]; t->h[rephash] = ta;
     ta->rep = *rep;
-    if (!(ta->rep.client = strdup(rep->client))) {
-        FREE(ta);
-        return CMP_MALLOC;
-    }
-    if (!(ta->rep.server = strdup(rep->server))) {
-        FREE(ta->rep.client);
-        FREE(ta);
-        return CMP_MALLOC;
-    }
-
+    ta->rep.client = ta->rep.server = ta->rep.msghash = NULL;
+    if (!(ta->rep.client = strdup(rep->client)))
+        goto error;
+    if (!(ta->rep.server = strdup(rep->server)))
+        goto error;
+    if (rep->msghash && !(ta->rep.msghash = strdup(rep->msghash)))
+        goto error;
     return CMP_HOHUM;
+error:
+    if (ta->rep.client)
+        free(ta->rep.client);
+    if (ta->rep.server)
+        free(ta->rep.server);
+    if (ta->rep.msghash)
+        free(ta->rep.msghash);
+    return CMP_MALLOC;
 }
 
 char * KRB5_CALLCONV
@@ -241,6 +250,8 @@
         t->a = q->na;
         FREE(q->rep.client);
         FREE(q->rep.server);
+        if (q->rep.msghash)
+            FREE(q->rep.msghash);
         FREE(q);
     }
 #ifndef NOIOSTUFF
@@ -328,11 +339,13 @@
     {
         if (rp->client)
             free(rp->client);
-
         if (rp->server)
             free(rp->server);
+        if (rp->msghash)
+            free(rp->msghash);
         rp->client = NULL;
         rp->server = NULL;
+        rp->msghash = NULL;
         free(rp);
     }
 }
@@ -345,7 +358,7 @@
     unsigned int len;
     krb5_error_code retval;
 
-    rep->client = rep->server = 0;
+    rep->client = rep->server = rep->msghash = NULL;
 
     retval = krb5_rc_io_read(context, &t->d, (krb5_pointer) &len2,
                              sizeof(len2));
@@ -423,6 +436,7 @@
     long max_size;
     int expired_entries = 0;
     krb5_int32 now;
+    char *msghash = NULL;
 
     if ((retval = krb5_rc_io_open(context, &t->d, t->name))) {
         return retval;
@@ -443,8 +457,7 @@
         retval = KRB5_RC_MALLOC;
         goto io_fail;
     }
-    rep->client = NULL;
-    rep->server = NULL;
+    rep->client = rep->server = rep->msghash = NULL;
 
     if (krb5_timeofday(context, &now))
         now = 0;
@@ -463,21 +476,38 @@
         else if (retval != 0)
             goto io_fail;
 
-
-        if (alive(now, rep, t->lifespan) != CMP_EXPIRED) {
-            if (rc_store(context, id, rep, now) == CMP_MALLOC) {
-                retval = KRB5_RC_MALLOC; goto io_fail;
+        if (!*rep->client) {
+            /* An empty client field indicates an extension record. */
+            if (strncmp(rep->server, "HASH:", 5) == 0) {
+                msghash = strdup(rep->server + 5);
+                if (msghash == NULL) {
+                    retval = KRB5_RC_MALLOC;
+                    goto io_fail;
+                }
             }
         } else {
-            expired_entries++;
+            /* This is a normal record. */
+            if (msghash) {
+                /* Use the hash from the prior extension record. */
+                rep->msghash = msghash;
+                msghash = NULL;
+            }
+            if (alive(now, rep, t->lifespan) != CMP_EXPIRED) {
+                if (rc_store(context, id, rep, now) == CMP_MALLOC) {
+                    retval = KRB5_RC_MALLOC; goto io_fail;
+                }
+            } else {
+                expired_entries++;
+            }
         }
         /*
-         *  free fields allocated by rc_io_fetch
+         *  free fields allocated by rc_io_fetch (or by us)
          */
         FREE(rep->server);
         FREE(rep->client);
-        rep->server = 0;
-        rep->client = 0;
+        if (rep->msghash)
+            FREE(rep->msghash);
+        rep->client = rep->server = rep->msghash = NULL;
     }
     retval = 0;
     krb5_rc_io_unmark(context, &t->d);
@@ -487,6 +517,8 @@
      */
 io_fail:
     krb5_rc_free_entry(context, &rep);
+    if (msghash)
+        FREE(msghash);
     if (retval)
         krb5_rc_io_close(context, &t->d);
     else if (expired_entries > EXCESSREPS)
@@ -529,27 +561,38 @@
 krb5_rc_io_store(krb5_context context, struct dfl_data *t,
                  krb5_donot_replay *rep)
 {
-    unsigned int clientlen, serverlen, len;
-    char *buf, *ptr;
+    unsigned int clientlen, serverlen;
     krb5_error_code ret;
+    struct k5buf buf;
+    char *ptr;
 
+    krb5int_buf_init_dynamic(&buf);
+    if (rep->msghash) {
+        clientlen = 1;
+        serverlen = strlen(rep->msghash) + 6;
+        krb5int_buf_add_len(&buf, (char *) &clientlen, sizeof(clientlen));
+        krb5int_buf_add_len(&buf, "", 1);
+        krb5int_buf_add_len(&buf, (char *) &serverlen, sizeof(serverlen));
+        krb5int_buf_add_fmt(&buf, "HASH:%s", rep->msghash);
+        krb5int_buf_add_len(&buf, "", 1);
+        krb5int_buf_add_len(&buf, (char *) &rep->cusec, sizeof(rep->cusec));
+        krb5int_buf_add_len(&buf, (char *) &rep->ctime, sizeof(rep->ctime));
+    }
     clientlen = strlen(rep->client) + 1;
     serverlen = strlen(rep->server) + 1;
-    len = sizeof(clientlen) + clientlen + sizeof(serverlen) + serverlen +
-        sizeof(rep->cusec) + sizeof(rep->ctime);
-    buf = malloc(len);
-    if (buf == 0)
+    krb5int_buf_add_len(&buf, (char *) &clientlen, sizeof(clientlen));
+    krb5int_buf_add_len(&buf, rep->client, clientlen);
+    krb5int_buf_add_len(&buf, (char *) &serverlen, sizeof(serverlen));
+    krb5int_buf_add_len(&buf, rep->server, serverlen);
+    krb5int_buf_add_len(&buf, (char *) &rep->cusec, sizeof(rep->cusec));
+    krb5int_buf_add_len(&buf, (char *) &rep->ctime, sizeof(rep->ctime));
+
+    ptr = krb5int_buf_data(&buf);
+    if (ptr == NULL)
         return KRB5_RC_MALLOC;
-    ptr = buf;
-    memcpy(ptr, &clientlen, sizeof(clientlen)); ptr += sizeof(clientlen);
-    memcpy(ptr, rep->client, clientlen); ptr += clientlen;
-    memcpy(ptr, &serverlen, sizeof(serverlen)); ptr += sizeof(serverlen);
-    memcpy(ptr, rep->server, serverlen); ptr += serverlen;
-    memcpy(ptr, &rep->cusec, sizeof(rep->cusec)); ptr += sizeof(rep->cusec);
-    memcpy(ptr, &rep->ctime, sizeof(rep->ctime)); ptr += sizeof(rep->ctime);
 
-    ret = krb5_rc_io_write(context, &t->d, buf, len);
-    free(buf);
+    ret = krb5_rc_io_write(context, &t->d, ptr, krb5int_buf_len(&buf));
+    krb5int_free_buf(&buf);
     return ret;
 }
 
@@ -628,6 +671,8 @@
         if (alive(now, &(*q)->rep, t->lifespan) == CMP_EXPIRED) {
             FREE((*q)->rep.client);
             FREE((*q)->rep.server);
+            if ((*q)->rep.msghash)
+                FREE((*q)->rep.msghash);
             FREE(*q);
             *q = *qt; /* why doesn't this feel right? */
         }

Added: trunk/src/lib/krb5/rcache/t_replay.c
===================================================================
--- trunk/src/lib/krb5/rcache/t_replay.c	2009-01-10 01:06:45 UTC (rev 21722)
+++ trunk/src/lib/krb5/rcache/t_replay.c	2009-01-12 18:29:42 UTC (rev 21723)
@@ -0,0 +1,227 @@
+/* -*- mode: c; indent-tabs-mode: nil -*- */
+/*
+ * test/threads/t_replay.c
+ *
+ * Copyright (C) 2009 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.
+ * 
+ * t_replay.c: Command-line interfaces to aid testing of replay cache
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "k5-int.h"
+
+static void usage(const char *progname)
+{
+    fprintf(stderr, "%s: Usage:\n", progname);
+    fprintf(stderr, "  %s dump <filename>\n", progname);
+    fprintf(stderr, "  %s store <rc> <cli> <srv> <msg> <tstamp> <usec>"
+            " <now> <now-usec>\n", progname);
+    exit(1);
+}
+
+static char *read_counted_string(FILE *fp)
+{
+    unsigned int len;
+    char *str;
+
+    if (fread(&len, sizeof(len), 1, fp) != 1)
+        return NULL;
+    if (len == 0 || len > 10000)
+        return NULL;
+    if ((str = malloc(len)) == NULL)
+        return NULL;
+    if (fread(str, 1, len, fp) != len)
+        return NULL;
+    if (str[len - 1] != 0)
+        return NULL;
+    return str;
+}
+
+static void dump_rcache(const char *filename)
+{
+    FILE *fp;
+    krb5_deltat lifespan;
+    krb5_int16 vno;
+
+    fp = fopen(filename, "r");
+    if (!fp) {
+        fprintf(stderr, "Can't open filename: %s\n", strerror(errno));
+        return;
+    }
+    if (fread(&vno, sizeof(vno), 1, fp) != 1)
+        return;
+    if (fread(&lifespan, sizeof(lifespan), 1, fp) != 1)
+        return;
+    printf("Lifespan: %ld\n", (long) lifespan);
+    while (1) {
+        char *str;
+        krb5_int32 usec;
+        krb5_timestamp timestamp;
+
+        printf("---\n");
+
+        if (!(str = read_counted_string(fp)))
+            return;
+        printf("Client: %s\n", str);
+        free(str);
+
+        if (!(str = read_counted_string(fp)))
+            return;
+        printf("Server: %s\n", str);
+        free(str);
+
+        if (fread(&usec, sizeof(usec), 1, fp) != 1)
+            return;
+        printf("Microseconds: %ld\n", (long) usec);
+
+        if (fread(&timestamp, sizeof(timestamp), 1, fp) != 1)
+            return;
+        printf("Timestamp: %ld\n", (long) timestamp);
+    }
+}
+
+static void store(krb5_context ctx, char *rcspec, char *client, char *server,
+                  char *msg, krb5_timestamp timestamp, krb5_int32 usec,
+                  krb5_timestamp now_timestamp, krb5_int32 now_usec)
+{
+    krb5_rcache rc = NULL;
+    krb5_error_code retval = 0;
+    char *hash = NULL;
+    krb5_donot_replay rep;
+
+    if (now_timestamp > 0)
+        krb5_set_debugging_time(ctx, now_timestamp, now_usec);
+    if ((retval = krb5_rc_resolve_full(ctx, &rc, rcspec)))
+        goto cleanup;
+    if ((retval = krb5_rc_recover_or_initialize(ctx, rc, ctx->clockskew)))
+        goto cleanup;
+    if (msg) {
+        krb5_data d;
+
+        d.data = msg;
+        d.length = strlen(msg);
+        if ((retval = krb5_rc_hash_message(ctx, &d, &hash)))
+            goto cleanup;
+    }
+    rep.client = client;
+    rep.server = server;
+    rep.msghash = hash;
+    rep.cusec = usec;
+    rep.ctime = timestamp;
+    retval = krb5_rc_store(ctx, rc, &rep);
+cleanup:
+    if (retval == KRB5KRB_AP_ERR_REPEAT)
+        printf("Replay\n");
+    else if (!retval)
+        printf("Entry successfully stored\n");
+    else
+        fprintf(stderr, "Failure: %s\n", krb5_get_error_message(ctx, retval));
+    if (rc)
+        krb5_rc_close(ctx, rc);
+    if (hash)
+        free(hash);
+}
+
+int main(int argc, char **argv)
+{
+    krb5_context ctx;
+    krb5_error_code retval;
+    const char *progname;
+
+    retval = krb5_init_context(&ctx);
+    if (retval) {
+        fprintf(stderr, "krb5_init_context returned error %ld\n",
+                (long) retval);
+        exit(1);
+    }
+    progname = argv[0];
+
+    /* Parse arguments. */
+    argc--; argv++;
+    while (argc) {
+        if (strcmp(*argv, "dump") == 0) {
+            /*
+             * Without going through the rcache interface, dump a
+             * named dfl-format rcache file to stdout.  Takes a full
+             * pathname argument.
+             */
+            const char *filename;
+
+            argc--; argv++;
+            if (!argc) usage(progname);
+            filename = *argv;
+            dump_rcache(filename);
+        } else if (strcmp(*argv, "store") == 0) {
+            /*
+             * Using the rcache interface, store a replay record.
+             * Takes an rcache spec like dfl:host as the first
+             * argument.  If non-empty, the "msg" argument will be
+             * hashed and provided in the replay record.  The
+             * now-timestamp argument can be 0 to use the current
+             * time.
+             */
+            char *rcspec, *client, *server, *msg;
+            krb5_timestamp timestamp, now_timestamp;
+            krb5_int32 usec, now_usec;
+
+            argc--; argv++;
+            if (!argc) usage(progname);
+            rcspec = *argv;
+            argc--; argv++;
+            if (!argc) usage(progname);
+            client = *argv;
+            argc--; argv++;
+            if (!argc) usage(progname);
+            server = *argv;
+            argc--; argv++;
+            if (!argc) usage(progname);
+            msg = (**argv) ? *argv : NULL;
+            argc--; argv++;
+            if (!argc) usage(progname);
+            timestamp = (krb5_timestamp) atol(*argv);
+            argc--; argv++;
+            if (!argc) usage(progname);
+            usec = (krb5_int32) atol(*argv);
+            argc--; argv++;
+            if (!argc) usage(progname);
+            now_timestamp = (krb5_timestamp) atol(*argv);
+            argc--; argv++;
+            if (!argc) usage(progname);
+            now_usec = (krb5_int32) atol(*argv);
+
+            store(ctx, rcspec, client, server, msg, timestamp, usec,
+                  now_timestamp, now_usec);
+        } else
+            usage(progname);
+        argc--; argv++;
+    }
+
+    krb5_free_context(ctx);
+
+    return 0;
+}

Modified: trunk/src/tests/threads/t_rcache.c
===================================================================
--- trunk/src/tests/threads/t_rcache.c	2009-01-10 01:06:45 UTC (rev 21722)
+++ trunk/src/tests/threads/t_rcache.c	2009-01-12 18:29:42 UTC (rev 21723)
@@ -62,6 +62,7 @@
 	     buf);
     r.server = buf;
     r.client = (t->my_cusec & 7) + "abcdefgh at ATHENA.MIT.EDU";
+    r.msghash = NULL;
     if (t->now != t->my_ctime) {
 	if (t->my_ctime != 0) {
 	    snprintf(buf2, sizeof(buf2), "%3d: %ld %5d\n", t->idx,




More information about the cvs-krb5 mailing list