This patch is derived from a patch originally submitted to RT
authorJeffrey Altman <jaltman@secure-endpoints.com>
Wed, 18 Jun 2008 19:36:49 +0000 (19:36 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Wed, 18 Jun 2008 19:36:49 +0000 (19:36 +0000)
by: Nik Conwell <nik@bu.edu>

krb5_set_real_time() accepts as input the time of the KDC
or an application server as a combination of seconds and
microseconds.  Often it is the case that the time source
does not provide the real time with less than one second
granularity.  Up until this patch such a caller would fill
in the microseconds parameter as zero.   krb5_set_real_time()
would treat the zero microseconds as the actual reported
time and compute a microsecond based offset.

During a one second window subsequent calls to
krb5_set_real_time() would have an ever increasing offset
size until the number of seconds is incremented.  This
in turn produces a side effect in which the microseconds
value of the local clock is effectively erased.

If there are multiple processes or threads on the same
machine each requesting service tickets using the same
client principal for the same service principal where
the number of seconds reported by the KDC are equivalent,
then they will now all create authenticators with
exactly the same timestamp.  As a result, the authenticating
service will detect a replay attack even though the
authenticators are actually unique.  The replay cache
only maintains a tuple of client, server and timestamp.

This patch modifies the interpretation of the microseconds
parameter.  If -1 is specified, the microseconds offset is
ignored.

ticket: 5924
tags: pullup

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

src/lib/krb5/krb/get_in_tkt.c
src/lib/krb5/os/toffset.c

index 5edbc26fa3abcf6d326f60ee2dcee32bf25accaf..8f4f57a13bf44e2fd2e3e3ade9d8ec00b2c2a77c 100644 (file)
@@ -335,7 +335,7 @@ verify_as_reply(krb5_context                context,
 
     if (context->library_options & KRB5_LIBOPT_SYNC_KDCTIME) {
        retval = krb5_set_real_time(context,
-                                   as_reply->enc_part2->times.authtime, 0);
+                                   as_reply->enc_part2->times.authtime, -1);
        if (retval)
            return retval;
     } else {
index 3a06e335b4b2770351d1d32a2d1239812d19d2d5..40bc108afa793f122b18838a172ba4eae6e58c95 100644 (file)
@@ -34,6 +34,9 @@
  * routines will return the correct time as corrected by difference
  * between the system time and the "real time" as passed to this
  * routine
+ *
+ * If the real time microseconds are given as -1 the caller doesn't
+ * know the microseconds value so the usec offset is always zero.
  */
 krb5_error_code KRB5_CALLCONV
 krb5_set_real_time(krb5_context context, krb5_timestamp seconds, krb5_int32 microseconds)
@@ -45,8 +48,10 @@ krb5_set_real_time(krb5_context context, krb5_timestamp seconds, krb5_int32 micr
     retval = krb5_crypto_us_timeofday(&sec, &usec);
     if (retval)
            return retval;
+
     os_ctx->time_offset = seconds - sec;
-    os_ctx->usec_offset = microseconds - usec;
+    os_ctx->usec_offset = (microseconds > -1) ? microseconds - usec : 0;
+
     os_ctx->os_flags = ((os_ctx->os_flags & ~KRB5_OS_TOFFSET_TIME) |
                        KRB5_OS_TOFFSET_VALID);
     return 0;