krb5 commit: Make timestamp manipulations y2038-safe

Greg Hudson ghudson at mit.edu
Tue May 16 12:08:28 EDT 2017


https://github.com/krb5/krb5/commit/a9cbbf0899f270fbb14f63ffbed1b6d542333641
commit a9cbbf0899f270fbb14f63ffbed1b6d542333641
Author: Greg Hudson <ghudson at mit.edu>
Date:   Sat Apr 22 12:52:17 2017 -0400

    Make timestamp manipulations y2038-safe
    
    Wherever we manipulate krb5_timestamp values using arithmetic,
    comparison operations, or conversion to time_t, use the new helper
    functions in k5-int.h to ensure that the operations work after y2038
    and do not exhibit undefined behavior.  (Relying on
    implementation-defined conversion to signed values is okay as we test
    that in configure.in.)
    
    In printf format strings, use %u instead of signed types.  When
    exporting creds with k5_json_array_fmt(), use a long long so that
    timestamps after y2038 aren't marshalled as negative numbers.  When
    parsing timestamps in test programs, use atoll() instead of atol() so
    that positive timestamps after y2038 can be used as input.
    
    In ksu and klist, make printtime() take a krb5_timestamp parameter to
    avoid an unnecessary conversion to time_t and back.
    
    As Leash does not use k5-int.h, use time_t values internally and
    safely convert from libkrb5 timestamp values.
    
    ticket: 8352

 src/clients/kinit/kinit.c                          |    2 +-
 src/clients/klist/klist.c                          |   22 ++++-------
 src/clients/ksu/ccache.c                           |   22 +++--------
 src/clients/ksu/ksu.h                              |    2 +-
 src/kadmin/cli/getdate.y                           |    2 +-
 src/kadmin/cli/kadmin.c                            |    5 +-
 src/kadmin/dbutil/dump.c                           |   27 +++++++------
 src/kadmin/dbutil/kdb5_mkey.c                      |    6 +-
 src/kadmin/dbutil/tabdump.c                        |    2 +-
 src/kadmin/testing/util/tcl_kadm5.c                |   12 +++---
 src/kdc/do_as_req.c                                |    2 +-
 src/kdc/do_tgs_req.c                               |    6 +-
 src/kdc/extern.c                                   |    4 +-
 src/kdc/fast_util.c                                |    4 +-
 src/kdc/kdc_log.c                                  |   14 +++---
 src/kdc/kdc_util.c                                 |   20 +++++-----
 src/kdc/kdc_util.h                                 |    2 +
 src/kdc/replay.c                                   |    2 +-
 src/kdc/tgs_policy.c                               |    7 ++-
 src/lib/gssapi/krb5/accept_sec_context.c           |    8 ++-
 src/lib/gssapi/krb5/acquire_cred.c                 |   13 ++++--
 src/lib/gssapi/krb5/context_time.c                 |    2 +-
 src/lib/gssapi/krb5/export_cred.c                  |    5 +-
 src/lib/gssapi/krb5/iakerb.c                       |    4 +-
 src/lib/gssapi/krb5/init_sec_context.c             |    9 ++--
 src/lib/gssapi/krb5/inq_context.c                  |    2 +-
 src/lib/gssapi/krb5/inq_cred.c                     |    5 +-
 src/lib/gssapi/krb5/s4u_gss_glue.c                 |    2 +-
 src/lib/kadm5/chpass_util.c                        |    8 +---
 src/lib/kadm5/srv/server_acl.c                     |    5 +-
 src/lib/kadm5/srv/svr_principal.c                  |   12 +++---
 src/lib/kdb/kdb5.c                                 |    2 +-
 src/lib/krb5/asn.1/asn1_k_encode.c                 |    3 +-
 src/lib/krb5/ccache/cc_keyring.c                   |   14 ++++---
 src/lib/krb5/ccache/cc_memory.c                    |    4 +-
 src/lib/krb5/ccache/cc_retr.c                      |    4 +-
 src/lib/krb5/ccache/ccapi/stdcc_util.c             |   40 ++++++++++----------
 src/lib/krb5/ccache/cccursor.c                     |    2 +-
 src/lib/krb5/keytab/kt_file.c                      |    6 ++-
 src/lib/krb5/krb/gc_via_tkt.c                      |    7 ++-
 src/lib/krb5/krb/get_creds.c                       |    2 +-
 src/lib/krb5/krb/get_in_tkt.c                      |   38 +++++-------------
 src/lib/krb5/krb/gic_pwd.c                         |    4 +-
 src/lib/krb5/krb/int-proto.h                       |    2 +-
 src/lib/krb5/krb/pac.c                             |    2 +-
 src/lib/krb5/krb/str_conv.c                        |    4 +-
 src/lib/krb5/krb/t_kerb.c                          |   12 +-----
 src/lib/krb5/krb/valid_times.c                     |    4 +-
 src/lib/krb5/krb/vfy_increds.c                     |    2 +-
 src/lib/krb5/os/timeofday.c                        |    2 +-
 src/lib/krb5/os/toffset.c                          |    2 +-
 src/lib/krb5/os/ustime.c                           |    6 +-
 src/lib/krb5/rcache/rc_dfl.c                       |    3 +-
 src/lib/krb5/rcache/t_replay.c                     |    8 ++--
 src/plugins/kdb/db2/lockout.c                      |    8 ++--
 src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c |    2 +-
 src/plugins/kdb/ldap/libkdb_ldap/lockout.c         |    8 ++--
 src/windows/cns/tktlist.c                          |   10 +++--
 src/windows/include/leashwin.h                     |   12 +++---
 src/windows/leash/KrbListTickets.cpp               |   12 +++---
 src/windows/leash/LeashView.cpp                    |   22 +++++-----
 src/windows/leashdll/lshfunc.c                     |    2 +-
 src/windows/ms2mit/ms2mit.c                        |    2 +-
 63 files changed, 232 insertions(+), 257 deletions(-)

diff --git a/src/clients/kinit/kinit.c b/src/clients/kinit/kinit.c
index f1cd1b7..50065e3 100644
--- a/src/clients/kinit/kinit.c
+++ b/src/clients/kinit/kinit.c
@@ -318,7 +318,7 @@ parse_options(argc, argv, opts)
                     fprintf(stderr, _("Bad start time value %s\n"), optarg);
                     errflg++;
                 } else {
-                    opts->starttime = abs_starttime - time(0);
+                    opts->starttime = ts_delta(abs_starttime, time(NULL));
                 }
             }
             break;
diff --git a/src/clients/klist/klist.c b/src/clients/klist/klist.c
index ba19788..ffeecc3 100644
--- a/src/clients/klist/klist.c
+++ b/src/clients/klist/klist.c
@@ -72,7 +72,7 @@ void do_ccache_name (char *);
 int show_ccache (krb5_ccache);
 int check_ccache (krb5_ccache);
 void do_keytab (char *);
-void printtime (time_t);
+void printtime (krb5_timestamp);
 void one_addr (krb5_address *);
 void fillit (FILE *, unsigned int, int);
 
@@ -538,10 +538,10 @@ check_ccache(krb5_ccache cache)
     while (!(ret = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
         if (is_local_tgt(creds.server, &princ->realm)) {
             found_tgt = TRUE;
-            if (creds.times.endtime > now)
+            if (ts_after(creds.times.endtime, now))
                 found_current_tgt = TRUE;
         } else if (!krb5_is_config_principal(kcontext, creds.server) &&
-                   creds.times.endtime > now) {
+                   ts_after(creds.times.endtime, now)) {
             found_current_cred = TRUE;
         }
         krb5_free_cred_contents(kcontext, &creds);
@@ -623,19 +623,13 @@ flags_string(cred)
 }
 
 void
-printtime(tv)
-    time_t tv;
+printtime(krb5_timestamp ts)
 {
-    char timestring[BUFSIZ];
-    char fill;
-
-    fill = ' ';
-    if (!krb5_timestamp_to_sfstring((krb5_timestamp) tv,
-                                    timestring,
-                                    timestamp_width+1,
-                                    &fill)) {
+    char timestring[BUFSIZ], fill = ' ';
+
+    if (!krb5_timestamp_to_sfstring(ts, timestring, timestamp_width + 1,
+                                    &fill))
         printf("%s", timestring);
-    }
 }
 
 static void
diff --git a/src/clients/ksu/ccache.c b/src/clients/ksu/ccache.c
index a0736f2..236313b 100644
--- a/src/clients/ksu/ccache.c
+++ b/src/clients/ksu/ccache.c
@@ -278,11 +278,11 @@ krb5_error_code krb5_check_exp(context, tkt_time)
                 context->clockskew);
 
         fprintf(stderr,"krb5_check_exp: currenttime - endtime %d \n",
-                (currenttime - tkt_time.endtime ));
+                ts_delta(currenttime, tkt_time.endtime));
 
     }
 
-    if (currenttime - tkt_time.endtime > context->clockskew){
+    if (ts_delta(currenttime, tkt_time.endtime) > context->clockskew) {
         retval = KRB5KRB_AP_ERR_TKT_EXPIRED ;
         return retval;
     }
@@ -323,21 +323,11 @@ char *flags_string(cred)
     return(buf);
 }
 
-void printtime(tv)
-    time_t tv;
+void printtime(krb5_timestamp ts)
 {
-    char fmtbuf[18];
-    char fill;
-    krb5_timestamp tstamp;
-
-    /* XXXX ASSUMES sizeof(krb5_timestamp) >= sizeof(time_t) */
-    (void) localtime((time_t *)&tv);
-    tstamp = tv;
-    fill = ' ';
-    if (!krb5_timestamp_to_sfstring(tstamp,
-                                    fmtbuf,
-                                    sizeof(fmtbuf),
-                                    &fill))
+    char fmtbuf[18], fill = ' ';
+
+    if (!krb5_timestamp_to_sfstring(ts, fmtbuf, sizeof(fmtbuf), &fill))
         printf("%s", fmtbuf);
 }
 
diff --git a/src/clients/ksu/ksu.h b/src/clients/ksu/ksu.h
index ee8e9d6..3bf0bd4 100644
--- a/src/clients/ksu/ksu.h
+++ b/src/clients/ksu/ksu.h
@@ -150,7 +150,7 @@ extern krb5_boolean krb5_find_princ_in_cred_list
 extern krb5_error_code krb5_find_princ_in_cache
 (krb5_context, krb5_ccache, krb5_principal, krb5_boolean *);
 
-extern void printtime (time_t);
+extern void printtime (krb5_timestamp);
 
 /* authorization.c */
 extern krb5_boolean fowner (FILE *, uid_t);
diff --git a/src/kadmin/cli/getdate.y b/src/kadmin/cli/getdate.y
index 4bfae66..059f112 100644
--- a/src/kadmin/cli/getdate.y
+++ b/src/kadmin/cli/getdate.y
@@ -118,7 +118,7 @@ static int getdate_yyerror (char *);
 
 
 #define EPOCH		1970
-#define EPOCH_END	2038 /* assumes 32 bits */
+#define EPOCH_END	2106 /* assumes unsigned 32-bit range */
 #define HOUR(x)		((time_t)(x) * 60)
 #define SECSPERDAY	(24L * 60L * 60L)
 
diff --git a/src/kadmin/cli/kadmin.c b/src/kadmin/cli/kadmin.c
index c53c677..aee5c83 100644
--- a/src/kadmin/cli/kadmin.c
+++ b/src/kadmin/cli/kadmin.c
@@ -31,8 +31,7 @@
  * library */
 
 /* for "_" macro */
-#include "k5-platform.h"
-#include <krb5.h>
+#include "k5-int.h"
 #include <kadm5/admin.h>
 #include <adm_proto.h>
 #include <errno.h>
@@ -144,8 +143,8 @@ strdate(krb5_timestamp when)
 {
     struct tm *tm;
     static char out[40];
+    time_t lcltim = ts2tt(when);
 
-    time_t lcltim = when;
     tm = localtime(&lcltim);
     strftime(out, sizeof(out), "%a %b %d %H:%M:%S %Z %Y", tm);
     return out;
diff --git a/src/kadmin/dbutil/dump.c b/src/kadmin/dbutil/dump.c
index 9f5c3d1..aca136f 100644
--- a/src/kadmin/dbutil/dump.c
+++ b/src/kadmin/dbutil/dump.c
@@ -370,11 +370,12 @@ k5beta7_common(krb5_context context, krb5_db_entry *entry,
     fprintf(fp, "princ\t%d\t%lu\t%d\t%d\t%d\t%s\t", (int)entry->len,
             (unsigned long)strlen(name), counter, (int)entry->n_key_data,
             (int)entry->e_length, name);
-    fprintf(fp, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d", entry->attributes,
-            entry->max_life, entry->max_renewable_life, entry->expiration,
-            entry->pw_expiration,
-            omit_nra ? 0 : entry->last_success,
-            omit_nra ? 0 : entry->last_failed,
+    fprintf(fp, "%d\t%d\t%d\t%u\t%u\t%u\t%u\t%d", entry->attributes,
+            entry->max_life, entry->max_renewable_life,
+            (unsigned int)entry->expiration,
+            (unsigned int)entry->pw_expiration,
+            (unsigned int)(omit_nra ? 0 : entry->last_success),
+            (unsigned int)(omit_nra ? 0 : entry->last_failed),
             omit_nra ? 0 : entry->fail_auth_count);
 
     /* Write out tagged data. */
@@ -712,7 +713,7 @@ process_k5beta7_princ(krb5_context context, const char *fname, FILE *filep,
 {
     int retval, nread, i, j;
     krb5_db_entry *dbentry;
-    int t1, t2, t3, t4, t5, t6, t7;
+    int t1, t2, t3, t4;
     unsigned int u1, u2, u3, u4, u5;
     char *name = NULL;
     krb5_key_data *kp = NULL, *kd;
@@ -772,8 +773,8 @@ process_k5beta7_princ(krb5_context context, const char *fname, FILE *filep,
     }
 
     /* Get the fixed principal attributes */
-    nread = fscanf(filep, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t",
-                   &t1, &t2, &t3, &t4, &t5, &t6, &t7, &u1);
+    nread = fscanf(filep, "%d\t%d\t%d\t%u\t%u\t%d\t%d\t%d\t",
+                   &t1, &t2, &t3, &u1, &u2, &u3, &u4, &u5);
     if (nread != 8) {
         load_err(fname, *linenop, _("cannot read principal attributes"));
         goto fail;
@@ -781,11 +782,11 @@ process_k5beta7_princ(krb5_context context, const char *fname, FILE *filep,
     dbentry->attributes = t1;
     dbentry->max_life = t2;
     dbentry->max_renewable_life = t3;
-    dbentry->expiration = t4;
-    dbentry->pw_expiration = t5;
-    dbentry->last_success = t6;
-    dbentry->last_failed = t7;
-    dbentry->fail_auth_count = u1;
+    dbentry->expiration = u1;
+    dbentry->pw_expiration = u2;
+    dbentry->last_success = u3;
+    dbentry->last_failed = u4;
+    dbentry->fail_auth_count = u5;
     dbentry->mask = KADM5_LOAD | KADM5_PRINCIPAL | KADM5_ATTRIBUTES |
         KADM5_MAX_LIFE | KADM5_MAX_RLIFE |
         KADM5_PRINC_EXPIRE_TIME | KADM5_LAST_SUCCESS |
diff --git a/src/kadmin/dbutil/kdb5_mkey.c b/src/kadmin/dbutil/kdb5_mkey.c
index 7df8cbc..2efe317 100644
--- a/src/kadmin/dbutil/kdb5_mkey.c
+++ b/src/kadmin/dbutil/kdb5_mkey.c
@@ -44,8 +44,8 @@ static char *strdate(krb5_timestamp when)
 {
     struct tm *tm;
     static char out[40];
+    time_t lcltim = ts2tt(when);
 
-    time_t lcltim = when;
     tm = localtime(&lcltim);
     strftime(out, sizeof(out), "%a %b %d %H:%M:%S %Z %Y", tm);
     return out;
@@ -481,7 +481,7 @@ kdb5_use_mkey(int argc, char *argv[])
                  cur_actkvno != NULL;
                  prev_actkvno = cur_actkvno, cur_actkvno = cur_actkvno->next) {
 
-                if (new_actkvno->act_time < cur_actkvno->act_time) {
+                if (ts_after(cur_actkvno->act_time, new_actkvno->act_time)) {
                     if (prev_actkvno) {
                         prev_actkvno->next = new_actkvno;
                         new_actkvno->next = cur_actkvno;
@@ -499,7 +499,7 @@ kdb5_use_mkey(int argc, char *argv[])
         }
     }
 
-    if (actkvno_list->act_time > now) {
+    if (ts_after(actkvno_list->act_time, now)) {
         com_err(progname, EINVAL,
                 _("there must be one master key currently active"));
         exit_status++;
diff --git a/src/kadmin/dbutil/tabdump.c b/src/kadmin/dbutil/tabdump.c
index 69a3482..fb36b06 100644
--- a/src/kadmin/dbutil/tabdump.c
+++ b/src/kadmin/dbutil/tabdump.c
@@ -148,7 +148,7 @@ write_date_iso(struct rec_args *args, krb5_timestamp when)
     struct tm *tm = NULL;
     struct rechandle *h = args->rh;
 
-    t = when;
+    t = ts2tt(when);
     tm = gmtime(&t);
     if (tm == NULL) {
         errno = EINVAL;
diff --git a/src/kadmin/testing/util/tcl_kadm5.c b/src/kadmin/testing/util/tcl_kadm5.c
index a4997c6..9dde579 100644
--- a/src/kadmin/testing/util/tcl_kadm5.c
+++ b/src/kadmin/testing/util/tcl_kadm5.c
@@ -697,13 +697,13 @@ static Tcl_DString *unparse_principal_ent(kadm5_principal_ent_t princ,
     } else
         Tcl_DStringAppendElement(str, "null");
 
-    sprintf(buf, "%d", princ->princ_expire_time);
+    sprintf(buf, "%u", (unsigned int)princ->princ_expire_time);
     Tcl_DStringAppendElement(str, buf);
 
-    sprintf(buf, "%d", princ->last_pwd_change);
+    sprintf(buf, "%u", (unsigned int)princ->last_pwd_change);
     Tcl_DStringAppendElement(str, buf);
 
-    sprintf(buf, "%d", princ->pw_expiration);
+    sprintf(buf, "%u", (unsigned int)princ->pw_expiration);
     Tcl_DStringAppendElement(str, buf);
 
     sprintf(buf, "%d", princ->max_life);
@@ -722,7 +722,7 @@ static Tcl_DString *unparse_principal_ent(kadm5_principal_ent_t princ,
     } else
         Tcl_DStringAppendElement(str, "null");
 
-    sprintf(buf, "%d", princ->mod_date);
+    sprintf(buf, "%u", (unsigned int)princ->mod_date);
     Tcl_DStringAppendElement(str, buf);
 
     if (mask & KADM5_ATTRIBUTES) {
@@ -758,10 +758,10 @@ static Tcl_DString *unparse_principal_ent(kadm5_principal_ent_t princ,
     sprintf(buf, "%d", princ->max_renewable_life);
     Tcl_DStringAppendElement(str, buf);
 
-    sprintf(buf, "%d", princ->last_success);
+    sprintf(buf, "%u", (unsigned int)princ->last_success);
     Tcl_DStringAppendElement(str, buf);
 
-    sprintf(buf, "%d", princ->last_failed);
+    sprintf(buf, "%u", (unsigned int)princ->last_failed);
     Tcl_DStringAppendElement(str, buf);
 
     sprintf(buf, "%d", princ->fail_auth_count);
diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c
index 611c69c..3be9ca6 100644
--- a/src/kdc/do_as_req.c
+++ b/src/kdc/do_as_req.c
@@ -87,7 +87,7 @@ get_key_exp(krb5_db_entry *entry)
         return entry->pw_expiration;
     if (entry->pw_expiration == 0)
         return entry->expiration;
-    return min(entry->expiration, entry->pw_expiration);
+    return ts_min(entry->expiration, entry->pw_expiration);
 }
 
 /*
diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c
index 81f9209..cdc79ad 100644
--- a/src/kdc/do_tgs_req.c
+++ b/src/kdc/do_tgs_req.c
@@ -500,12 +500,12 @@ process_tgs_req(struct server_handle *handle, krb5_data *pkt,
 
         old_starttime = enc_tkt_reply.times.starttime ?
             enc_tkt_reply.times.starttime : enc_tkt_reply.times.authtime;
-        old_life = enc_tkt_reply.times.endtime - old_starttime;
+        old_life = ts_delta(enc_tkt_reply.times.endtime, old_starttime);
 
         enc_tkt_reply.times.starttime = kdc_time;
         enc_tkt_reply.times.endtime =
-            min(header_ticket->enc_part2->times.renew_till,
-                kdc_time + old_life);
+            ts_min(header_ticket->enc_part2->times.renew_till,
+                   ts_incr(kdc_time, old_life));
     } else {
         /* not a renew request */
         enc_tkt_reply.times.starttime = kdc_time;
diff --git a/src/kdc/extern.c b/src/kdc/extern.c
index fe62749..84b5c6a 100644
--- a/src/kdc/extern.c
+++ b/src/kdc/extern.c
@@ -37,6 +37,8 @@
 kdc_realm_t     **kdc_realmlist = (kdc_realm_t **) NULL;
 int             kdc_numrealms = 0;
 krb5_data empty_string = {0, 0, ""};
-krb5_timestamp kdc_infinity = KRB5_INT32_MAX; /* XXX */
 krb5_keyblock   psr_key;
 krb5_int32      max_dgram_reply_size = MAX_DGRAM_SIZE;
+
+/* With ts_after(), this is the largest timestamp value. */
+krb5_timestamp kdc_infinity = -1;
diff --git a/src/kdc/fast_util.c b/src/kdc/fast_util.c
index 9df9402..e05107e 100644
--- a/src/kdc/fast_util.c
+++ b/src/kdc/fast_util.c
@@ -607,7 +607,7 @@ kdc_fast_read_cookie(krb5_context context, struct kdc_request_state *state,
     ret = krb5_timeofday(context, &now);
     if (ret)
         goto cleanup;
-    if (now - COOKIE_LIFETIME > cookie->time) {
+    if (ts2tt(now) > cookie->time + COOKIE_LIFETIME) {
         /* Don't accept the cookie contents.  Only return an error if the
          * cookie is relevant to the request. */
         if (is_relevant(cookie->data, req->padata))
@@ -700,7 +700,7 @@ kdc_fast_make_cookie(krb5_context context, struct kdc_request_state *state,
     ret = krb5_timeofday(context, &now);
     if (ret)
         goto cleanup;
-    cookie.time = now;
+    cookie.time = ts2tt(now);
     cookie.data = contents;
     ret = encode_krb5_secure_cookie(&cookie, &der_cookie);
     if (ret)
diff --git a/src/kdc/kdc_log.c b/src/kdc/kdc_log.c
index 94a2a1c..c044a35 100644
--- a/src/kdc/kdc_log.c
+++ b/src/kdc/kdc_log.c
@@ -79,9 +79,9 @@ log_as_req(krb5_context context, const krb5_fulladdr *from,
         /* success */
         char rep_etypestr[128];
         rep_etypes2str(rep_etypestr, sizeof(rep_etypestr), reply);
-        krb5_klog_syslog(LOG_INFO, _("AS_REQ (%s) %s: ISSUE: authtime %d, %s, "
+        krb5_klog_syslog(LOG_INFO, _("AS_REQ (%s) %s: ISSUE: authtime %u, %s, "
                                      "%s for %s"),
-                         ktypestr, fromstring, authtime,
+                         ktypestr, fromstring, (unsigned int)authtime,
                          rep_etypestr, cname2, sname2);
     } else {
         /* fail */
@@ -156,10 +156,10 @@ log_tgs_req(krb5_context ctx, const krb5_fulladdr *from,
        name (useful), and doesn't log ktypestr (probably not
        important).  */
     if (errcode != KRB5KDC_ERR_SERVER_NOMATCH) {
-        krb5_klog_syslog(LOG_INFO, _("TGS_REQ (%s) %s: %s: authtime %d, %s%s "
+        krb5_klog_syslog(LOG_INFO, _("TGS_REQ (%s) %s: %s: authtime %u, %s%s "
                                      "%s for %s%s%s"),
-                         ktypestr, fromstring, status, authtime, rep_etypestr,
-                         !errcode ? "," : "", logcname, logsname,
+                         ktypestr, fromstring, status, (unsigned int)authtime,
+                         rep_etypestr, !errcode ? "," : "", logcname, logsname,
                          errcode ? ", " : "", errcode ? emsg : "");
         if (isflagset(c_flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION))
             krb5_klog_syslog(LOG_INFO,
@@ -171,9 +171,9 @@ log_tgs_req(krb5_context ctx, const krb5_fulladdr *from,
                              logaltcname);
 
     } else
-        krb5_klog_syslog(LOG_INFO, _("TGS_REQ %s: %s: authtime %d, %s for %s, "
+        krb5_klog_syslog(LOG_INFO, _("TGS_REQ %s: %s: authtime %u, %s for %s, "
                                      "2nd tkt client %s"),
-                         fromstring, status, authtime,
+                         fromstring, status, (unsigned int)authtime,
                          logcname, logsname, logaltcname);
 
     /* OpenSolaris: audit_krb5kdc_tgs_req(...)  or
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
index 29f9dbb..778a629 100644
--- a/src/kdc/kdc_util.c
+++ b/src/kdc/kdc_util.c
@@ -654,7 +654,7 @@ validate_as_request(kdc_realm_t *kdc_active_realm,
     }
 
     /* The client must not be expired */
-    if (client.expiration && client.expiration < kdc_time) {
+    if (client.expiration && ts_after(kdc_time, client.expiration)) {
         *status = "CLIENT EXPIRED";
         if (vague_errors)
             return(KRB_ERR_GENERIC);
@@ -664,7 +664,7 @@ validate_as_request(kdc_realm_t *kdc_active_realm,
 
     /* The client's password must not be expired, unless the server is
        a KRB5_KDC_PWCHANGE_SERVICE. */
-    if (client.pw_expiration && client.pw_expiration < kdc_time &&
+    if (client.pw_expiration && ts_after(kdc_time, client.pw_expiration) &&
         !isflagset(server.attributes, KRB5_KDB_PWCHANGE_SERVICE)) {
         *status = "CLIENT KEY EXPIRED";
         if (vague_errors)
@@ -674,7 +674,7 @@ validate_as_request(kdc_realm_t *kdc_active_realm,
     }
 
     /* The server must not be expired */
-    if (server.expiration && server.expiration < kdc_time) {
+    if (server.expiration && ts_after(kdc_time, server.expiration)) {
         *status = "SERVICE EXPIRED";
         return(KDC_ERR_SERVICE_EXP);
     }
@@ -1765,9 +1765,9 @@ kdc_get_ticket_endtime(kdc_realm_t *kdc_active_realm,
     if (till == 0)
         till = kdc_infinity;
 
-    until = min(till, endtime);
+    until = ts_min(till, endtime);
 
-    life = until - starttime;
+    life = ts_delta(until, starttime);
 
     if (client != NULL && client->max_life != 0)
         life = min(life, client->max_life);
@@ -1776,7 +1776,7 @@ kdc_get_ticket_endtime(kdc_realm_t *kdc_active_realm,
     if (kdc_active_realm->realm_maxlife != 0)
         life = min(life, kdc_active_realm->realm_maxlife);
 
-    *out_endtime = starttime + life;
+    *out_endtime = ts_incr(starttime, life);
 }
 
 /*
@@ -1806,22 +1806,22 @@ kdc_get_ticket_renewtime(kdc_realm_t *realm, krb5_kdc_req *request,
     if (isflagset(request->kdc_options, KDC_OPT_RENEWABLE))
         rtime = request->rtime ? request->rtime : kdc_infinity;
     else if (isflagset(request->kdc_options, KDC_OPT_RENEWABLE_OK) &&
-             tkt->times.endtime < request->till)
+             ts_after(request->till, tkt->times.endtime))
         rtime = request->till;
     else
         return;
 
     /* Truncate it to the allowable renewable time. */
     if (tgt != NULL)
-        rtime = min(rtime, tgt->times.renew_till);
+        rtime = ts_min(rtime, tgt->times.renew_till);
     max_rlife = min(server->max_renewable_life, realm->realm_maxrlife);
     if (client != NULL)
         max_rlife = min(max_rlife, client->max_renewable_life);
-    rtime = min(rtime, tkt->times.starttime + max_rlife);
+    rtime = ts_min(rtime, ts_incr(tkt->times.starttime, max_rlife));
 
     /* Make the ticket renewable if the truncated requested time is larger than
      * the ticket end time. */
-    if (rtime > tkt->times.endtime) {
+    if (ts_after(rtime, tkt->times.endtime)) {
         setflag(tkt->flags, TKT_FLG_RENEWABLE);
         tkt->times.renew_till = rtime;
     }
diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h
index bcf05fc..672f943 100644
--- a/src/kdc/kdc_util.h
+++ b/src/kdc/kdc_util.h
@@ -452,6 +452,8 @@ struct krb5_kdcpreauth_rock_st {
 #define max(a, b)       ((a) > (b) ? (a) : (b))
 #endif
 
+#define ts_min(a, b) (ts_after(a, b) ? (b) : (a))
+
 #define ADDRTYPE2FAMILY(X)                                              \
     ((X) == ADDRTYPE_INET6 ? AF_INET6 : (X) == ADDRTYPE_INET ? AF_INET : -1)
 
diff --git a/src/kdc/replay.c b/src/kdc/replay.c
index 8da7ac1..fab39cf 100644
--- a/src/kdc/replay.c
+++ b/src/kdc/replay.c
@@ -61,7 +61,7 @@ static size_t total_size = 0;
 static krb5_ui_4 seed;
 
 #define STALE_TIME      (2*60)            /* two minutes */
-#define STALE(ptr, now) (abs((ptr)->timein - (now)) >= STALE_TIME)
+#define STALE(ptr, now) (labs(ts_delta((ptr)->timein, now)) >= STALE_TIME)
 
 /* Return x rotated to the left by r bits. */
 static inline krb5_ui_4
diff --git a/src/kdc/tgs_policy.c b/src/kdc/tgs_policy.c
index a30cacc..d0f25d1 100644
--- a/src/kdc/tgs_policy.c
+++ b/src/kdc/tgs_policy.c
@@ -186,7 +186,7 @@ static int
 check_tgs_svc_time(krb5_kdc_req *req, krb5_db_entry server, krb5_ticket *tkt,
                    krb5_timestamp kdc_time, const char **status)
 {
-    if (server.expiration && server.expiration < kdc_time) {
+    if (server.expiration && ts_after(kdc_time, server.expiration)) {
         *status = "SERVICE EXPIRED";
         return KDC_ERR_SERVICE_EXP;
     }
@@ -222,7 +222,7 @@ check_tgs_times(krb5_kdc_req *req, krb5_ticket_times *times,
        KDC time. */
     if (req->kdc_options & KDC_OPT_VALIDATE) {
         starttime = times->starttime ? times->starttime : times->authtime;
-        if (starttime > kdc_time) {
+        if (ts_after(starttime, kdc_time)) {
             *status = "NOT_YET_VALID";
             return KRB_AP_ERR_TKT_NYV;
         }
@@ -231,7 +231,8 @@ check_tgs_times(krb5_kdc_req *req, krb5_ticket_times *times,
      * Check the renew_till time.  The endtime was already
      * been checked in the initial authentication check.
      */
-    if ((req->kdc_options & KDC_OPT_RENEW) && times->renew_till < kdc_time) {
+    if ((req->kdc_options & KDC_OPT_RENEW) &&
+        ts_after(kdc_time, times->renew_till)) {
         *status = "TKT_EXPIRED";
         return KRB_AP_ERR_TKT_EXPIRED;
     }
diff --git a/src/lib/gssapi/krb5/accept_sec_context.c b/src/lib/gssapi/krb5/accept_sec_context.c
index 580d08c..06967aa 100644
--- a/src/lib/gssapi/krb5/accept_sec_context.c
+++ b/src/lib/gssapi/krb5/accept_sec_context.c
@@ -351,8 +351,10 @@ kg_accept_dce(minor_status, context_handle, verifier_cred_handle,
     if (mech_type)
         *mech_type = ctx->mech_used;
 
-    if (time_rec)
-        *time_rec = ctx->krb_times.endtime + ctx->k5_context->clockskew - now;
+    if (time_rec) {
+        *time_rec = ts_delta(ctx->krb_times.endtime, now) +
+            ctx->k5_context->clockskew;
+    }
 
     /* Never return GSS_C_DELEG_FLAG since we don't support DCE credential
      * delegation yet. */
@@ -1146,7 +1148,7 @@ kg_accept_krb5(minor_status, context_handle,
     /* Add the maximum allowable clock skew as a grace period for context
      * expiration, just as we do for the ticket. */
     if (time_rec)
-        *time_rec = ctx->krb_times.endtime + context->clockskew - now;
+        *time_rec = ts_delta(ctx->krb_times.endtime, now) + context->clockskew;
 
     if (ret_flags)
         *ret_flags = ctx->gss_flags;
diff --git a/src/lib/gssapi/krb5/acquire_cred.c b/src/lib/gssapi/krb5/acquire_cred.c
index 03ee25e..362ba9d 100644
--- a/src/lib/gssapi/krb5/acquire_cred.c
+++ b/src/lib/gssapi/krb5/acquire_cred.c
@@ -550,7 +550,7 @@ set_refresh_time(krb5_context context, krb5_ccache ccache,
     char buf[128];
     krb5_data d;
 
-    snprintf(buf, sizeof(buf), "%ld", (long)refresh_time);
+    snprintf(buf, sizeof(buf), "%u", (unsigned int)ts2tt(refresh_time));
     d = string2data(buf);
     (void)krb5_cc_set_config(context, ccache, NULL, KRB5_CC_CONF_REFRESH_TIME,
                              &d);
@@ -566,8 +566,9 @@ kg_cred_time_to_refresh(krb5_context context, krb5_gss_cred_id_rec *cred)
 
     if (krb5_timeofday(context, &now))
         return FALSE;
-    if (cred->refresh_time != 0 && now >= cred->refresh_time) {
-        set_refresh_time(context, cred->ccache, cred->refresh_time + 30);
+    if (cred->refresh_time != 0 && !ts_after(cred->refresh_time, now)) {
+        set_refresh_time(context, cred->ccache,
+                         ts_incr(cred->refresh_time, 30));
         return TRUE;
     }
     return FALSE;
@@ -586,7 +587,8 @@ kg_cred_set_initial_refresh(krb5_context context, krb5_gss_cred_id_rec *cred,
         return;
 
     /* Make a note to refresh these when they are halfway to expired. */
-    refresh = times->starttime + (times->endtime - times->starttime) / 2;
+    refresh = ts_incr(times->starttime,
+                      ts_delta(times->endtime, times->starttime) / 2);
     set_refresh_time(context, cred->ccache, refresh);
 }
 
@@ -848,7 +850,8 @@ acquire_cred_context(krb5_context context, OM_uint32 *minor_status,
                                   GSS_C_NO_NAME);
             if (GSS_ERROR(ret))
                 goto error_out;
-            *time_rec = (cred->expire > now) ? (cred->expire - now) : 0;
+            *time_rec = ts_after(cred->expire, now) ?
+                ts_delta(cred->expire, now) : 0;
             k5_mutex_unlock(&cred->lock);
         }
     }
diff --git a/src/lib/gssapi/krb5/context_time.c b/src/lib/gssapi/krb5/context_time.c
index 4505932..1fdb5a1 100644
--- a/src/lib/gssapi/krb5/context_time.c
+++ b/src/lib/gssapi/krb5/context_time.c
@@ -51,7 +51,7 @@ krb5_gss_context_time(minor_status, context_handle, time_rec)
         return(GSS_S_FAILURE);
     }
 
-    lifetime = ctx->krb_times.endtime - now;
+    lifetime = ts_delta(ctx->krb_times.endtime, now);
     if (!ctx->initiate)
         lifetime += ctx->k5_context->clockskew;
     if (lifetime <= 0) {
diff --git a/src/lib/gssapi/krb5/export_cred.c b/src/lib/gssapi/krb5/export_cred.c
index 652b260..8054e4a 100644
--- a/src/lib/gssapi/krb5/export_cred.c
+++ b/src/lib/gssapi/krb5/export_cred.c
@@ -410,10 +410,11 @@ json_kgcred(krb5_context context, krb5_gss_cred_id_t cred,
     if (ret)
         goto cleanup;
 
-    ret = k5_json_array_fmt(&array, "ivvbbvvvvbiivs", cred->usage, name, imp,
+    ret = k5_json_array_fmt(&array, "ivvbbvvvvbLLvs", cred->usage, name, imp,
                             cred->default_identity, cred->iakerb_mech, keytab,
                             rcache, ccache, ckeytab, cred->have_tgt,
-                            cred->expire, cred->refresh_time, etypes,
+                            (long long)ts2tt(cred->expire),
+                            (long long)ts2tt(cred->refresh_time), etypes,
                             cred->password);
     if (ret)
         goto cleanup;
diff --git a/src/lib/gssapi/krb5/iakerb.c b/src/lib/gssapi/krb5/iakerb.c
index 2dc4d0c..bb1072f 100644
--- a/src/lib/gssapi/krb5/iakerb.c
+++ b/src/lib/gssapi/krb5/iakerb.c
@@ -494,7 +494,7 @@ iakerb_tkt_creds_ctx(iakerb_ctx_id_t ctx,
         if (code != 0)
             goto cleanup;
 
-        creds.times.endtime = now + time_req;
+        creds.times.endtime = ts_incr(now, time_req);
     }
 
     if (cred->name->ad_context != NULL) {
@@ -669,7 +669,7 @@ iakerb_get_initial_state(iakerb_ctx_id_t ctx,
         if (code != 0)
             goto cleanup;
 
-        in_creds.times.endtime = now + time_req;
+        in_creds.times.endtime = ts_incr(now, time_req);
     }
 
     /* Make an AS request if we have no creds or it's time to refresh them. */
diff --git a/src/lib/gssapi/krb5/init_sec_context.c b/src/lib/gssapi/krb5/init_sec_context.c
index 70f7955..8e5cc37 100644
--- a/src/lib/gssapi/krb5/init_sec_context.c
+++ b/src/lib/gssapi/krb5/init_sec_context.c
@@ -214,7 +214,8 @@ static krb5_error_code get_credentials(context, cred, server, now,
      * boundaries) because accept_sec_context code is also similarly
      * non-forgiving.
      */
-    if (!krb5_gss_dbg_client_expcreds && result_creds->times.endtime < now) {
+    if (!krb5_gss_dbg_client_expcreds &&
+        ts_after(now, result_creds->times.endtime)) {
         code = KRB5KRB_AP_ERR_TKT_EXPIRED;
         goto cleanup;
     }
@@ -575,7 +576,7 @@ kg_new_connection(
     if (time_req == 0 || time_req == GSS_C_INDEFINITE) {
         ctx->krb_times.endtime = 0;
     } else {
-        ctx->krb_times.endtime = now + time_req;
+        ctx->krb_times.endtime = ts_incr(now, time_req);
     }
 
     if ((code = kg_duplicate_name(context, cred->name, &ctx->here)))
@@ -659,7 +660,7 @@ kg_new_connection(
     if (time_rec) {
         if ((code = krb5_timeofday(context, &now)))
             goto cleanup;
-        *time_rec = ctx->krb_times.endtime - now;
+        *time_rec = ts_delta(ctx->krb_times.endtime, now);
     }
 
     /* set the other returns */
@@ -873,7 +874,7 @@ mutual_auth(
     if (time_rec) {
         if ((code = krb5_timeofday(context, &now)))
             goto fail;
-        *time_rec = ctx->krb_times.endtime - now;
+        *time_rec = ts_delta(ctx->krb_times.endtime, now);
     }
 
     if (ret_flags)
diff --git a/src/lib/gssapi/krb5/inq_context.c b/src/lib/gssapi/krb5/inq_context.c
index d2e466e..cac024d 100644
--- a/src/lib/gssapi/krb5/inq_context.c
+++ b/src/lib/gssapi/krb5/inq_context.c
@@ -120,7 +120,7 @@ krb5_gss_inquire_context(minor_status, context_handle, initiator_name,
 
         /* Add the maximum allowable clock skew as a grace period for context
          * expiration, just as we do for the ticket during authentication. */
-        lifetime = ctx->krb_times.endtime - now;
+        lifetime = ts_delta(ctx->krb_times.endtime, now);
         if (!ctx->initiate)
             lifetime += context->clockskew;
         if (lifetime < 0)
diff --git a/src/lib/gssapi/krb5/inq_cred.c b/src/lib/gssapi/krb5/inq_cred.c
index d375f86..3a73417 100644
--- a/src/lib/gssapi/krb5/inq_cred.c
+++ b/src/lib/gssapi/krb5/inq_cred.c
@@ -130,8 +130,9 @@ krb5_gss_inquire_cred(minor_status, cred_handle, name, lifetime_ret,
         goto fail;
     }
 
-    if (cred->expire > 0) {
-        if ((lifetime = cred->expire - now) < 0)
+    if (cred->expire != 0) {
+        lifetime = ts_delta(cred->expire, now);
+        if (lifetime < 0)
             lifetime = 0;
     }
     else
diff --git a/src/lib/gssapi/krb5/s4u_gss_glue.c b/src/lib/gssapi/krb5/s4u_gss_glue.c
index ff1c310..10848c1 100644
--- a/src/lib/gssapi/krb5/s4u_gss_glue.c
+++ b/src/lib/gssapi/krb5/s4u_gss_glue.c
@@ -284,7 +284,7 @@ kg_compose_deleg_cred(OM_uint32 *minor_status,
         if (code != 0)
             goto cleanup;
 
-        *time_rec = cred->expire - now;
+        *time_rec = ts_delta(cred->expire, now);
     }
 
     major_status = GSS_S_COMPLETE;
diff --git a/src/lib/kadm5/chpass_util.c b/src/lib/kadm5/chpass_util.c
index 408b0eb..1680a55 100644
--- a/src/lib/kadm5/chpass_util.c
+++ b/src/lib/kadm5/chpass_util.c
@@ -4,15 +4,11 @@
  */
 
 
-#include "autoconf.h"
-#include <stdio.h>
-#include <time.h>
-#include <string.h>
+#include "k5-int.h"
 
 #include <kadm5/admin.h>
 #include "admin_internal.h"
 
-#include <krb5.h>
 
 #define string_text error_message
 
@@ -218,7 +214,7 @@ kadm5_ret_t _kadm5_chpass_principal_util(void *server_handle,
         time_t until;
         char *time_string, *ptr;
 
-        until = princ_ent.last_pwd_change + policy_ent.pw_min_life;
+        until = ts_incr(princ_ent.last_pwd_change, policy_ent.pw_min_life);
 
         time_string = ctime(&until);
         if (*(ptr = &time_string[strlen(time_string)-1]) == '\n')
diff --git a/src/lib/kadm5/srv/server_acl.c b/src/lib/kadm5/srv/server_acl.c
index 59ed0b9..656dddf 100644
--- a/src/lib/kadm5/srv/server_acl.c
+++ b/src/lib/kadm5/srv/server_acl.c
@@ -408,13 +408,14 @@ kadm5int_acl_impose_restrictions(kcontext, recp, maskp, rp)
     }
     if (rp->mask & KADM5_PRINC_EXPIRE_TIME) {
         if (!(*maskp & KADM5_PRINC_EXPIRE_TIME)
-            || (recp->princ_expire_time > (now + rp->princ_lifetime)))
+            || ts_after(recp->princ_expire_time,
+                        ts_incr(now, rp->princ_lifetime)))
             recp->princ_expire_time = now + rp->princ_lifetime;
         *maskp |= KADM5_PRINC_EXPIRE_TIME;
     }
     if (rp->mask & KADM5_PW_EXPIRATION) {
         if (!(*maskp & KADM5_PW_EXPIRATION)
-            || (recp->pw_expiration > (now + rp->pw_lifetime)))
+            || ts_after(recp->pw_expiration, ts_incr(now, rp->pw_lifetime)))
             recp->pw_expiration = now + rp->pw_lifetime;
         *maskp |= KADM5_PW_EXPIRATION;
     }
diff --git a/src/lib/kadm5/srv/svr_principal.c b/src/lib/kadm5/srv/svr_principal.c
index 0640b47..f4a9a2a 100644
--- a/src/lib/kadm5/srv/svr_principal.c
+++ b/src/lib/kadm5/srv/svr_principal.c
@@ -400,7 +400,7 @@ kadm5_create_principal_3(void *server_handle,
     kdb->pw_expiration = 0;
     if (have_polent) {
         if(polent.pw_max_life)
-            kdb->pw_expiration = now + polent.pw_max_life;
+            kdb->pw_expiration = ts_incr(now, polent.pw_max_life);
         else
             kdb->pw_expiration = 0;
     }
@@ -612,7 +612,7 @@ kadm5_modify_principal(void *server_handle,
                                                   &(kdb->pw_expiration));
             if (ret)
                 goto done;
-            kdb->pw_expiration += pol.pw_max_life;
+            kdb->pw_expiration = ts_incr(kdb->pw_expiration, pol.pw_max_life);
         } else {
             kdb->pw_expiration = 0;
         }
@@ -1445,7 +1445,7 @@ kadm5_chpass_principal_3(void *server_handle,
         }
 
         if (pol.pw_max_life)
-            kdb->pw_expiration = now + pol.pw_max_life;
+            kdb->pw_expiration = ts_incr(now, pol.pw_max_life);
         else
             kdb->pw_expiration = 0;
     } else {
@@ -1624,7 +1624,7 @@ kadm5_randkey_principal_3(void *server_handle,
 #endif
 
         if (pol.pw_max_life)
-            kdb->pw_expiration = now + pol.pw_max_life;
+            kdb->pw_expiration = ts_incr(now, pol.pw_max_life);
         else
             kdb->pw_expiration = 0;
     } else {
@@ -1774,7 +1774,7 @@ kadm5_setv4key_principal(void *server_handle,
 #endif
 
         if (pol.pw_max_life)
-            kdb->pw_expiration = now + pol.pw_max_life;
+            kdb->pw_expiration = ts_incr(now, pol.pw_max_life);
         else
             kdb->pw_expiration = 0;
     } else {
@@ -2024,7 +2024,7 @@ kadm5_setkey_principal_4(void *server_handle, krb5_principal principal,
     }
     if (have_pol) {
         if (pol.pw_max_life)
-            kdb->pw_expiration = now + pol.pw_max_life;
+            kdb->pw_expiration = ts_incr(now, pol.pw_max_life);
         else
             kdb->pw_expiration = 0;
     } else {
diff --git a/src/lib/kdb/kdb5.c b/src/lib/kdb/kdb5.c
index 4adf0fc..7f33c7e 100644
--- a/src/lib/kdb/kdb5.c
+++ b/src/lib/kdb/kdb5.c
@@ -1296,7 +1296,7 @@ find_actkvno(krb5_actkvno_node *list, krb5_timestamp now)
      * are in the future, we will return the first node; if all are in the
      * past, we will return the last node.
      */
-    while (list->next != NULL && list->next->act_time <= now)
+    while (list->next != NULL && !ts_after(list->next->act_time, now))
         list = list->next;
     return list->act_kvno;
 }
diff --git a/src/lib/krb5/asn.1/asn1_k_encode.c b/src/lib/krb5/asn.1/asn1_k_encode.c
index a827ca6..8894609 100644
--- a/src/lib/krb5/asn.1/asn1_k_encode.c
+++ b/src/lib/krb5/asn.1/asn1_k_encode.c
@@ -158,8 +158,7 @@ static asn1_error_code
 encode_kerberos_time(asn1buf *buf, const void *p, taginfo *rettag,
                      size_t *len_out)
 {
-    /* Range checking for time_t vs krb5_timestamp?  */
-    time_t val = *(krb5_timestamp *)p;
+    time_t val = ts2tt(*(krb5_timestamp *)p);
     rettag->asn1class = UNIVERSAL;
     rettag->construction = PRIMITIVE;
     rettag->tagnum = ASN1_GENERALTIME;
diff --git a/src/lib/krb5/ccache/cc_keyring.c b/src/lib/krb5/ccache/cc_keyring.c
index 4fe3f0d..fba710b 100644
--- a/src/lib/krb5/ccache/cc_keyring.c
+++ b/src/lib/krb5/ccache/cc_keyring.c
@@ -751,7 +751,7 @@ update_keyring_expiration(krb5_context context, krb5_ccache id)
     for (;;) {
         if (krcc_next_cred(context, id, &cursor, &creds) != 0)
             break;
-        if (creds.times.endtime > endtime)
+        if (ts_after(creds.times.endtime, endtime))
             endtime = creds.times.endtime;
         krb5_free_cred_contents(context, &creds);
     }
@@ -765,7 +765,7 @@ update_keyring_expiration(krb5_context context, krb5_ccache id)
 
     /* Setting the timeout to zero would reset the timeout, so we set it to one
      * second instead if creds are already expired. */
-    timeout = (endtime > now) ? endtime - now : 1;
+    timeout = ts_after(endtime, now) ? ts_delta(endtime, now) : 1;
     (void)keyctl_set_timeout(data->cache_id, timeout);
 }
 
@@ -1316,8 +1316,10 @@ krcc_store(krb5_context context, krb5_ccache id, krb5_creds *creds)
     if (ret)
         goto errout;
 
-    if (creds->times.endtime > now)
-        (void)keyctl_set_timeout(cred_key, creds->times.endtime - now);
+    if (ts_after(creds->times.endtime, now)) {
+        (void)keyctl_set_timeout(cred_key,
+                                 ts_delta(creds->times.endtime, now));
+    }
 
     update_keyring_expiration(context, id);
 
@@ -1680,8 +1682,8 @@ static void
 krcc_update_change_time(krcc_data *data)
 {
     krb5_timestamp now_time = time(NULL);
-    data->changetime = (data->changetime >= now_time) ?
-        data->changetime + 1 : now_time;
+    data->changetime = ts_after(now_time, data->changetime) ?
+        now_time : ts_incr(data->changetime, 1);
 }
 
 /*
diff --git a/src/lib/krb5/ccache/cc_memory.c b/src/lib/krb5/ccache/cc_memory.c
index 0354575..c5425eb 100644
--- a/src/lib/krb5/ccache/cc_memory.c
+++ b/src/lib/krb5/ccache/cc_memory.c
@@ -720,8 +720,8 @@ static void
 update_mcc_change_time(krb5_mcc_data *d)
 {
     krb5_timestamp now_time = time(NULL);
-    d->changetime = (d->changetime >= now_time) ?
-        d->changetime + 1 : now_time;
+    d->changetime = ts_after(now_time, d->changetime) ?
+        now_time : ts_incr(d->changetime, 1);
 }
 
 static krb5_error_code KRB5_CALLCONV
diff --git a/src/lib/krb5/ccache/cc_retr.c b/src/lib/krb5/ccache/cc_retr.c
index 163b227..e8a20fe 100644
--- a/src/lib/krb5/ccache/cc_retr.c
+++ b/src/lib/krb5/ccache/cc_retr.c
@@ -46,11 +46,11 @@ static krb5_boolean
 times_match(const krb5_ticket_times *t1, const krb5_ticket_times *t2)
 {
     if (t1->renew_till) {
-        if (t1->renew_till > t2->renew_till)
+        if (ts_after(t1->renew_till, t2->renew_till))
             return FALSE;               /* this one expires too late */
     }
     if (t1->endtime) {
-        if (t1->endtime > t2->endtime)
+        if (ts_after(t1->endtime, t2->endtime))
             return FALSE;               /* this one expires too late */
     }
     /* only care about expiration on a times_match */
diff --git a/src/lib/krb5/ccache/ccapi/stdcc_util.c b/src/lib/krb5/ccache/ccapi/stdcc_util.c
index 9f44af3..6092ee4 100644
--- a/src/lib/krb5/ccache/ccapi/stdcc_util.c
+++ b/src/lib/krb5/ccache/ccapi/stdcc_util.c
@@ -16,8 +16,8 @@
 #include <malloc.h>
 #endif
 
+#include "k5-int.h"
 #include "stdcc_util.h"
-#include "krb5.h"
 #ifdef _WIN32                   /* it's part of krb5.h everywhere else */
 #include "kv5m_err.h"
 #endif
@@ -321,10 +321,10 @@ copy_cc_cred_union_to_krb5_creds (krb5_context in_context,
         keyblock_contents = NULL;
 
         /* copy times */
-        out_creds->times.authtime   = cv5->authtime     + offset_seconds;
-        out_creds->times.starttime  = cv5->starttime    + offset_seconds;
-        out_creds->times.endtime    = cv5->endtime      + offset_seconds;
-        out_creds->times.renew_till = cv5->renew_till   + offset_seconds;
+        out_creds->times.authtime   = ts_incr(cv5->authtime, offset_seconds);
+        out_creds->times.starttime  = ts_incr(cv5->starttime, offset_seconds);
+        out_creds->times.endtime    = ts_incr(cv5->endtime, offset_seconds);
+        out_creds->times.renew_till = ts_incr(cv5->renew_till, offset_seconds);
         out_creds->is_skey          = cv5->is_skey;
         out_creds->ticket_flags     = cv5->ticket_flags;
 
@@ -451,11 +451,11 @@ copy_krb5_creds_to_cc_cred_union (krb5_context in_context,
         cv5->keyblock.data = keyblock_data;
         keyblock_data = NULL;
 
-        cv5->authtime     = in_creds->times.authtime   - offset_seconds;
-        cv5->starttime    = in_creds->times.starttime  - offset_seconds;
-        cv5->endtime      = in_creds->times.endtime    - offset_seconds;
-        cv5->renew_till   = in_creds->times.renew_till - offset_seconds;
-        cv5->is_skey      = in_creds->is_skey;
+        cv5->authtime = ts_incr(in_creds->times.authtime, -offset_seconds);
+        cv5->starttime = ts_incr(in_creds->times.starttime, -offset_seconds);
+        cv5->endtime = ts_incr(in_creds->times.endtime, -offset_seconds);
+        cv5->renew_till = ts_incr(in_creds->times.renew_till, -offset_seconds);
+        cv5->is_skey = in_creds->is_skey;
         cv5->ticket_flags = in_creds->ticket_flags;
 
         if (in_creds->ticket.data) {
@@ -732,10 +732,10 @@ void dupCCtoK5(krb5_context context, cc_creds *src, krb5_creds *dest)
     err = krb5_get_time_offsets(context, &offset_seconds, &offset_microseconds);
     if (err) return;
 #endif
-    dest->times.authtime   = src->authtime     + offset_seconds;
-    dest->times.starttime  = src->starttime    + offset_seconds;
-    dest->times.endtime    = src->endtime      + offset_seconds;
-    dest->times.renew_till = src->renew_till   + offset_seconds;
+    dest->times.authtime   = ts_incr(src->authtime, offset_seconds);
+    dest->times.starttime  = ts_incr(src->starttime, offset_seconds);
+    dest->times.endtime    = ts_incr(src->endtime, offset_seconds);
+    dest->times.renew_till = ts_incr(src->renew_till, offset_seconds);
     dest->is_skey          = src->is_skey;
     dest->ticket_flags     = src->ticket_flags;
 
@@ -804,10 +804,10 @@ void dupK5toCC(krb5_context context, krb5_creds *creds, cred_union **cu)
     err = krb5_get_time_offsets(context, &offset_seconds, &offset_microseconds);
     if (err) return;
 #endif
-    c->authtime     = creds->times.authtime   - offset_seconds;
-    c->starttime    = creds->times.starttime  - offset_seconds;
-    c->endtime      = creds->times.endtime    - offset_seconds;
-    c->renew_till   = creds->times.renew_till - offset_seconds;
+    c->authtime     = ts_incr(creds->times.authtime, -offset_seconds);
+    c->starttime    = ts_incr(creds->times.starttime, -offset_seconds);
+    c->endtime      = ts_incr(creds->times.endtime, -offset_seconds);
+    c->renew_till   = ts_incr(creds->times.renew_till, -offset_seconds);
     c->is_skey      = creds->is_skey;
     c->ticket_flags = creds->ticket_flags;
 
@@ -925,11 +925,11 @@ times_match(t1, t2)
     register const krb5_ticket_times *t2;
 {
     if (t1->renew_till) {
-        if (t1->renew_till > t2->renew_till)
+        if (ts_after(t1->renew_till, t2->renew_till))
             return FALSE;               /* this one expires too late */
     }
     if (t1->endtime) {
-        if (t1->endtime > t2->endtime)
+        if (ts_after(t1->endtime, t2->endtime))
             return FALSE;               /* this one expires too late */
     }
     /* only care about expiration on a times_match */
diff --git a/src/lib/krb5/ccache/cccursor.c b/src/lib/krb5/ccache/cccursor.c
index 9ebcdc2..506a27c 100644
--- a/src/lib/krb5/ccache/cccursor.c
+++ b/src/lib/krb5/ccache/cccursor.c
@@ -159,7 +159,7 @@ krb5_cccol_last_change_time(krb5_context context,
         ret = krb5_cccol_cursor_next(context, c, &ccache);
         if (ccache) {
             ret = krb5_cc_last_change_time(context, ccache, &last_time);
-            if (!ret && last_time > max_change_time) {
+            if (!ret && ts_after(last_time, max_change_time)) {
                 max_change_time = last_time;
             }
             ret = 0;
diff --git a/src/lib/krb5/keytab/kt_file.c b/src/lib/krb5/keytab/kt_file.c
index 6a42f26..f6124af 100644
--- a/src/lib/krb5/keytab/kt_file.c
+++ b/src/lib/krb5/keytab/kt_file.c
@@ -264,9 +264,11 @@ more_recent(const krb5_keytab_entry *k1, const krb5_keytab_entry *k2)
      * limitations (8-bit kvno storage), pre-1.14 kadmin protocol limitations
      * (8-bit kvno marshalling), or KDB limitations (16-bit kvno storage).
      */
-    if (k1->timestamp >= k2->timestamp && k1->vno < 128 && k2->vno > 240)
+    if (!ts_after(k2->timestamp, k1->timestamp) &&
+        k1->vno < 128 && k2->vno > 240)
         return TRUE;
-    if (k1->timestamp <= k2->timestamp && k1->vno > 240 && k2->vno < 128)
+    if (!ts_after(k1->timestamp, k2->timestamp) &&
+        k1->vno > 240 && k2->vno < 128)
         return FALSE;
 
     /* Otherwise do a simple version comparison. */
diff --git a/src/lib/krb5/krb/gc_via_tkt.c b/src/lib/krb5/krb/gc_via_tkt.c
index c85d8b8..cf1ea36 100644
--- a/src/lib/krb5/krb/gc_via_tkt.c
+++ b/src/lib/krb5/krb/gc_via_tkt.c
@@ -287,18 +287,19 @@ krb5int_process_tgs_reply(krb5_context context,
         retval = KRB5_KDCREP_MODIFIED;
 
     if ((in_cred->times.endtime != 0) &&
-        (dec_rep->enc_part2->times.endtime > in_cred->times.endtime))
+        ts_after(dec_rep->enc_part2->times.endtime, in_cred->times.endtime))
         retval = KRB5_KDCREP_MODIFIED;
 
     if ((kdcoptions & KDC_OPT_RENEWABLE) &&
         (in_cred->times.renew_till != 0) &&
-        (dec_rep->enc_part2->times.renew_till > in_cred->times.renew_till))
+        ts_after(dec_rep->enc_part2->times.renew_till,
+                 in_cred->times.renew_till))
         retval = KRB5_KDCREP_MODIFIED;
 
     if ((kdcoptions & KDC_OPT_RENEWABLE_OK) &&
         (dec_rep->enc_part2->flags & KDC_OPT_RENEWABLE) &&
         (in_cred->times.endtime != 0) &&
-        (dec_rep->enc_part2->times.renew_till > in_cred->times.endtime))
+        ts_after(dec_rep->enc_part2->times.renew_till, in_cred->times.endtime))
         retval = KRB5_KDCREP_MODIFIED;
 
     if (retval != 0)
diff --git a/src/lib/krb5/krb/get_creds.c b/src/lib/krb5/krb/get_creds.c
index 8890ee1..69900ad 100644
--- a/src/lib/krb5/krb/get_creds.c
+++ b/src/lib/krb5/krb/get_creds.c
@@ -808,7 +808,7 @@ get_cached_local_tgt(krb5_context context, krb5_tkt_creds_context ctx,
         return code;
 
     /* Check if the TGT is expired before bothering the KDC with it. */
-    if (now > tgt->times.endtime) {
+    if (ts_after(now, tgt->times.endtime)) {
         krb5_free_creds(context, tgt);
         return KRB5KRB_AP_ERR_TKT_EXPIRED;
     }
diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
index 310c325..4b983f4 100644
--- a/src/lib/krb5/krb/get_in_tkt.c
+++ b/src/lib/krb5/krb/get_in_tkt.c
@@ -40,24 +40,6 @@ static krb5_error_code sort_krb5_padata_sequence(krb5_context context,
                                                  krb5_pa_data **padata);
 
 /*
- * This function performs 32 bit bounded addition so we can generate
- * lifetimes without overflowing krb5_int32
- */
-static krb5_int32
-krb5int_addint32 (krb5_int32 x, krb5_int32 y)
-{
-    if ((x > 0) && (y > (KRB5_INT32_MAX - x))) {
-        /* sum will be be greater than KRB5_INT32_MAX */
-        return KRB5_INT32_MAX;
-    } else if ((x < 0) && (y < (KRB5_INT32_MIN - x))) {
-        /* sum will be less than KRB5_INT32_MIN */
-        return KRB5_INT32_MIN;
-    }
-
-    return x + y;
-}
-
-/*
  * Decrypt the AS reply in ctx, populating ctx->reply->enc_part2.  If
  * strengthen_key is not null, combine it with the reply key as specified in
  * RFC 6113 section 5.4.3.  Place the key used in *key_out.
@@ -267,21 +249,21 @@ verify_as_reply(krb5_context            context,
             (request->from != 0) &&
             (request->from != as_reply->enc_part2->times.starttime))
         || ((request->till != 0) &&
-            (as_reply->enc_part2->times.endtime > request->till))
+            ts_after(as_reply->enc_part2->times.endtime, request->till))
         || ((request->kdc_options & KDC_OPT_RENEWABLE) &&
             (request->rtime != 0) &&
-            (as_reply->enc_part2->times.renew_till > request->rtime))
+            ts_after(as_reply->enc_part2->times.renew_till, request->rtime))
         || ((request->kdc_options & KDC_OPT_RENEWABLE_OK) &&
             !(request->kdc_options & KDC_OPT_RENEWABLE) &&
             (as_reply->enc_part2->flags & KDC_OPT_RENEWABLE) &&
             (request->till != 0) &&
-            (as_reply->enc_part2->times.renew_till > request->till))
+            ts_after(as_reply->enc_part2->times.renew_till, request->till))
     ) {
         return KRB5_KDCREP_MODIFIED;
     }
 
     if (context->library_options & KRB5_LIBOPT_SYNC_KDCTIME) {
-        time_offset = as_reply->enc_part2->times.authtime - time_now;
+        time_offset = ts_delta(as_reply->enc_part2->times.authtime, time_now);
         retval = krb5_set_time_offsets(context, time_offset, 0);
         if (retval)
             return retval;
@@ -775,15 +757,15 @@ set_request_times(krb5_context context, krb5_init_creds_context ctx)
         return code;
 
     /* Omit request start time unless the caller explicitly asked for one. */
-    from = krb5int_addint32(now, ctx->start_time);
+    from = ts_incr(now, ctx->start_time);
     if (ctx->start_time != 0)
         ctx->request->from = from;
 
-    ctx->request->till = krb5int_addint32(from, ctx->tkt_life);
+    ctx->request->till = ts_incr(from, ctx->tkt_life);
 
     if (ctx->renew_life > 0) {
         /* Don't ask for a smaller renewable time than the lifetime. */
-        ctx->request->rtime = krb5int_addint32(from, ctx->renew_life);
+        ctx->request->rtime = ts_incr(from, ctx->renew_life);
         if (ctx->request->rtime < ctx->request->till)
             ctx->request->rtime = ctx->request->till;
         ctx->request->kdc_options &= ~KDC_OPT_RENEWABLE_OK;
@@ -1459,7 +1441,7 @@ note_req_timestamp(krb5_context context, krb5_init_creds_context ctx,
 
     if (k5_time_with_offset(0, 0, &now, &usec) != 0)
         return;
-    ctx->pa_offset = kdc_time - now;
+    ctx->pa_offset = ts_delta(kdc_time, now);
     ctx->pa_offset_usec = kdc_usec - usec;
     ctx->pa_offset_state = (ctx->fast_state->armor_key != NULL) ?
         AUTH_OFFSET : UNAUTH_OFFSET;
@@ -1850,6 +1832,7 @@ k5_populate_gic_opt(krb5_context context, krb5_get_init_creds_opt **out,
 {
     int i;
     krb5_int32 starttime;
+    krb5_deltat lifetime;
     krb5_get_init_creds_opt *opt;
     krb5_error_code retval;
 
@@ -1881,7 +1864,8 @@ k5_populate_gic_opt(krb5_context context, krb5_get_init_creds_opt **out,
         if (retval)
             goto cleanup;
         if (creds->times.starttime) starttime = creds->times.starttime;
-        krb5_get_init_creds_opt_set_tkt_life(opt, creds->times.endtime - starttime);
+        lifetime = ts_delta(creds->times.endtime, starttime);
+        krb5_get_init_creds_opt_set_tkt_life(opt, lifetime);
     }
     *out = opt;
     return 0;
diff --git a/src/lib/krb5/krb/gic_pwd.c b/src/lib/krb5/krb/gic_pwd.c
index 6f3a29f..3565a7c 100644
--- a/src/lib/krb5/krb/gic_pwd.c
+++ b/src/lib/krb5/krb/gic_pwd.c
@@ -211,7 +211,7 @@ warn_pw_expiry(krb5_context context, krb5_get_init_creds_opt *options,
     if (ret != 0)
         return;
     if (!is_last_req &&
-        (pw_exp < now || (pw_exp - now) > 7 * 24 * 60 * 60))
+        (ts_after(now, pw_exp) || ts_delta(pw_exp, now) > 7 * 24 * 60 * 60))
         return;
 
     if (!prompter)
@@ -221,7 +221,7 @@ warn_pw_expiry(krb5_context context, krb5_get_init_creds_opt *options,
     if (ret != 0)
         return;
 
-    delta = pw_exp - now;
+    delta = ts_delta(pw_exp, now);
     if (delta < 3600) {
         snprintf(banner, sizeof(banner),
                  _("Warning: Your password will expire in less than one hour "
diff --git a/src/lib/krb5/krb/int-proto.h b/src/lib/krb5/krb/int-proto.h
index 7271257..6a45c6f 100644
--- a/src/lib/krb5/krb/int-proto.h
+++ b/src/lib/krb5/krb/int-proto.h
@@ -84,7 +84,7 @@ krb5int_construct_matching_creds(krb5_context context, krb5_flags options,
                                  krb5_flags *fields);
 
 #define in_clock_skew(context, date, now)               \
-    (labs((date) - (now)) < (context)->clockskew)
+    (labs(ts_delta(date, now)) < (context)->clockskew)
 
 #define IS_TGS_PRINC(p) ((p)->length == 2 &&                            \
                          data_eq_string((p)->data[0], KRB5_TGS_NAME))
diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c
index d1662b9..0eb19e6 100644
--- a/src/lib/krb5/krb/pac.c
+++ b/src/lib/krb5/krb/pac.c
@@ -378,7 +378,7 @@ k5_time_to_seconds_since_1970(int64_t ntTime, krb5_timestamp *elapsedSeconds)
 
     abstime = ntTime > 0 ? ntTime - NT_TIME_EPOCH : -ntTime;
 
-    if (abstime > KRB5_INT32_MAX)
+    if (abstime > UINT32_MAX)
         return ERANGE;
 
     *elapsedSeconds = abstime;
diff --git a/src/lib/krb5/krb/str_conv.c b/src/lib/krb5/krb/str_conv.c
index 3ab7eac..f0a2ae2 100644
--- a/src/lib/krb5/krb/str_conv.c
+++ b/src/lib/krb5/krb/str_conv.c
@@ -207,7 +207,7 @@ krb5_error_code KRB5_CALLCONV
 krb5_timestamp_to_string(krb5_timestamp timestamp, char *buffer, size_t buflen)
 {
     size_t ret;
-    time_t timestamp2 = timestamp;
+    time_t timestamp2 = ts2tt(timestamp);
     struct tm tmbuf;
     const char *fmt = "%c"; /* This is to get around gcc -Wall warning that
                                the year returned might be two digits */
@@ -229,7 +229,7 @@ krb5_timestamp_to_sfstring(krb5_timestamp timestamp, char *buffer, size_t buflen
     struct tm   *tmp;
     size_t i;
     size_t      ndone;
-    time_t timestamp2 = timestamp;
+    time_t timestamp2 = ts2tt(timestamp);
     struct tm tmbuf;
 
     static const char * const sftime_format_table[] = {
diff --git a/src/lib/krb5/krb/t_kerb.c b/src/lib/krb5/krb/t_kerb.c
index 60cfb5b..74ac14d 100644
--- a/src/lib/krb5/krb/t_kerb.c
+++ b/src/lib/krb5/krb/t_kerb.c
@@ -5,16 +5,8 @@
  */
 
 #include "autoconf.h"
-#include "krb5.h"
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
+#include "k5-int.h"
 #include <time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
 
 #include "com_err.h"
 
@@ -37,7 +29,7 @@ test_string_to_timestamp(krb5_context ctx, char *ktime)
         com_err("krb5_string_to_timestamp", retval, 0);
         return;
     }
-    t = (time_t) timestamp;
+    t = ts2tt(timestamp);
     printf("Parsed time was %s", ctime(&t));
 }
 
diff --git a/src/lib/krb5/krb/valid_times.c b/src/lib/krb5/krb/valid_times.c
index d631221..9e509b2 100644
--- a/src/lib/krb5/krb/valid_times.c
+++ b/src/lib/krb5/krb/valid_times.c
@@ -47,10 +47,10 @@ krb5int_validate_times(krb5_context context, krb5_ticket_times *times)
     else
         starttime = times->authtime;
 
-    if (starttime - currenttime > context->clockskew)
+    if (ts_delta(starttime, currenttime) > context->clockskew)
         return KRB5KRB_AP_ERR_TKT_NYV;  /* ticket not yet valid */
 
-    if ((currenttime - times->endtime) > context->clockskew)
+    if (ts_delta(currenttime, times->endtime) > context->clockskew)
         return KRB5KRB_AP_ERR_TKT_EXPIRED; /* ticket expired */
 
     return 0;
diff --git a/src/lib/krb5/krb/vfy_increds.c b/src/lib/krb5/krb/vfy_increds.c
index 9786d63..b4878ba 100644
--- a/src/lib/krb5/krb/vfy_increds.c
+++ b/src/lib/krb5/krb/vfy_increds.c
@@ -120,7 +120,7 @@ get_vfy_cred(krb5_context context, krb5_creds *creds, krb5_principal server,
         ret = krb5_timeofday(context, &in_creds.times.endtime);
         if (ret)
             goto cleanup;
-        in_creds.times.endtime += 5*60;
+        in_creds.times.endtime = ts_incr(in_creds.times.endtime, 5 * 60);
         ret = krb5_get_credentials(context, 0, ccache, &in_creds, &out_creds);
         if (ret)
             goto cleanup;
diff --git a/src/lib/krb5/os/timeofday.c b/src/lib/krb5/os/timeofday.c
index fddb121..887f24c 100644
--- a/src/lib/krb5/os/timeofday.c
+++ b/src/lib/krb5/os/timeofday.c
@@ -60,7 +60,7 @@ krb5_check_clockskew(krb5_context context, krb5_timestamp date)
     retval = krb5_timeofday(context, &currenttime);
     if (retval)
         return retval;
-    if (!(labs((date)-currenttime) < context->clockskew))
+    if (labs(ts_delta(date, currenttime)) >= context->clockskew)
         return KRB5KRB_AP_ERR_SKEW;
 
     return 0;
diff --git a/src/lib/krb5/os/toffset.c b/src/lib/krb5/os/toffset.c
index 456193a..37bc69f 100644
--- a/src/lib/krb5/os/toffset.c
+++ b/src/lib/krb5/os/toffset.c
@@ -47,7 +47,7 @@ krb5_set_real_time(krb5_context context, krb5_timestamp seconds, krb5_int32 micr
     if (retval)
         return retval;
 
-    os_ctx->time_offset = seconds - sec;
+    os_ctx->time_offset = ts_delta(seconds, sec);
     os_ctx->usec_offset = (microseconds > -1) ? microseconds - usec : 0;
 
     os_ctx->os_flags = ((os_ctx->os_flags & ~KRB5_OS_TOFFSET_TIME) |
diff --git a/src/lib/krb5/os/ustime.c b/src/lib/krb5/os/ustime.c
index 0563576..1c1b571 100644
--- a/src/lib/krb5/os/ustime.c
+++ b/src/lib/krb5/os/ustime.c
@@ -49,13 +49,13 @@ k5_time_with_offset(krb5_timestamp offset, krb5_int32 offset_usec,
     usec += offset_usec;
     if (usec > 1000000) {
         usec -= 1000000;
-        sec++;
+        sec = ts_incr(sec, 1);
     }
     if (usec < 0) {
         usec += 1000000;
-        sec--;
+        sec = ts_incr(sec, -1);
     }
-    sec += offset;
+    sec = ts_incr(sec, offset);
 
     *time_out = sec;
     *usec_out = usec;
diff --git a/src/lib/krb5/rcache/rc_dfl.c b/src/lib/krb5/rcache/rc_dfl.c
index 80c22ae..33f3c14 100644
--- a/src/lib/krb5/rcache/rc_dfl.c
+++ b/src/lib/krb5/rcache/rc_dfl.c
@@ -97,8 +97,7 @@ alive(krb5_int32 mytime, krb5_donot_replay *new1, krb5_deltat t)
 {
     if (mytime == 0)
         return CMP_HOHUM; /* who cares? */
-    /* I hope we don't have to worry about overflow */
-    if (new1->ctime + t < mytime)
+    if (ts_after(mytime, ts_incr(new1->ctime, t)))
         return CMP_EXPIRED;
     return CMP_HOHUM;
 }
diff --git a/src/lib/krb5/rcache/t_replay.c b/src/lib/krb5/rcache/t_replay.c
index db273ec..b99cdf1 100644
--- a/src/lib/krb5/rcache/t_replay.c
+++ b/src/lib/krb5/rcache/t_replay.c
@@ -110,7 +110,7 @@ store(krb5_context ctx, char *rcspec, char *client, char *server, char *msg,
     krb5_donot_replay rep;
     krb5_data d;
 
-    if (now_timestamp > 0)
+    if (now_timestamp != 0)
         krb5_set_debugging_time(ctx, now_timestamp, now_usec);
     if ((retval = krb5_rc_resolve_full(ctx, &rc, rcspec)))
         goto cleanup;
@@ -221,13 +221,13 @@ main(int argc, char **argv)
             msg = (**argv) ? *argv : NULL;
             argc--; argv++;
             if (!argc) usage(progname);
-            timestamp = (krb5_timestamp) atol(*argv);
+            timestamp = (krb5_timestamp) atoll(*argv);
             argc--; argv++;
             if (!argc) usage(progname);
             usec = (krb5_int32) atol(*argv);
             argc--; argv++;
             if (!argc) usage(progname);
-            now_timestamp = (krb5_timestamp) atol(*argv);
+            now_timestamp = (krb5_timestamp) atoll(*argv);
             argc--; argv++;
             if (!argc) usage(progname);
             now_usec = (krb5_int32) atol(*argv);
@@ -249,7 +249,7 @@ main(int argc, char **argv)
             rcspec = *argv;
             argc--; argv++;
             if (!argc) usage(progname);
-            now_timestamp = (krb5_timestamp) atol(*argv);
+            now_timestamp = (krb5_timestamp) atoll(*argv);
             argc--; argv++;
             if (!argc) usage(progname);
             now_usec = (krb5_int32) atol(*argv);
diff --git a/src/plugins/kdb/db2/lockout.c b/src/plugins/kdb/db2/lockout.c
index 7d151b5..3a4f418 100644
--- a/src/plugins/kdb/db2/lockout.c
+++ b/src/plugins/kdb/db2/lockout.c
@@ -100,7 +100,7 @@ locked_check_p(krb5_context context,
 
     /* If the entry was unlocked since the last failure, it's not locked. */
     if (krb5_dbe_lookup_last_admin_unlock(context, entry, &unlock_time) == 0 &&
-        entry->last_failed <= unlock_time)
+        !ts_after(entry->last_failed, unlock_time))
         return FALSE;
 
     if (max_fail == 0 || entry->fail_auth_count < max_fail)
@@ -109,7 +109,7 @@ locked_check_p(krb5_context context,
     if (lockout_duration == 0)
         return TRUE; /* principal permanently locked */
 
-    return (stamp < entry->last_failed + lockout_duration);
+    return ts_after(ts_incr(entry->last_failed, lockout_duration), stamp);
 }
 
 krb5_error_code
@@ -200,13 +200,13 @@ krb5_db2_lockout_audit(krb5_context context,
                 status == KRB5KRB_AP_ERR_BAD_INTEGRITY)) {
         if (krb5_dbe_lookup_last_admin_unlock(context, entry,
                                               &unlock_time) == 0 &&
-            entry->last_failed <= unlock_time) {
+            !ts_after(entry->last_failed, unlock_time)) {
             /* Reset fail_auth_count after administrative unlock. */
             entry->fail_auth_count = 0;
         }
 
         if (failcnt_interval != 0 &&
-            stamp > entry->last_failed + failcnt_interval) {
+            ts_after(stamp, ts_incr(entry->last_failed, failcnt_interval))) {
             /* Reset fail_auth_count after failcnt_interval. */
             entry->fail_auth_count = 0;
         }
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c
index 7ba53f9..88a1704 100644
--- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c
@@ -1734,7 +1734,7 @@ getstringtime(krb5_timestamp epochtime)
 {
     struct tm           tme;
     char                *strtime=NULL;
-    time_t              posixtime = epochtime;
+    time_t              posixtime = ts2tt(epochtime);
 
     strtime = calloc (50, 1);
     if (strtime == NULL)
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/lockout.c b/src/plugins/kdb/ldap/libkdb_ldap/lockout.c
index 0fc56c2..1088ecc 100644
--- a/src/plugins/kdb/ldap/libkdb_ldap/lockout.c
+++ b/src/plugins/kdb/ldap/libkdb_ldap/lockout.c
@@ -93,7 +93,7 @@ locked_check_p(krb5_context context,
 
     /* If the entry was unlocked since the last failure, it's not locked. */
     if (krb5_dbe_lookup_last_admin_unlock(context, entry, &unlock_time) == 0 &&
-        entry->last_failed <= unlock_time)
+        !ts_after(entry->last_failed, unlock_time))
         return FALSE;
 
     if (max_fail == 0 || entry->fail_auth_count < max_fail)
@@ -102,7 +102,7 @@ locked_check_p(krb5_context context,
     if (lockout_duration == 0)
         return TRUE; /* principal permanently locked */
 
-    return (stamp < entry->last_failed + lockout_duration);
+    return ts_after(ts_incr(entry->last_failed, lockout_duration), stamp);
 }
 
 krb5_error_code
@@ -196,14 +196,14 @@ krb5_ldap_lockout_audit(krb5_context context,
                 status == KRB5KRB_AP_ERR_BAD_INTEGRITY)) {
         if (krb5_dbe_lookup_last_admin_unlock(context, entry,
                                               &unlock_time) == 0 &&
-            entry->last_failed <= unlock_time) {
+            !ts_after(entry->last_failed, unlock_time)) {
             /* Reset fail_auth_count after administrative unlock. */
             entry->fail_auth_count = 0;
             entry->mask |= KADM5_FAIL_AUTH_COUNT;
         }
 
         if (failcnt_interval != 0 &&
-            stamp > entry->last_failed + failcnt_interval) {
+            ts_after(stamp, ts_incr(entry->last_failed, failcnt_interval))) {
             /* Reset fail_auth_count after failcnt_interval */
             entry->fail_auth_count = 0;
             entry->mask |= KADM5_FAIL_AUTH_COUNT;
diff --git a/src/windows/cns/tktlist.c b/src/windows/cns/tktlist.c
index f2805f5..26e699f 100644
--- a/src/windows/cns/tktlist.c
+++ b/src/windows/cns/tktlist.c
@@ -35,6 +35,8 @@
 #include "cns.h"
 #include "tktlist.h"
 
+#define ts2tt(t) (time_t)(uint32_t)(t)
+
 /*
  * Ticket information for a list line
  */
@@ -167,10 +169,10 @@ ticket_init_list (HWND hwnd)
 
       ncred++;
       strcpy (buf, "  ");
-      strncat(buf, short_date (c.times.starttime - kwin_get_epoch()),
+      strncat(buf, short_date(ts2tt(c.times.starttime) - kwin_get_epoch()),
 	      sizeof(buf) - 1 - strlen(buf));
       strncat(buf, "      ", sizeof(buf) - 1 - strlen(buf));
-      strncat(buf, short_date (c.times.endtime - kwin_get_epoch()),
+      strncat(buf, short_date(ts2tt(c.times.endtime) - kwin_get_epoch()),
 	      sizeof(buf) - 1 - strlen(buf));
       strncat(buf, "      ", sizeof(buf) - 1 - strlen(buf));
 
@@ -192,8 +194,8 @@ ticket_init_list (HWND hwnd)
 	return -1;
 
       lpinfo->ticket = TRUE;
-      lpinfo->issue_time = c.times.starttime - kwin_get_epoch();
-      lpinfo->lifetime = c.times.endtime - c.times.starttime;
+      lpinfo->issue_time = ts2tt(c.times.starttime) - kwin_get_epoch();
+      lpinfo->lifetime = ts2tt(c.times.endtime) - c.times.starttime;
       strcpy(lpinfo->buf, buf);
 
       rc = ListBox_AddItemData(hwnd, lpinfo);
diff --git a/src/windows/include/leashwin.h b/src/windows/include/leashwin.h
index 9577365..325dce2 100644
--- a/src/windows/include/leashwin.h
+++ b/src/windows/include/leashwin.h
@@ -111,9 +111,9 @@ struct TicketList {
     TicketList *next;
     char *service;
     char *encTypes;
-    krb5_timestamp issued;
-    krb5_timestamp valid_until;
-    krb5_timestamp renew_until;
+    time_t issued;
+    time_t valid_until;
+    time_t renew_until;
     unsigned long flags;
 };
 
@@ -124,9 +124,9 @@ struct TICKETINFO {
     char   *ccache_name;
     TicketList *ticket_list;
     int     btickets;                 /* Do we have tickets? */
-    long    issued;                   /* The issue time */
-    long    valid_until;              /* */
-    long    renew_until;              /* The Renew time (k5 only) */
+    time_t  issued;                   /* The issue time */
+    time_t  valid_until;              /* */
+    time_t  renew_until;              /* The Renew time (k5 only) */
     unsigned long flags;
 };
 
diff --git a/src/windows/leash/KrbListTickets.cpp b/src/windows/leash/KrbListTickets.cpp
index beab0ea..5dd37b0 100644
--- a/src/windows/leash/KrbListTickets.cpp
+++ b/src/windows/leash/KrbListTickets.cpp
@@ -92,10 +92,10 @@ etype_string(krb5_enctype enctype)
 static void
 CredToTicketInfo(krb5_creds KRBv5Credentials, TICKETINFO *ticketinfo)
 {
-    ticketinfo->issued = KRBv5Credentials.times.starttime;
-    ticketinfo->valid_until = KRBv5Credentials.times.endtime;
+    ticketinfo->issued = (DWORD)KRBv5Credentials.times.starttime;
+    ticketinfo->valid_until = (DWORD)KRBv5Credentials.times.endtime;
     ticketinfo->renew_until = KRBv5Credentials.ticket_flags & TKT_FLG_RENEWABLE ?
-        KRBv5Credentials.times.renew_till : 0;
+        (DWORD)KRBv5Credentials.times.renew_till : (DWORD)0;
     _tzset();
     if ( ticketinfo->valid_until - time(0) <= 0L )
         ticketinfo->btickets = EXPD_TICKETS;
@@ -137,10 +137,10 @@ CredToTicketList(krb5_context ctx, krb5_creds KRBv5Credentials,
         functionName = "calloc()";
         goto cleanup;
     }
-    list->issued = KRBv5Credentials.times.starttime;
-    list->valid_until = KRBv5Credentials.times.endtime;
+    list->issued = (DWORD)KRBv5Credentials.times.starttime;
+    list->valid_until = (DWORD)KRBv5Credentials.times.endtime;
     if (KRBv5Credentials.ticket_flags & TKT_FLG_RENEWABLE)
-        list->renew_until = KRBv5Credentials.times.renew_till;
+        list->renew_until = (DWORD)KRBv5Credentials.times.renew_till;
     else
         list->renew_until = 0;
 
diff --git a/src/windows/leash/LeashView.cpp b/src/windows/leash/LeashView.cpp
index ef2a5a3..253ae3f 100644
--- a/src/windows/leash/LeashView.cpp
+++ b/src/windows/leash/LeashView.cpp
@@ -229,22 +229,22 @@ static HFONT CreateBoldItalicFont(HFONT font)
 
 bool change_icon_size = true;
 
-void krb5TimestampToFileTime(krb5_timestamp t, LPFILETIME pft)
+void TimestampToFileTime(time_t t, LPFILETIME pft)
 {
     // Note that LONGLONG is a 64-bit value
-    LONGLONG ll;
+    ULONGLONG ll;
 
-    ll = Int32x32To64(t, 10000000) + 116444736000000000;
+    ll = UInt32x32To64((DWORD)t, 10000000) + 116444736000000000;
     pft->dwLowDateTime = (DWORD)ll;
     pft->dwHighDateTime = ll >> 32;
 }
 
 // allocate outstr
-void krb5TimestampToLocalizedString(krb5_timestamp t, LPTSTR *outStr)
+void TimestampToLocalizedString(time_t t, LPTSTR *outStr)
 {
     FILETIME ft, lft;
     SYSTEMTIME st;
-    krb5TimestampToFileTime(t, &ft);
+    TimestampToFileTime(t, &ft);
     FileTimeToLocalFileTime(&ft, &lft);
     FileTimeToSystemTime(&lft, &st);
     TCHAR timeFormat[80]; // 80 is max required for LOCALE_STIMEFORMAT
@@ -1125,9 +1125,9 @@ void CLeashView::AddDisplayItem(CListCtrl &list,
                                 CCacheDisplayData *elem,
                                 int iItem,
                                 char *principal,
-                                long issued,
-                                long valid_until,
-                                long renew_until,
+                                time_t issued,
+                                time_t valid_until,
+                                time_t renew_until,
                                 char *encTypes,
                                 unsigned long flags,
                                 char *ccache_name)
@@ -1145,7 +1145,7 @@ void CLeashView::AddDisplayItem(CListCtrl &list,
         if (issued == 0) {
             list.SetItemText(iItem, iSubItem++, "Unknown");
         } else {
-            krb5TimestampToLocalizedString(issued, &localTimeStr);
+            TimestampToLocalizedString(issued, &localTimeStr);
             list.SetItemText(iItem, iSubItem++, localTimeStr);
         }
     }
@@ -1155,7 +1155,7 @@ void CLeashView::AddDisplayItem(CListCtrl &list,
         } else if (valid_until < now) {
             list.SetItemText(iItem, iSubItem++, "Expired");
         } else if (renew_until) {
-            krb5TimestampToLocalizedString(renew_until, &localTimeStr);
+            TimestampToLocalizedString(renew_until, &localTimeStr);
             DurationToString(renew_until - now, &durationStr);
             if (localTimeStr && durationStr) {
                 _snprintf(tempStr, MAX_DURATION_STR, "%s %s", localTimeStr, durationStr);
@@ -1172,7 +1172,7 @@ void CLeashView::AddDisplayItem(CListCtrl &list,
         } else if (valid_until < now) {
             list.SetItemText(iItem, iSubItem++, "Expired");
         } else {
-            krb5TimestampToLocalizedString(valid_until, &localTimeStr);
+            TimestampToLocalizedString(valid_until, &localTimeStr);
             DurationToString(valid_until - now, &durationStr);
             if (localTimeStr && durationStr) {
                 _snprintf(tempStr, MAX_DURATION_STR, "%s %s", localTimeStr, durationStr);
diff --git a/src/windows/leashdll/lshfunc.c b/src/windows/leashdll/lshfunc.c
index 0f76cc3..8dafb7b 100644
--- a/src/windows/leashdll/lshfunc.c
+++ b/src/windows/leashdll/lshfunc.c
@@ -2898,7 +2898,7 @@ static BOOL cc_have_tickets(krb5_context ctx, krb5_ccache cache)
     _tzset();
     while (!(code = pkrb5_cc_next_cred(ctx, cache, &cur, &creds))) {
         if ((!pkrb5_is_config_principal(ctx, creds.server)) &&
-            (creds.times.endtime - time(0) > 0))
+            ((time_t)(DWORD)creds.times.endtime - time(0) > 0))
             have_tickets = TRUE;
 
         pkrb5_free_cred_contents(ctx, &creds);
diff --git a/src/windows/ms2mit/ms2mit.c b/src/windows/ms2mit/ms2mit.c
index c332503..2b4373c 100644
--- a/src/windows/ms2mit/ms2mit.c
+++ b/src/windows/ms2mit/ms2mit.c
@@ -74,7 +74,7 @@ cc_has_tickets(krb5_context kcontext, krb5_ccache ccache, int *has_tickets)
             break;
 
         if (!krb5_is_config_principal(kcontext, creds.server) &&
-            creds.times.endtime > now)
+            ts_after(creds.times.endtime, now))
             *has_tickets = 1;
 
         krb5_free_cred_contents(kcontext, &creds);


More information about the cvs-krb5 mailing list