Blame SOURCES/Limit-ticket-lifetime-to-2-31-1-seconds.patch

819f75
From 31d5c854198ed91fc2bd0b9fb87ed0dcd5a40eb6 Mon Sep 17 00:00:00 2001
819f75
From: Greg Hudson <ghudson@mit.edu>
819f75
Date: Thu, 24 Aug 2017 16:00:33 -0400
819f75
Subject: [PATCH] Limit ticket lifetime to 2^31-1 seconds
819f75
819f75
Although timestamps above 2^31-1 are now valid, intervals exceeding
819f75
2^31-1 seconds may be treated incorrectly by comparison operations.
819f75
819f75
The initially computed interval in kdc_get_ticket_endtime() could be
819f75
negative if the requested end time is far in the future, causing the
819f75
function to yield an incorrect result.  (With the new larger value of
819f75
kdc_infinity, this could specifically happen if a KDC-REQ contains a
819f75
zero till field.)  Cap the interval at the maximum valid value.
819f75
Reported by Weijun Wang.
819f75
819f75
Avoid delta comparisons in favor of timestamp comparions in
819f75
krb5int_validate_times(), ksu's krb5_check_exp(), and clockskew
819f75
checks.
819f75
819f75
Also use a y2038-safe timestamp comparison in set_request_times() when
819f75
comparing the requested renewable end time to the requested ticket end
819f75
time.
819f75
819f75
ticket: 8352
819f75
(cherry picked from commit 54e58755368b58ba5894a14c1d02626da42d8003)
819f75
---
819f75
 src/clients/ksu/ccache.c       | 2 +-
819f75
 src/include/k5-int.h           | 7 +++++++
819f75
 src/kdc/kdc_util.c             | 7 ++++++-
819f75
 src/kdc/replay.c               | 2 +-
819f75
 src/kdc/t_replay.c             | 2 +-
819f75
 src/lib/krb5/krb/gc_via_tkt.c  | 4 ++--
819f75
 src/lib/krb5/krb/get_in_tkt.c  | 6 +++---
819f75
 src/lib/krb5/krb/int-proto.h   | 3 ---
819f75
 src/lib/krb5/krb/valid_times.c | 4 ++--
819f75
 src/lib/krb5/os/timeofday.c    | 2 +-
819f75
 10 files changed, 24 insertions(+), 15 deletions(-)
819f75
819f75
diff --git a/src/clients/ksu/ccache.c b/src/clients/ksu/ccache.c
819f75
index 236313b7b..2a99521d4 100644
819f75
--- a/src/clients/ksu/ccache.c
819f75
+++ b/src/clients/ksu/ccache.c
819f75
@@ -282,7 +282,7 @@ krb5_error_code krb5_check_exp(context, tkt_time)
819f75
 
819f75
     }
819f75
 
819f75
-    if (ts_delta(currenttime, tkt_time.endtime) > context->clockskew) {
819f75
+    if (ts_after(currenttime, ts_incr(tkt_time.endtime, context->clockskew))) {
819f75
         retval = KRB5KRB_AP_ERR_TKT_EXPIRED ;
819f75
         return retval;
819f75
     }
819f75
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
819f75
index 39ffb9568..e31004a7c 100644
819f75
--- a/src/include/k5-int.h
819f75
+++ b/src/include/k5-int.h
819f75
@@ -2386,6 +2386,13 @@ ts_after(krb5_timestamp a, krb5_timestamp b)
819f75
     return (uint32_t)a > (uint32_t)b;
819f75
 }
819f75
 
819f75
+/* Return true if a and b are within d seconds. */
819f75
+static inline krb5_boolean
819f75
+ts_within(krb5_timestamp a, krb5_timestamp b, krb5_deltat d)
819f75
+{
819f75
+    return !ts_after(a, ts_incr(b, d)) && !ts_after(b, ts_incr(a, d));
819f75
+}
819f75
+
819f75
 krb5_error_code KRB5_CALLCONV
819f75
 krb5_get_credentials_for_user(krb5_context context, krb5_flags options,
819f75
                               krb5_ccache ccache,
819f75
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
819f75
index 5455e2a67..770163b94 100644
819f75
--- a/src/kdc/kdc_util.c
819f75
+++ b/src/kdc/kdc_util.c
819f75
@@ -1759,14 +1759,19 @@ kdc_get_ticket_endtime(kdc_realm_t *kdc_active_realm,
819f75
                        krb5_db_entry *server,
819f75
                        krb5_timestamp *out_endtime)
819f75
 {
819f75
-    krb5_timestamp until, life;
819f75
+    krb5_timestamp until;
819f75
+    krb5_deltat life;
819f75
 
819f75
     if (till == 0)
819f75
         till = kdc_infinity;
819f75
 
819f75
     until = ts_min(till, endtime);
819f75
 
819f75
+    /* Determine the requested lifetime, capped at the maximum valid time
819f75
+     * interval. */
819f75
     life = ts_delta(until, starttime);
819f75
+    if (ts_after(until, starttime) && life < 0)
819f75
+        life = INT32_MAX;
819f75
 
819f75
     if (client != NULL && client->max_life != 0)
819f75
         life = min(life, client->max_life);
819f75
diff --git a/src/kdc/replay.c b/src/kdc/replay.c
819f75
index fab39cf88..caca783bf 100644
819f75
--- a/src/kdc/replay.c
819f75
+++ b/src/kdc/replay.c
819f75
@@ -61,7 +61,7 @@ static size_t total_size = 0;
819f75
 static krb5_ui_4 seed;
819f75
 
819f75
 #define STALE_TIME      (2*60)            /* two minutes */
819f75
-#define STALE(ptr, now) (labs(ts_delta((ptr)->timein, now)) >= STALE_TIME)
819f75
+#define STALE(ptr, now) (ts_after(now, ts_incr((ptr)->timein, STALE_TIME)))
819f75
 
819f75
 /* Return x rotated to the left by r bits. */
819f75
 static inline krb5_ui_4
819f75
diff --git a/src/kdc/t_replay.c b/src/kdc/t_replay.c
819f75
index 1442e0e8c..bb7e2faff 100644
819f75
--- a/src/kdc/t_replay.c
819f75
+++ b/src/kdc/t_replay.c
819f75
@@ -903,7 +903,7 @@ test_kdc_insert_lookaside_cache_expire(void **state)
819f75
     assert_non_null(e);
819f75
     e->num_hits = 5;
819f75
 
819f75
-    time_return(STALE_TIME, 0);
819f75
+    time_return(STALE_TIME + 1, 0);
819f75
     kdc_insert_lookaside(context, &req2, NULL);
819f75
 
819f75
     assert_null(K5_LIST_FIRST(&hash_table[req_hash1]));
819f75
diff --git a/src/lib/krb5/krb/gc_via_tkt.c b/src/lib/krb5/krb/gc_via_tkt.c
819f75
index cf1ea361f..5b9bb9573 100644
819f75
--- a/src/lib/krb5/krb/gc_via_tkt.c
819f75
+++ b/src/lib/krb5/krb/gc_via_tkt.c
819f75
@@ -306,8 +306,8 @@ krb5int_process_tgs_reply(krb5_context context,
819f75
         goto cleanup;
819f75
 
819f75
     if (!in_cred->times.starttime &&
819f75
-        !in_clock_skew(context, dec_rep->enc_part2->times.starttime,
819f75
-                       timestamp)) {
819f75
+        !ts_within(dec_rep->enc_part2->times.starttime, timestamp,
819f75
+                   context->clockskew)) {
819f75
         retval = KRB5_KDCREP_SKEW;
819f75
         goto cleanup;
819f75
     }
819f75
diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
819f75
index 7178bd87b..ed15550f0 100644
819f75
--- a/src/lib/krb5/krb/get_in_tkt.c
819f75
+++ b/src/lib/krb5/krb/get_in_tkt.c
819f75
@@ -269,8 +269,8 @@ verify_as_reply(krb5_context            context,
819f75
             return retval;
819f75
     } else {
819f75
         if ((request->from == 0) &&
819f75
-            !in_clock_skew(context, as_reply->enc_part2->times.starttime,
819f75
-                           time_now))
819f75
+            !ts_within(as_reply->enc_part2->times.starttime, time_now,
819f75
+                       context->clockskew))
819f75
             return (KRB5_KDCREP_SKEW);
819f75
     }
819f75
     return 0;
819f75
@@ -781,7 +781,7 @@ set_request_times(krb5_context context, krb5_init_creds_context ctx)
819f75
     if (ctx->renew_life > 0) {
819f75
         /* Don't ask for a smaller renewable time than the lifetime. */
819f75
         ctx->request->rtime = ts_incr(from, ctx->renew_life);
819f75
-        if (ctx->request->rtime < ctx->request->till)
819f75
+        if (ts_after(ctx->request->till, ctx->request->rtime))
819f75
             ctx->request->rtime = ctx->request->till;
819f75
         ctx->request->kdc_options &= ~KDC_OPT_RENEWABLE_OK;
819f75
     } else {
819f75
diff --git a/src/lib/krb5/krb/int-proto.h b/src/lib/krb5/krb/int-proto.h
819f75
index 48bd9f8f7..9c746d05b 100644
819f75
--- a/src/lib/krb5/krb/int-proto.h
819f75
+++ b/src/lib/krb5/krb/int-proto.h
819f75
@@ -83,9 +83,6 @@ krb5int_construct_matching_creds(krb5_context context, krb5_flags options,
819f75
                                  krb5_creds *in_creds, krb5_creds *mcreds,
819f75
                                  krb5_flags *fields);
819f75
 
819f75
-#define in_clock_skew(context, date, now)               \
819f75
-    (labs(ts_delta(date, now)) < (context)->clockskew)
819f75
-
819f75
 #define IS_TGS_PRINC(p) ((p)->length == 2 &&                            \
819f75
                          data_eq_string((p)->data[0], KRB5_TGS_NAME))
819f75
 
819f75
diff --git a/src/lib/krb5/krb/valid_times.c b/src/lib/krb5/krb/valid_times.c
819f75
index 9e509b2dd..294761a88 100644
819f75
--- a/src/lib/krb5/krb/valid_times.c
819f75
+++ b/src/lib/krb5/krb/valid_times.c
819f75
@@ -47,10 +47,10 @@ krb5int_validate_times(krb5_context context, krb5_ticket_times *times)
819f75
     else
819f75
         starttime = times->authtime;
819f75
 
819f75
-    if (ts_delta(starttime, currenttime) > context->clockskew)
819f75
+    if (ts_after(starttime, ts_incr(currenttime, context->clockskew)))
819f75
         return KRB5KRB_AP_ERR_TKT_NYV;  /* ticket not yet valid */
819f75
 
819f75
-    if (ts_delta(currenttime, times->endtime) > context->clockskew)
819f75
+    if (ts_after(currenttime, ts_incr(times->endtime, context->clockskew)))
819f75
         return KRB5KRB_AP_ERR_TKT_EXPIRED; /* ticket expired */
819f75
 
819f75
     return 0;
819f75
diff --git a/src/lib/krb5/os/timeofday.c b/src/lib/krb5/os/timeofday.c
819f75
index 887f24c22..d4e36b1c7 100644
819f75
--- a/src/lib/krb5/os/timeofday.c
819f75
+++ b/src/lib/krb5/os/timeofday.c
819f75
@@ -60,7 +60,7 @@ krb5_check_clockskew(krb5_context context, krb5_timestamp date)
819f75
     retval = krb5_timeofday(context, &currenttime);
819f75
     if (retval)
819f75
         return retval;
819f75
-    if (labs(ts_delta(date, currenttime)) >= context->clockskew)
819f75
+    if (!ts_within(date, currenttime, context->clockskew))
819f75
         return KRB5KRB_AP_ERR_SKEW;
819f75
 
819f75
     return 0;