diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..61533df
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+SOURCES/krb5-1.15.1-pdfs.tar
+SOURCES/krb5-1.15.1.tar.gz
+SOURCES/nss_wrapper-0.0-20140204195100.git3d58327.tar.xz
+SOURCES/socket_wrapper-0.0-20140204194748.gitf3b2ece.tar.xz
diff --git a/.krb5.metadata b/.krb5.metadata
new file mode 100644
index 0000000..22193ae
--- /dev/null
+++ b/.krb5.metadata
@@ -0,0 +1,4 @@
+0feda2b6393a4ac9ecc449fc7b4215da5ca6860d SOURCES/krb5-1.15.1-pdfs.tar
+810210a61070ea371014ac514d191bbe5cdac2e2 SOURCES/krb5-1.15.1.tar.gz
+7e2c80565c726a6be9a62615752196710e2e2faa SOURCES/nss_wrapper-0.0-20140204195100.git3d58327.tar.xz
+ca7b62bd60d45817a059063bb0efd68cd1ecc889 SOURCES/socket_wrapper-0.0-20140204194748.gitf3b2ece.tar.xz
diff --git a/README.md b/README.md
deleted file mode 100644
index 0e7897f..0000000
--- a/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
-The master branch has no content
- 
-Look at the c7 branch if you are working with CentOS-7, or the c4/c5/c6 branch for CentOS-4, 5 or 6
- 
-If you find this file in a distro specific branch, it means that no content has been checked in yet
diff --git a/SOURCES/Add-KDC-policy-pluggable-interface.patch b/SOURCES/Add-KDC-policy-pluggable-interface.patch
new file mode 100644
index 0000000..19cb799
--- /dev/null
+++ b/SOURCES/Add-KDC-policy-pluggable-interface.patch
@@ -0,0 +1,995 @@
+From f12b57979012f93b339982ba335093d7c0d364f7 Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Tue, 27 Jun 2017 17:15:39 -0400
+Subject: [PATCH] Add KDC policy pluggable interface
+
+Add the header include/krb5/kdcpolicy_plugin.h, defining a pluggable
+interface for modules to deny AS and TGS requests and set maximum
+ticket lifetimes.  This interface replaces the policy.c stub functions.
+
+Add check_kdcpolicy_as() and check_kdcpolicy_tgs() as entry functions.
+Call them after auth indicators and ticket lifetimes have been
+determined.
+
+Add a test module and a test script with basic kdcpolicy tests.  Add
+plugin interface documentation in doc/plugindev/policy.rst.
+
+Also authored by Matt Rogers <mrogers@redhat.com>.
+
+ticket: 8606 (new)
+(cherry picked from commit d0969f6a8170344031ef58fd2a161190f1edfb96)
+[rharwood@redhat.com: mention but do not use kadm_auth]
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ doc/plugindev/index.rst                        |   1 +
+ doc/plugindev/kdcpolicy.rst                    |  24 +++
+ src/Makefile.in                                |   1 +
+ src/configure.in                               |   1 +
+ src/include/Makefile.in                        |   1 +
+ src/include/k5-int.h                           |   4 +-
+ src/include/k5-trace.h                         |   5 +
+ src/include/krb5/kdcpolicy_plugin.h            | 128 ++++++++++++
+ src/kdc/do_as_req.c                            |   7 +
+ src/kdc/do_tgs_req.c                           |   6 +
+ src/kdc/kdc_util.c                             |   7 -
+ src/kdc/kdc_util.h                             |  11 -
+ src/kdc/main.c                                 |   8 +
+ src/kdc/policy.c                               | 267 +++++++++++++++++++++----
+ src/kdc/policy.h                               |  19 +-
+ src/kdc/tgs_policy.c                           |   6 -
+ src/lib/krb5/krb/plugin.c                      |   4 +-
+ src/plugins/kdcpolicy/test/Makefile.in         |  20 ++
+ src/plugins/kdcpolicy/test/deps                |   0
+ src/plugins/kdcpolicy/test/main.c              | 111 ++++++++++
+ src/plugins/kdcpolicy/test/policy_test.exports |   1 +
+ src/tests/Makefile.in                          |   1 +
+ src/tests/t_kdcpolicy.py                       |  57 ++++++
+ 23 files changed, 616 insertions(+), 74 deletions(-)
+ create mode 100644 doc/plugindev/kdcpolicy.rst
+ create mode 100644 src/include/krb5/kdcpolicy_plugin.h
+ create mode 100644 src/plugins/kdcpolicy/test/Makefile.in
+ create mode 100644 src/plugins/kdcpolicy/test/deps
+ create mode 100644 src/plugins/kdcpolicy/test/main.c
+ create mode 100644 src/plugins/kdcpolicy/test/policy_test.exports
+ create mode 100644 src/tests/t_kdcpolicy.py
+
+diff --git a/doc/plugindev/index.rst b/doc/plugindev/index.rst
+index 67dbc2790..0a012b82b 100644
+--- a/doc/plugindev/index.rst
++++ b/doc/plugindev/index.rst
+@@ -32,5 +32,6 @@ Contents
+    gssapi.rst
+    internal.rst
+    certauth.rst
++   kdcpolicy.rst
+ 
+ .. TODO: GSSAPI mechanism plugins
+diff --git a/doc/plugindev/kdcpolicy.rst b/doc/plugindev/kdcpolicy.rst
+new file mode 100644
+index 000000000..74f21f08f
+--- /dev/null
++++ b/doc/plugindev/kdcpolicy.rst
+@@ -0,0 +1,24 @@
++.. _kdcpolicy_plugin:
++
++KDC policy interface (kdcpolicy)
++================================
++
++The kdcpolicy interface was first introduced in release 1.16.  It
++allows modules to veto otherwise valid AS and TGS requests or restrict
++the lifetime and renew time of the resulting ticket.  For a detailed
++description of the kdcpolicy interface, see the header file
++``<krb5/kdcpolicy_plugin.h>``.
++
++The optional **check_as** and **check_tgs** functions allow the module
++to perform access control.  Additionally, a module can create and
++destroy module data with the **init** and **fini** methods.  Module
++data objects last for the lifetime of the KDC process, and are
++provided to all other methods.  The data has the type
++krb5_kdcpolicy_moddata, which should be cast to the appropriate
++internal type.
++
++kdcpolicy modules can optionally inspect principal entries.  To do
++this, the module must also include ``<kdb.h>`` to gain access to the
++principal entry structure definition.  As the KDB interface is
++explicitly not as stable as other public interfaces, modules which do
++this may not retain compatibility across releases.
+diff --git a/src/Makefile.in b/src/Makefile.in
+index ad8565056..e47bddcb1 100644
+--- a/src/Makefile.in
++++ b/src/Makefile.in
+@@ -21,6 +21,7 @@ SUBDIRS=util include lib \
+ 	plugins/kdb/db2 \
+ 	@ldap_plugin_dir@ \
+ 	plugins/kdb/test \
++	plugins/kdcpolicy/test \
+ 	plugins/preauth/otp \
+ 	plugins/preauth/pkinit \
+ 	plugins/preauth/test \
+diff --git a/src/configure.in b/src/configure.in
+index 4ae2c07d5..ee1983043 100644
+--- a/src/configure.in
++++ b/src/configure.in
+@@ -1470,6 +1470,7 @@ dnl	ccapi ccapi/lib ccapi/lib/unix ccapi/server ccapi/server/unix ccapi/test
+ 	plugins/kdb/db2/libdb2/recno
+ 	plugins/kdb/db2/libdb2/test
+ 	plugins/kdb/test
++	plugins/kdcpolicy/test
+ 	plugins/preauth/otp
+ 	plugins/preauth/test
+ 	plugins/authdata/greet_client
+diff --git a/src/include/Makefile.in b/src/include/Makefile.in
+index 0239338a1..6a3fa8242 100644
+--- a/src/include/Makefile.in
++++ b/src/include/Makefile.in
+@@ -144,6 +144,7 @@ install-headers-unix install: krb5/krb5.h profile.h
+ 	$(INSTALL_DATA) $(srcdir)/krb5/ccselect_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)ccselect_plugin.h
+ 	$(INSTALL_DATA) $(srcdir)/krb5/clpreauth_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)clpreauth_plugin.h
+ 	$(INSTALL_DATA) $(srcdir)/krb5/hostrealm_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)hostrealm_plugin.h
++	$(INSTALL_DATA) $(srcdir)/krb5/kdcpolicy_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)kdcpolicy_plugin.h
+ 	$(INSTALL_DATA) $(srcdir)/krb5/kdcpreauth_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)kdcpreauth_plugin.h
+ 	$(INSTALL_DATA) $(srcdir)/krb5/localauth_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)localauth_plugin.h
+ 	$(INSTALL_DATA) $(srcdir)/krb5/locate_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)locate_plugin.h
+diff --git a/src/include/k5-int.h b/src/include/k5-int.h
+index ed9c7bf75..39ffb9568 100644
+--- a/src/include/k5-int.h
++++ b/src/include/k5-int.h
+@@ -1157,7 +1157,9 @@ struct plugin_interface {
+ #define PLUGIN_INTERFACE_TLS         8
+ #define PLUGIN_INTERFACE_KDCAUTHDATA 9
+ #define PLUGIN_INTERFACE_CERTAUTH    10
+-#define PLUGIN_NUM_INTERFACES        11
++#define PLUGIN_INTERFACE_KADM5_AUTH  11
++#define PLUGIN_INTERFACE_KDCPOLICY   12
++#define PLUGIN_NUM_INTERFACES        13
+ 
+ /* Retrieve the plugin module of type interface_id and name modname,
+  * storing the result into module. */
+diff --git a/src/include/k5-trace.h b/src/include/k5-trace.h
+index c75e264e0..2885408a2 100644
+--- a/src/include/k5-trace.h
++++ b/src/include/k5-trace.h
+@@ -454,4 +454,9 @@ void krb5int_trace(krb5_context context, const char *fmt, ...);
+ #define TRACE_GET_CRED_VIA_TKT_EXT_RETURN(c, ret) \
+     TRACE(c, "Got cred; {kerr}", ret)
+ 
++#define TRACE_KDCPOLICY_VTINIT_FAIL(c, ret)                             \
++    TRACE(c, "KDC policy module failed to init vtable: {kerr}", ret)
++#define TRACE_KDCPOLICY_INIT_SKIP(c, name)                              \
++    TRACE(c, "kadm5_auth module {str} declined to initialize", name)
++
+ #endif /* K5_TRACE_H */
+diff --git a/src/include/krb5/kdcpolicy_plugin.h b/src/include/krb5/kdcpolicy_plugin.h
+new file mode 100644
+index 000000000..c7592c5db
+--- /dev/null
++++ b/src/include/krb5/kdcpolicy_plugin.h
+@@ -0,0 +1,128 @@
++/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
++/* include/krb5/kdcpolicy_plugin.h - KDC policy plugin interface */
++/*
++ * Copyright (C) 2017 by Red Hat, Inc.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * * Redistributions of source code must retain the above copyright
++ *   notice, this list of conditions and the following disclaimer.
++ *
++ * * Redistributions in binary form must reproduce the above copyright
++ *   notice, this list of conditions and the following disclaimer in
++ *   the documentation and/or other materials provided with the
++ *   distribution.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
++ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ */
++
++/*
++ * Declarations for kdcpolicy plugin module implementors.
++ *
++ * The kdcpolicy pluggable interface currently has only one supported major
++ * version, which is 1.  Major version 1 has a current minor version number of
++ * 1.
++ *
++ * kdcpolicy plugin modules should define a function named
++ * kdcpolicy_<modulename>_initvt, matching the signature:
++ *
++ *   krb5_error_code
++ *   kdcpolicy_modname_initvt(krb5_context context, int maj_ver, int min_ver,
++ *                            krb5_plugin_vtable vtable);
++ *
++ * The initvt function should:
++ *
++ * - Check that the supplied maj_ver number is supported by the module, or
++ *   return KRB5_PLUGIN_VER_NOTSUPP if it is not.
++ *
++ * - Cast the vtable pointer as appropriate for maj_ver:
++ *   maj_ver == 1: Cast to krb5_kdcpolicy_vtable
++ *
++ * - Initialize the methods of the vtable, stopping as appropriate for the
++ *   supplied min_ver.  Optional methods may be left uninitialized.
++ *
++ * Memory for the vtable is allocated by the caller, not by the module.
++ */
++
++#ifndef KRB5_POLICY_PLUGIN_H
++#define KRB5_POLICY_PLUGIN_H
++
++#include <krb5/krb5.h>
++
++/* Abstract module datatype. */
++typedef struct krb5_kdcpolicy_moddata_st *krb5_kdcpolicy_moddata;
++
++/* A module can optionally include kdb.h to inspect principal entries when
++ * authorizing requests. */
++struct _krb5_db_entry_new;
++
++/*
++ * Optional: Initialize module data.  Return 0 on success,
++ * KRB5_PLUGIN_NO_HANDLE if the module is inoperable (due to configuration, for
++ * example), and any other error code to abort KDC startup.  Optionally set
++ * *data_out to a module data object to be passed to future calls.
++ */
++typedef krb5_error_code
++(*krb5_kdcpolicy_init_fn)(krb5_context context,
++                          krb5_kdcpolicy_moddata *data_out);
++
++/* Optional: Clean up module data. */
++typedef krb5_error_code
++(*krb5_kdcpolicy_fini_fn)(krb5_context context,
++                          krb5_kdcpolicy_moddata moddata);
++
++/*
++ * Optional: return an error code and set status to an appropriate string
++ * literal to deny an AS request; otherwise return 0.  lifetime_out, if set,
++ * restricts the ticket lifetime.  renew_lifetime_out, if set, restricts the
++ * ticket renewable lifetime.
++ */
++typedef krb5_error_code
++(*krb5_kdcpolicy_check_as_fn)(krb5_context context,
++                              krb5_kdcpolicy_moddata moddata,
++                              const krb5_kdc_req *request,
++                              const struct _krb5_db_entry_new *client,
++                              const struct _krb5_db_entry_new *server,
++                              const char *const *auth_indicators,
++                              const char **status, krb5_deltat *lifetime_out,
++                              krb5_deltat *renew_lifetime_out);
++
++/*
++ * Optional: return an error code and set status to an appropriate string
++ * literal to deny a TGS request; otherwise return 0.  lifetime_out, if set,
++ * restricts the ticket lifetime.  renew_lifetime_out, if set, restricts the
++ * ticket renewable lifetime.
++ */
++typedef krb5_error_code
++(*krb5_kdcpolicy_check_tgs_fn)(krb5_context context,
++                               krb5_kdcpolicy_moddata moddata,
++                               const krb5_kdc_req *request,
++                               const struct _krb5_db_entry_new *server,
++                               const krb5_ticket *ticket,
++                               const char *const *auth_indicators,
++                               const char **status, krb5_deltat *lifetime_out,
++                               krb5_deltat *renew_lifetime_out);
++
++typedef struct krb5_kdcpolicy_vtable_st {
++    const char *name;
++    krb5_kdcpolicy_init_fn init;
++    krb5_kdcpolicy_fini_fn fini;
++    krb5_kdcpolicy_check_as_fn check_as;
++    krb5_kdcpolicy_check_tgs_fn check_tgs;
++} *krb5_kdcpolicy_vtable;
++
++#endif /* KRB5_POLICY_PLUGIN_H */
+diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c
+index 59a39cd30..241b05b40 100644
+--- a/src/kdc/do_as_req.c
++++ b/src/kdc/do_as_req.c
+@@ -207,6 +207,13 @@ finish_process_as_req(struct as_req_state *state, krb5_error_code errcode)
+ 
+     state->ticket_reply.enc_part2 = &state->enc_tkt_reply;
+ 
++    errcode = check_kdcpolicy_as(kdc_context, state->request, state->client,
++                                 state->server, state->auth_indicators,
++                                 state->kdc_time, &state->enc_tkt_reply.times,
++                                 &state->status);
++    if (errcode)
++        goto egress;
++
+     /*
+      * Find the server key
+      */
+diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c
+index aacd2f20d..4c722a4a3 100644
+--- a/src/kdc/do_tgs_req.c
++++ b/src/kdc/do_tgs_req.c
+@@ -518,6 +518,12 @@ process_tgs_req(struct server_handle *handle, krb5_data *pkt,
+     kdc_get_ticket_renewtime(kdc_active_realm, request, header_enc_tkt, client,
+                              server, &enc_tkt_reply);
+ 
++    errcode = check_kdcpolicy_tgs(kdc_context, request, server, header_ticket,
++                                  auth_indicators, kdc_time,
++                                  &enc_tkt_reply.times, &status);
++    if (errcode)
++        goto cleanup;
++
+     /*
+      * Set authtime to be the same as header or evidence ticket's
+      */
+diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
+index 778a629e5..8cbdf2c5b 100644
+--- a/src/kdc/kdc_util.c
++++ b/src/kdc/kdc_util.c
+@@ -642,7 +642,6 @@ validate_as_request(kdc_realm_t *kdc_active_realm,
+                     krb5_db_entry server, krb5_timestamp kdc_time,
+                     const char **status, krb5_pa_data ***e_data)
+ {
+-    int errcode;
+     krb5_error_code ret;
+ 
+     /*
+@@ -750,12 +749,6 @@ validate_as_request(kdc_realm_t *kdc_active_realm,
+     if (ret && ret != KRB5_PLUGIN_OP_NOTSUPP)
+         return errcode_to_protocol(ret);
+ 
+-    /* Check against local policy. */
+-    errcode = against_local_policy_as(request, client, server,
+-                                      kdc_time, status, e_data);
+-    if (errcode)
+-        return errcode;
+-
+     return 0;
+ }
+ 
+diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h
+index 672f94380..dcedfd538 100644
+--- a/src/kdc/kdc_util.h
++++ b/src/kdc/kdc_util.h
+@@ -166,17 +166,6 @@ kdc_err(krb5_context call_context, errcode_t code, const char *fmt, ...)
+ #endif
+     ;
+ 
+-/* policy.c */
+-int
+-against_local_policy_as (krb5_kdc_req *, krb5_db_entry,
+-                         krb5_db_entry, krb5_timestamp,
+-                         const char **, krb5_pa_data ***);
+-
+-int
+-against_local_policy_tgs (krb5_kdc_req *, krb5_db_entry,
+-                          krb5_ticket *, const char **,
+-                          krb5_pa_data ***);
+-
+ /* kdc_preauth.c */
+ krb5_boolean
+ enctype_requires_etype_info_2(krb5_enctype enctype);
+diff --git a/src/kdc/main.c b/src/kdc/main.c
+index a4dffb29a..ccac3a759 100644
+--- a/src/kdc/main.c
++++ b/src/kdc/main.c
+@@ -31,6 +31,7 @@
+ #include "kdc_util.h"
+ #include "kdc_audit.h"
+ #include "extern.h"
++#include "policy.h"
+ #include "kdc5_err.h"
+ #include "kdb_kt.h"
+ #include "net-server.h"
+@@ -986,6 +987,12 @@ int main(int argc, char **argv)
+ 
+     load_preauth_plugins(&shandle, kcontext, ctx);
+     load_authdata_plugins(kcontext);
++    retval = load_kdcpolicy_plugins(kcontext);
++    if (retval) {
++        kdc_err(kcontext, retval, _("while loading KDC policy plugin"));
++        finish_realms();
++        return 1;
++    }
+ 
+     retval = setup_sam();
+     if (retval) {
+@@ -1068,6 +1075,7 @@ int main(int argc, char **argv)
+     krb5_klog_syslog(LOG_INFO, _("shutting down"));
+     unload_preauth_plugins(kcontext);
+     unload_authdata_plugins(kcontext);
++    unload_kdcpolicy_plugins(kcontext);
+     unload_audit_modules(kcontext);
+     krb5_klog_close(kcontext);
+     finish_realms();
+diff --git a/src/kdc/policy.c b/src/kdc/policy.c
+index 6cba4303f..e49644e06 100644
+--- a/src/kdc/policy.c
++++ b/src/kdc/policy.c
+@@ -1,67 +1,246 @@
+ /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+ /* kdc/policy.c - Policy decision routines for KDC */
+ /*
+- * Copyright 1990 by the Massachusetts Institute of Technology.
++ * Copyright (C) 2017 by Red Hat, Inc.
++ * 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.
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
+  *
+- * 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.
++ * * Redistributions of source code must retain the above copyright
++ *   notice, this list of conditions and the following disclaimer.
++ *
++ * * Redistributions in binary form must reproduce the above copyright
++ *   notice, this list of conditions and the following disclaimer in
++ *   the documentation and/or other materials provided with the
++ *   distribution.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
++ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
+  */
+ 
+ #include "k5-int.h"
+ #include "kdc_util.h"
+ #include "extern.h"
++#include "policy.h"
++#include "adm_proto.h"
++#include <krb5/kdcpolicy_plugin.h>
++#include <syslog.h>
+ 
+-int
+-against_local_policy_as(register krb5_kdc_req *request, krb5_db_entry client,
+-                        krb5_db_entry server, krb5_timestamp kdc_time,
+-                        const char **status, krb5_pa_data ***e_data)
++typedef struct kdcpolicy_handle_st {
++    struct krb5_kdcpolicy_vtable_st vt;
++    krb5_kdcpolicy_moddata moddata;
++} *kdcpolicy_handle;
++
++static kdcpolicy_handle *handles;
++
++static void
++free_indicators(char **ais)
+ {
+-#if 0
+-    /* An AS request must include the addresses field */
+-    if (request->addresses == 0) {
+-        *status = "NO ADDRESS";
+-        return KRB5KDC_ERR_POLICY;
+-    }
+-#endif
++    size_t i;
+ 
+-    return 0;                   /* not against policy */
++    if (ais == NULL)
++        return;
++    for (i = 0; ais[i] != NULL; i++)
++        free(ais[i]);
++    free(ais);
++}
++
++/* Convert inds to a null-terminated list of C strings. */
++static krb5_error_code
++authind_strings(krb5_data *const *inds, char ***strs_out)
++{
++    krb5_error_code ret;
++    char **list = NULL;
++    size_t i, count;
++
++    *strs_out = NULL;
++
++    for (count = 0; inds != NULL && inds[count] != NULL; count++);
++    list = k5calloc(count + 1, sizeof(*list), &ret);
++    if (list == NULL)
++        goto error;
++
++    for (i = 0; i < count; i++) {
++        list[i] = k5memdup0(inds[i]->data, inds[i]->length, &ret);
++        if (list[i] == NULL)
++            goto error;
++    }
++
++    *strs_out = list;
++    return 0;
++
++error:
++    free_indicators(list);
++    return ret;
++}
++
++/* Constrain times->endtime to life and times->renew_till to rlife, relative to
++ * now. */
++static void
++update_ticket_times(krb5_ticket_times *times, krb5_timestamp now,
++                    krb5_deltat life, krb5_deltat rlife)
++{
++    if (life)
++        times->endtime = ts_min(ts_incr(now, life), times->endtime);
++    if (rlife)
++        times->renew_till = ts_min(ts_incr(now, rlife), times->renew_till);
++}
++
++/* Check an AS request against kdcpolicy modules, updating times with any
++ * module endtime constraints.  Set an appropriate status string on error. */
++krb5_error_code
++check_kdcpolicy_as(krb5_context context, const krb5_kdc_req *request,
++                   const krb5_db_entry *client, const krb5_db_entry *server,
++                   krb5_data *const *auth_indicators, krb5_timestamp kdc_time,
++                   krb5_ticket_times *times, const char **status)
++{
++    krb5_deltat life, rlife;
++    krb5_error_code ret;
++    kdcpolicy_handle *hp, h;
++    char **ais = NULL;
++
++    *status = NULL;
++
++    ret = authind_strings(auth_indicators, &ais);
++    if (ret)
++        goto done;
++
++    for (hp = handles; *hp != NULL; hp++) {
++        h = *hp;
++        if (h->vt.check_as == NULL)
++            continue;
++
++        ret = h->vt.check_as(context, h->moddata, request, client, server,
++                             (const char **)ais, status, &life, &rlife);
++        if (ret)
++            goto done;
++
++        update_ticket_times(times, kdc_time, life, rlife);
++    }
++
++done:
++    free_indicators(ais);
++    return ret;
+ }
+ 
+ /*
+- * This is where local policy restrictions for the TGS should placed.
++ * Check the TGS request against the local TGS policy.  Accepts an
++ * authentication indicator for the module policy decisions.  Returns 0 and a
++ * NULL status string on success.
+  */
+ krb5_error_code
+-against_local_policy_tgs(register krb5_kdc_req *request, krb5_db_entry server,
+-                         krb5_ticket *ticket, const char **status,
+-                         krb5_pa_data ***e_data)
++check_kdcpolicy_tgs(krb5_context context, const krb5_kdc_req *request,
++                    const krb5_db_entry *server, const krb5_ticket *ticket,
++                    krb5_data *const *auth_indicators, krb5_timestamp kdc_time,
++                    krb5_ticket_times *times, const char **status)
+ {
+-#if 0
+-    /*
+-     * For example, if your site wants to disallow ticket forwarding,
+-     * you might do something like this:
+-     */
++    krb5_deltat life, rlife;
++    krb5_error_code ret;
++    kdcpolicy_handle *hp, h;
++    char **ais = NULL;
+ 
+-    if (isflagset(request->kdc_options, KDC_OPT_FORWARDED)) {
+-        *status = "FORWARD POLICY";
+-        return KRB5KDC_ERR_POLICY;
++    *status = NULL;
++
++    ret = authind_strings(auth_indicators, &ais);
++    if (ret)
++        goto done;
++
++    for (hp = handles; *hp != NULL; hp++) {
++        h = *hp;
++        if (h->vt.check_tgs == NULL)
++            continue;
++
++        ret = h->vt.check_tgs(context, h->moddata, request, server, ticket,
++                              (const char **)ais, status, &life, &rlife);
++        if (ret)
++            goto done;
++
++        update_ticket_times(times, kdc_time, life, rlife);
+     }
+-#endif
+ 
+-    return 0;                           /* not against policy */
++done:
++    free_indicators(ais);
++    return ret;
++}
++
++void
++unload_kdcpolicy_plugins(krb5_context context)
++{
++    kdcpolicy_handle *hp, h;
++
++    for (hp = handles; *hp != NULL; hp++) {
++        h = *hp;
++        if (h->vt.fini != NULL)
++            h->vt.fini(context, h->moddata);
++        free(h);
++    }
++    free(handles);
++    handles = NULL;
++}
++
++krb5_error_code
++load_kdcpolicy_plugins(krb5_context context)
++{
++    krb5_error_code ret;
++    krb5_plugin_initvt_fn *modules = NULL, *mod;
++    kdcpolicy_handle h;
++    size_t count;
++
++    ret = k5_plugin_load_all(context, PLUGIN_INTERFACE_KDCPOLICY, &modules);
++    if (ret)
++        goto cleanup;
++
++    for (count = 0; modules[count] != NULL; count++);
++    handles = k5calloc(count + 1, sizeof(*handles), &ret);
++    if (handles == NULL)
++        goto cleanup;
++
++    count = 0;
++    for (mod = modules; *mod != NULL; mod++) {
++        h = k5calloc(1, sizeof(*h), &ret);
++        if (h == NULL)
++            goto cleanup;
++
++        ret = (*mod)(context, 1, 1, (krb5_plugin_vtable)&h->vt);
++        if (ret) {              /* Version mismatch. */
++            TRACE_KDCPOLICY_VTINIT_FAIL(context, ret);
++            free(h);
++            continue;
++        }
++        if (h->vt.init != NULL) {
++            ret = h->vt.init(context, &h->moddata);
++            if (ret == KRB5_PLUGIN_NO_HANDLE) {
++                TRACE_KADM5_AUTH_INIT_SKIP(context, h->vt.name);
++                free(h);
++                continue;
++            }
++            if (ret) {
++                kdc_err(context, ret, _("while loading policy module %s"),
++                        h->vt.name);
++                free(h);
++                goto cleanup;
++            }
++        }
++        handles[count++] = h;
++    }
++
++    ret = 0;
++
++cleanup:
++    if (ret)
++        unload_kdcpolicy_plugins(context);
++    k5_plugin_free_modules(context, modules);
++    return ret;
+ }
+diff --git a/src/kdc/policy.h b/src/kdc/policy.h
+index 6b000dc90..2a57b0a01 100644
+--- a/src/kdc/policy.h
++++ b/src/kdc/policy.h
+@@ -26,11 +26,22 @@
+ #ifndef __KRB5_KDC_POLICY__
+ #define __KRB5_KDC_POLICY__
+ 
+-extern int against_postdate_policy (krb5_timestamp);
++krb5_error_code
++load_kdcpolicy_plugins(krb5_context context);
+ 
+-extern int against_flag_policy_as (const krb5_kdc_req *);
++void
++unload_kdcpolicy_plugins(krb5_context context);
+ 
+-extern int against_flag_policy_tgs (const krb5_kdc_req *,
+-                                    const krb5_ticket *);
++krb5_error_code
++check_kdcpolicy_as(krb5_context context, const krb5_kdc_req *request,
++                   const krb5_db_entry *client, const krb5_db_entry *server,
++                   krb5_data *const *auth_indicators, krb5_timestamp kdc_time,
++                   krb5_ticket_times *times, const char **status);
++
++krb5_error_code
++check_kdcpolicy_tgs(krb5_context context, const krb5_kdc_req *request,
++                    const krb5_db_entry *server, const krb5_ticket *ticket,
++                    krb5_data *const *auth_indicators, krb5_timestamp kdc_time,
++                    krb5_ticket_times *times, const char **status);
+ 
+ #endif /* __KRB5_KDC_POLICY__ */
+diff --git a/src/kdc/tgs_policy.c b/src/kdc/tgs_policy.c
+index d0f25d1b7..33cfbcd81 100644
+--- a/src/kdc/tgs_policy.c
++++ b/src/kdc/tgs_policy.c
+@@ -375,11 +375,5 @@ validate_tgs_request(kdc_realm_t *kdc_active_realm,
+     if (ret && ret != KRB5_PLUGIN_OP_NOTSUPP)
+         return errcode_to_protocol(ret);
+ 
+-    /* Check local policy. */
+-    errcode = against_local_policy_tgs(request, server, ticket,
+-                                       status, e_data);
+-    if (errcode)
+-        return errcode;
+-
+     return 0;
+ }
+diff --git a/src/lib/krb5/krb/plugin.c b/src/lib/krb5/krb/plugin.c
+index 17dd6bd30..31aaf661d 100644
+--- a/src/lib/krb5/krb/plugin.c
++++ b/src/lib/krb5/krb/plugin.c
+@@ -58,7 +58,9 @@ const char *interface_names[] = {
+     "audit",
+     "tls",
+     "kdcauthdata",
+-    "certauth"
++    "certauth",
++    "kadm5_auth",
++    "kdcpolicy",
+ };
+ 
+ /* Return the context's interface structure for id, or NULL if invalid. */
+diff --git a/src/plugins/kdcpolicy/test/Makefile.in b/src/plugins/kdcpolicy/test/Makefile.in
+new file mode 100644
+index 000000000..b81f1a7ce
+--- /dev/null
++++ b/src/plugins/kdcpolicy/test/Makefile.in
+@@ -0,0 +1,20 @@
++mydir=plugins$(S)policy$(S)test
++BUILDTOP=$(REL)..$(S)..$(S)..
++
++LIBBASE=policy_test
++LIBMAJOR=0
++LIBMINOR=0
++RELDIR=../plugins/kdcpolicy/test
++SHLIB_EXPDEPS=$(KRB5_BASE_DEPLIBS)
++SHLIB_EXPLIBS=$(KRB5_BASE_LIBS)
++
++STLIBOBJS=main.o
++
++SRCS=$(srcdir)/main.c
++
++all-unix: all-libs
++install-unix:
++clean-unix:: clean-libs clean-libobjs
++
++@libnover_frag@
++@libobj_frag@
+diff --git a/src/plugins/kdcpolicy/test/deps b/src/plugins/kdcpolicy/test/deps
+new file mode 100644
+index 000000000..e69de29bb
+diff --git a/src/plugins/kdcpolicy/test/main.c b/src/plugins/kdcpolicy/test/main.c
+new file mode 100644
+index 000000000..eb8fde053
+--- /dev/null
++++ b/src/plugins/kdcpolicy/test/main.c
+@@ -0,0 +1,111 @@
++/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
++/* include/krb5/kdcpolicy_plugin.h - KDC policy plugin interface */
++/*
++ * Copyright (C) 2017 by Red Hat, Inc.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * * Redistributions of source code must retain the above copyright
++ *   notice, this list of conditions and the following disclaimer.
++ *
++ * * Redistributions in binary form must reproduce the above copyright
++ *   notice, this list of conditions and the following disclaimer in
++ *   the documentation and/or other materials provided with the
++ *   distribution.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
++ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ */
++
++#include "k5-int.h"
++#include "kdb.h"
++#include <krb5/kdcpolicy_plugin.h>
++
++static krb5_error_code
++output_from_indicator(const char *const *auth_indicators,
++                      krb5_deltat *lifetime_out,
++                      krb5_deltat *renew_lifetime_out,
++                      const char **status)
++{
++    if (auth_indicators[0] == NULL) {
++        *status = NULL;
++        return 0;
++    }
++
++    if (strcmp(auth_indicators[0], "ONE_HOUR") == 0) {
++        *lifetime_out = 3600;
++        *renew_lifetime_out = *lifetime_out * 2;
++        return 0;
++    } else if (strcmp(auth_indicators[0], "SEVEN_HOURS") == 0) {
++        *lifetime_out = 7 * 3600;
++        *renew_lifetime_out = *lifetime_out * 2;
++        return 0;
++    }
++
++    *status = "LOCAL_POLICY";
++    return KRB5KDC_ERR_POLICY;
++}
++
++static krb5_error_code
++test_check_as(krb5_context context, krb5_kdcpolicy_moddata moddata,
++              const krb5_kdc_req *request, const krb5_db_entry *client,
++              const krb5_db_entry *server, const char *const *auth_indicators,
++              const char **status, krb5_deltat *lifetime_out,
++              krb5_deltat *renew_lifetime_out)
++{
++    if (request->client != NULL && request->client->length >= 1 &&
++        data_eq_string(request->client->data[0], "fail")) {
++        *status = "LOCAL_POLICY";
++        return KRB5KDC_ERR_POLICY;
++    }
++    return output_from_indicator(auth_indicators, lifetime_out,
++                                 renew_lifetime_out, status);
++}
++
++static krb5_error_code
++test_check_tgs(krb5_context context, krb5_kdcpolicy_moddata moddata,
++               const krb5_kdc_req *request, const krb5_db_entry *server,
++               const krb5_ticket *ticket, const char *const *auth_indicators,
++               const char **status, krb5_deltat *lifetime_out,
++               krb5_deltat *renew_lifetime_out)
++{
++    if (request->server != NULL && request->server->length >= 1 &&
++        data_eq_string(request->server->data[0], "fail")) {
++        *status = "LOCAL_POLICY";
++        return KRB5KDC_ERR_POLICY;
++    }
++    return output_from_indicator(auth_indicators, lifetime_out,
++                                 renew_lifetime_out, status);
++}
++
++krb5_error_code
++kdcpolicy_test_initvt(krb5_context context, int maj_ver, int min_ver,
++                      krb5_plugin_vtable vtable);
++krb5_error_code
++kdcpolicy_test_initvt(krb5_context context, int maj_ver, int min_ver,
++                      krb5_plugin_vtable vtable)
++{
++    krb5_kdcpolicy_vtable vt;
++
++    if (maj_ver != 1)
++        return KRB5_PLUGIN_VER_NOTSUPP;
++
++    vt = (krb5_kdcpolicy_vtable)vtable;
++    vt->name = "test";
++    vt->check_as = test_check_as;
++    vt->check_tgs = test_check_tgs;
++    return 0;
++}
+diff --git a/src/plugins/kdcpolicy/test/policy_test.exports b/src/plugins/kdcpolicy/test/policy_test.exports
+new file mode 100644
+index 000000000..9682ec74f
+--- /dev/null
++++ b/src/plugins/kdcpolicy/test/policy_test.exports
+@@ -0,0 +1 @@
++kdcpolicy_test_initvt
+diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in
+index 2b3112537..a2093108b 100644
+--- a/src/tests/Makefile.in
++++ b/src/tests/Makefile.in
+@@ -169,6 +169,7 @@ check-pytests: localauth plugorder rdreq responder s2p s4u2proxy unlockiter
+ 	$(RUNPYTEST) $(srcdir)/t_tabdump.py $(PYTESTFLAGS)
+ 	$(RUNPYTEST) $(srcdir)/t_certauth.py $(PYTESTFLAGS)
+ 	$(RUNPYTEST) $(srcdir)/t_y2038.py $(PYTESTFLAGS)
++	$(RUNPYTEST) $(srcdir)/t_kdcpolicy.py $(PYTESTFLAGS)
+ 
+ clean:
+ 	$(RM) adata etinfo forward gcred hist hooks hrealm icred kdbtest
+diff --git a/src/tests/t_kdcpolicy.py b/src/tests/t_kdcpolicy.py
+new file mode 100644
+index 000000000..6a745b959
+--- /dev/null
++++ b/src/tests/t_kdcpolicy.py
+@@ -0,0 +1,57 @@
++#!/usr/bin/python
++from k5test import *
++from datetime import datetime
++import re
++
++testpreauth = os.path.join(buildtop, 'plugins', 'preauth', 'test', 'test.so')
++testpolicy = os.path.join(buildtop, 'plugins', 'kdcpolicy', 'test',
++                          'policy_test.so')
++krb5_conf = {'plugins': {'kdcpreauth': {'module': 'test:' + testpreauth},
++                         'clpreauth': {'module': 'test:' + testpreauth},
++                         'kdcpolicy': {'module': 'test:' + testpolicy}}}
++kdc_conf = {'realms': {'$realm': {'default_principal_flags': '+preauth',
++                                  'max_renewable_life': '1d'}}}
++realm = K5Realm(krb5_conf=krb5_conf, kdc_conf=kdc_conf)
++
++realm.run([kadminl, 'addprinc', '-pw', password('fail'), 'fail'])
++
++def verify_time(out, target_time):
++    times = re.findall(r'\d\d/\d\d/\d\d \d\d:\d\d:\d\d', out)
++    times = [datetime.strptime(t, '%m/%d/%y %H:%M:%S') for t in times]
++    while len(times) > 0:
++        starttime = times.pop(0)
++        endtime = times.pop(0)
++        renewtime = times.pop(0)
++
++        if str(endtime - starttime) != target_time:
++            fail('unexpected lifetime value')
++        if str(renewtime - endtime) != target_time:
++            fail('unexpected renewable value')
++
++rflags = ['-r', '1d', '-l', '12h']
++
++# Test AS+TGS success path.
++realm.kinit(realm.user_princ, password('user'),
++            rflags + ['-X', 'indicators=SEVEN_HOURS'])
++realm.run([kvno, realm.host_princ])
++realm.run(['./adata', realm.host_princ], expected_msg='+97: [SEVEN_HOURS]')
++out = realm.run([klist, realm.ccache, '-e'])
++verify_time(out, '7:00:00')
++
++# Test AS+TGS success path with different values.
++realm.kinit(realm.user_princ, password('user'),
++            rflags + ['-X', 'indicators=ONE_HOUR'])
++realm.run([kvno, realm.host_princ])
++realm.run(['./adata', realm.host_princ], expected_msg='+97: [ONE_HOUR]')
++out = realm.run([klist, realm.ccache, '-e'])
++verify_time(out, '1:00:00')
++
++# Test TGS failure path (using previous creds).
++realm.run([kvno, 'fail@%s' % realm.realm], expected_code=1,
++          expected_msg='KDC policy rejects request')
++
++# Test AS failure path.
++realm.kinit('fail@%s' % realm.realm, password('fail'),
++            expected_code=1, expected_msg='KDC policy rejects request')
++
++success('kdcpolicy tests')
diff --git a/SOURCES/Add-PKINIT-UPN-tests-to-t_pkinit.py.patch b/SOURCES/Add-PKINIT-UPN-tests-to-t_pkinit.py.patch
new file mode 100644
index 0000000..5d43ea7
--- /dev/null
+++ b/SOURCES/Add-PKINIT-UPN-tests-to-t_pkinit.py.patch
@@ -0,0 +1,102 @@
+From f726fe232a16a51ca277b660c61aa9cfc2f512f1 Mon Sep 17 00:00:00 2001
+From: Matt Rogers <mrogers@redhat.com>
+Date: Fri, 9 Dec 2016 11:43:27 -0500
+Subject: [PATCH] Add PKINIT UPN tests to t_pkinit.py
+
+[ghudson@mit.edu: simplify and explain tests; add test for
+id-pkinit-san match against canonicalized client principal]
+
+ticket: 8528
+(cherry picked from commit d520fd3f032121b61b22681838af96ee505fe44d)
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/tests/t_pkinit.py | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 57 insertions(+)
+
+diff --git a/src/tests/t_pkinit.py b/src/tests/t_pkinit.py
+index 526473b42..ac4d326b6 100755
+--- a/src/tests/t_pkinit.py
++++ b/src/tests/t_pkinit.py
+@@ -23,6 +23,9 @@ privkey_pem = os.path.join(certs, 'privkey.pem')
+ privkey_enc_pem = os.path.join(certs, 'privkey-enc.pem')
+ user_p12 = os.path.join(certs, 'user.p12')
+ user_enc_p12 = os.path.join(certs, 'user-enc.p12')
++user_upn_p12 = os.path.join(certs, 'user-upn.p12')
++user_upn2_p12 = os.path.join(certs, 'user-upn2.p12')
++user_upn3_p12 = os.path.join(certs, 'user-upn3.p12')
+ path = os.path.join(os.getcwd(), 'testdir', 'tmp-pkinit-certs')
+ path_enc = os.path.join(os.getcwd(), 'testdir', 'tmp-pkinit-certs-enc')
+ 
+@@ -36,6 +39,20 @@ pkinit_kdc_conf = {'realms': {'$realm': {
+ restrictive_kdc_conf = {'realms': {'$realm': {
+             'restrict_anonymous_to_tgt': 'true' }}}
+ 
++testprincs = {'krbtgt/KRBTEST.COM': {'keys': 'aes128-cts'},
++              'user': {'keys': 'aes128-cts', 'flags': '+preauth'},
++              'user2': {'keys': 'aes128-cts', 'flags': '+preauth'}}
++alias_kdc_conf = {'realms': {'$realm': {
++            'default_principal_flags': '+preauth',
++            'pkinit_eku_checking': 'none',
++            'pkinit_allow_upn': 'true',
++            'pkinit_identity': 'FILE:%s,%s' % (kdc_pem, privkey_pem),
++            'database_module': 'test'}},
++                  'dbmodules': {'test': {
++                      'db_library': 'test',
++                      'alias': {'user@krbtest.com': 'user'},
++                      'princs': testprincs}}}
++
+ file_identity = 'FILE:%s,%s' % (user_pem, privkey_pem)
+ file_enc_identity = 'FILE:%s,%s' % (user_pem, privkey_enc_pem)
+ dir_identity = 'DIR:%s' % path
+@@ -45,11 +62,51 @@ dir_file_identity = 'FILE:%s,%s' % (os.path.join(path, 'user.crt'),
+ dir_file_enc_identity = 'FILE:%s,%s' % (os.path.join(path_enc, 'user.crt'),
+                                         os.path.join(path_enc, 'user.key'))
+ p12_identity = 'PKCS12:%s' % user_p12
++p12_upn_identity = 'PKCS12:%s' % user_upn_p12
++p12_upn2_identity = 'PKCS12:%s' % user_upn2_p12
++p12_upn3_identity = 'PKCS12:%s' % user_upn3_p12
+ p12_enc_identity = 'PKCS12:%s' % user_enc_p12
+ p11_identity = 'PKCS11:soft-pkcs11.so'
+ p11_token_identity = ('PKCS11:module_name=soft-pkcs11.so:'
+                       'slotid=1:token=SoftToken (token)')
+ 
++# Start a realm with the test kdb module for the following UPN SAN tests.
++realm = K5Realm(krb5_conf=pkinit_krb5_conf, kdc_conf=alias_kdc_conf,
++                create_kdb=False)
++realm.start_kdc()
++
++# Compatibility check: cert contains UPN "user", which matches the
++# request principal user@KRBTEST.COM if parsed as a normal principal.
++realm.kinit(realm.user_princ,
++            flags=['-X', 'X509_user_identity=%s' % p12_upn2_identity])
++
++# Compatibility check: cert contains UPN "user@KRBTEST.COM", which matches
++# the request principal user@KRBTEST.COM if parsed as a normal principal.
++realm.kinit(realm.user_princ,
++            flags=['-X', 'X509_user_identity=%s' % p12_upn3_identity])
++
++# Cert contains UPN "user@krbtest.com" which is aliased to the request
++# principal.
++realm.kinit(realm.user_princ,
++            flags=['-X', 'X509_user_identity=%s' % p12_upn_identity])
++
++# Test an id-pkinit-san match to a post-canonical principal.
++realm.kinit('user@krbtest.com',
++            flags=['-E', '-X', 'X509_user_identity=%s' % p12_identity])
++
++# Test a UPN match to a post-canonical principal.  (This only works
++# for the cert with the UPN containing just "user", as we don't allow
++# UPN reparsing when comparing to the canonicalized client principal.)
++realm.kinit('user@krbtest.com',
++            flags=['-E', '-X', 'X509_user_identity=%s' % p12_upn2_identity])
++
++# Test a mismatch.
++out = realm.run([kinit, '-X', 'X509_user_identity=%s' % p12_upn2_identity,
++                 'user2'], expected_code=1)
++if 'kinit: Client name mismatch while getting initial credentials' not in out:
++    fail('Wrong error for UPN SAN mismatch')
++realm.stop()
++
+ realm = K5Realm(krb5_conf=pkinit_krb5_conf, kdc_conf=pkinit_kdc_conf,
+                 get_creds=False)
+ 
diff --git a/SOURCES/Add-certauth-pluggable-interface.patch b/SOURCES/Add-certauth-pluggable-interface.patch
new file mode 100644
index 0000000..79bd718
--- /dev/null
+++ b/SOURCES/Add-certauth-pluggable-interface.patch
@@ -0,0 +1,1147 @@
+From 5a0b9b43a070c273ae4ee39ee460fa759ff9d934 Mon Sep 17 00:00:00 2001
+From: Matt Rogers <mrogers@redhat.com>
+Date: Tue, 28 Feb 2017 15:55:24 -0500
+Subject: [PATCH] Add certauth pluggable interface
+
+Add the header include/krb5/certauth_plugin.h, defining a pluggable
+interface to control authorization of PKINIT client certificates.
+
+Add the "pkinit_san" and "pkinit_eku" builtin certauth modules and
+related PKINIT crypto X.509 helper functions.  Add authorize_cert() as
+the entry function for certauth plugin module checks called in
+pkinit_server_verify_padata().  Modify kdcpreauth_moddata to hold the
+list of certauth module handles, and load the modules when the PKINIT
+kdcpreauth server plugin is initialized.  Change
+crypto_retrieve_X509_sans() to return ENOENT when no SAN is found.
+
+Add test modules in plugins/certauth/test.  Create t_certauth.py with
+basic certauth tests.  Add plugin interface documentation in
+doc/plugindev/certauth.rst and doc/admin/krb5_conf.rst.
+
+[ghudson@mit.edu: simplified code, edited docs]
+
+ticket: 8561 (new)
+(cherry picked from commit b619ce84470519bea65470be3263cd85fba94f57)
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ doc/admin/conf_files/krb5_conf.rst                 |  21 ++
+ doc/plugindev/certauth.rst                         |  27 ++
+ doc/plugindev/index.rst                            |   1 +
+ src/Makefile.in                                    |   1 +
+ src/configure.in                                   |   1 +
+ src/include/Makefile.in                            |   1 +
+ src/include/k5-int.h                               |   3 +-
+ src/include/krb5/certauth_plugin.h                 | 103 +++++++
+ src/lib/krb5/krb/plugin.c                          |   3 +-
+ src/plugins/certauth/test/Makefile.in              |  20 ++
+ src/plugins/certauth/test/certauth_test.exports    |   2 +
+ src/plugins/certauth/test/deps                     |  14 +
+ src/plugins/certauth/test/main.c                   | 209 +++++++++++++
+ src/plugins/preauth/pkinit/pkinit_crypto.h         |   4 +
+ src/plugins/preauth/pkinit/pkinit_crypto_openssl.c |  30 ++
+ src/plugins/preauth/pkinit/pkinit_srv.c            | 335 ++++++++++++++++++---
+ src/plugins/preauth/pkinit/pkinit_trace.h          |   5 +
+ src/tests/Makefile.in                              |   1 +
+ src/tests/t_certauth.py                            |  47 +++
+ 19 files changed, 786 insertions(+), 42 deletions(-)
+ create mode 100644 doc/plugindev/certauth.rst
+ create mode 100644 src/include/krb5/certauth_plugin.h
+ create mode 100644 src/plugins/certauth/test/Makefile.in
+ create mode 100644 src/plugins/certauth/test/certauth_test.exports
+ create mode 100644 src/plugins/certauth/test/deps
+ create mode 100644 src/plugins/certauth/test/main.c
+ create mode 100644 src/tests/t_certauth.py
+
+diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
+index 653aad613..c0e4349c0 100644
+--- a/doc/admin/conf_files/krb5_conf.rst
++++ b/doc/admin/conf_files/krb5_conf.rst
+@@ -858,6 +858,27 @@ built-in modules exist for this interface:
+     This module authorizes a principal to a local account if the
+     principal name maps to the local account name.
+ 
++.. _certauth:
++
++certauth interface
++##################
++
++The certauth section (introduced in release 1.16) controls modules for
++the certificate authorization interface, which determines whether a
++certificate is allowed to preauthenticate a user via PKINIT.  The
++following built-in modules exist for this interface:
++
++**pkinit_san**
++    This module authorizes the certificate if it contains a PKINIT
++    Subject Alternative Name for the requested client principal, or a
++    Microsoft UPN SAN matching the principal if **pkinit_allow_upn**
++    is set to true for the realm.
++
++**pkinit_eku**
++    This module rejects the certificate if it does not contain an
++    Extended Key Usage attribute consistent with the
++    **pkinit_eku_checking** value for the realm.
++
+ 
+ PKINIT options
+ --------------
+diff --git a/doc/plugindev/certauth.rst b/doc/plugindev/certauth.rst
+new file mode 100644
+index 000000000..8a7f7c5eb
+--- /dev/null
++++ b/doc/plugindev/certauth.rst
+@@ -0,0 +1,27 @@
++.. _certauth_plugin:
++
++PKINIT certificate authorization interface (certauth)
++=====================================================
++
++The certauth interface was first introduced in release 1.16.  It
++allows customization of the X.509 certificate attribute requirements
++placed on certificates used by PKINIT enabled clients.  For a detailed
++description of the certauth interface, see the header file
++``<krb5/certauth_plugin.h>``
++
++A certauth module implements the **authorize** method to determine
++whether a client's certificate is authorized to authenticate a client
++principal.  **authorize** receives the DER-encoded certificate, the
++requested client principal, and a pointer to the client's
++krb5_db_entry (for modules that link against libkdb5).  It returns the
++authorization status and optionally outputs a list of authentication
++indicator strings to be added to the ticket.  A module must use its
++own internal or library-provided ASN.1 certificate decoder.
++
++A module can optionally create and destroy module data with the
++**init** and **fini** methods.  Module data objects last for the
++lifetime of the KDC process.
++
++If a module allocates and returns a list of authentication indicators
++from **authorize**, it must also implement the **free_ind** method
++to free the list.
+diff --git a/doc/plugindev/index.rst b/doc/plugindev/index.rst
+index 3fb921778..67dbc2790 100644
+--- a/doc/plugindev/index.rst
++++ b/doc/plugindev/index.rst
+@@ -31,5 +31,6 @@ Contents
+    profile.rst
+    gssapi.rst
+    internal.rst
++   certauth.rst
+ 
+ .. TODO: GSSAPI mechanism plugins
+diff --git a/src/Makefile.in b/src/Makefile.in
+index 2ebf2fb4d..b0249778c 100644
+--- a/src/Makefile.in
++++ b/src/Makefile.in
+@@ -17,6 +17,7 @@ SUBDIRS=util include lib \
+ 	plugins/pwqual/test \
+ 	plugins/authdata/greet_server \
+ 	plugins/authdata/greet_client \
++	plugins/certauth/test \
+ 	plugins/kdb/db2 \
+ 	@ldap_plugin_dir@ \
+ 	plugins/kdb/test \
+diff --git a/src/configure.in b/src/configure.in
+index acf3a458b..24f653f0d 100644
+--- a/src/configure.in
++++ b/src/configure.in
+@@ -1451,6 +1451,7 @@ dnl	ccapi ccapi/lib ccapi/lib/unix ccapi/server ccapi/server/unix ccapi/test
+ 
+ 	kdc slave config-files build-tools man doc include
+ 
++	plugins/certauth/test
+ 	plugins/hostrealm/test
+ 	plugins/localauth/test
+ 	plugins/kadm5_hook/test
+diff --git a/src/include/Makefile.in b/src/include/Makefile.in
+index f5b921833..0239338a1 100644
+--- a/src/include/Makefile.in
++++ b/src/include/Makefile.in
+@@ -140,6 +140,7 @@ install-headers-unix install: krb5/krb5.h profile.h
+ 	$(INSTALL_DATA) $(srcdir)/krb5.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5.h
+ 	$(INSTALL_DATA) $(srcdir)/kdb.h $(DESTDIR)$(KRB5_INCDIR)$(S)kdb.h
+ 	$(INSTALL_DATA) krb5/krb5.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)krb5.h
++	$(INSTALL_DATA) $(srcdir)/krb5/certauth_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)certauth_plugin.h
+ 	$(INSTALL_DATA) $(srcdir)/krb5/ccselect_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)ccselect_plugin.h
+ 	$(INSTALL_DATA) $(srcdir)/krb5/clpreauth_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)clpreauth_plugin.h
+ 	$(INSTALL_DATA) $(srcdir)/krb5/hostrealm_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)hostrealm_plugin.h
+diff --git a/src/include/k5-int.h b/src/include/k5-int.h
+index 173cb0264..cea644d0a 100644
+--- a/src/include/k5-int.h
++++ b/src/include/k5-int.h
+@@ -1156,7 +1156,8 @@ struct plugin_interface {
+ #define PLUGIN_INTERFACE_AUDIT       7
+ #define PLUGIN_INTERFACE_TLS         8
+ #define PLUGIN_INTERFACE_KDCAUTHDATA 9
+-#define PLUGIN_NUM_INTERFACES        10
++#define PLUGIN_INTERFACE_CERTAUTH    10
++#define PLUGIN_NUM_INTERFACES        11
+ 
+ /* Retrieve the plugin module of type interface_id and name modname,
+  * storing the result into module. */
+diff --git a/src/include/krb5/certauth_plugin.h b/src/include/krb5/certauth_plugin.h
+new file mode 100644
+index 000000000..f22fc1e84
+--- /dev/null
++++ b/src/include/krb5/certauth_plugin.h
+@@ -0,0 +1,103 @@
++/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
++/* include/krb5/certauth_plugin.h - certauth plugin header. */
++/*
++ * Copyright (C) 2017 by Red Hat, Inc.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * * Redistributions of source code must retain the above copyright
++ *   notice, this list of conditions and the following disclaimer.
++ *
++ * * Redistributions in binary form must reproduce the above copyright
++ *   notice, this list of conditions and the following disclaimer in
++ *   the documentation and/or other materials provided with the
++ *   distribution.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
++ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ */
++
++/*
++ * Certificate authorization plugin interface.  The PKINIT server module uses
++ * this interface to check client certificate attributes after the certificate
++ * signature has been verified.
++ */
++#ifndef KRB5_CERTAUTH_PLUGIN_H
++#define KRB5_CERTAUTH_PLUGIN_H
++
++#include <krb5/krb5.h>
++#include <krb5/plugin.h>
++
++/* Abstract module data type. */
++typedef struct krb5_certauth_moddata_st *krb5_certauth_moddata;
++
++typedef struct _krb5_db_entry_new krb5_db_entry;
++
++/*
++ * Optional: Initialize module data.
++ */
++typedef krb5_error_code
++(*krb5_certauth_init_fn)(krb5_context context,
++                         krb5_certauth_moddata *moddata_out);
++
++/*
++ * Optional: Clean up the module data.
++ */
++typedef void
++(*krb5_certauth_fini_fn)(krb5_context context, krb5_certauth_moddata moddata);
++
++/*
++ * Mandatory:
++ * Return 0 if the DER-encoded cert is authorized for PKINIT authentication by
++ * princ; otherwise return one of the following error codes:
++ * - KRB5KDC_ERR_CLIENT_NAME_MISMATCH - incorrect SAN value
++ * - KRB5KDC_ERR_INCONSISTENT_KEY_PURPOSE - incorrect EKU
++ * - KRB5KDC_ERR_CERTIFICATE_MISMATCH - other extension error
++ * - KRB5_PLUGIN_NO_HANDLE - the module has no opinion about cert
++ *
++ * - opts is used by built-in modules to receive internal data, and must be
++ *   ignored by other modules.
++ * - db_entry receives the client principal database entry, and can be ignored
++ *   by modules that do not link with libkdb5.
++ * - *authinds_out optionally returns a null-terminated list of authentication
++ *   indicator strings upon KRB5_PLUGIN_NO_HANDLE or accepted authorization.
++ */
++typedef krb5_error_code
++(*krb5_certauth_authorize_fn)(krb5_context context,
++                              krb5_certauth_moddata moddata,
++                              const uint8_t *cert, size_t cert_len,
++                              krb5_const_principal princ, const void *opts,
++                              const krb5_db_entry *db_entry,
++                              char ***authinds_out);
++
++/*
++ * Free indicators allocated by a module.  Mandatory if authorize returns
++ * authentication indicators.
++ */
++typedef void
++(*krb5_certauth_free_indicator_fn)(krb5_context context,
++                                   krb5_certauth_moddata moddata,
++                                   char **authinds);
++
++typedef struct krb5_certauth_vtable_st {
++    char *name;
++    krb5_certauth_init_fn init;
++    krb5_certauth_fini_fn fini;
++    krb5_certauth_authorize_fn authorize;
++    krb5_certauth_free_indicator_fn free_ind;
++} *krb5_certauth_vtable;
++
++#endif /* KRB5_CERTAUTH_PLUGIN_H */
+diff --git a/src/lib/krb5/krb/plugin.c b/src/lib/krb5/krb/plugin.c
+index 7d64b7c7e..17dd6bd30 100644
+--- a/src/lib/krb5/krb/plugin.c
++++ b/src/lib/krb5/krb/plugin.c
+@@ -57,7 +57,8 @@ const char *interface_names[] = {
+     "hostrealm",
+     "audit",
+     "tls",
+-    "kdcauthdata"
++    "kdcauthdata",
++    "certauth"
+ };
+ 
+ /* Return the context's interface structure for id, or NULL if invalid. */
+diff --git a/src/plugins/certauth/test/Makefile.in b/src/plugins/certauth/test/Makefile.in
+new file mode 100644
+index 000000000..d3524084c
+--- /dev/null
++++ b/src/plugins/certauth/test/Makefile.in
+@@ -0,0 +1,20 @@
++mydir=plugins$(S)certauth$(S)test
++BUILDTOP=$(REL)..$(S)..$(S)..
++
++LIBBASE=certauth_test
++LIBMAJOR=0
++LIBMINOR=0
++RELDIR=../plugins/certauth/test
++SHLIB_EXPDEPS=$(KRB5_BASE_DEPLIBS)
++SHLIB_EXPLIBS=$(KRB5_BASE_LIBS)
++
++STLIBOBJS=main.o
++
++SRCS=$(srcdir)/main.c
++
++all-unix: all-libs
++install-unix:
++clean-unix:: clean-libs clean-libobjs
++
++@libnover_frag@
++@libobj_frag@
+diff --git a/src/plugins/certauth/test/certauth_test.exports b/src/plugins/certauth/test/certauth_test.exports
+new file mode 100644
+index 000000000..1c8cd24e2
+--- /dev/null
++++ b/src/plugins/certauth/test/certauth_test.exports
+@@ -0,0 +1,2 @@
++certauth_test1_initvt
++certauth_test2_initvt
+diff --git a/src/plugins/certauth/test/deps b/src/plugins/certauth/test/deps
+new file mode 100644
+index 000000000..2974b3b57
+--- /dev/null
++++ b/src/plugins/certauth/test/deps
+@@ -0,0 +1,14 @@
++#
++# Generated makefile dependencies follow.
++#
++main.so main.po $(OUTPRE)main.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
++  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
++  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \
++  $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
++  $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
++  $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
++  $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
++  $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
++  $(top_srcdir)/include/krb5/certauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \
++  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
++  main.c
+diff --git a/src/plugins/certauth/test/main.c b/src/plugins/certauth/test/main.c
+new file mode 100644
+index 000000000..7ef7377fb
+--- /dev/null
++++ b/src/plugins/certauth/test/main.c
+@@ -0,0 +1,209 @@
++/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
++/* plugins/certauth/main.c - certauth plugin test modules. */
++/*
++ * Copyright (C) 2017 by Red Hat, Inc.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * * Redistributions of source code must retain the above copyright
++ *   notice, this list of conditions and the following disclaimer.
++ *
++ * * Redistributions in binary form must reproduce the above copyright
++ *   notice, this list of conditions and the following disclaimer in
++ *   the documentation and/or other materials provided with the
++ *   distribution.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
++ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ */
++
++#include <k5-int.h>
++#include "krb5/certauth_plugin.h"
++
++struct krb5_certauth_moddata_st {
++    int initialized;
++};
++
++/* Test module 1 returns OK with an indicator. */
++static krb5_error_code
++test1_authorize(krb5_context context, krb5_certauth_moddata moddata,
++                const uint8_t *cert, size_t cert_len,
++                krb5_const_principal princ, const void *opts,
++                const krb5_db_entry *db_entry, char ***authinds_out)
++{
++    char **ais = NULL;
++
++    ais = calloc(2, sizeof(*ais));
++    assert(ais != NULL);
++    ais[0] = strdup("test1");
++    assert(ais[0] != NULL);
++    *authinds_out = ais;
++    return KRB5_PLUGIN_NO_HANDLE;
++}
++
++static void
++test_free_ind(krb5_context context, krb5_certauth_moddata moddata,
++              char **authinds)
++{
++    size_t i;
++
++    if (authinds == NULL)
++        return;
++    for (i = 0; authinds[i] != NULL; i++)
++        free(authinds[i]);
++    free(authinds);
++}
++
++/* A basic moddata test. */
++static krb5_error_code
++test2_init(krb5_context context, krb5_certauth_moddata *moddata_out)
++{
++    krb5_certauth_moddata mod;
++
++    mod = calloc(1, sizeof(*mod));
++    assert(mod != NULL);
++    mod->initialized = 1;
++    *moddata_out = mod;
++    return 0;
++}
++
++static void
++test2_fini(krb5_context context, krb5_certauth_moddata moddata)
++{
++    free(moddata);
++}
++
++/* Return true if cert appears to contain the CN name, based on a search of the
++ * DER encoding. */
++static krb5_boolean
++has_cn(krb5_context context, const uint8_t *cert, size_t cert_len,
++       const char *name)
++{
++    krb5_boolean match = FALSE;
++    uint8_t name_len, cntag[5] = "\x06\x03\x55\x04\x03";
++    const uint8_t *c;
++    struct k5buf buf;
++    size_t c_left;
++
++    /* Construct a DER search string of the CN AttributeType encoding followed
++     * by a UTF8String encoding containing name as the AttributeValue. */
++    k5_buf_init_dynamic(&buf);
++    k5_buf_add_len(&buf, cntag, sizeof(cntag));
++    k5_buf_add(&buf, "\x0C");
++    assert(strlen(name) < 128);
++    name_len = strlen(name);
++    k5_buf_add_len(&buf, &name_len, 1);
++    k5_buf_add_len(&buf, name, name_len);
++    assert(k5_buf_status(&buf) == 0);
++
++    /* Check for the CN needle in the certificate haystack. */
++    c_left = cert_len;
++    c = memchr(cert, *cntag, c_left);
++    while (c != NULL) {
++        c_left = cert_len - (c - cert);
++        if (buf.len > c_left)
++            break;
++        if (memcmp(c, buf.data, buf.len) == 0) {
++            match = TRUE;
++            break;
++        }
++        assert(c_left >= 1);
++        c = memchr(c + 1, *cntag, c_left - 1);
++    }
++
++    k5_buf_free(&buf);
++    return match;
++}
++
++/*
++ * Test module 2 returns OK if princ matches the CN part of the subject name,
++ * and returns indicators of the module name and princ.
++ */
++static krb5_error_code
++test2_authorize(krb5_context context, krb5_certauth_moddata moddata,
++                const uint8_t *cert, size_t cert_len,
++                krb5_const_principal princ, const void *opts,
++                const krb5_db_entry *db_entry, char ***authinds_out)
++{
++    krb5_error_code ret;
++    char *name = NULL, **ais = NULL;
++
++    *authinds_out = NULL;
++
++    assert(moddata != NULL && moddata->initialized);
++
++    ret = krb5_unparse_name_flags(context, princ,
++                                  KRB5_PRINCIPAL_UNPARSE_NO_REALM, &name);
++    if (ret)
++        goto cleanup;
++
++    if (!has_cn(context, cert, cert_len, name)) {
++        ret = KRB5KDC_ERR_CERTIFICATE_MISMATCH;
++        goto cleanup;
++    }
++
++    /* Create an indicator list with the module name and CN. */
++    ais = calloc(3, sizeof(*ais));
++    assert(ais != NULL);
++    ais[0] = strdup("test2");
++    ais[1] = strdup(name);
++    assert(ais[0] != NULL && ais[1] != NULL);
++    *authinds_out = ais;
++
++    ais = NULL;
++
++cleanup:
++    krb5_free_unparsed_name(context, name);
++    return ret;
++}
++
++krb5_error_code
++certauth_test1_initvt(krb5_context context, int maj_ver, int min_ver,
++                      krb5_plugin_vtable vtable);
++krb5_error_code
++certauth_test1_initvt(krb5_context context, int maj_ver, int min_ver,
++                      krb5_plugin_vtable vtable)
++{
++    krb5_certauth_vtable vt;
++
++    if (maj_ver != 1)
++        return KRB5_PLUGIN_VER_NOTSUPP;
++    vt = (krb5_certauth_vtable)vtable;
++    vt->name = "test1";
++    vt->authorize = test1_authorize;
++    vt->free_ind = test_free_ind;
++    return 0;
++}
++
++krb5_error_code
++certauth_test2_initvt(krb5_context context, int maj_ver, int min_ver,
++                      krb5_plugin_vtable vtable);
++krb5_error_code
++certauth_test2_initvt(krb5_context context, int maj_ver, int min_ver,
++                      krb5_plugin_vtable vtable)
++{
++    krb5_certauth_vtable vt;
++
++    if (maj_ver != 1)
++        return KRB5_PLUGIN_VER_NOTSUPP;
++    vt = (krb5_certauth_vtable)vtable;
++    vt->name = "test2";
++    vt->authorize = test2_authorize;
++    vt->init = test2_init;
++    vt->fini = test2_fini;
++    vt->free_ind = test_free_ind;
++    return 0;
++}
+diff --git a/src/plugins/preauth/pkinit/pkinit_crypto.h b/src/plugins/preauth/pkinit/pkinit_crypto.h
+index b483affed..49b96b8ee 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto.h
++++ b/src/plugins/preauth/pkinit/pkinit_crypto.h
+@@ -664,4 +664,8 @@ extern const size_t  krb5_pkinit_sha512_oid_len;
+  */
+ extern krb5_data const * const supported_kdf_alg_ids[];
+ 
++krb5_error_code
++crypto_encode_der_cert(krb5_context context, pkinit_req_crypto_context reqctx,
++		       uint8_t **der_out, size_t *der_len);
++
+ #endif	/* _PKINIT_CRYPTO_H */
+diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+index 8def8c542..a5b010b26 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+@@ -2137,6 +2137,7 @@ crypto_retrieve_X509_sans(krb5_context context,
+ 
+     if (!(ext = X509_get_ext(cert, l)) || !(ialt = X509V3_EXT_d2i(ext))) {
+         pkiDebug("%s: found no subject alt name extensions\n", __FUNCTION__);
++        retval = ENOENT;
+         goto cleanup;
+     }
+     num_sans = sk_GENERAL_NAME_num(ialt);
+@@ -6176,3 +6177,32 @@ crypto_get_deferred_ids(krb5_context context,
+     ret = (const pkinit_deferred_id *)deferred;
+     return ret;
+ }
++
++/* Return the received certificate as DER-encoded data. */
++krb5_error_code
++crypto_encode_der_cert(krb5_context context, pkinit_req_crypto_context reqctx,
++                       uint8_t **der_out, size_t *der_len)
++{
++    int len;
++    unsigned char *der, *p;
++
++    *der_out = NULL;
++    *der_len = 0;
++
++    if (reqctx->received_cert == NULL)
++        return EINVAL;
++    p = NULL;
++    len = i2d_X509(reqctx->received_cert, NULL);
++    if (len <= 0)
++        return EINVAL;
++    p = der = malloc(len);
++    if (p == NULL)
++        return ENOMEM;
++    if (i2d_X509(reqctx->received_cert, &p) <= 0) {
++        free(p);
++        return EINVAL;
++    }
++    *der_out = der;
++    *der_len = len;
++    return 0;
++}
+diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c
+index b5638a367..731d14eb8 100644
+--- a/src/plugins/preauth/pkinit/pkinit_srv.c
++++ b/src/plugins/preauth/pkinit/pkinit_srv.c
+@@ -31,6 +31,25 @@
+ 
+ #include <k5-int.h>
+ #include "pkinit.h"
++#include "krb5/certauth_plugin.h"
++
++/* Aliases used by the built-in certauth modules */
++struct certauth_req_opts {
++    krb5_kdcpreauth_callbacks cb;
++    krb5_kdcpreauth_rock rock;
++    pkinit_kdc_context plgctx;
++    pkinit_kdc_req_context reqctx;
++};
++
++typedef struct certauth_module_handle_st {
++    struct krb5_certauth_vtable_st vt;
++    krb5_certauth_moddata moddata;
++} *certauth_handle;
++
++struct krb5_kdcpreauth_moddata_st {
++    pkinit_kdc_context *realm_contexts;
++    certauth_handle *certauth_modules;
++};
+ 
+ static krb5_error_code
+ pkinit_init_kdc_req_context(krb5_context, pkinit_kdc_req_context *blob);
+@@ -51,6 +70,34 @@ pkinit_find_realm_context(krb5_context context,
+                           krb5_kdcpreauth_moddata moddata,
+                           krb5_principal princ);
+ 
++static void
++free_realm_contexts(krb5_context context, pkinit_kdc_context *realm_contexts)
++{
++    int i;
++
++    if (realm_contexts == NULL)
++        return;
++    for (i = 0; realm_contexts[i] != NULL; i++)
++        pkinit_server_plugin_fini_realm(context, realm_contexts[i]);
++    pkiDebug("%s: freeing context at %p\n", __FUNCTION__, realm_contexts);
++    free(realm_contexts);
++}
++
++static void
++free_certauth_handles(krb5_context context, certauth_handle *list)
++{
++    int i;
++
++    if (list == NULL)
++        return;
++    for (i = 0; list[i] != NULL; i++) {
++        if (list[i]->vt.fini != NULL)
++            list[i]->vt.fini(context, list[i]->moddata);
++        free(list[i]);
++    }
++    free(list);
++}
++
+ static krb5_error_code
+ pkinit_create_edata(krb5_context context,
+                     pkinit_plg_crypto_context plg_cryptoctx,
+@@ -123,7 +170,7 @@ verify_client_san(krb5_context context,
+                   pkinit_kdc_req_context reqctx,
+                   krb5_kdcpreauth_callbacks cb,
+                   krb5_kdcpreauth_rock rock,
+-                  krb5_principal client,
++                  krb5_const_principal client,
+                   int *valid_san)
+ {
+     krb5_error_code retval;
+@@ -134,12 +181,15 @@ verify_client_san(krb5_context context,
+     char *client_string = NULL, *san_string;
+ #endif
+ 
++    *valid_san = 0;
+     retval = crypto_retrieve_cert_sans(context, plgctx->cryptoctx,
+                                        reqctx->cryptoctx, plgctx->idctx,
+                                        &princs,
+                                        plgctx->opts->allow_upn ? &upns : NULL,
+                                        NULL);
+-    if (retval) {
++    if (retval == ENOENT) {
++        goto out;
++    } else if (retval) {
+         pkiDebug("%s: error from retrieve_certificate_sans()\n", __FUNCTION__);
+         retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
+         goto out;
+@@ -273,6 +323,73 @@ out:
+     return retval;
+ }
+ 
++
++/* Run the received, verified certificate through certauth modules, to verify
++ * that it is authorized to authenticate as client. */
++static krb5_error_code
++authorize_cert(krb5_context context, certauth_handle *certauth_modules,
++               pkinit_kdc_context plgctx, pkinit_kdc_req_context reqctx,
++               krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
++               krb5_principal client)
++{
++    krb5_error_code ret;
++    certauth_handle h;
++    struct certauth_req_opts opts;
++    krb5_boolean accepted = FALSE;
++    uint8_t *cert;
++    size_t i, cert_len;
++    void *db_ent = NULL;
++    char **ais = NULL, **ai = NULL;
++
++    /* Re-encode the received certificate into DER, which is extra work, but
++     * avoids creating an X.509 library dependency in the interface. */
++    ret = crypto_encode_der_cert(context, reqctx->cryptoctx, &cert, &cert_len);
++    if (ret)
++        goto cleanup;
++
++    /* Set options for the builtin module. */
++    opts.plgctx = plgctx;
++    opts.reqctx = reqctx;
++    opts.cb = cb;
++    opts.rock = rock;
++
++    db_ent = cb->client_entry(context, rock);
++
++    /*
++     * Check the certificate against each certauth module.  For the certificate
++     * to be authorized at least one module must return 0, and no module can an
++     * error code other than KRB5_PLUGIN_NO_HANDLE (pass).  Add indicators from
++     * modules that return 0 or pass.
++     */
++    ret = KRB5_PLUGIN_NO_HANDLE;
++    for (i = 0; certauth_modules != NULL && certauth_modules[i] != NULL; i++) {
++        h = certauth_modules[i];
++        ret = h->vt.authorize(context, h->moddata, cert, cert_len, client,
++                              &opts, db_ent, &ais);
++        if (ret == 0)
++            accepted = TRUE;
++        else if (ret != KRB5_PLUGIN_NO_HANDLE)
++            goto cleanup;
++
++        if (ais != NULL) {
++            /* Assert authentication indicators from the module. */
++            for (ai = ais; *ai != NULL; ai++) {
++                ret = cb->add_auth_indicator(context, rock, *ai);
++                if (ret)
++                    goto cleanup;
++            }
++            h->vt.free_ind(context, h->moddata, ais);
++            ais = NULL;
++        }
++    }
++
++    ret = accepted ? 0 : KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
++
++cleanup:
++    free(cert);
++    return ret;
++}
++
+ static void
+ pkinit_server_verify_padata(krb5_context context,
+                             krb5_data *req_pkt,
+@@ -295,7 +412,6 @@ pkinit_server_verify_padata(krb5_context context,
+     pkinit_kdc_req_context reqctx = NULL;
+     krb5_checksum cksum = {0, 0, 0, NULL};
+     krb5_data *der_req = NULL;
+-    int valid_eku = 0, valid_san = 0;
+     krb5_data k5data;
+     int is_signed = 1;
+     krb5_pa_data **e_data = NULL;
+@@ -388,27 +504,11 @@ pkinit_server_verify_padata(krb5_context context,
+         goto cleanup;
+     }
+     if (is_signed) {
+-
+-        retval = verify_client_san(context, plgctx, reqctx, cb, rock,
+-                                   request->client, &valid_san);
+-        if (retval)
+-            goto cleanup;
+-        if (!valid_san) {
+-            pkiDebug("%s: did not find an acceptable SAN in user "
+-                     "certificate\n", __FUNCTION__);
+-            retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
+-            goto cleanup;
+-        }
+-        retval = verify_client_eku(context, plgctx, reqctx, &valid_eku);
++        retval = authorize_cert(context, moddata->certauth_modules, plgctx,
++                                reqctx, cb, rock, request->client);
+         if (retval)
+             goto cleanup;
+ 
+-        if (!valid_eku) {
+-            pkiDebug("%s: did not find an acceptable EKU in user "
+-                     "certificate\n", __FUNCTION__);
+-            retval = KRB5KDC_ERR_INCONSISTENT_KEY_PURPOSE;
+-            goto cleanup;
+-        }
+     } else { /* !is_signed */
+         if (!krb5_principal_compare(context, request->client,
+                                     krb5_anonymous_principal())) {
+@@ -1245,11 +1345,15 @@ pkinit_find_realm_context(krb5_context context,
+                           krb5_principal princ)
+ {
+     int i;
+-    pkinit_kdc_context *realm_contexts = (pkinit_kdc_context *)moddata;
++    pkinit_kdc_context *realm_contexts;
+ 
+     if (moddata == NULL)
+         return NULL;
+ 
++    realm_contexts = moddata->realm_contexts;
++    if (realm_contexts == NULL)
++        return NULL;
++
+     for (i = 0; realm_contexts[i] != NULL; i++) {
+         pkinit_kdc_context p = realm_contexts[i];
+ 
+@@ -1331,6 +1435,155 @@ errout:
+     return retval;
+ }
+ 
++static krb5_error_code
++pkinit_san_authorize(krb5_context context, krb5_certauth_moddata moddata,
++                     const uint8_t *cert, size_t cert_len,
++                     krb5_const_principal princ, const void *opts,
++                     const krb5_db_entry *db_entry, char ***authinds_out)
++{
++    krb5_error_code ret;
++    int valid_san;
++    const struct certauth_req_opts *req_opts = opts;
++
++    *authinds_out = NULL;
++
++    ret = verify_client_san(context, req_opts->plgctx, req_opts->reqctx,
++                            req_opts->cb, req_opts->rock, princ, &valid_san);
++    if (ret == ENOENT)
++        return KRB5_PLUGIN_NO_HANDLE;
++    else if (ret)
++        return ret;
++
++    if (!valid_san) {
++        pkiDebug("%s: did not find an acceptable SAN in user certificate\n",
++                 __FUNCTION__);
++        return KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
++    }
++
++    return 0;
++}
++
++static krb5_error_code
++pkinit_eku_authorize(krb5_context context, krb5_certauth_moddata moddata,
++                     const uint8_t *cert, size_t cert_len,
++                     krb5_const_principal princ, const void *opts,
++                     const krb5_db_entry *db_entry, char ***authinds_out)
++{
++    krb5_error_code ret;
++    int valid_eku;
++    const struct certauth_req_opts *req_opts = opts;
++
++    *authinds_out = NULL;
++
++    /* Verify the client EKU. */
++    ret = verify_client_eku(context, req_opts->plgctx, req_opts->reqctx,
++                            &valid_eku);
++    if (ret)
++        return ret;
++
++    if (!valid_eku) {
++        pkiDebug("%s: did not find an acceptable EKU in user certificate\n",
++                 __FUNCTION__);
++        return KRB5KDC_ERR_INCONSISTENT_KEY_PURPOSE;
++    }
++
++    return 0;
++}
++
++static krb5_error_code
++certauth_pkinit_san_initvt(krb5_context context, int maj_ver, int min_ver,
++                           krb5_plugin_vtable vtable)
++{
++    krb5_certauth_vtable vt;
++
++    if (maj_ver != 1)
++        return KRB5_PLUGIN_VER_NOTSUPP;
++    vt = (krb5_certauth_vtable)vtable;
++    vt->name = "pkinit_san";
++    vt->authorize = pkinit_san_authorize;
++    return 0;
++}
++
++static krb5_error_code
++certauth_pkinit_eku_initvt(krb5_context context, int maj_ver, int min_ver,
++                           krb5_plugin_vtable vtable)
++{
++    krb5_certauth_vtable vt;
++
++    if (maj_ver != 1)
++        return KRB5_PLUGIN_VER_NOTSUPP;
++    vt = (krb5_certauth_vtable)vtable;
++    vt->name = "pkinit_eku";
++    vt->authorize = pkinit_eku_authorize;
++    return 0;
++}
++
++static krb5_error_code
++load_certauth_plugins(krb5_context context, certauth_handle **handle_out)
++{
++    krb5_error_code ret;
++    krb5_plugin_initvt_fn *modules = NULL, *mod;
++    certauth_handle *list = NULL, h;
++    size_t count;
++
++    /* Register the builtin modules. */
++    ret = k5_plugin_register(context, PLUGIN_INTERFACE_CERTAUTH,
++                             "pkinit_san", certauth_pkinit_san_initvt);
++    if (ret)
++        goto cleanup;
++
++    ret = k5_plugin_register(context, PLUGIN_INTERFACE_CERTAUTH,
++                             "pkinit_eku", certauth_pkinit_eku_initvt);
++    if (ret)
++        goto cleanup;
++
++    ret = k5_plugin_load_all(context, PLUGIN_INTERFACE_CERTAUTH, &modules);
++    if (ret)
++        goto cleanup;
++
++    /* Allocate handle list. */
++    for (count = 0; modules[count]; count++);
++    list = k5calloc(count + 1, sizeof(*list), &ret);
++    if (list == NULL)
++        goto cleanup;
++
++    /* Initialize each module, ignoring ones that fail. */
++    count = 0;
++    for (mod = modules; *mod != NULL; mod++) {
++        h = k5calloc(1, sizeof(*h), &ret);
++        if (h == NULL)
++            goto cleanup;
++
++        ret = (*mod)(context, 1, 1, (krb5_plugin_vtable)&h->vt);
++        if (ret) {
++            TRACE_CERTAUTH_VTINIT_FAIL(context, ret);
++            free(h);
++            continue;
++        }
++        h->moddata = NULL;
++        if (h->vt.init != NULL) {
++            ret = h->vt.init(context, &h->moddata);
++            if (ret) {
++                TRACE_CERTAUTH_INIT_FAIL(context, h->vt.name, ret);
++                free(h);
++                continue;
++            }
++        }
++        list[count++] = h;
++        list[count] = NULL;
++    }
++    list[count] = NULL;
++
++    ret = 0;
++    *handle_out = list;
++    list = NULL;
++
++cleanup:
++    k5_plugin_free_modules(context, modules);
++    free_certauth_handles(context, list);
++    return ret;
++}
++
+ static int
+ pkinit_server_plugin_init(krb5_context context,
+                           krb5_kdcpreauth_moddata *moddata_out,
+@@ -1338,6 +1591,8 @@ pkinit_server_plugin_init(krb5_context context,
+ {
+     krb5_error_code retval = ENOMEM;
+     pkinit_kdc_context plgctx, *realm_contexts = NULL;
++    certauth_handle *certauth_modules = NULL;
++    krb5_kdcpreauth_moddata moddata;
+     size_t  i, j;
+     size_t numrealms;
+ 
+@@ -1368,16 +1623,22 @@ pkinit_server_plugin_init(krb5_context context,
+         goto errout;
+     }
+ 
+-    *moddata_out = (krb5_kdcpreauth_moddata)realm_contexts;
+-    retval = 0;
+-    pkiDebug("%s: returning context at %p\n", __FUNCTION__, realm_contexts);
++    retval = load_certauth_plugins(context, &certauth_modules);
++    if (retval)
++        goto errout;
++
++    moddata = k5calloc(1, sizeof(*moddata), &retval);
++    if (moddata == NULL)
++        goto errout;
++    moddata->realm_contexts = realm_contexts;
++    moddata->certauth_modules = certauth_modules;
++    *moddata_out = moddata;
++    pkiDebug("%s: returning context at %p\n", __FUNCTION__, moddata);
++    return 0;
+ 
+ errout:
+-    if (retval) {
+-        pkinit_server_plugin_fini(context,
+-                                  (krb5_kdcpreauth_moddata)realm_contexts);
+-    }
+-
++    free_realm_contexts(context, realm_contexts);
++    free_certauth_handles(context, certauth_modules);
+     return retval;
+ }
+ 
+@@ -1405,17 +1666,11 @@ static void
+ pkinit_server_plugin_fini(krb5_context context,
+                           krb5_kdcpreauth_moddata moddata)
+ {
+-    pkinit_kdc_context *realm_contexts = (pkinit_kdc_context *)moddata;
+-    int i;
+-
+-    if (realm_contexts == NULL)
++    if (moddata == NULL)
+         return;
+-
+-    for (i = 0; realm_contexts[i] != NULL; i++) {
+-        pkinit_server_plugin_fini_realm(context, realm_contexts[i]);
+-    }
+-    pkiDebug("%s: freeing context at %p\n", __FUNCTION__, realm_contexts);
+-    free(realm_contexts);
++    free_realm_contexts(context, moddata->realm_contexts);
++    free_certauth_handles(context, moddata->certauth_modules);
++    free(moddata);
+ }
+ 
+ static krb5_error_code
+diff --git a/src/plugins/preauth/pkinit/pkinit_trace.h b/src/plugins/preauth/pkinit/pkinit_trace.h
+index b3f5cbb20..458d0961e 100644
+--- a/src/plugins/preauth/pkinit/pkinit_trace.h
++++ b/src/plugins/preauth/pkinit/pkinit_trace.h
+@@ -91,4 +91,9 @@
+ #define TRACE_PKINIT_OPENSSL_ERROR(c, msg)              \
+     TRACE(c, "PKINIT OpenSSL error: {str}", msg)
+ 
++#define TRACE_CERTAUTH_VTINIT_FAIL(c, ret)                              \
++    TRACE(c, "certauth module failed to init vtable: {kerr}", ret)
++#define TRACE_CERTAUTH_INIT_FAIL(c, name, ret)                          \
++    TRACE(c, "certauth module {str} failed to init: {kerr}", name, ret)
++
+ #endif /* PKINIT_TRACE_H */
+diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in
+index b55469146..0e93d6b59 100644
+--- a/src/tests/Makefile.in
++++ b/src/tests/Makefile.in
+@@ -167,6 +167,7 @@ check-pytests: localauth plugorder rdreq responder s2p s4u2proxy unlockiter
+ 	$(RUNPYTEST) $(srcdir)/t_preauth.py $(PYTESTFLAGS)
+ 	$(RUNPYTEST) $(srcdir)/t_princflags.py $(PYTESTFLAGS)
+ 	$(RUNPYTEST) $(srcdir)/t_tabdump.py $(PYTESTFLAGS)
++	$(RUNPYTEST) $(srcdir)/t_certauth.py $(PYTESTFLAGS)
+ 
+ clean:
+ 	$(RM) adata etinfo forward gcred hist hooks hrealm icred kdbtest
+diff --git a/src/tests/t_certauth.py b/src/tests/t_certauth.py
+new file mode 100644
+index 000000000..e64a57b0d
+--- /dev/null
++++ b/src/tests/t_certauth.py
+@@ -0,0 +1,47 @@
++#!/usr/bin/python
++from k5test import *
++
++# Skip this test if pkinit wasn't built.
++if not os.path.exists(os.path.join(plugins, 'preauth', 'pkinit.so')):
++    skip_rest('certauth tests', 'PKINIT module not built')
++
++certs = os.path.join(srctop, 'tests', 'dejagnu', 'pkinit-certs')
++ca_pem = os.path.join(certs, 'ca.pem')
++kdc_pem = os.path.join(certs, 'kdc.pem')
++privkey_pem = os.path.join(certs, 'privkey.pem')
++user_pem = os.path.join(certs, 'user.pem')
++
++modpath = os.path.join(buildtop, 'plugins', 'certauth', 'test',
++                       'certauth_test.so')
++pkinit_krb5_conf = {'realms': {'$realm': {
++            'pkinit_anchors': 'FILE:%s' % ca_pem}},
++            'plugins': {'certauth': {'module': ['test1:' + modpath,
++                                                'test2:' + modpath],
++                                     'enable_only': ['test1', 'test2']}}}
++pkinit_kdc_conf = {'realms': {'$realm': {
++            'default_principal_flags': '+preauth',
++            'pkinit_eku_checking': 'none',
++            'pkinit_identity': 'FILE:%s,%s' % (kdc_pem, privkey_pem),
++            'pkinit_indicator': ['indpkinit1', 'indpkinit2']}}}
++
++file_identity = 'FILE:%s,%s' % (user_pem, privkey_pem)
++
++realm = K5Realm(krb5_conf=pkinit_krb5_conf, kdc_conf=pkinit_kdc_conf,
++                get_creds=False)
++
++# Let the test module match user to CN=user, with indicators.
++realm.kinit(realm.user_princ,
++            flags=['-X', 'X509_user_identity=%s' % file_identity])
++realm.klist(realm.user_princ)
++realm.run([kvno, realm.host_princ])
++realm.run(['./adata', realm.host_princ],
++          expected_msg='+97: [test1, test2, user, indpkinit1, indpkinit2]')
++
++# Let the test module mismatch with user2 to CN=user.
++realm.addprinc("user2@KRBTEST.COM")
++out = realm.kinit("user2@KRBTEST.COM",
++                  flags=['-X', 'X509_user_identity=%s' % file_identity],
++                  expected_code=1,
++                  expected_msg='kinit: Certificate mismatch')
++
++success("certauth tests")
diff --git a/SOURCES/Add-k5test-expected_msg-expected_trace.patch b/SOURCES/Add-k5test-expected_msg-expected_trace.patch
new file mode 100644
index 0000000..c07c519
--- /dev/null
+++ b/SOURCES/Add-k5test-expected_msg-expected_trace.patch
@@ -0,0 +1,97 @@
+From c099e896f28d8c5ccacc9df086a8f4297c6b484e Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Tue, 17 Jan 2017 11:24:41 -0500
+Subject: [PATCH] Add k5test expected_msg, expected_trace
+
+In k5test.py, add the optional keyword argument "expected_msg" to
+methods that run commands, to make it easier to look for substrings in
+the command output.  Add the optional keyword "expected_trace" to run
+the command with KRB5_TRACE enabled and look for an ordered series of
+substrings in the trace output.
+
+(cherry picked from commit 8bb5fce69a4aa6c3082fa7def66a93974e10e17a)
+[rharwood@redhat.com: back out .gitignore]
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/config/post.in |  2 +-
+ src/util/k5test.py | 37 ++++++++++++++++++++++++++++++++++---
+ 2 files changed, 35 insertions(+), 4 deletions(-)
+
+diff --git a/src/config/post.in b/src/config/post.in
+index 77a9bffdf..aecac9d3b 100644
+--- a/src/config/post.in
++++ b/src/config/post.in
+@@ -156,7 +156,7 @@ clean: clean-$(WHAT)
+ 
+ clean-unix::
+ 	$(RM) $(OBJS) $(DEPTARGETS_CLEAN) $(EXTRA_FILES)
+-	$(RM) et-[ch]-*.et et-[ch]-*.[ch] testlog
++	$(RM) et-[ch]-*.et et-[ch]-*.[ch] testlog testtrace
+ 	-$(RM) -r testdir
+ 
+ clean-windows::
+diff --git a/src/util/k5test.py b/src/util/k5test.py
+index c3d026377..4d30baf40 100644
+--- a/src/util/k5test.py
++++ b/src/util/k5test.py
+@@ -223,8 +223,11 @@ Scripts may use the following realm methods and attributes:
+   command-line debugging options.  Fail if the command does not return
+   0.  Log the command output appropriately, and return it as a single
+   multi-line string.  Keyword arguments can contain input='string' to
+-  send an input string to the command, and expected_code=N to expect a
+-  return code other than 0.
++  send an input string to the command, expected_code=N to expect a
++  return code other than 0, expected_msg=MSG to expect a substring in
++  the command output, and expected_trace=('a', 'b', ...) to expect an
++  ordered series of line substrings in the command's KRB5_TRACE
++  output.
+ 
+ * realm.kprop_port(): Returns a port number based on realm.portbase
+   intended for use by kprop and kpropd.
+@@ -647,10 +650,31 @@ def _stop_or_shell(stop, shell, env, ind):
+         subprocess.call(os.getenv('SHELL'), env=env)
+ 
+ 
+-def _run_cmd(args, env, input=None, expected_code=0):
++# Read tracefile and look for the expected strings in successive lines.
++def _check_trace(tracefile, expected):
++    output('*** Trace output for previous command:\n')
++    i = 0
++    with open(tracefile, 'r') as f:
++        for line in f:
++            output(line)
++            if i < len(expected) and expected[i] in line:
++                i += 1
++    if i < len(expected):
++        fail('Expected string not found in trace output: ' + expected[i])
++
++
++def _run_cmd(args, env, input=None, expected_code=0, expected_msg=None,
++             expected_trace=None):
+     global null_input, _cmd_index, _last_cmd, _last_cmd_output, _debug
+     global _stop_before, _stop_after, _shell_before, _shell_after
+ 
++    if expected_trace is not None:
++        tracefile = 'testtrace'
++        if os.path.exists(tracefile):
++            os.remove(tracefile)
++        env = env.copy()
++        env['KRB5_TRACE'] = tracefile
++
+     if (_match_cmdnum(_debug, _cmd_index)):
+         return _debug_cmd(args, env, input)
+ 
+@@ -679,6 +703,13 @@ def _run_cmd(args, env, input=None, expected_code=0):
+     # Check the return code and return the output.
+     if code != expected_code:
+         fail('%s failed with code %d.' % (args[0], code))
++
++    if expected_msg is not None and expected_msg not in outdata:
++        fail('Expected string not found in command output: ' + expected_msg)
++
++    if expected_trace is not None:
++        _check_trace(tracefile, expected_trace)
++
+     return outdata
+ 
+ 
diff --git a/SOURCES/Add-support-to-query-the-SSF-of-a-GSS-context.patch b/SOURCES/Add-support-to-query-the-SSF-of-a-GSS-context.patch
new file mode 100644
index 0000000..cc0ddb3
--- /dev/null
+++ b/SOURCES/Add-support-to-query-the-SSF-of-a-GSS-context.patch
@@ -0,0 +1,420 @@
+From 1f7d42707585e552842455857070fff8957fcb7c Mon Sep 17 00:00:00 2001
+From: Simo Sorce <simo@redhat.com>
+Date: Thu, 30 Mar 2017 11:27:09 -0400
+Subject: [PATCH] Add support to query the SSF of a GSS context
+
+Cyrus SASL provides a Security Strength Factor number to assess the
+relative "strength" of the negotiated mechanism, and applications
+sometimes make access control decisions based on it.
+
+Add a call that allows us to query the mechanism that established the
+GSS security context to ask what is the current SSF, based on the
+enctype of the session key.
+
+ticket: 8569 (new)
+(cherry picked from commit 7feb7da54c0321b5a3eeb6c3797846a3cf7eda28)
+[rharwood@redhat.com: stub out GSS_KRB5_GET_CRED_IMPERSONATOR]
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/include/k5-int.h                    |  1 +
+ src/lib/crypto/krb/crypto_int.h         |  1 +
+ src/lib/crypto/krb/enctype_util.c       | 16 ++++++++++++++++
+ src/lib/crypto/krb/etypes.c             | 33 ++++++++++++++++++---------------
+ src/lib/crypto/libk5crypto.exports      |  1 +
+ src/lib/gssapi/generic/gssapi_ext.h     | 11 +++++++++++
+ src/lib/gssapi/generic/gssapi_generic.c |  9 +++++++++
+ src/lib/gssapi/krb5/gssapiP_krb5.h      |  6 ++++++
+ src/lib/gssapi/krb5/gssapi_krb5.c       |  4 ++++
+ src/lib/gssapi/krb5/inq_context.c       | 27 +++++++++++++++++++++++++++
+ src/lib/gssapi/libgssapi_krb5.exports   |  1 +
+ src/lib/gssapi32.def                    |  3 +++
+ src/lib/krb5_32.def                     |  3 +++
+ src/tests/gssapi/t_enctypes.c           | 14 ++++++++++++++
+ 14 files changed, 115 insertions(+), 15 deletions(-)
+
+diff --git a/src/include/k5-int.h b/src/include/k5-int.h
+index cea644d0a..06ca2b66d 100644
+--- a/src/include/k5-int.h
++++ b/src/include/k5-int.h
+@@ -2114,6 +2114,7 @@ krb5_get_tgs_ktypes(krb5_context, krb5_const_principal, krb5_enctype **);
+ krb5_boolean krb5_is_permitted_enctype(krb5_context, krb5_enctype);
+ 
+ krb5_boolean KRB5_CALLCONV krb5int_c_weak_enctype(krb5_enctype);
++krb5_error_code k5_enctype_to_ssf(krb5_enctype enctype, unsigned int *ssf_out);
+ 
+ krb5_error_code krb5_kdc_rep_decrypt_proc(krb5_context, const krb5_keyblock *,
+                                           krb5_const_pointer, krb5_kdc_rep *);
+diff --git a/src/lib/crypto/krb/crypto_int.h b/src/lib/crypto/krb/crypto_int.h
+index d75b49c69..e5099291e 100644
+--- a/src/lib/crypto/krb/crypto_int.h
++++ b/src/lib/crypto/krb/crypto_int.h
+@@ -111,6 +111,7 @@ struct krb5_keytypes {
+     prf_func prf;
+     krb5_cksumtype required_ctype;
+     krb5_flags flags;
++    unsigned int ssf;
+ };
+ 
+ #define ETYPE_WEAK 1
+diff --git a/src/lib/crypto/krb/enctype_util.c b/src/lib/crypto/krb/enctype_util.c
+index 0ed74bd6e..b1b40e7ec 100644
+--- a/src/lib/crypto/krb/enctype_util.c
++++ b/src/lib/crypto/krb/enctype_util.c
+@@ -131,3 +131,19 @@ krb5_enctype_to_name(krb5_enctype enctype, krb5_boolean shortest,
+         return ENOMEM;
+     return 0;
+ }
++
++/* The security of a mechanism cannot be summarized with a simple integer
++ * value, but we provide a per-enctype value for Cyrus SASL's SSF. */
++krb5_error_code
++k5_enctype_to_ssf(krb5_enctype enctype, unsigned int *ssf_out)
++{
++    const struct krb5_keytypes *ktp;
++
++    *ssf_out = 0;
++
++    ktp = find_enctype(enctype);
++    if (ktp == NULL)
++        return EINVAL;
++    *ssf_out = ktp->ssf;
++    return 0;
++}
+diff --git a/src/lib/crypto/krb/etypes.c b/src/lib/crypto/krb/etypes.c
+index 0e5e977d4..53d4a5c79 100644
+--- a/src/lib/crypto/krb/etypes.c
++++ b/src/lib/crypto/krb/etypes.c
+@@ -42,7 +42,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
+       krb5int_des_string_to_key, k5_rand2key_des,
+       krb5int_des_prf,
+       CKSUMTYPE_RSA_MD5_DES,
+-      ETYPE_WEAK },
++      ETYPE_WEAK, 56 },
+     { ENCTYPE_DES_CBC_MD4,
+       "des-cbc-md4", { 0 }, "DES cbc mode with RSA-MD4",
+       &krb5int_enc_des, &krb5int_hash_md4,
+@@ -51,7 +51,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
+       krb5int_des_string_to_key, k5_rand2key_des,
+       krb5int_des_prf,
+       CKSUMTYPE_RSA_MD4_DES,
+-      ETYPE_WEAK },
++      ETYPE_WEAK, 56 },
+     { ENCTYPE_DES_CBC_MD5,
+       "des-cbc-md5", { "des" }, "DES cbc mode with RSA-MD5",
+       &krb5int_enc_des, &krb5int_hash_md5,
+@@ -60,7 +60,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
+       krb5int_des_string_to_key, k5_rand2key_des,
+       krb5int_des_prf,
+       CKSUMTYPE_RSA_MD5_DES,
+-      ETYPE_WEAK },
++      ETYPE_WEAK, 56 },
+     { ENCTYPE_DES_CBC_RAW,
+       "des-cbc-raw", { 0 }, "DES cbc mode raw",
+       &krb5int_enc_des, NULL,
+@@ -69,7 +69,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
+       krb5int_des_string_to_key, k5_rand2key_des,
+       krb5int_des_prf,
+       0,
+-      ETYPE_WEAK },
++      ETYPE_WEAK, 56 },
+     { ENCTYPE_DES3_CBC_RAW,
+       "des3-cbc-raw", { 0 }, "Triple DES cbc mode raw",
+       &krb5int_enc_des3, NULL,
+@@ -78,7 +78,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
+       krb5int_dk_string_to_key, k5_rand2key_des3,
+       NULL, /*PRF*/
+       0,
+-      ETYPE_WEAK },
++      ETYPE_WEAK, 112 },
+ 
+     { ENCTYPE_DES3_CBC_SHA1,
+       "des3-cbc-sha1", { "des3-hmac-sha1", "des3-cbc-sha1-kd" },
+@@ -89,7 +89,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
+       krb5int_dk_string_to_key, k5_rand2key_des3,
+       krb5int_dk_prf,
+       CKSUMTYPE_HMAC_SHA1_DES3,
+-      0 /*flags*/ },
++      0 /*flags*/, 112 },
+ 
+     { ENCTYPE_DES_HMAC_SHA1,
+       "des-hmac-sha1", { 0 }, "DES with HMAC/sha1",
+@@ -99,7 +99,10 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
+       krb5int_dk_string_to_key, k5_rand2key_des,
+       NULL, /*PRF*/
+       0,
+-      ETYPE_WEAK },
++      ETYPE_WEAK, 56 },
++
++    /* rc4-hmac uses a 128-bit key, but due to weaknesses in the RC4 cipher, we
++     * consider its strength degraded and assign it an SSF value of 64. */
+     { ENCTYPE_ARCFOUR_HMAC,
+       "arcfour-hmac", { "rc4-hmac", "arcfour-hmac-md5" },
+       "ArcFour with HMAC/md5",
+@@ -110,7 +113,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
+       krb5int_arcfour_decrypt, krb5int_arcfour_string_to_key,
+       k5_rand2key_direct, krb5int_arcfour_prf,
+       CKSUMTYPE_HMAC_MD5_ARCFOUR,
+-      0 /*flags*/ },
++      0 /*flags*/, 64 },
+     { ENCTYPE_ARCFOUR_HMAC_EXP,
+       "arcfour-hmac-exp", { "rc4-hmac-exp", "arcfour-hmac-md5-exp" },
+       "Exportable ArcFour with HMAC/md5",
+@@ -121,7 +124,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
+       krb5int_arcfour_decrypt, krb5int_arcfour_string_to_key,
+       k5_rand2key_direct, krb5int_arcfour_prf,
+       CKSUMTYPE_HMAC_MD5_ARCFOUR,
+-      ETYPE_WEAK
++      ETYPE_WEAK, 40
+     },
+ 
+     { ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+@@ -133,7 +136,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
+       krb5int_aes_string_to_key, k5_rand2key_direct,
+       krb5int_dk_prf,
+       CKSUMTYPE_HMAC_SHA1_96_AES128,
+-      0 /*flags*/ },
++      0 /*flags*/, 128 },
+     { ENCTYPE_AES256_CTS_HMAC_SHA1_96,
+       "aes256-cts-hmac-sha1-96", { "aes256-cts", "aes256-sha1" },
+       "AES-256 CTS mode with 96-bit SHA-1 HMAC",
+@@ -143,7 +146,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
+       krb5int_aes_string_to_key, k5_rand2key_direct,
+       krb5int_dk_prf,
+       CKSUMTYPE_HMAC_SHA1_96_AES256,
+-      0 /*flags*/ },
++      0 /*flags*/, 256 },
+ 
+     { ENCTYPE_CAMELLIA128_CTS_CMAC,
+       "camellia128-cts-cmac", { "camellia128-cts" },
+@@ -155,7 +158,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
+       krb5int_camellia_string_to_key, k5_rand2key_direct,
+       krb5int_dk_cmac_prf,
+       CKSUMTYPE_CMAC_CAMELLIA128,
+-      0 /*flags*/ },
++      0 /*flags*/, 128 },
+     { ENCTYPE_CAMELLIA256_CTS_CMAC,
+       "camellia256-cts-cmac", { "camellia256-cts" },
+       "Camellia-256 CTS mode with CMAC",
+@@ -166,7 +169,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
+       krb5int_camellia_string_to_key, k5_rand2key_direct,
+       krb5int_dk_cmac_prf,
+       CKSUMTYPE_CMAC_CAMELLIA256,
+-      0 /*flags */ },
++      0 /*flags */, 256 },
+ 
+     { ENCTYPE_AES128_CTS_HMAC_SHA256_128,
+       "aes128-cts-hmac-sha256-128", { "aes128-sha2" },
+@@ -177,7 +180,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
+       krb5int_aes2_string_to_key, k5_rand2key_direct,
+       krb5int_aes2_prf,
+       CKSUMTYPE_HMAC_SHA256_128_AES128,
+-      0 /*flags*/ },
++      0 /*flags*/, 128 },
+     { ENCTYPE_AES256_CTS_HMAC_SHA384_192,
+       "aes256-cts-hmac-sha384-192", { "aes256-sha2" },
+       "AES-256 CTS mode with 192-bit SHA-384 HMAC",
+@@ -187,7 +190,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
+       krb5int_aes2_string_to_key, k5_rand2key_direct,
+       krb5int_aes2_prf,
+       CKSUMTYPE_HMAC_SHA384_192_AES256,
+-      0 /*flags*/ },
++      0 /*flags*/, 256 },
+ };
+ 
+ const int krb5int_enctypes_length =
+diff --git a/src/lib/crypto/libk5crypto.exports b/src/lib/crypto/libk5crypto.exports
+index 447e45644..82eb5f30c 100644
+--- a/src/lib/crypto/libk5crypto.exports
++++ b/src/lib/crypto/libk5crypto.exports
+@@ -108,3 +108,4 @@ krb5int_nfold
+ k5_allow_weak_pbkdf2iter
+ krb5_c_prfplus
+ krb5_c_derive_prfplus
++k5_enctype_to_ssf
+diff --git a/src/lib/gssapi/generic/gssapi_ext.h b/src/lib/gssapi/generic/gssapi_ext.h
+index 9ad44216d..9d3a7e736 100644
+--- a/src/lib/gssapi/generic/gssapi_ext.h
++++ b/src/lib/gssapi/generic/gssapi_ext.h
+@@ -575,4 +575,15 @@ gss_import_cred(
+ }
+ #endif
+ 
++/*
++ * When used with gss_inquire_sec_context_by_oid(), return a buffer set with
++ * the first member containing an unsigned 32-bit integer in network byte
++ * order.  This is the Security Strength Factor (SSF) associated with the
++ * secure channel established by the security context.  NOTE: This value is
++ * made available solely as an indication for use by APIs like Cyrus SASL that
++ * classify the strength of a secure channel via this number.  The strength of
++ * a channel cannot necessarily be represented by a simple number.
++ */
++GSS_DLLIMP extern gss_OID GSS_C_SEC_CONTEXT_SASL_SSF;
++
+ #endif /* GSSAPI_EXT_H_ */
+diff --git a/src/lib/gssapi/generic/gssapi_generic.c b/src/lib/gssapi/generic/gssapi_generic.c
+index 5496aa335..fa144c2bf 100644
+--- a/src/lib/gssapi/generic/gssapi_generic.c
++++ b/src/lib/gssapi/generic/gssapi_generic.c
+@@ -157,6 +157,13 @@ static const gss_OID_desc const_oids[] = {
+     {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x19"},
+     {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x1a"},
+     {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x1b"},
++
++    /*
++     * GSS_SEC_CONTEXT_SASL_SSF_OID 1.2.840.113554.1.2.2.5.15
++     * iso(1) member-body(2) United States(840) mit(113554)
++     * infosys(1) gssapi(2) krb5(2) krb5-gssapi-ext(5) sasl-ssf(15)
++     */
++    {11, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0f"},
+ };
+ 
+ /* Here are the constants which point to the static structure above.
+@@ -218,6 +225,8 @@ GSS_DLLIMP gss_const_OID GSS_C_MA_PFS               = oids+33;
+ GSS_DLLIMP gss_const_OID GSS_C_MA_COMPRESS          = oids+34;
+ GSS_DLLIMP gss_const_OID GSS_C_MA_CTX_TRANS         = oids+35;
+ 
++GSS_DLLIMP gss_OID GSS_C_SEC_CONTEXT_SASL_SSF = oids+36;
++
+ static gss_OID_set_desc gss_ma_known_attrs_desc = { 27, oids+9 };
+ gss_OID_set gss_ma_known_attrs = &gss_ma_known_attrs_desc;
+ 
+diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h
+index d7bdef7e2..ef030707e 100644
+--- a/src/lib/gssapi/krb5/gssapiP_krb5.h
++++ b/src/lib/gssapi/krb5/gssapiP_krb5.h
+@@ -1144,6 +1144,12 @@ gss_krb5int_extract_authtime_from_sec_context(OM_uint32 *,
+                                               const gss_OID,
+                                               gss_buffer_set_t *);
+ 
++#define GET_SEC_CONTEXT_SASL_SSF_OID_LENGTH 11
++#define GET_SEC_CONTEXT_SASL_SSF_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0f"
++OM_uint32
++gss_krb5int_sec_context_sasl_ssf(OM_uint32 *, const gss_ctx_id_t,
++                                 const gss_OID, gss_buffer_set_t *);
++
+ #define GSS_KRB5_IMPORT_CRED_OID_LENGTH 11
+ #define GSS_KRB5_IMPORT_CRED_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0d"
+ 
+diff --git a/src/lib/gssapi/krb5/gssapi_krb5.c b/src/lib/gssapi/krb5/gssapi_krb5.c
+index 99092ccab..de4131980 100644
+--- a/src/lib/gssapi/krb5/gssapi_krb5.c
++++ b/src/lib/gssapi/krb5/gssapi_krb5.c
+@@ -352,6 +352,10 @@ static struct {
+     {
+         {GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID_LENGTH, GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID},
+         gss_krb5int_extract_authtime_from_sec_context
++    },
++    {
++        {GET_SEC_CONTEXT_SASL_SSF_OID_LENGTH, GET_SEC_CONTEXT_SASL_SSF_OID},
++        gss_krb5int_sec_context_sasl_ssf
+     }
+ };
+ 
+diff --git a/src/lib/gssapi/krb5/inq_context.c b/src/lib/gssapi/krb5/inq_context.c
+index 9024b3c7e..d2e466e60 100644
+--- a/src/lib/gssapi/krb5/inq_context.c
++++ b/src/lib/gssapi/krb5/inq_context.c
+@@ -310,3 +310,30 @@ gss_krb5int_extract_authtime_from_sec_context(OM_uint32 *minor_status,
+ 
+     return generic_gss_add_buffer_set_member(minor_status, &rep, data_set);
+ }
++
++OM_uint32
++gss_krb5int_sec_context_sasl_ssf(OM_uint32 *minor_status,
++                                 const gss_ctx_id_t context_handle,
++                                 const gss_OID desired_object,
++                                 gss_buffer_set_t *data_set)
++{
++    krb5_gss_ctx_id_rec *ctx;
++    krb5_key key;
++    krb5_error_code code;
++    gss_buffer_desc ssfbuf;
++    unsigned int ssf;
++    uint8_t buf[4];
++
++    ctx = (krb5_gss_ctx_id_rec *)context_handle;
++    key = ctx->have_acceptor_subkey ? ctx->acceptor_subkey : ctx->subkey;
++
++    code = k5_enctype_to_ssf(key->keyblock.enctype, &ssf);
++    if (code)
++        return GSS_S_FAILURE;
++
++    store_32_be(ssf, buf);
++    ssfbuf.value = buf;
++    ssfbuf.length = sizeof(buf);
++
++    return generic_gss_add_buffer_set_member(minor_status, &ssfbuf, data_set);
++}
+diff --git a/src/lib/gssapi/libgssapi_krb5.exports b/src/lib/gssapi/libgssapi_krb5.exports
+index 9facb3f42..936540e41 100644
+--- a/src/lib/gssapi/libgssapi_krb5.exports
++++ b/src/lib/gssapi/libgssapi_krb5.exports
+@@ -37,6 +37,7 @@ GSS_C_MA_CBINDINGS
+ GSS_C_MA_PFS
+ GSS_C_MA_COMPRESS
+ GSS_C_MA_CTX_TRANS
++GSS_C_SEC_CONTEXT_SASL_SSF
+ gss_accept_sec_context
+ gss_acquire_cred
+ gss_acquire_cred_with_password
+diff --git a/src/lib/gssapi32.def b/src/lib/gssapi32.def
+index 362b9bce8..dff057754 100644
+--- a/src/lib/gssapi32.def
++++ b/src/lib/gssapi32.def
+@@ -182,3 +182,6 @@ EXPORTS
+ 	gss_verify_mic_iov				@146
+ ; Added in 1.14
+ 	GSS_KRB5_CRED_NO_CI_FLAGS_X			@147	DATA
++; Added in 1.16
++;	GSS_KRB5_GET_CRED_IMPERSONATOR			@148	DATA
++	GSS_C_SEC_CONTEXT_SASL_SSF			@149	DATA
+diff --git a/src/lib/krb5_32.def b/src/lib/krb5_32.def
+index e5b560dfc..f7b428e16 100644
+--- a/src/lib/krb5_32.def
++++ b/src/lib/krb5_32.def
+@@ -470,3 +470,6 @@ EXPORTS
+ 	krb5_get_init_creds_opt_set_pac_request		@435
+ 	krb5int_trace					@436 ; PRIVATE GSSAPI
+ 	krb5_expand_hostname				@437
++
++; new in 1.16
++	k5_enctype_to_ssf				@438 ; PRIVATE GSSAPI
+diff --git a/src/tests/gssapi/t_enctypes.c b/src/tests/gssapi/t_enctypes.c
+index a2ad18f47..3fd31e2f8 100644
+--- a/src/tests/gssapi/t_enctypes.c
++++ b/src/tests/gssapi/t_enctypes.c
+@@ -32,6 +32,7 @@
+ 
+ #include "k5-int.h"
+ #include "common.h"
++#include "gssapi_ext.h"
+ 
+ /*
+  * This test program establishes contexts with the krb5 mech, the default
+@@ -86,6 +87,9 @@ main(int argc, char *argv[])
+     gss_krb5_lucid_context_v1_t *ilucid, *alucid;
+     gss_krb5_rfc1964_keydata_t *i1964, *a1964;
+     gss_krb5_cfx_keydata_t *icfx, *acfx;
++    gss_buffer_set_t bufset = GSS_C_NO_BUFFER_SET;
++    gss_OID ssf_oid = GSS_C_SEC_CONTEXT_SASL_SSF;
++    unsigned int ssf;
+     size_t count;
+     void *lptr;
+     int c;
+@@ -139,6 +143,16 @@ main(int argc, char *argv[])
+     establish_contexts(&mech_krb5, icred, acred, tname, flags, &ictx, &actx,
+                        NULL, NULL, NULL);
+ 
++    /* Query the SSF value and range-check the result. */
++    major = gss_inquire_sec_context_by_oid(&minor, ictx, ssf_oid, &bufset);
++    check_gsserr("gss_inquire_sec_context_by_oid(ssf)", major, minor);
++    if (bufset->elements[0].length != 4)
++        errout("SSF buffer has unexpected length");
++    ssf = load_32_be(bufset->elements[0].value);
++    if (ssf < 56 || ssf > 256)
++        errout("SSF value not within acceptable range (56-256)");
++    (void)gss_release_buffer_set(&minor, &bufset);
++
+     /* Export to lucid contexts. */
+     major = gss_krb5_export_lucid_sec_context(&minor, &ictx, 1, &lptr);
+     check_gsserr("gss_export_lucid_sec_context(initiator)", major, minor);
diff --git a/SOURCES/Add-test-cert-generation-to-make-certs.sh.patch b/SOURCES/Add-test-cert-generation-to-make-certs.sh.patch
new file mode 100644
index 0000000..9c1dcf9
--- /dev/null
+++ b/SOURCES/Add-test-cert-generation-to-make-certs.sh.patch
@@ -0,0 +1,92 @@
+From fd8ce9e1ed7a8d6cf5ac7d27d6acf40b0453c45e Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Tue, 5 Sep 2017 15:54:31 -0400
+Subject: [PATCH] Add test cert generation to make-certs.sh
+
+Based on commit 5a1d0388ba2e4ec510ed715ce5fbc7f748941425 but missing
+everything but the make-certs change since infrastructure cannot patch
+binaries.  Plan to run make-certs during build, but this will only
+work with openssl < 1.1.
+
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/tests/dejagnu/pkinit-certs/make-certs.sh | 53 +++++++++++++++++++++++++++-
+ 1 file changed, 52 insertions(+), 1 deletion(-)
+
+diff --git a/src/tests/dejagnu/pkinit-certs/make-certs.sh b/src/tests/dejagnu/pkinit-certs/make-certs.sh
+index b82ef6f83..0f07709b0 100755
+--- a/src/tests/dejagnu/pkinit-certs/make-certs.sh
++++ b/src/tests/dejagnu/pkinit-certs/make-certs.sh
+@@ -4,7 +4,9 @@ NAMETYPE=1
+ KEYSIZE=2048
+ DAYS=4000
+ REALM=KRBTEST.COM
++LOWREALM=krbtest.com
+ KRB5_PRINCIPAL_SAN=1.3.6.1.5.2.2
++KRB5_UPN_SAN=1.3.6.1.4.1.311.20.2.3
+ PKINIT_KDC_EKU=1.3.6.1.5.2.3.5
+ PKINIT_CLIENT_EKU=1.3.6.1.5.2.3.4
+ TLS_SERVER_EKU=1.3.6.1.5.5.7.3.1
+@@ -85,6 +87,30 @@ keyUsage = nonRepudiation,digitalSignature,keyEncipherment,keyAgreement
+ basicConstraints = critical,CA:FALSE
+ subjectAltName = otherName:$KRB5_PRINCIPAL_SAN;SEQUENCE:krb5princ_client
+ extendedKeyUsage = $CLIENT_EKU_LIST
++
++[exts_upn_client]
++subjectKeyIdentifier = hash
++authorityKeyIdentifier = keyid:always,issuer:always
++keyUsage = nonRepudiation,digitalSignature,keyEncipherment,keyAgreement
++basicConstraints = critical,CA:FALSE
++subjectAltName = otherName:$KRB5_UPN_SAN;UTF8:user@$LOWREALM
++extendedKeyUsage = $CLIENT_EKU_LIST
++
++[exts_upn2_client]
++subjectKeyIdentifier = hash
++authorityKeyIdentifier = keyid:always,issuer:always
++keyUsage = nonRepudiation,digitalSignature,keyEncipherment,keyAgreement
++basicConstraints = critical,CA:FALSE
++subjectAltName = otherName:$KRB5_UPN_SAN;UTF8:user
++extendedKeyUsage = $CLIENT_EKU_LIST
++
++[exts_upn3_client]
++subjectKeyIdentifier = hash
++authorityKeyIdentifier = keyid:always,issuer:always
++keyUsage = nonRepudiation,digitalSignature,keyEncipherment,keyAgreement
++basicConstraints = critical,CA:FALSE
++subjectAltName = otherName:$KRB5_UPN_SAN;UTF8:user@$REALM
++extendedKeyUsage = $CLIENT_EKU_LIST
+ EOF
+ 
+ # Generate a private key.
+@@ -113,5 +139,30 @@ openssl pkcs12 -export -in user.pem -inkey privkey.pem -out user.p12 \
+ openssl pkcs12 -export -in user.pem -inkey privkey.pem -out user-enc.p12 \
+     -passout pass:encrypted
+ 
++# Generate a client certificate and PKCS#12 bundles with a UPN SAN.
++SUBJECT=user openssl req -config openssl.cnf -new -subj /CN=user \
++    -key privkey.pem -out user-upn.csr
++SUBJECT=user openssl x509 -extfile openssl.cnf -extensions exts_upn_client \
++    -set_serial 4 -days $DAYS -req -CA ca.pem -CAkey privkey.pem \
++    -out user-upn.pem -in user-upn.csr
++openssl pkcs12 -export -in user-upn.pem -inkey privkey.pem -out user-upn.p12 \
++    -passout pass:
++
++SUBJECT=user openssl req -config openssl.cnf -new -subj /CN=user \
++    -key privkey.pem -out user-upn2.csr
++SUBJECT=user openssl x509 -extfile openssl.cnf -extensions exts_upn2_client \
++    -set_serial 5 -days $DAYS -req -CA ca.pem -CAkey privkey.pem \
++    -out user-upn2.pem -in user-upn2.csr
++openssl pkcs12 -export -in user-upn2.pem -inkey privkey.pem \
++     -out user-upn2.p12 -passout pass:
++
++SUBJECT=user openssl req -config openssl.cnf -new -subj /CN=user \
++    -key privkey.pem -out user-upn3.csr
++SUBJECT=user openssl x509 -extfile openssl.cnf -extensions exts_upn3_client \
++    -set_serial 6 -days $DAYS -req -CA ca.pem -CAkey privkey.pem \
++    -out user-upn3.pem -in user-upn3.csr
++openssl pkcs12 -export -in user-upn3.pem -inkey privkey.pem \
++     -out user-upn3.p12 -passout pass:
++
+ # Clean up.
+-rm -f openssl.cnf kdc.csr user.csr
++rm -f openssl.cnf kdc.csr user.csr user-upn.csr user-upn2.csr user-upn3.csr
diff --git a/SOURCES/Add-test-cert-with-no-extensions.patch b/SOURCES/Add-test-cert-with-no-extensions.patch
new file mode 100644
index 0000000..90201f1
--- /dev/null
+++ b/SOURCES/Add-test-cert-with-no-extensions.patch
@@ -0,0 +1,36 @@
+From dd189f46b9e43392b842c4309c95dc7e71963261 Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Thu, 5 Oct 2017 12:54:13 -0400
+Subject: [PATCH] Add test cert with no extensions
+
+Add commands to make-certs.sh to generate a test client certificate
+with no certificate extensions.  Re-run make-certs.sh.
+
+ticket: 8562
+(cherry-picked from commit 0d23835660ab131d244d395e4568969b5c0dc678)
+[rharwood@redhat.com: only backport the make-certs.sh changes]
+
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/tests/dejagnu/pkinit-certs/make-certs.sh | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/src/tests/dejagnu/pkinit-certs/make-certs.sh b/src/tests/dejagnu/pkinit-certs/make-certs.sh
+index 0d8c2019a..23426af8a 100755
+--- a/src/tests/dejagnu/pkinit-certs/make-certs.sh
++++ b/src/tests/dejagnu/pkinit-certs/make-certs.sh
+@@ -163,5 +163,14 @@ SUBJECT=user openssl x509 -extfile openssl.cnf -extensions exts_upn3_client \
+ openssl pkcs12 -export -in user-upn3.pem -inkey privkey.pem \
+      -out user-upn3.p12 -passout pass:
+ 
++# Generate a client certificate and PKCS#12 bundle with no PKINIT extensions.
++SUBJECT=user openssl req -config openssl.cnf -new -subj /CN=user \
++    -key privkey.pem -out generic.csr
++SUBJECT=user openssl x509 -set_serial 7 -days $DAYS -req -CA ca.pem \
++    -CAkey privkey.pem -out generic.pem -in generic.csr
++openssl pkcs12 -export -in generic.pem -inkey privkey.pem -out generic.p12 \
++    -passout pass:
++
+ # Clean up.
+ rm -f openssl.cnf kdc.csr user.csr user-upn.csr user-upn2.csr user-upn3.csr
++rm -f generic.csr
diff --git a/SOURCES/Add-the-client_name-kdcpreauth-callback.patch b/SOURCES/Add-the-client_name-kdcpreauth-callback.patch
new file mode 100644
index 0000000..25f4dea
--- /dev/null
+++ b/SOURCES/Add-the-client_name-kdcpreauth-callback.patch
@@ -0,0 +1,59 @@
+From aa153bb60c4fdc05adbc88cca578612fce6c8ce0 Mon Sep 17 00:00:00 2001
+From: Matt Rogers <mrogers@redhat.com>
+Date: Tue, 4 Apr 2017 16:54:56 -0400
+Subject: [PATCH] Add the client_name() kdcpreauth callback
+
+Add a kdcpreauth callback to returns the canonicalized client principal.
+
+ticket: 8570 (new)
+(cherry picked from commit a84f39ec30f3deeda7836da6e8b3d8dcf7a045b1)
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/include/krb5/kdcpreauth_plugin.h | 6 ++++++
+ src/kdc/kdc_preauth.c                | 9 ++++++++-
+ 2 files changed, 14 insertions(+), 1 deletion(-)
+
+diff --git a/src/include/krb5/kdcpreauth_plugin.h b/src/include/krb5/kdcpreauth_plugin.h
+index 92aa5a5a5..fa4436b83 100644
+--- a/src/include/krb5/kdcpreauth_plugin.h
++++ b/src/include/krb5/kdcpreauth_plugin.h
+@@ -232,6 +232,12 @@ typedef struct krb5_kdcpreauth_callbacks_st {
+                                  krb5_kdcpreauth_rock rock,
+                                  krb5_principal princ);
+ 
++    /*
++     * Get an alias to the client DB entry principal (possibly canonicalized).
++     */
++    krb5_principal (*client_name)(krb5_context context,
++                                  krb5_kdcpreauth_rock rock);
++
+     /* End of version 4 kdcpreauth callbacks. */
+ 
+ } *krb5_kdcpreauth_callbacks;
+diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c
+index 0ce79c667..81d0b8cff 100644
+--- a/src/kdc/kdc_preauth.c
++++ b/src/kdc/kdc_preauth.c
+@@ -591,6 +591,12 @@ match_client(krb5_context context, krb5_kdcpreauth_rock rock,
+     return match;
+ }
+ 
++static krb5_principal
++client_name(krb5_context context, krb5_kdcpreauth_rock rock)
++{
++    return rock->client->princ;
++}
++
+ static struct krb5_kdcpreauth_callbacks_st callbacks = {
+     4,
+     max_time_skew,
+@@ -607,7 +613,8 @@ static struct krb5_kdcpreauth_callbacks_st callbacks = {
+     add_auth_indicator,
+     get_cookie,
+     set_cookie,
+-    match_client
++    match_client,
++    client_name
+ };
+ 
+ static krb5_error_code
diff --git a/SOURCES/Add-timestamp-helper-functions.patch b/SOURCES/Add-timestamp-helper-functions.patch
new file mode 100644
index 0000000..1bd6a8e
--- /dev/null
+++ b/SOURCES/Add-timestamp-helper-functions.patch
@@ -0,0 +1,81 @@
+From 6437685130b68670888db1d0551f5464d56c4cec Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Sat, 22 Apr 2017 09:49:12 -0400
+Subject: [PATCH] Add timestamp helper functions
+
+Add k5-int.h helper functions to manipulate krb5_timestamp values,
+avoiding undefined behavior and treating negative timestamp values as
+times between 2038 and 2106.  Add a doxygen comment for krb5_timestamp
+indicating how third-party code should use it safely.
+
+ticket: 8352
+(cherry picked from commit 58e9155060cd93b1a7557e37fbc9b077b76465c2)
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/include/k5-int.h      | 31 +++++++++++++++++++++++++++++++
+ src/include/krb5/krb5.hin |  9 +++++++++
+ 2 files changed, 40 insertions(+)
+
+diff --git a/src/include/k5-int.h b/src/include/k5-int.h
+index 06ca2b66d..82ee20760 100644
+--- a/src/include/k5-int.h
++++ b/src/include/k5-int.h
+@@ -2353,6 +2353,37 @@ k5memdup0(const void *in, size_t len, krb5_error_code *code)
+     return ptr;
+ }
+ 
++/* Convert a krb5_timestamp to a time_t value, treating the negative range of
++ * krb5_timestamp as times between 2038 and 2106 (if time_t is 64-bit). */
++static inline time_t
++ts2tt(krb5_timestamp timestamp)
++{
++    return (time_t)(uint32_t)timestamp;
++}
++
++/* Return the delta between two timestamps (a - b) as a signed 32-bit value,
++ * without relying on undefined behavior. */
++static inline krb5_deltat
++ts_delta(krb5_timestamp a, krb5_timestamp b)
++{
++    return (krb5_deltat)((uint32_t)a - (uint32_t)b);
++}
++
++/* Increment a timestamp by a signed 32-bit interval, without relying on
++ * undefined behavior. */
++static inline krb5_timestamp
++ts_incr(krb5_timestamp ts, krb5_deltat delta)
++{
++    return (krb5_timestamp)((uint32_t)ts + (uint32_t)delta);
++}
++
++/* Return true if a comes after b. */
++static inline krb5_boolean
++ts_after(krb5_timestamp a, krb5_timestamp b)
++{
++    return (uint32_t)a > (uint32_t)b;
++}
++
+ krb5_error_code KRB5_CALLCONV
+ krb5_get_credentials_for_user(krb5_context context, krb5_flags options,
+                               krb5_ccache ccache,
+diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
+index cf60d6c41..53ad85384 100644
+--- a/src/include/krb5/krb5.hin
++++ b/src/include/krb5/krb5.hin
+@@ -187,7 +187,16 @@ typedef krb5_int32 krb5_cryptotype;
+ 
+ typedef krb5_int32      krb5_preauthtype; /* This may change, later on */
+ typedef krb5_int32      krb5_flags;
++
++/**
++ * Represents a timestamp in seconds since the POSIX epoch.  This legacy type
++ * is used frequently in the ABI, but cannot represent timestamps after 2038 as
++ * a positive number.  Code which uses this type should cast values of it to
++ * uint32_t so that negative values are treated as timestamps between 2038 and
++ * 2106 on platforms with 64-bit time_t.
++ */
+ typedef krb5_int32      krb5_timestamp;
++
+ typedef krb5_int32      krb5_deltat;
+ 
+ /**
diff --git a/SOURCES/Add-timestamp-tests.patch b/SOURCES/Add-timestamp-tests.patch
new file mode 100644
index 0000000..4fe37aa
--- /dev/null
+++ b/SOURCES/Add-timestamp-tests.patch
@@ -0,0 +1,600 @@
+From 47999bb8735f653f06e0eb46e7eced600210b9da Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Sat, 29 Apr 2017 17:30:36 -0400
+Subject: [PATCH] Add timestamp tests
+
+Add a test program for krb5int_validate_times() covering cases before
+and across the y2038 boundary.  Add a GSSAPI test program to exercise
+lifetime queries, and tests using it in t_gssapi.py for ticket end
+times after y2038.  Add a new test script t_y2038.py which only runs
+on platforms with 64-bit time_t to exercise end-user operations across
+and after y2038.  Add an LDAP test case to test storage of post-y2038
+timestamps.
+
+ticket: 8352
+(cherry picked from commit 8ca62e54e89e2fbd6a089e8ab20b4e374a486003)
+[rharwood@redhat.com: prune gitignore]
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/Makefile.in                  |   1 +
+ src/config/pre.in                |   2 +
+ src/configure.in                 |   3 +
+ src/lib/krb5/krb/Makefile.in     |  14 ++--
+ src/lib/krb5/krb/t_valid_times.c | 109 ++++++++++++++++++++++++++++++
+ src/tests/Makefile.in            |   1 +
+ src/tests/gssapi/Makefile.in     |  27 ++++----
+ src/tests/gssapi/t_gssapi.py     |  32 +++++++++
+ src/tests/gssapi/t_lifetime.c    | 140 +++++++++++++++++++++++++++++++++++++++
+ src/tests/t_kdb.py               |   7 ++
+ src/tests/t_y2038.py             |  75 +++++++++++++++++++++
+ 11 files changed, 395 insertions(+), 16 deletions(-)
+ create mode 100644 src/lib/krb5/krb/t_valid_times.c
+ create mode 100644 src/tests/gssapi/t_lifetime.c
+ create mode 100644 src/tests/t_y2038.py
+
+diff --git a/src/Makefile.in b/src/Makefile.in
+index b0249778c..ad8565056 100644
+--- a/src/Makefile.in
++++ b/src/Makefile.in
+@@ -521,6 +521,7 @@ pyrunenv.vals: Makefile
+ 	done > $@
+ 	echo "tls_impl = '$(TLS_IMPL)'" >> $@
+ 	echo "have_sasl = '$(HAVE_SASL)'" >> $@
++	echo "sizeof_time_t = $(SIZEOF_TIME_T)" >> $@
+ 
+ runenv.py: pyrunenv.vals
+ 	echo 'env = {}' > $@
+diff --git a/src/config/pre.in b/src/config/pre.in
+index d961b5621..f23c07d9d 100644
+--- a/src/config/pre.in
++++ b/src/config/pre.in
+@@ -452,6 +452,8 @@ HAVE_SASL = @HAVE_SASL@
+ # Whether we have libresolv 1.1.5 for URI discovery tests
+ HAVE_RESOLV_WRAPPER = @HAVE_RESOLV_WRAPPER@
+ 
++SIZEOF_TIME_T = @SIZEOF_TIME_T@
++
+ # error table rules
+ #
+ ### /* these are invoked as $(...) foo.et, which works, but could be better */
+diff --git a/src/configure.in b/src/configure.in
+index 24f653f0d..4ae2c07d5 100644
+--- a/src/configure.in
++++ b/src/configure.in
+@@ -744,6 +744,9 @@ fi
+ 
+ AC_HEADER_TIME
+ AC_CHECK_TYPE(time_t, long)
++AC_CHECK_SIZEOF(time_t)
++SIZEOF_TIME_T=$ac_cv_sizeof_time_t
++AC_SUBST(SIZEOF_TIME_T)
+ 
+ # Determine where to put the replay cache.
+ 
+diff --git a/src/lib/krb5/krb/Makefile.in b/src/lib/krb5/krb/Makefile.in
+index 0fe02a95d..55f82b147 100644
+--- a/src/lib/krb5/krb/Makefile.in
++++ b/src/lib/krb5/krb/Makefile.in
+@@ -364,6 +364,7 @@ SRCS=	$(srcdir)/addr_comp.c	\
+ 	$(srcdir)/t_in_ccache.c	\
+ 	$(srcdir)/t_response_items.c \
+ 	$(srcdir)/t_sname_match.c \
++	$(srcdir)/t_valid_times.c \
+ 	$(srcdir)/t_vfy_increds.c
+ 
+ # Someday, when we have a "maintainer mode", do this right:
+@@ -457,9 +458,12 @@ t_response_items: t_response_items.o response_items.o $(KRB5_BASE_DEPLIBS)
+ t_sname_match: t_sname_match.o sname_match.o $(KRB5_BASE_DEPLIBS)
+ 	$(CC_LINK) -o $@ t_sname_match.o sname_match.o $(KRB5_BASE_LIBS)
+ 
++t_valid_times: t_valid_times.o valid_times.o $(KRB5_BASE_DEPLIBS)
++	$(CC_LINK) -o $@ t_valid_times.o valid_times.o $(KRB5_BASE_LIBS)
++
+ TEST_PROGS= t_walk_rtree t_kerb t_ser t_deltat t_expand t_authdata t_pac \
+-	t_in_ccache t_cc_config t_copy_context \
+-	t_princ t_etypes t_vfy_increds t_response_items t_sname_match
++	t_in_ccache t_cc_config t_copy_context t_princ t_etypes t_vfy_increds \
++	t_response_items t_sname_match t_valid_times
+ 
+ check-unix: $(TEST_PROGS)
+ 	$(RUN_TEST_LOCAL_CONF) ./t_kerb \
+@@ -496,6 +500,7 @@ check-unix: $(TEST_PROGS)
+ 	$(RUN_TEST) ./t_response_items
+ 	$(RUN_TEST) ./t_copy_context
+ 	$(RUN_TEST) ./t_sname_match
++	$(RUN_TEST) ./t_valid_times
+ 
+ check-pytests: t_expire_warn t_vfy_increds
+ 	$(RUNPYTEST) $(srcdir)/t_expire_warn.py $(PYTESTFLAGS)
+@@ -522,8 +527,9 @@ clean:
+ 	$(OUTPRE)t_ad_fx_armor$(EXEEXT) $(OUTPRE)t_ad_fx_armor.$(OBJEXT) \
+ 	$(OUTPRE)t_vfy_increds$(EXEEXT) $(OUTPRE)t_vfy_increds.$(OBJEXT) \
+ 	$(OUTPRE)t_response_items$(EXEEXT) \
+-	$(OUTPRE)t_response_items.$(OBJEXT) $(OUTPRE)t_sname_match$(EXEEXT) \
+-	$(OUTPRE)t_sname_match.$(OBJEXT) \
++	$(OUTPRE)t_response_items.$(OBJEXT) \
++	$(OUTPRE)t_sname_match$(EXEEXT) $(OUTPRE)t_sname_match.$(OBJEXT) \
++	$(OUTPRE)t_valid_times$(EXEEXT) $(OUTPRE)t_valid_times.$(OBJECT) \
+ 	$(OUTPRE)t_parse_host_string$(EXEEXT) \
+ 	$(OUTPRE)t_parse_host_string.$(OBJEXT)
+ 
+diff --git a/src/lib/krb5/krb/t_valid_times.c b/src/lib/krb5/krb/t_valid_times.c
+new file mode 100644
+index 000000000..1b469ffc2
+--- /dev/null
++++ b/src/lib/krb5/krb/t_valid_times.c
+@@ -0,0 +1,109 @@
++/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
++/* lib/krb5/krb/t_valid_times.c - test program for krb5int_validate_times() */
++/*
++ * Copyright (C) 2017 by the Massachusetts Institute of Technology.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * * Redistributions of source code must retain the above copyright
++ *   notice, this list of conditions and the following disclaimer.
++ *
++ * * Redistributions in binary form must reproduce the above copyright
++ *   notice, this list of conditions and the following disclaimer in
++ *   the documentation and/or other materials provided with the
++ *   distribution.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
++ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ */
++
++#include "k5-int.h"
++#include "int-proto.h"
++
++#define BOUNDARY (uint32_t)INT32_MIN
++
++int
++main()
++{
++    krb5_error_code ret;
++    krb5_context context;
++    krb5_ticket_times times = { 0, 0, 0, 0 };
++
++    ret = krb5_init_context(&context);
++    assert(!ret);
++
++    /* Current time is within authtime and end time. */
++    ret = krb5_set_debugging_time(context, 1000, 0);
++    times.authtime = 500;
++    times.endtime = 1500;
++    ret = krb5int_validate_times(context, &times);
++    assert(!ret);
++
++    /* Current time is before starttime, but within clock skew. */
++    times.starttime = 1100;
++    ret = krb5int_validate_times(context, &times);
++    assert(!ret);
++
++    /* Current time is before starttime by more than clock skew. */
++    times.starttime = 1400;
++    ret = krb5int_validate_times(context, &times);
++    assert(ret == KRB5KRB_AP_ERR_TKT_NYV);
++
++    /* Current time is after end time, but within clock skew. */
++    times.starttime = 500;
++    times.endtime = 800;
++    ret = krb5int_validate_times(context, &times);
++    assert(!ret);
++
++    /* Current time is after end time by more than clock skew. */
++    times.endtime = 600;
++    ret = krb5int_validate_times(context, &times);
++    assert(ret == KRB5KRB_AP_ERR_TKT_EXPIRED);
++
++    /* Current time is within starttime and endtime; current time and
++     * endtime are across y2038 boundary. */
++    ret = krb5_set_debugging_time(context, BOUNDARY - 100, 0);
++    assert(!ret);
++    times.starttime = BOUNDARY - 200;
++    times.endtime = BOUNDARY + 500;
++    ret = krb5int_validate_times(context, &times);
++    assert(!ret);
++
++    /* Current time is before starttime, but by less than clock skew. */
++    times.starttime = BOUNDARY + 100;
++    ret = krb5int_validate_times(context, &times);
++    assert(!ret);
++
++    /* Current time is before starttime by more than clock skew. */
++    times.starttime = BOUNDARY + 250;
++    ret = krb5int_validate_times(context, &times);
++    assert(ret == KRB5KRB_AP_ERR_TKT_NYV);
++
++    /* Current time is after endtime, but by less than clock skew. */
++    ret = krb5_set_debugging_time(context, BOUNDARY + 100, 0);
++    assert(!ret);
++    times.starttime = BOUNDARY - 1000;
++    times.endtime = BOUNDARY - 100;
++    ret = krb5int_validate_times(context, &times);
++    assert(!ret);
++
++    /* Current time is after endtime by more than clock skew. */
++    times.endtime = BOUNDARY - 300;
++    ret = krb5int_validate_times(context, &times);
++    assert(ret == KRB5KRB_AP_ERR_TKT_EXPIRED);
++
++    return 0;
++}
+diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in
+index 0e93d6b59..2b3112537 100644
+--- a/src/tests/Makefile.in
++++ b/src/tests/Makefile.in
+@@ -168,6 +168,7 @@ check-pytests: localauth plugorder rdreq responder s2p s4u2proxy unlockiter
+ 	$(RUNPYTEST) $(srcdir)/t_princflags.py $(PYTESTFLAGS)
+ 	$(RUNPYTEST) $(srcdir)/t_tabdump.py $(PYTESTFLAGS)
+ 	$(RUNPYTEST) $(srcdir)/t_certauth.py $(PYTESTFLAGS)
++	$(RUNPYTEST) $(srcdir)/t_y2038.py $(PYTESTFLAGS)
+ 
+ clean:
+ 	$(RM) adata etinfo forward gcred hist hooks hrealm icred kdbtest
+diff --git a/src/tests/gssapi/Makefile.in b/src/tests/gssapi/Makefile.in
+index 6c1464297..604f926de 100644
+--- a/src/tests/gssapi/Makefile.in
++++ b/src/tests/gssapi/Makefile.in
+@@ -15,15 +15,16 @@ SRCS=	$(srcdir)/ccinit.c $(srcdir)/ccrefresh.c $(srcdir)/common.c \
+ 	$(srcdir)/t_gssexts.c $(srcdir)/t_imp_cred.c $(srcdir)/t_imp_name.c \
+ 	$(srcdir)/t_invalid.c $(srcdir)/t_inq_cred.c $(srcdir)/t_inq_ctx.c \
+ 	$(srcdir)/t_inq_mechs_name.c $(srcdir)/t_iov.c \
+-	$(srcdir)/t_namingexts.c $(srcdir)/t_oid.c $(srcdir)/t_pcontok.c \
+-	$(srcdir)/t_prf.c $(srcdir)/t_s4u.c $(srcdir)/t_s4u2proxy_krb5.c \
+-	$(srcdir)/t_saslname.c $(srcdir)/t_spnego.c $(srcdir)/t_srcattrs.c
++	$(srcdir)/t_lifetime.c $(srcdir)/t_namingexts.c $(srcdir)/t_oid.c \
++	$(srcdir)/t_pcontok.c $(srcdir)/t_prf.c $(srcdir)/t_s4u.c \
++	$(srcdir)/t_s4u2proxy_krb5.c $(srcdir)/t_saslname.c \
++	$(srcdir)/t_spnego.c $(srcdir)/t_srcattrs.c
+ 
+ OBJS=	ccinit.o ccrefresh.o common.o t_accname.o t_ccselect.o t_ciflags.o \
+ 	t_credstore.o t_enctypes.o t_err.o t_export_cred.o t_export_name.o \
+ 	t_gssexts.o t_imp_cred.o t_imp_name.o t_invalid.o t_inq_cred.o \
+-	t_inq_ctx.o t_inq_mechs_name.o t_iov.o t_namingexts.o t_oid.o \
+-	t_pcontok.o t_prf.o t_s4u.o t_s4u2proxy_krb5.o t_saslname.o \
++	t_inq_ctx.o t_inq_mechs_name.o t_iov.o t_lifetime.o t_namingexts.o \
++	t_oid.o t_pcontok.o t_prf.o t_s4u.o t_s4u2proxy_krb5.o t_saslname.o \
+ 	t_spnego.o t_srcattrs.o
+ 
+ COMMON_DEPS= common.o $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+@@ -31,9 +32,9 @@ COMMON_LIBS= common.o $(GSS_LIBS) $(KRB5_BASE_LIBS)
+ 
+ all: ccinit ccrefresh t_accname t_ccselect t_ciflags t_credstore t_enctypes \
+ 	t_err t_export_cred t_export_name t_gssexts t_imp_cred t_imp_name \
+-	t_invalid t_inq_cred t_inq_ctx t_inq_mechs_name t_iov t_namingexts \
+-	t_oid t_pcontok t_prf t_s4u t_s4u2proxy_krb5 t_saslname t_spnego \
+-	t_srcattrs
++	t_invalid t_inq_cred t_inq_ctx t_inq_mechs_name t_iov t_lifetime \
++	t_namingexts t_oid t_pcontok t_prf t_s4u t_s4u2proxy_krb5 t_saslname \
++	t_spnego t_srcattrs
+ 
+ check-unix: t_oid
+ 	$(RUN_TEST) ./t_invalid
+@@ -42,8 +43,8 @@ check-unix: t_oid
+ 
+ check-pytests: ccinit ccrefresh t_accname t_ccselect t_ciflags t_credstore \
+ 	t_enctypes t_err t_export_cred t_export_name t_imp_cred t_inq_cred \
+-	t_inq_ctx t_inq_mechs_name t_iov t_pcontok t_s4u t_s4u2proxy_krb5 \
+-	t_spnego t_srcattrs
++	t_inq_ctx t_inq_mechs_name t_iov t_lifetime t_pcontok t_s4u \
++	t_s4u2proxy_krb5 t_spnego t_srcattrs
+ 	$(RUNPYTEST) $(srcdir)/t_gssapi.py $(PYTESTFLAGS)
+ 	$(RUNPYTEST) $(srcdir)/t_ccselect.py $(PYTESTFLAGS)
+ 	$(RUNPYTEST) $(srcdir)/t_client_keytab.py $(PYTESTFLAGS)
+@@ -88,6 +89,8 @@ t_inq_mechs_name: t_inq_mechs_name.o $(COMMON_DEPS)
+ 	$(CC_LINK) -o $@ t_inq_mechs_name.o $(COMMON_LIBS)
+ t_iov: t_iov.o $(COMMON_DEPS)
+ 	$(CC_LINK) -o $@ t_iov.o $(COMMON_LIBS)
++t_lifetime: t_lifetime.o $(COMMON_DEPS)
++	$(CC_LINK) -o $@ t_lifetime.o $(COMMON_LIBS)
+ t_namingexts: t_namingexts.o $(COMMON_DEPS)
+ 	$(CC_LINK) -o $@ t_namingexts.o $(COMMON_LIBS)
+ t_pcontok: t_pcontok.o $(COMMON_DEPS)
+@@ -111,5 +114,5 @@ clean:
+ 	$(RM) ccinit ccrefresh t_accname t_ccselect t_ciflags t_credstore
+ 	$(RM) t_enctypes t_err t_export_cred t_export_name t_gssexts t_imp_cred
+ 	$(RM) t_imp_name t_invalid t_inq_cred t_inq_ctx t_inq_mechs_name t_iov
+-	$(RM) t_namingexts t_oid t_pcontok t_prf t_s4u t_s4u2proxy_krb5
+-	$(RM) t_saslname t_spnego t_srcattrs
++	$(RM) t_lifetime t_namingexts t_oid t_pcontok t_prf t_s4u
++	$(RM) t_s4u2proxy_krb5 t_saslname t_spnego t_srcattrs
+diff --git a/src/tests/gssapi/t_gssapi.py b/src/tests/gssapi/t_gssapi.py
+index e23c936d7..fa214242f 100755
+--- a/src/tests/gssapi/t_gssapi.py
++++ b/src/tests/gssapi/t_gssapi.py
+@@ -220,4 +220,36 @@ realm.run(['./t_ciflags', 'p:' + realm.host_princ])
+ # contexts.
+ realm.run(['./t_inq_ctx', 'user', password('user'), 'p:%s' % realm.host_princ])
+ 
++# Test lifetime results, using a realm with a large maximum lifetime
++# so that we can test ticket end dates after y2038.  There are no
++# time_t conversions involved, so we can run these tests on platforms
++# with 32-bit time_t.
++realm.stop()
++conf = {'realms': {'$realm': {'max_life': '9000d'}}}
++realm = K5Realm(kdc_conf=conf, get_creds=False)
++
++# Check a lifetime string result against an expected number value (or None).
++# Allow some variance due to time elapsed during the tests.
++def check_lifetime(msg, val, expected):
++    if expected is None and val != 'indefinite':
++        fail('%s: expected indefinite, got %s' % (msg, val))
++    if expected is not None and val == 'indefinite':
++        fail('%s: expected %d, got indefinite' % (msg, expected))
++    if expected is not None and abs(int(val) - expected) > 100:
++        fail('%s: expected %d, got %s' % (msg, expected, val))
++
++realm.kinit(realm.user_princ, password('user'), flags=['-l', '8500d'])
++out = realm.run(['./t_lifetime', 'p:' + realm.host_princ, str(8000 * 86400)])
++ln = out.split('\n')
++check_lifetime('icred gss_acquire_cred', ln[0], 8500 * 86400)
++check_lifetime('icred gss_inquire_cred', ln[1], 8500 * 86400)
++check_lifetime('acred gss_acquire_cred', ln[2], None)
++check_lifetime('acred gss_inquire_cred', ln[3], None)
++check_lifetime('ictx gss_init_sec_context', ln[4], 8000 * 86400)
++check_lifetime('ictx gss_inquire_context', ln[5], 8000 * 86400)
++check_lifetime('ictx gss_context_time', ln[6], 8000 * 86400)
++check_lifetime('actx gss_accept_sec_context', ln[7], 8000 * 86400 + 300)
++check_lifetime('actx gss_inquire_context', ln[8], 8000 * 86400 + 300)
++check_lifetime('actx gss_context_time', ln[9], 8000 * 86400 + 300)
++
+ success('GSSAPI tests')
+diff --git a/src/tests/gssapi/t_lifetime.c b/src/tests/gssapi/t_lifetime.c
+new file mode 100644
+index 000000000..8dcf18621
+--- /dev/null
++++ b/src/tests/gssapi/t_lifetime.c
+@@ -0,0 +1,140 @@
++/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
++/* tests/gssapi/t_lifetime.c - display cred and context lifetimes */
++/*
++ * Copyright (C) 2017 by the Massachusetts Institute of Technology.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * * Redistributions of source code must retain the above copyright
++ *   notice, this list of conditions and the following disclaimer.
++ *
++ * * Redistributions in binary form must reproduce the above copyright
++ *   notice, this list of conditions and the following disclaimer in
++ *   the documentation and/or other materials provided with the
++ *   distribution.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
++ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <assert.h>
++#include "common.h"
++
++/*
++ * Using the default credential, exercise the GSS functions which accept or
++ * produce lifetimes.  Display the following results, one per line, as ASCII
++ * integers or the string "indefinite":
++ *
++ *   initiator cred lifetime according to gss_acquire_cred()
++ *   initiator cred lifetime according to gss_inquire_cred()
++ *   acceptor cred lifetime according to gss_acquire_cred()
++ *   acceptor cred lifetime according to gss_inquire_cred()
++ *   initiator context lifetime according to gss_init_sec_context()
++ *   initiator context lifetime according to gss_inquire_context()
++ *   initiator context lifetime according to gss_context_time()
++ *   acceptor context lifetime according to gss_init_sec_context()
++ *   acceptor context lifetime according to gss_inquire_context()
++ *   acceptor context lifetime according to gss_context_time()
++ */
++
++static void
++display_time(OM_uint32 tval)
++{
++    if (tval == GSS_C_INDEFINITE)
++        puts("indefinite");
++    else
++        printf("%u\n", (unsigned int)tval);
++}
++
++int
++main(int argc, char *argv[])
++{
++    OM_uint32 minor, major;
++    gss_cred_id_t icred, acred;
++    gss_name_t tname;
++    gss_ctx_id_t ictx = GSS_C_NO_CONTEXT, actx = GSS_C_NO_CONTEXT;
++    gss_buffer_desc itok = GSS_C_EMPTY_BUFFER, atok = GSS_C_EMPTY_BUFFER;
++    OM_uint32 time_req = GSS_C_INDEFINITE, time_rec;
++
++    if (argc < 2 || argc > 3) {
++        fprintf(stderr, "Usage: %s targetname [time_req]\n", argv[0]);
++        return 1;
++    }
++    tname = import_name(argv[1]);
++    if (argc >= 3)
++        time_req = atoll(argv[2]);
++
++    /* Get initiator cred and display its lifetime according to
++     * gss_acquire_cred and gss_inquire_cred. */
++    major = gss_acquire_cred(&minor, GSS_C_NO_NAME, time_req, &mechset_krb5,
++                             GSS_C_INITIATE, &icred, NULL, &time_rec);
++    check_gsserr("gss_acquire_cred(initiate)", major, minor);
++    display_time(time_rec);
++    major = gss_inquire_cred(&minor, icred, NULL, &time_rec, NULL, NULL);
++    check_gsserr("gss_inquire_cred(initiate)", major, minor);
++    display_time(time_rec);
++
++    /* Get acceptor cred and display its lifetime according to gss_acquire_cred
++     * and gss_inquire_cred. */
++    major = gss_acquire_cred(&minor, GSS_C_NO_NAME, time_req, &mechset_krb5,
++                             GSS_C_ACCEPT, &acred, NULL, &time_rec);
++    check_gsserr("gss_acquire_cred(accept)", major, minor);
++    display_time(time_rec);
++    major = gss_inquire_cred(&minor, acred, NULL, &time_rec, NULL, NULL);
++    check_gsserr("gss_inquire_cred(accept)", major, minor);
++    display_time(time_rec);
++
++    /* Make an initiator context and display its lifetime according to
++     * gss_init_sec_context, gss_inquire_context, and gss_context_time. */
++    major = gss_init_sec_context(&minor, icred, &ictx, tname, &mech_krb5, 0,
++                                 time_req, GSS_C_NO_CHANNEL_BINDINGS, &atok,
++                                 NULL, &itok, NULL, &time_rec);
++    check_gsserr("gss_init_sec_context", major, minor);
++    assert(major == GSS_S_COMPLETE);
++    display_time(time_rec);
++    major = gss_inquire_context(&minor, ictx, NULL, NULL, &time_rec, NULL,
++                                NULL, NULL, NULL);
++    check_gsserr("gss_inquire_context(initiate)", major, minor);
++    display_time(time_rec);
++    major = gss_context_time(&minor, ictx, &time_rec);
++    check_gsserr("gss_context_time(initiate)", major, minor);
++    display_time(time_rec);
++
++    major = gss_accept_sec_context(&minor, &actx, acred, &itok,
++                                   GSS_C_NO_CHANNEL_BINDINGS, NULL,
++                                   NULL, &atok, NULL, &time_rec, NULL);
++    check_gsserr("gss_accept_sec_context", major, minor);
++    assert(major == GSS_S_COMPLETE);
++    display_time(time_rec);
++    major = gss_inquire_context(&minor, actx, NULL, NULL, &time_rec, NULL,
++                                NULL, NULL, NULL);
++    check_gsserr("gss_inquire_context(accept)", major, minor);
++    display_time(time_rec);
++    major = gss_context_time(&minor, actx, &time_rec);
++    check_gsserr("gss_context_time(accept)", major, minor);
++    display_time(time_rec);
++
++    (void)gss_release_buffer(&minor, &itok);
++    (void)gss_release_buffer(&minor, &atok);
++    (void)gss_release_name(&minor, &tname);
++    (void)gss_release_cred(&minor, &icred);
++    (void)gss_release_cred(&minor, &acred);
++    (void)gss_delete_sec_context(&minor, &ictx, NULL);
++    (void)gss_delete_sec_context(&minor, &actx, NULL);
++    return 0;
++}
+diff --git a/src/tests/t_kdb.py b/src/tests/t_kdb.py
+index 185225afa..c0eeb0118 100755
+--- a/src/tests/t_kdb.py
++++ b/src/tests/t_kdb.py
+@@ -446,6 +446,13 @@ realm.run([kadminl, 'addprinc', '-policy', 'keepoldpasspol', '-pw', 'aaaa',
+ for p in ('bbbb', 'cccc', 'aaaa'):
+     realm.run([kadminl, 'cpw', '-keepold', '-pw', p, 'keepoldpassprinc'])
+ 
++if runenv.sizeof_time_t <= 4:
++    skipped('y2038 LDAP test', 'platform has 32-bit time_t')
++else:
++    # Test storage of timestamps after y2038.
++    realm.run([kadminl, 'modprinc', '-pwexpire', '2040-02-03', 'user'])
++    realm.run([kadminl, 'getprinc', 'user'], expected_msg=' 2040\n')
++
+ realm.stop()
+ 
+ # Briefly test dump and load.
+diff --git a/src/tests/t_y2038.py b/src/tests/t_y2038.py
+new file mode 100644
+index 000000000..02e946df4
+--- /dev/null
++++ b/src/tests/t_y2038.py
+@@ -0,0 +1,75 @@
++#!/usr/bin/python
++from k5test import *
++
++# These tests will become much less important after the y2038 boundary
++# has elapsed, and may start exhibiting problems around the year 2075.
++
++if runenv.sizeof_time_t <= 4:
++    skip_rest('y2038 timestamp tests', 'platform has 32-bit time_t')
++
++# Start a KDC running roughly 21 years in the future, after the y2038
++# boundary.  Set long maximum lifetimes for later tests.
++conf = {'realms': {'$realm': {'max_life': '9000d',
++                              'max_renewable_life': '9000d'}}}
++realm = K5Realm(start_kdc=False, kdc_conf=conf)
++realm.start_kdc(['-T', '662256000'])
++
++# kinit without preauth should succeed with clock skew correction, but
++# will result in an expired ticket, because we sent an absolute end
++# time and didn't get a chance to correct it..
++realm.kinit(realm.user_princ, password('user'))
++realm.run([kvno, realm.host_princ], expected_code=1,
++          expected_msg='Ticket expired')
++
++# kinit with preauth should succeed and result in a valid ticket, as
++# we get a chance to correct the end time based on the KDC time.  Try
++# with encrypted timestamp and encrypted challenge.
++realm.run([kadminl, 'modprinc', '+requires_preauth', 'user'])
++realm.kinit(realm.user_princ, password('user'))
++realm.run([kvno, realm.host_princ])
++realm.kinit(realm.user_princ, password('user'), flags=['-T', realm.ccache])
++realm.run([kvno, realm.host_princ])
++
++# Test that expiration warning works after y2038, by setting a
++# password expiration time ten minutes after the KDC time.
++realm.run([kadminl, 'modprinc', '-pwexpire', '662256600 seconds', 'user'])
++out = realm.kinit(realm.user_princ, password('user'))
++if 'will expire in less than one hour' not in out:
++    fail('password expiration message')
++year = int(out.split()[-1])
++if year < 2038 or year > 9999:
++    fail('password expiration year')
++
++realm.stop_kdc()
++realm.start_kdc()
++realm.start_kadmind()
++realm.prep_kadmin()
++
++# Test getdate parsing of absolute timestamps after 2038 and
++# marshalling over the kadmin protocol.  The local time zone will
++# affect the display time by a little bit, so just look for the year.
++realm.run_kadmin(['modprinc', '-pwexpire', '2040-02-03', realm.host_princ])
++realm.run_kadmin(['getprinc', realm.host_princ], expected_msg=' 2040\n')
++
++# Get a ticket whose lifetime crosses the y2038 boundary and
++# range-check the expiration year as reported by klist.
++realm.kinit(realm.user_princ, password('user'),
++            flags=['-l', '8000d', '-r', '8500d'])
++realm.run([kvno, realm.host_princ])
++out = realm.run([klist])
++if int(out.split('\n')[4].split()[2].split('/')[2]) < 39:
++    fail('unexpected tgt expiration year')
++if int(out.split('\n')[5].split()[2].split('/')[2]) < 40:
++    fail('unexpected tgt rtill year')
++if int(out.split('\n')[6].split()[2].split('/')[2]) < 39:
++    fail('unexpected service ticket expiration year')
++if int(out.split('\n')[7].split()[2].split('/')[2]) < 40:
++    fail('unexpected service ticket rtill year')
++realm.kinit(realm.user_princ, None, ['-R'])
++out = realm.run([klist])
++if int(out.split('\n')[4].split()[2].split('/')[2]) < 39:
++    fail('unexpected renewed tgt expiration year')
++if int(out.split('\n')[5].split()[2].split('/')[2]) < 40:
++    fail('unexpected renewed tgt rtill year')
++
++success('y2038 tests')
diff --git a/SOURCES/Add-y2038-documentation.patch b/SOURCES/Add-y2038-documentation.patch
new file mode 100644
index 0000000..01642e1
--- /dev/null
+++ b/SOURCES/Add-y2038-documentation.patch
@@ -0,0 +1,60 @@
+From f9702eabc568679f48ea5d0bc7be073582cc52ad Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Thu, 4 May 2017 17:03:35 -0400
+Subject: [PATCH] Add y2038 documentation
+
+ticket: 8352
+(cherry picked from commit 85d64c43dbf7a7faa56a1999494cdfa49e8bd2c9)
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ doc/appdev/index.rst |  1 +
+ doc/appdev/y2038.rst | 28 ++++++++++++++++++++++++++++
+ 2 files changed, 29 insertions(+)
+ create mode 100644 doc/appdev/y2038.rst
+
+diff --git a/doc/appdev/index.rst b/doc/appdev/index.rst
+index 3d62045ca..961bb1e9e 100644
+--- a/doc/appdev/index.rst
++++ b/doc/appdev/index.rst
+@@ -5,6 +5,7 @@ For application developers
+    :maxdepth: 1
+ 
+    gssapi.rst
++   y2038.rst
+    h5l_mit_apidiff.rst
+    init_creds.rst
+    princ_handle.rst
+diff --git a/doc/appdev/y2038.rst b/doc/appdev/y2038.rst
+new file mode 100644
+index 000000000..bc4122dad
+--- /dev/null
++++ b/doc/appdev/y2038.rst
+@@ -0,0 +1,28 @@
++Year 2038 considerations for uses of krb5_timestamp
++===================================================
++
++POSIX time values, which measure the number of seconds since January 1
++1970, will exceed the maximum value representable in a signed 32-bit
++integer in January 2038.  This documentation describes considerations
++for consumers of the MIT krb5 libraries.
++
++Applications or libraries which use libkrb5 and consume the timestamps
++included in credentials or other structures make use of the
++:c:type:`krb5_timestamp` type.  For historical reasons, krb5_timestamp
++is a signed 32-bit integer, even on platforms where a larger type is
++natively used to represent time values.  To behave properly for time
++values after January 2038, calling code should cast krb5_timestamp
++values to uint32_t, and then to time_t::
++
++    (time_t)(uint32_t)timestamp
++
++Used in this way, krb5_timestamp values can represent time values up
++until February 2106, provided that the platform uses a 64-bit or
++larger time_t type.  This usage will also remain safe if a later
++version of MIT krb5 changes krb5_timestamp to an unsigned 32-bit
++integer.
++
++The GSSAPI only uses representations of time intervals, not absolute
++times.  Callers of the GSSAPI should require no changes to behave
++correctly after January 2038, provided that they use MIT krb5 release
++1.16 or later.
diff --git a/SOURCES/Allow-clock-skew-in-krb5-gss_context_time.patch b/SOURCES/Allow-clock-skew-in-krb5-gss_context_time.patch
new file mode 100644
index 0000000..8eb9c2e
--- /dev/null
+++ b/SOURCES/Allow-clock-skew-in-krb5-gss_context_time.patch
@@ -0,0 +1,37 @@
+From 498b43b1a58795773834c1c5bb2b61dd801b9a03 Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Sat, 22 Apr 2017 16:51:23 -0400
+Subject: [PATCH] Allow clock skew in krb5 gss_context_time()
+
+Commit b496ce4095133536e0ace36b74130e4b9ecb5e11 (ticket #8268) adds
+the clock skew to krb5 acceptor context lifetimes for
+gss_accept_sec_context() and gss_inquire_context(), but not for
+gss_context_time().  Add the clock skew in gss_context_time() as well.
+
+ticket: 8581 (new)
+target_version: 1.14-next
+target_version: 1.15-next
+tags: pullup
+
+(cherry picked from commit b0a072e6431261734e7350996a363801f180e8ea)
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/lib/gssapi/krb5/context_time.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/src/lib/gssapi/krb5/context_time.c b/src/lib/gssapi/krb5/context_time.c
+index a18cfb05b..450593288 100644
+--- a/src/lib/gssapi/krb5/context_time.c
++++ b/src/lib/gssapi/krb5/context_time.c
+@@ -51,7 +51,10 @@ krb5_gss_context_time(minor_status, context_handle, time_rec)
+         return(GSS_S_FAILURE);
+     }
+ 
+-    if ((lifetime = ctx->krb_times.endtime - now) <= 0) {
++    lifetime = ctx->krb_times.endtime - now;
++    if (!ctx->initiate)
++        lifetime += ctx->k5_context->clockskew;
++    if (lifetime <= 0) {
+         *time_rec = 0;
+         *minor_status = 0;
+         return(GSS_S_CONTEXT_EXPIRED);
diff --git a/SOURCES/Convert-some-pkiDebug-messages-to-TRACE-macros.patch b/SOURCES/Convert-some-pkiDebug-messages-to-TRACE-macros.patch
new file mode 100644
index 0000000..69f99cb
--- /dev/null
+++ b/SOURCES/Convert-some-pkiDebug-messages-to-TRACE-macros.patch
@@ -0,0 +1,424 @@
+From b4c2212ae7412e21f4965acdb8c10e4a60b65b9b Mon Sep 17 00:00:00 2001
+From: Matt Rogers <mrogers@redhat.com>
+Date: Wed, 29 Mar 2017 10:35:13 -0400
+Subject: [PATCH] Convert some pkiDebug messages to TRACE macros
+
+ticket: 8568 (new)
+(cherry picked from commit 9852862a83952a94300adfafa3e333f43396ec33)
+(cherry picked from commit 686fa6476eb759532d566794fa8d430774d44cf7)
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/plugins/preauth/pkinit/pkinit_crypto_openssl.c | 46 ++++++---------
+ src/plugins/preauth/pkinit/pkinit_identity.c       |  3 -
+ src/plugins/preauth/pkinit/pkinit_matching.c       |  1 +
+ src/plugins/preauth/pkinit/pkinit_srv.c            | 24 ++++----
+ src/plugins/preauth/pkinit/pkinit_trace.h          | 68 +++++++++++++++++++++-
+ 5 files changed, 97 insertions(+), 45 deletions(-)
+
+diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+index 90c30dbf5..70e230ec2 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+@@ -2320,7 +2320,6 @@ crypto_check_cert_eku(krb5_context context,
+ 
+     X509_NAME_oneline(X509_get_subject_name(reqctx->received_cert),
+                       buf, sizeof(buf));
+-    pkiDebug("%s: looking for EKUs in cert = %s\n", __FUNCTION__, buf);
+ 
+     if ((i = X509_get_ext_by_NID(reqctx->received_cert,
+                                  NID_ext_key_usage, -1)) >= 0) {
+@@ -2354,7 +2353,6 @@ crypto_check_cert_eku(krb5_context context,
+ 
+         if (found_eku) {
+             ASN1_BIT_STRING *usage = NULL;
+-            pkiDebug("%s: found acceptable EKU, checking for digitalSignature\n", __FUNCTION__);
+ 
+             /* check that digitalSignature KeyUsage is present */
+             X509_check_ca(reqctx->received_cert);
+@@ -2363,12 +2361,10 @@ crypto_check_cert_eku(krb5_context context,
+ 
+                 if (!ku_reject(reqctx->received_cert,
+                                X509v3_KU_DIGITAL_SIGNATURE)) {
+-                    pkiDebug("%s: found digitalSignature KU\n",
+-                             __FUNCTION__);
++                    TRACE_PKINIT_EKU(context);
+                     *valid_eku = 1;
+                 } else
+-                    pkiDebug("%s: didn't find digitalSignature KU\n",
+-                             __FUNCTION__);
++                    TRACE_PKINIT_EKU_NO_KU(context);
+             }
+             ASN1_BIT_STRING_free(usage);
+         }
+@@ -4317,8 +4313,7 @@ pkinit_get_certs_pkcs12(krb5_context context,
+ 
+     fp = fopen(idopts->cert_filename, "rb");
+     if (fp == NULL) {
+-        pkiDebug("Failed to open PKCS12 file '%s', error %d\n",
+-                 idopts->cert_filename, errno);
++        TRACE_PKINIT_PKCS_OPEN_FAIL(context, idopts->cert_filename, errno);
+         goto cleanup;
+     }
+     set_cloexec_file(fp);
+@@ -4326,8 +4321,7 @@ pkinit_get_certs_pkcs12(krb5_context context,
+     p12 = d2i_PKCS12_fp(fp, NULL);
+     fclose(fp);
+     if (p12 == NULL) {
+-        pkiDebug("Failed to decode PKCS12 file '%s' contents\n",
+-                 idopts->cert_filename);
++        TRACE_PKINIT_PKCS_DECODE_FAIL(context, idopts->cert_filename);
+         goto cleanup;
+     }
+     /*
+@@ -4345,7 +4339,7 @@ pkinit_get_certs_pkcs12(krb5_context context,
+         char *p12name = reassemble_pkcs12_name(idopts->cert_filename);
+         const char *tmp;
+ 
+-        pkiDebug("Initial PKCS12_parse with no password failed\n");
++        TRACE_PKINIT_PKCS_PARSE_FAIL_FIRST(context);
+ 
+         if (id_cryptoctx->defer_id_prompt) {
+             /* Supply the identity name to be passed to the responder. */
+@@ -4386,14 +4380,14 @@ pkinit_get_certs_pkcs12(krb5_context context,
+                                           NULL, NULL, 1, &kprompt);
+             k5int_set_prompt_types(context, 0);
+             if (r) {
+-                pkiDebug("Failed to prompt for PKCS12 password");
++                TRACE_PKINIT_PKCS_PROMPT_FAIL(context);
+                 goto cleanup;
+             }
+         }
+ 
+         ret = PKCS12_parse(p12, rdat.data, &y, &x, NULL);
+         if (ret == 0) {
+-            pkiDebug("Second PKCS12_parse with password failed\n");
++            TRACE_PKINIT_PKCS_PARSE_FAIL_SECOND(context);
+             goto cleanup;
+         }
+     }
+@@ -4516,8 +4510,7 @@ pkinit_get_certs_fs(krb5_context context,
+     }
+ 
+     if (idopts->key_filename == NULL) {
+-        pkiDebug("%s: failed to get user's private key location\n",
+-                 __FUNCTION__);
++        TRACE_PKINIT_NO_PRIVKEY(context);
+         goto cleanup;
+     }
+ 
+@@ -4545,8 +4538,7 @@ pkinit_get_certs_dir(krb5_context context,
+     char *dirname, *suf;
+ 
+     if (idopts->cert_filename == NULL) {
+-        pkiDebug("%s: failed to get user's certificate directory location\n",
+-                 __FUNCTION__);
++        TRACE_PKINIT_NO_CERT(context);
+         return ENOENT;
+     }
+ 
+@@ -4590,8 +4582,7 @@ pkinit_get_certs_dir(krb5_context context,
+         retval = pkinit_load_fs_cert_and_key(context, id_cryptoctx,
+                                              certname, keyname, i);
+         if (retval == 0) {
+-            pkiDebug("%s: Successfully loaded cert (and key) for %s\n",
+-                     __FUNCTION__, dentry->d_name);
++            TRACE_PKINIT_LOADED_CERT(context, dentry->d_name);
+             i++;
+         }
+         else
+@@ -4599,8 +4590,7 @@ pkinit_get_certs_dir(krb5_context context,
+     }
+ 
+     if (!id_cryptoctx->defer_id_prompt && i == 0) {
+-        pkiDebug("%s: No cert/key pairs found in directory '%s'\n",
+-                 __FUNCTION__, idopts->cert_filename);
++        TRACE_PKINIT_NO_CERT_AND_KEY(context, idopts->cert_filename);
+         retval = ENOENT;
+         goto cleanup;
+     }
+@@ -5370,9 +5360,7 @@ crypto_cert_select_default(krb5_context context,
+         goto errout;
+     }
+     if (cert_count != 1) {
+-        pkiDebug("%s: ERROR: There are %d certs to choose from, "
+-                 "but there must be exactly one.\n",
+-                 __FUNCTION__, cert_count);
++        TRACE_PKINIT_NO_DEFAULT_CERT(context, cert_count);
+         retval = EINVAL;
+         goto errout;
+     }
+@@ -5520,7 +5508,7 @@ load_cas_and_crls(krb5_context context,
+     switch(catype) {
+     case CATYPE_ANCHORS:
+         if (sk_X509_num(ca_certs) == 0) {
+-            pkiDebug("no anchors in file, %s\n", filename);
++            TRACE_PKINIT_NO_CA_ANCHOR(context, filename);
+             if (id_cryptoctx->trustedCAs == NULL)
+                 sk_X509_free(ca_certs);
+         } else {
+@@ -5530,7 +5518,7 @@ load_cas_and_crls(krb5_context context,
+         break;
+     case CATYPE_INTERMEDIATES:
+         if (sk_X509_num(ca_certs) == 0) {
+-            pkiDebug("no intermediates in file, %s\n", filename);
++            TRACE_PKINIT_NO_CA_INTERMEDIATE(context, filename);
+             if (id_cryptoctx->intermediateCAs == NULL)
+                 sk_X509_free(ca_certs);
+         } else {
+@@ -5540,7 +5528,7 @@ load_cas_and_crls(krb5_context context,
+         break;
+     case CATYPE_CRLS:
+         if (sk_X509_CRL_num(ca_crls) == 0) {
+-            pkiDebug("no crls in file, %s\n", filename);
++            TRACE_PKINIT_NO_CRL(context, filename);
+             if (id_cryptoctx->revoked == NULL)
+                 sk_X509_CRL_free(ca_crls);
+         } else {
+@@ -5626,14 +5614,14 @@ crypto_load_cas_and_crls(krb5_context context,
+                          int catype,
+                          char *id)
+ {
+-    pkiDebug("%s: called with idtype %s and catype %s\n",
+-             __FUNCTION__, idtype2string(idtype), catype2string(catype));
+     switch (idtype) {
+     case IDTYPE_FILE:
++        TRACE_PKINIT_LOAD_FROM_FILE(context);
+         return load_cas_and_crls(context, plg_cryptoctx, req_cryptoctx,
+                                  id_cryptoctx, catype, id);
+         break;
+     case IDTYPE_DIR:
++        TRACE_PKINIT_LOAD_FROM_DIR(context);
+         return load_cas_and_crls_dir(context, plg_cryptoctx, req_cryptoctx,
+                                      id_cryptoctx, catype, id);
+         break;
+diff --git a/src/plugins/preauth/pkinit/pkinit_identity.c b/src/plugins/preauth/pkinit/pkinit_identity.c
+index a897efa25..737552e85 100644
+--- a/src/plugins/preauth/pkinit/pkinit_identity.c
++++ b/src/plugins/preauth/pkinit/pkinit_identity.c
+@@ -608,7 +608,6 @@ pkinit_identity_prompt(krb5_context context,
+             retval = pkinit_cert_matching(context, plg_cryptoctx,
+                                           req_cryptoctx, id_cryptoctx, princ);
+             if (retval) {
+-                pkiDebug("%s: No matching certificate found\n", __FUNCTION__);
+                 crypto_free_cert_info(context, plg_cryptoctx, req_cryptoctx,
+                                       id_cryptoctx);
+                 goto errout;
+@@ -621,8 +620,6 @@ pkinit_identity_prompt(krb5_context context,
+             retval = crypto_cert_select_default(context, plg_cryptoctx,
+                                                 req_cryptoctx, id_cryptoctx);
+             if (retval) {
+-                pkiDebug("%s: Failed while selecting default certificate\n",
+-                         __FUNCTION__);
+                 crypto_free_cert_info(context, plg_cryptoctx, req_cryptoctx,
+                                       id_cryptoctx);
+                 goto errout;
+diff --git a/src/plugins/preauth/pkinit/pkinit_matching.c b/src/plugins/preauth/pkinit/pkinit_matching.c
+index a50c50c8d..cad4c2b9a 100644
+--- a/src/plugins/preauth/pkinit/pkinit_matching.c
++++ b/src/plugins/preauth/pkinit/pkinit_matching.c
+@@ -812,6 +812,7 @@ pkinit_cert_matching(krb5_context context,
+             goto cleanup;
+         }
+     } else {
++        TRACE_PKINIT_NO_MATCHING_CERT(context);
+         retval = ENOENT;    /* XXX */
+         goto cleanup;
+     }
+diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c
+index 32ca122f2..9c6e96c9e 100644
+--- a/src/plugins/preauth/pkinit/pkinit_srv.c
++++ b/src/plugins/preauth/pkinit/pkinit_srv.c
+@@ -188,6 +188,7 @@ verify_client_san(krb5_context context,
+                                        plgctx->opts->allow_upn ? &upns : NULL,
+                                        NULL);
+     if (retval == ENOENT) {
++        TRACE_PKINIT_SERVER_NO_SAN(context);
+         goto out;
+     } else if (retval) {
+         pkiDebug("%s: error from retrieve_certificate_sans()\n", __FUNCTION__);
+@@ -224,7 +225,7 @@ verify_client_san(krb5_context context,
+         krb5_free_unparsed_name(context, san_string);
+ #endif
+         if (cb->match_client(context, rock, princs[i])) {
+-            pkiDebug("%s: pkinit san match found\n", __FUNCTION__);
++            TRACE_PKINIT_SERVER_MATCHING_SAN_FOUND(context);
+             *valid_san = 1;
+             retval = 0;
+             goto out;
+@@ -252,7 +253,7 @@ verify_client_san(krb5_context context,
+         krb5_free_unparsed_name(context, san_string);
+ #endif
+         if (cb->match_client(context, rock, upns[i])) {
+-            pkiDebug("%s: upn san match found\n", __FUNCTION__);
++            TRACE_PKINIT_SERVER_MATCHING_UPN_FOUND(context);
+             *valid_san = 1;
+             retval = 0;
+             goto out;
+@@ -300,7 +301,7 @@ verify_client_eku(krb5_context context,
+     *eku_accepted = 0;
+ 
+     if (plgctx->opts->require_eku == 0) {
+-        pkiDebug("%s: configuration requests no EKU checking\n", __FUNCTION__);
++        TRACE_PKINIT_SERVER_EKU_SKIP(context);
+         *eku_accepted = 1;
+         retval = 0;
+         goto out;
+@@ -364,6 +365,7 @@ authorize_cert(krb5_context context, certauth_handle *certauth_modules,
+     ret = KRB5_PLUGIN_NO_HANDLE;
+     for (i = 0; certauth_modules != NULL && certauth_modules[i] != NULL; i++) {
+         h = certauth_modules[i];
++        TRACE_PKINIT_SERVER_CERT_AUTH(context, h->vt.name);
+         ret = h->vt.authorize(context, h->moddata, cert, cert_len, client,
+                               &opts, db_ent, &ais);
+         if (ret == 0)
+@@ -449,7 +451,7 @@ pkinit_server_verify_padata(krb5_context context,
+ 
+     switch ((int)data->pa_type) {
+     case KRB5_PADATA_PK_AS_REQ:
+-        pkiDebug("processing KRB5_PADATA_PK_AS_REQ\n");
++        TRACE_PKINIT_SERVER_PADATA_VERIFY(context);
+         retval = k5int_decode_krb5_pa_pk_as_req(&k5data, &reqp);
+         if (retval) {
+             pkiDebug("decode_krb5_pa_pk_as_req failed\n");
+@@ -472,7 +474,7 @@ pkinit_server_verify_padata(krb5_context context,
+         break;
+     case KRB5_PADATA_PK_AS_REP_OLD:
+     case KRB5_PADATA_PK_AS_REQ_OLD:
+-        pkiDebug("processing KRB5_PADATA_PK_AS_REQ_OLD\n");
++        TRACE_PKINIT_SERVER_PADATA_VERIFY_OLD(context);
+         retval = k5int_decode_krb5_pa_pk_as_req_draft9(&k5data, &reqp9);
+         if (retval) {
+             pkiDebug("decode_krb5_pa_pk_as_req_draft9 failed\n");
+@@ -500,7 +502,7 @@ pkinit_server_verify_padata(krb5_context context,
+         goto cleanup;
+     }
+     if (retval) {
+-        pkiDebug("pkcs7_signeddata_verify failed\n");
++        TRACE_PKINIT_SERVER_PADATA_VERIFY_FAIL(context);
+         goto cleanup;
+     }
+     if (is_signed) {
+@@ -830,7 +832,7 @@ pkinit_server_return_padata(krb5_context context,
+         return ENOENT;
+     }
+ 
+-    pkiDebug("pkinit_return_padata: entered!\n");
++    TRACE_PKINIT_SERVER_RETURN_PADATA(context);
+     reqctx = (pkinit_kdc_req_context)modreq;
+ 
+     if (encrypting_key->contents) {
+@@ -1463,8 +1465,7 @@ pkinit_san_authorize(krb5_context context, krb5_certauth_moddata moddata,
+         return ret;
+ 
+     if (!valid_san) {
+-        pkiDebug("%s: did not find an acceptable SAN in user certificate\n",
+-                 __FUNCTION__);
++        TRACE_PKINIT_SERVER_SAN_REJECT(context);
+         return KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
+     }
+ 
+@@ -1490,8 +1491,7 @@ pkinit_eku_authorize(krb5_context context, krb5_certauth_moddata moddata,
+         return ret;
+ 
+     if (!valid_eku) {
+-        pkiDebug("%s: did not find an acceptable EKU in user certificate\n",
+-                 __FUNCTION__);
++        TRACE_PKINIT_SERVER_EKU_REJECT(context);
+         return KRB5KDC_ERR_INCONSISTENT_KEY_PURPOSE;
+     }
+ 
+@@ -1617,7 +1617,7 @@ pkinit_server_plugin_init(krb5_context context,
+         return ENOMEM;
+ 
+     for (i = 0, j = 0; i < numrealms; i++) {
+-        pkiDebug("%s: processing realm '%s'\n", __FUNCTION__, realmnames[i]);
++        TRACE_PKINIT_SERVER_INIT_REALM(context, realmnames[i]);
+         retval = pkinit_server_plugin_init_realm(context, realmnames[i], &plgctx);
+         if (retval == 0 && plgctx != NULL)
+             realm_contexts[j++] = plgctx;
+diff --git a/src/plugins/preauth/pkinit/pkinit_trace.h b/src/plugins/preauth/pkinit/pkinit_trace.h
+index 458d0961e..6abe28c0c 100644
+--- a/src/plugins/preauth/pkinit/pkinit_trace.h
++++ b/src/plugins/preauth/pkinit/pkinit_trace.h
+@@ -52,7 +52,7 @@
+ #define TRACE_PKINIT_CLIENT_REP_CHECKSUM_FAIL(c, expected, received)    \
+     TRACE(c, "PKINIT client checksum mismatch: expected {cksum}, "      \
+           "received {cksum}", expected, received)
+-#define TRACE_PKINIT_CLIENT_REP_DH(c)                   \
++#define TRACE_PKINIT_CLIENT_REP_DH(c)           \
+     TRACE(c, "PKINIT client verified DH reply")
+ #define TRACE_PKINIT_CLIENT_REP_DH_FAIL(c)              \
+     TRACE(c, "PKINIT client could not verify DH reply")
+@@ -91,6 +91,72 @@
+ #define TRACE_PKINIT_OPENSSL_ERROR(c, msg)              \
+     TRACE(c, "PKINIT OpenSSL error: {str}", msg)
+ 
++#define TRACE_PKINIT_SERVER_CERT_AUTH(c, modname)                       \
++    TRACE(c, "PKINIT server authorizing cert with module {str}",        \
++          modname)
++#define TRACE_PKINIT_SERVER_EKU_REJECT(c)                               \
++    TRACE(c, "PKINIT server found no acceptable EKU in client cert")
++#define TRACE_PKINIT_SERVER_EKU_SKIP(c)                                 \
++    TRACE(c, "PKINIT server skipping EKU check due to configuration")
++#define TRACE_PKINIT_SERVER_INIT_REALM(c, realm)                \
++    TRACE(c, "PKINIT server initializing realm {str}", realm)
++#define TRACE_PKINIT_SERVER_MATCHING_UPN_FOUND(c)                       \
++    TRACE(c, "PKINIT server found a matching UPN SAN in client cert")
++#define TRACE_PKINIT_SERVER_MATCHING_SAN_FOUND(c)                       \
++    TRACE(c, "PKINIT server found a matching SAN in client cert")
++#define TRACE_PKINIT_SERVER_NO_SAN(c)                           \
++    TRACE(c, "PKINIT server found no SAN in client cert")
++#define TRACE_PKINIT_SERVER_PADATA_VERIFY(c)                    \
++    TRACE(c, "PKINIT server verifying KRB5_PADATA_PK_AS_REQ")
++#define TRACE_PKINIT_SERVER_PADATA_VERIFY_OLD(c)                        \
++    TRACE(c, "PKINIT server verifying KRB5_PADATA_PK_AS_REQ_OLD")
++#define TRACE_PKINIT_SERVER_PADATA_VERIFY_FAIL(c)       \
++    TRACE(c, "PKINIT server failed to verify PA data")
++#define TRACE_PKINIT_SERVER_RETURN_PADATA(c)    \
++    TRACE(c, "PKINIT server returning PA data")
++#define TRACE_PKINIT_SERVER_SAN_REJECT(c)                               \
++    TRACE(c, "PKINIT server found no acceptable SAN in client cert")
++
++#define TRACE_PKINIT_EKU(c)                                             \
++    TRACE(c, "PKINIT found acceptable EKU and digitalSignature KU")
++#define TRACE_PKINIT_EKU_NO_KU(c)                                       \
++    TRACE(c, "PKINIT found acceptable EKU but no digitalSignature KU")
++#define TRACE_PKINIT_LOADED_CERT(c, name)                       \
++    TRACE(c, "PKINIT loaded cert and key for {str}", name)
++#define TRACE_PKINIT_LOAD_FROM_FILE(c)                          \
++    TRACE(c, "PKINIT loading CA certs and CRLs from FILE")
++#define TRACE_PKINIT_LOAD_FROM_DIR(c)                           \
++    TRACE(c, "PKINIT loading CA certs and CRLs from DIR")
++#define TRACE_PKINIT_NO_CA_ANCHOR(c, file)              \
++    TRACE(c, "PKINIT no anchor CA in file {str}", file)
++#define TRACE_PKINIT_NO_CA_INTERMEDIATE(c, file)                \
++    TRACE(c, "PKINIT no intermediate CA in file {str}", file)
++#define TRACE_PKINIT_NO_CERT(c)                 \
++    TRACE(c, "PKINIT no certificate provided")
++#define TRACE_PKINIT_NO_CERT_AND_KEY(c, dirname)                        \
++    TRACE(c, "PKINIT no cert and key pair found in directory {str}",    \
++          dirname)
++#define TRACE_PKINIT_NO_CRL(c, file)                    \
++    TRACE(c, "PKINIT no CRL in file {str}", file)
++#define TRACE_PKINIT_NO_DEFAULT_CERT(c, count)                          \
++    TRACE(c, "PKINIT error: There are {int} certs, but there must "     \
++          "be exactly one.", count)
++#define TRACE_PKINIT_NO_MATCHING_CERT(c)                \
++    TRACE(c, "PKINIT no matching certificate found")
++#define TRACE_PKINIT_NO_PRIVKEY(c)              \
++    TRACE(c, "PKINIT no private key provided")
++#define TRACE_PKINIT_PKCS_DECODE_FAIL(c, name)                          \
++    TRACE(c, "PKINIT failed to decode PKCS12 file {str} contents", name)
++#define TRACE_PKINIT_PKCS_OPEN_FAIL(c, name, err)                       \
++    TRACE(c, "PKINIT failed to open PKCS12 file {str}: err {errno}",    \
++          name, err)
++#define TRACE_PKINIT_PKCS_PARSE_FAIL_FIRST(c)                           \
++    TRACE(c, "PKINIT initial PKCS12_parse with no password failed")
++#define TRACE_PKINIT_PKCS_PARSE_FAIL_SECOND(c)                          \
++    TRACE(c, "PKINIT second PKCS12_parse with password failed")
++#define TRACE_PKINIT_PKCS_PROMPT_FAIL(c)                        \
++    TRACE(c, "PKINIT failed to prompt for PKCS12 password")
++
+ #define TRACE_CERTAUTH_VTINIT_FAIL(c, ret)                              \
+     TRACE(c, "certauth module failed to init vtable: {kerr}", ret)
+ #define TRACE_CERTAUTH_INIT_FAIL(c, name, ret)                          \
diff --git a/SOURCES/Correct-error-handling-bug-in-prior-commit.patch b/SOURCES/Correct-error-handling-bug-in-prior-commit.patch
new file mode 100644
index 0000000..83da7f4
--- /dev/null
+++ b/SOURCES/Correct-error-handling-bug-in-prior-commit.patch
@@ -0,0 +1,33 @@
+From ca3e61600f1400974c63b2abb30b44f0c94d550b Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Thu, 23 Mar 2017 13:42:55 -0400
+Subject: [PATCH] Correct error handling bug in prior commit
+
+In crypto_encode_der_cert(), if the second i2d_X509() invocation
+fails, make sure to free the allocated pointer and not the
+possibly-modified alias.
+
+ticket: 8561
+(cherry picked from commit 7fdaef7c3280c86b5df25ae061fb04cc56d8620c)
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/plugins/preauth/pkinit/pkinit_crypto_openssl.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+index a5b010b26..90c30dbf5 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+@@ -6196,10 +6196,10 @@ crypto_encode_der_cert(krb5_context context, pkinit_req_crypto_context reqctx,
+     if (len <= 0)
+         return EINVAL;
+     p = der = malloc(len);
+-    if (p == NULL)
++    if (der == NULL)
+         return ENOMEM;
+     if (i2d_X509(reqctx->received_cert, &p) <= 0) {
+-        free(p);
++        free(der);
+         return EINVAL;
+     }
+     *der_out = der;
diff --git a/SOURCES/Deindent-crypto_retrieve_X509_sans.patch b/SOURCES/Deindent-crypto_retrieve_X509_sans.patch
new file mode 100644
index 0000000..3864cd3
--- /dev/null
+++ b/SOURCES/Deindent-crypto_retrieve_X509_sans.patch
@@ -0,0 +1,265 @@
+From 54c5bec8deb2d4e972795e37273ad17a0b1e2f4f Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Wed, 4 Jan 2017 11:33:57 -0500
+Subject: [PATCH] Deindent crypto_retrieve_X509_sans()
+
+Fix some long lines in crypto_retrieve_X509_sans() by returning early
+if X509_get_ext_by_NID() returns a negative result.  Also ensure that
+return parameters are always initialized.
+
+(cherry picked from commit c6b772523db9d7791ee1c56eb512c4626556a4e7)
+(cherry picked from commit 23086ac768a32db1e40a9b63684dbcfd76aba033)
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/plugins/preauth/pkinit/pkinit_crypto_openssl.c | 224 +++++++++++----------
+ 1 file changed, 114 insertions(+), 110 deletions(-)
+
+diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+index bc6e7662e..8def8c542 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+@@ -2101,11 +2101,21 @@ crypto_retrieve_X509_sans(krb5_context context,
+ {
+     krb5_error_code retval = EINVAL;
+     char buf[DN_BUF_LEN];
+-    int p = 0, u = 0, d = 0, l;
++    int p = 0, u = 0, d = 0, ret = 0, l;
+     krb5_principal *princs = NULL;
+     krb5_principal *upns = NULL;
+     unsigned char **dnss = NULL;
+-    unsigned int i, num_found = 0;
++    unsigned int i, num_found = 0, num_sans = 0;
++    X509_EXTENSION *ext = NULL;
++    GENERAL_NAMES *ialt = NULL;
++    GENERAL_NAME *gen = NULL;
++
++    if (princs_ret != NULL)
++        *princs_ret = NULL;
++    if (upn_ret != NULL)
++        *upn_ret = NULL;
++    if (dns_ret != NULL)
++        *dns_ret = NULL;
+ 
+     if (princs_ret == NULL && upn_ret == NULL && dns_ret == NULL) {
+         pkiDebug("%s: nowhere to return any values!\n", __FUNCTION__);
+@@ -2121,118 +2131,112 @@ crypto_retrieve_X509_sans(krb5_context context,
+                       buf, sizeof(buf));
+     pkiDebug("%s: looking for SANs in cert = %s\n", __FUNCTION__, buf);
+ 
+-    if ((l = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1)) >= 0) {
+-        X509_EXTENSION *ext = NULL;
+-        GENERAL_NAMES *ialt = NULL;
+-        GENERAL_NAME *gen = NULL;
+-        int ret = 0;
+-        unsigned int num_sans = 0;
++    l = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
++    if (l < 0)
++        return 0;
+ 
+-        if (!(ext = X509_get_ext(cert, l)) || !(ialt = X509V3_EXT_d2i(ext))) {
+-            pkiDebug("%s: found no subject alt name extensions\n",
+-                     __FUNCTION__);
++    if (!(ext = X509_get_ext(cert, l)) || !(ialt = X509V3_EXT_d2i(ext))) {
++        pkiDebug("%s: found no subject alt name extensions\n", __FUNCTION__);
++        goto cleanup;
++    }
++    num_sans = sk_GENERAL_NAME_num(ialt);
++
++    pkiDebug("%s: found %d subject alt name extension(s)\n", __FUNCTION__,
++             num_sans);
++
++    /* OK, we're likely returning something. Allocate return values */
++    if (princs_ret != NULL) {
++        princs = calloc(num_sans + 1, sizeof(krb5_principal));
++        if (princs == NULL) {
++            retval = ENOMEM;
+             goto cleanup;
+         }
+-        num_sans = sk_GENERAL_NAME_num(ialt);
+-
+-        pkiDebug("%s: found %d subject alt name extension(s)\n",
+-                 __FUNCTION__, num_sans);
+-
+-        /* OK, we're likely returning something. Allocate return values */
+-        if (princs_ret != NULL) {
+-            princs = calloc(num_sans + 1, sizeof(krb5_principal));
+-            if (princs == NULL) {
+-                retval = ENOMEM;
+-                goto cleanup;
+-            }
+-        }
+-        if (upn_ret != NULL) {
+-            upns = calloc(num_sans + 1, sizeof(krb5_principal));
+-            if (upns == NULL) {
+-                retval = ENOMEM;
+-                goto cleanup;
+-            }
+-        }
+-        if (dns_ret != NULL) {
+-            dnss = calloc(num_sans + 1, sizeof(*dnss));
+-            if (dnss == NULL) {
+-                retval = ENOMEM;
+-                goto cleanup;
+-            }
+-        }
+-
+-        for (i = 0; i < num_sans; i++) {
+-            krb5_data name = { 0, 0, NULL };
+-
+-            gen = sk_GENERAL_NAME_value(ialt, i);
+-            switch (gen->type) {
+-            case GEN_OTHERNAME:
+-                name.length = gen->d.otherName->value->value.sequence->length;
+-                name.data = (char *)gen->d.otherName->value->value.sequence->data;
+-                if (princs != NULL
+-                    && OBJ_cmp(plgctx->id_pkinit_san,
+-                               gen->d.otherName->type_id) == 0) {
+-#ifdef DEBUG_ASN1
+-                    print_buffer_bin((unsigned char *)name.data, name.length,
+-                                     "/tmp/pkinit_san");
+-#endif
+-                    ret = k5int_decode_krb5_principal_name(&name, &princs[p]);
+-                    if (ret) {
+-                        pkiDebug("%s: failed decoding pkinit san value\n",
+-                                 __FUNCTION__);
+-                    } else {
+-                        p++;
+-                        num_found++;
+-                    }
+-                } else if (upns != NULL
+-                           && OBJ_cmp(plgctx->id_ms_san_upn,
+-                                      gen->d.otherName->type_id) == 0) {
+-                    /* Prevent abuse of embedded null characters. */
+-                    if (memchr(name.data, '\0', name.length))
+-                        break;
+-                    ret = krb5_parse_name_flags(context, name.data,
+-                                                KRB5_PRINCIPAL_PARSE_ENTERPRISE,
+-                                                &upns[u]);
+-                    if (ret) {
+-                        pkiDebug("%s: failed parsing ms-upn san value\n",
+-                                 __FUNCTION__);
+-                    } else {
+-                        u++;
+-                        num_found++;
+-                    }
+-                } else {
+-                    pkiDebug("%s: unrecognized othername oid in SAN\n",
+-                             __FUNCTION__);
+-                    continue;
+-                }
+-
+-                break;
+-            case GEN_DNS:
+-                if (dnss != NULL) {
+-                    /* Prevent abuse of embedded null characters. */
+-                    if (memchr(gen->d.dNSName->data, '\0',
+-                               gen->d.dNSName->length))
+-                        break;
+-                    pkiDebug("%s: found dns name = %s\n",
+-                             __FUNCTION__, gen->d.dNSName->data);
+-                    dnss[d] = (unsigned char *)
+-                        strdup((char *)gen->d.dNSName->data);
+-                    if (dnss[d] == NULL) {
+-                        pkiDebug("%s: failed to duplicate dns name\n",
+-                                 __FUNCTION__);
+-                    } else {
+-                        d++;
+-                        num_found++;
+-                    }
+-                }
+-                break;
+-            default:
+-                pkiDebug("%s: SAN type = %d expecting %d\n",
+-                         __FUNCTION__, gen->type, GEN_OTHERNAME);
+-            }
+-        }
+-        sk_GENERAL_NAME_pop_free(ialt, GENERAL_NAME_free);
+     }
++    if (upn_ret != NULL) {
++        upns = calloc(num_sans + 1, sizeof(krb5_principal));
++        if (upns == NULL) {
++            retval = ENOMEM;
++            goto cleanup;
++        }
++    }
++    if (dns_ret != NULL) {
++        dnss = calloc(num_sans + 1, sizeof(*dnss));
++        if (dnss == NULL) {
++            retval = ENOMEM;
++            goto cleanup;
++        }
++    }
++
++    for (i = 0; i < num_sans; i++) {
++        krb5_data name = { 0, 0, NULL };
++
++        gen = sk_GENERAL_NAME_value(ialt, i);
++        switch (gen->type) {
++        case GEN_OTHERNAME:
++            name.length = gen->d.otherName->value->value.sequence->length;
++            name.data = (char *)gen->d.otherName->value->value.sequence->data;
++            if (princs != NULL &&
++                OBJ_cmp(plgctx->id_pkinit_san,
++                        gen->d.otherName->type_id) == 0) {
++#ifdef DEBUG_ASN1
++                print_buffer_bin((unsigned char *)name.data, name.length,
++                                 "/tmp/pkinit_san");
++#endif
++                ret = k5int_decode_krb5_principal_name(&name, &princs[p]);
++                if (ret) {
++                    pkiDebug("%s: failed decoding pkinit san value\n",
++                             __FUNCTION__);
++                } else {
++                    p++;
++                    num_found++;
++                }
++            } else if (upns != NULL &&
++                       OBJ_cmp(plgctx->id_ms_san_upn,
++                               gen->d.otherName->type_id) == 0) {
++                /* Prevent abuse of embedded null characters. */
++                if (memchr(name.data, '\0', name.length))
++                    break;
++                ret = krb5_parse_name_flags(context, name.data,
++                                            KRB5_PRINCIPAL_PARSE_ENTERPRISE,
++                                            &upns[u]);
++                if (ret) {
++                    pkiDebug("%s: failed parsing ms-upn san value\n",
++                             __FUNCTION__);
++                } else {
++                    u++;
++                    num_found++;
++                }
++            } else {
++                pkiDebug("%s: unrecognized othername oid in SAN\n",
++                         __FUNCTION__);
++                continue;
++            }
++
++            break;
++        case GEN_DNS:
++            if (dnss != NULL) {
++                /* Prevent abuse of embedded null characters. */
++                if (memchr(gen->d.dNSName->data, '\0', gen->d.dNSName->length))
++                    break;
++                pkiDebug("%s: found dns name = %s\n", __FUNCTION__,
++                         gen->d.dNSName->data);
++                dnss[d] = (unsigned char *)
++                    strdup((char *)gen->d.dNSName->data);
++                if (dnss[d] == NULL) {
++                    pkiDebug("%s: failed to duplicate dns name\n",
++                             __FUNCTION__);
++                } else {
++                    d++;
++                    num_found++;
++                }
++            }
++            break;
++        default:
++            pkiDebug("%s: SAN type = %d expecting %d\n", __FUNCTION__,
++                     gen->type, GEN_OTHERNAME);
++        }
++    }
++    sk_GENERAL_NAME_pop_free(ialt, GENERAL_NAME_free);
+ 
+     retval = 0;
+     if (princs)
diff --git a/SOURCES/Expose-context-errors-in-pkinit_server_plugin_init.patch b/SOURCES/Expose-context-errors-in-pkinit_server_plugin_init.patch
new file mode 100644
index 0000000..3144401
--- /dev/null
+++ b/SOURCES/Expose-context-errors-in-pkinit_server_plugin_init.patch
@@ -0,0 +1,74 @@
+From 9c0a06f38189d255575acdae5efb22b76b4c33b3 Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Mon, 13 Nov 2017 13:32:37 -0500
+Subject: [PATCH] Expose context errors in pkinit_server_plugin_init
+
+Commit 3ff426b9048a8024e5c175256c63cd0ad0572320 attempted to display
+an error when OCSP support was requested, but this error message was
+suppressed in pkinit_server_plugin_init().  Add a trace log for each
+realm initialization error, and pass through the realm initialization
+error when the KDC serves only one realm.  Other error messages from
+pkinit_init_kdc_profile(), such as missing pkinit_identity or
+pkinit_anchors, are also now exposted.
+
+[ghudson@mit.edu: clarified commit message]
+
+ticket: 8621 (new)
+target_version: 1.16
+tags: pullup
+
+(cherry picked from commit 225aab3540c13c6289b22022d5e110f6fc26151d)
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/plugins/preauth/pkinit/pkinit_srv.c   | 19 +++++++++++++------
+ src/plugins/preauth/pkinit/pkinit_trace.h |  3 +++
+ 2 files changed, 16 insertions(+), 6 deletions(-)
+
+diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c
+index 8e77606f8..143d331a2 100644
+--- a/src/plugins/preauth/pkinit/pkinit_srv.c
++++ b/src/plugins/preauth/pkinit/pkinit_srv.c
+@@ -1622,16 +1622,23 @@ pkinit_server_plugin_init(krb5_context context,
+ 
+     for (i = 0, j = 0; i < numrealms; i++) {
+         TRACE_PKINIT_SERVER_INIT_REALM(context, realmnames[i]);
+-        retval = pkinit_server_plugin_init_realm(context, realmnames[i], &plgctx);
+-        if (retval == 0 && plgctx != NULL)
++        krb5_clear_error_message(context);
++        retval = pkinit_server_plugin_init_realm(context, realmnames[i],
++                                                 &plgctx);
++        if (retval)
++            TRACE_PKINIT_SERVER_INIT_FAIL(context, realmnames[i], retval);
++        else
+             realm_contexts[j++] = plgctx;
+     }
+ 
+     if (j == 0) {
+-        retval = EINVAL;
+-        krb5_set_error_message(context, retval,
+-                               _("No realms configured correctly for pkinit "
+-                                 "support"));
++        if (numrealms == 1) {
++            k5_prependmsg(context, retval, "PKINIT initialization failed");
++        } else {
++            retval = EINVAL;
++            k5_setmsg(context, retval,
++                      _("No realms configured correctly for pkinit support"));
++        }
+         goto errout;
+     }
+ 
+diff --git a/src/plugins/preauth/pkinit/pkinit_trace.h b/src/plugins/preauth/pkinit/pkinit_trace.h
+index 6abe28c0c..8d489469f 100644
+--- a/src/plugins/preauth/pkinit/pkinit_trace.h
++++ b/src/plugins/preauth/pkinit/pkinit_trace.h
+@@ -100,6 +100,9 @@
+     TRACE(c, "PKINIT server skipping EKU check due to configuration")
+ #define TRACE_PKINIT_SERVER_INIT_REALM(c, realm)                \
+     TRACE(c, "PKINIT server initializing realm {str}", realm)
++#define TRACE_PKINIT_SERVER_INIT_FAIL(c, realm, retval)                 \
++    TRACE(c, "PKINIT server initialization failed for realm {str}: {kerr}", \
++          realm, retval)
+ #define TRACE_PKINIT_SERVER_MATCHING_UPN_FOUND(c)                       \
+     TRACE(c, "PKINIT server found a matching UPN SAN in client cert")
+ #define TRACE_PKINIT_SERVER_MATCHING_SAN_FOUND(c)                       \
diff --git a/SOURCES/Fix-bugs-in-kdcpolicy-commit.patch b/SOURCES/Fix-bugs-in-kdcpolicy-commit.patch
new file mode 100644
index 0000000..533818c
--- /dev/null
+++ b/SOURCES/Fix-bugs-in-kdcpolicy-commit.patch
@@ -0,0 +1,131 @@
+From d59b00fd1fdcc473739f3033c0f67eb402f20d9c Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Sat, 19 Aug 2017 19:09:24 -0400
+Subject: [PATCH] Fix bugs in kdcpolicy commit
+
+Commit d0969f6a8170344031ef58fd2a161190f1edfb96 added tests using
+"klist ccachname -e", which does not work with a POSIX-conformant
+getopt() implementation such as the one in Solaris.  Fix
+t_kdcpolicy.py to use "klist -e ccachename" instead.
+
+The tests could fail if the clock second rolled over between kinit and
+kvno.  Divide service ticket maximum lifetimes by 2 in the test module
+to correctly exercise TGS policy restrictions and ensure that service
+tickets are not constrained by the TGT end time.
+
+Also use the correct trace macro when a kdcpolicy module declines to
+initialize (my mistake when revising the commit, noted by rharwood).
+
+ticket: 8606
+(cherry picked from commit 09acbd91efc6df54e1572285ffc94c6acb3a9113)
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/kdc/policy.c                  |  2 +-
+ src/plugins/kdcpolicy/test/main.c | 10 +++++-----
+ src/tests/t_kdcpolicy.py          | 13 +++++++++----
+ 3 files changed, 15 insertions(+), 10 deletions(-)
+
+diff --git a/src/kdc/policy.c b/src/kdc/policy.c
+index e49644e06..26c16f97c 100644
+--- a/src/kdc/policy.c
++++ b/src/kdc/policy.c
+@@ -222,7 +222,7 @@ load_kdcpolicy_plugins(krb5_context context)
+         if (h->vt.init != NULL) {
+             ret = h->vt.init(context, &h->moddata);
+             if (ret == KRB5_PLUGIN_NO_HANDLE) {
+-                TRACE_KADM5_AUTH_INIT_SKIP(context, h->vt.name);
++                TRACE_KDCPOLICY_INIT_SKIP(context, h->vt.name);
+                 free(h);
+                 continue;
+             }
+diff --git a/src/plugins/kdcpolicy/test/main.c b/src/plugins/kdcpolicy/test/main.c
+index eb8fde053..86c808958 100644
+--- a/src/plugins/kdcpolicy/test/main.c
++++ b/src/plugins/kdcpolicy/test/main.c
+@@ -35,7 +35,7 @@
+ #include <krb5/kdcpolicy_plugin.h>
+ 
+ static krb5_error_code
+-output_from_indicator(const char *const *auth_indicators,
++output_from_indicator(const char *const *auth_indicators, int divisor,
+                       krb5_deltat *lifetime_out,
+                       krb5_deltat *renew_lifetime_out,
+                       const char **status)
+@@ -46,11 +46,11 @@ output_from_indicator(const char *const *auth_indicators,
+     }
+ 
+     if (strcmp(auth_indicators[0], "ONE_HOUR") == 0) {
+-        *lifetime_out = 3600;
++        *lifetime_out = 3600 / divisor;
+         *renew_lifetime_out = *lifetime_out * 2;
+         return 0;
+     } else if (strcmp(auth_indicators[0], "SEVEN_HOURS") == 0) {
+-        *lifetime_out = 7 * 3600;
++        *lifetime_out = 7 * 3600 / divisor;
+         *renew_lifetime_out = *lifetime_out * 2;
+         return 0;
+     }
+@@ -71,7 +71,7 @@ test_check_as(krb5_context context, krb5_kdcpolicy_moddata moddata,
+         *status = "LOCAL_POLICY";
+         return KRB5KDC_ERR_POLICY;
+     }
+-    return output_from_indicator(auth_indicators, lifetime_out,
++    return output_from_indicator(auth_indicators, 1, lifetime_out,
+                                  renew_lifetime_out, status);
+ }
+ 
+@@ -87,7 +87,7 @@ test_check_tgs(krb5_context context, krb5_kdcpolicy_moddata moddata,
+         *status = "LOCAL_POLICY";
+         return KRB5KDC_ERR_POLICY;
+     }
+-    return output_from_indicator(auth_indicators, lifetime_out,
++    return output_from_indicator(auth_indicators, 2, lifetime_out,
+                                  renew_lifetime_out, status);
+ }
+ 
+diff --git a/src/tests/t_kdcpolicy.py b/src/tests/t_kdcpolicy.py
+index 6a745b959..b5d308461 100644
+--- a/src/tests/t_kdcpolicy.py
++++ b/src/tests/t_kdcpolicy.py
+@@ -18,16 +18,21 @@ realm.run([kadminl, 'addprinc', '-pw', password('fail'), 'fail'])
+ def verify_time(out, target_time):
+     times = re.findall(r'\d\d/\d\d/\d\d \d\d:\d\d:\d\d', out)
+     times = [datetime.strptime(t, '%m/%d/%y %H:%M:%S') for t in times]
++    divisor = 1
+     while len(times) > 0:
+         starttime = times.pop(0)
+         endtime = times.pop(0)
+         renewtime = times.pop(0)
+ 
+-        if str(endtime - starttime) != target_time:
++        if str((endtime - starttime) * divisor) != target_time:
+             fail('unexpected lifetime value')
+-        if str(renewtime - endtime) != target_time:
++        if str((renewtime - endtime) * divisor) != target_time:
+             fail('unexpected renewable value')
+ 
++        # Service tickets should have half the lifetime of initial
++        # tickets.
++        divisor = 2
++
+ rflags = ['-r', '1d', '-l', '12h']
+ 
+ # Test AS+TGS success path.
+@@ -35,7 +40,7 @@ realm.kinit(realm.user_princ, password('user'),
+             rflags + ['-X', 'indicators=SEVEN_HOURS'])
+ realm.run([kvno, realm.host_princ])
+ realm.run(['./adata', realm.host_princ], expected_msg='+97: [SEVEN_HOURS]')
+-out = realm.run([klist, realm.ccache, '-e'])
++out = realm.run([klist, '-e', realm.ccache])
+ verify_time(out, '7:00:00')
+ 
+ # Test AS+TGS success path with different values.
+@@ -43,7 +48,7 @@ realm.kinit(realm.user_princ, password('user'),
+             rflags + ['-X', 'indicators=ONE_HOUR'])
+ realm.run([kvno, realm.host_princ])
+ realm.run(['./adata', realm.host_princ], expected_msg='+97: [ONE_HOUR]')
+-out = realm.run([klist, realm.ccache, '-e'])
++out = realm.run([klist, '-e', realm.ccache])
+ verify_time(out, '1:00:00')
+ 
+ # Test TGS failure path (using previous creds).
diff --git a/SOURCES/Fix-certauth-built-in-module-returns.patch b/SOURCES/Fix-certauth-built-in-module-returns.patch
new file mode 100644
index 0000000..f512f49
--- /dev/null
+++ b/SOURCES/Fix-certauth-built-in-module-returns.patch
@@ -0,0 +1,125 @@
+From 41b9111b48e53bf7864ed1f134e0433b070fa900 Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Thu, 24 Aug 2017 11:11:46 -0400
+Subject: [PATCH] Fix certauth built-in module returns
+
+The PKINIT certauth eku module should never authoritatively authorize
+a certificate, because an extended key usage does not establish a
+relationship between the certificate and any specific user; it only
+establishes that the certificate was created for PKINIT client
+authentication.  Therefore, pkinit_eku_authorize() should return
+KRB5_PLUGIN_NO_HANDLE on success, not 0.
+
+The certauth san module should pass if it does not find any SANs of
+the types it can match against; the presence of other types of SANs
+should not cause it to explicitly deny a certificate.  Check for an
+empty result from crypto_retrieve_cert_sans() in verify_client_san(),
+instead of returning ENOENT from crypto_retrieve_cert_sans() when
+there are no SANs at all.
+
+ticket: 8561
+(cherry picked from commit 07243f85a760fb37f0622d7ff0177db3f19ab025)
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/plugins/preauth/pkinit/pkinit_crypto_openssl.c | 39 ++++++++++------------
+ src/plugins/preauth/pkinit/pkinit_srv.c            | 14 +++++---
+ 2 files changed, 27 insertions(+), 26 deletions(-)
+
+diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+index 70e230ec2..7fa2efd21 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+@@ -2137,7 +2137,6 @@ crypto_retrieve_X509_sans(krb5_context context,
+ 
+     if (!(ext = X509_get_ext(cert, l)) || !(ialt = X509V3_EXT_d2i(ext))) {
+         pkiDebug("%s: found no subject alt name extensions\n", __FUNCTION__);
+-        retval = ENOENT;
+         goto cleanup;
+     }
+     num_sans = sk_GENERAL_NAME_num(ialt);
+@@ -2240,31 +2239,29 @@ crypto_retrieve_X509_sans(krb5_context context,
+     sk_GENERAL_NAME_pop_free(ialt, GENERAL_NAME_free);
+ 
+     retval = 0;
+-    if (princs)
++    if (princs != NULL && *princs != NULL) {
+         *princs_ret = princs;
+-    if (upns)
++        princs = NULL;
++    }
++    if (upns != NULL && *upns != NULL) {
+         *upn_ret = upns;
+-    if (dnss)
++        upns = NULL;
++    }
++    if (dnss != NULL && *dnss != NULL) {
+         *dns_ret = dnss;
++        dnss = NULL;
++    }
+ 
+ cleanup:
+-    if (retval) {
+-        if (princs != NULL) {
+-            for (i = 0; princs[i] != NULL; i++)
+-                krb5_free_principal(context, princs[i]);
+-            free(princs);
+-        }
+-        if (upns != NULL) {
+-            for (i = 0; upns[i] != NULL; i++)
+-                krb5_free_principal(context, upns[i]);
+-            free(upns);
+-        }
+-        if (dnss != NULL) {
+-            for (i = 0; dnss[i] != NULL; i++)
+-                free(dnss[i]);
+-            free(dnss);
+-        }
+-    }
++    for (i = 0; princs != NULL && princs[i] != NULL; i++)
++        krb5_free_principal(context, princs[i]);
++    free(princs);
++    for (i = 0; upns != NULL && upns[i] != NULL; i++)
++        krb5_free_principal(context, upns[i]);
++    free(upns);
++    for (i = 0; dnss != NULL && dnss[i] != NULL; i++)
++        free(dnss[i]);
++    free(dnss);
+     return retval;
+ }
+ 
+diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c
+index 9c6e96c9e..8e77606f8 100644
+--- a/src/plugins/preauth/pkinit/pkinit_srv.c
++++ b/src/plugins/preauth/pkinit/pkinit_srv.c
+@@ -187,14 +187,18 @@ verify_client_san(krb5_context context,
+                                        &princs,
+                                        plgctx->opts->allow_upn ? &upns : NULL,
+                                        NULL);
+-    if (retval == ENOENT) {
+-        TRACE_PKINIT_SERVER_NO_SAN(context);
+-        goto out;
+-    } else if (retval) {
++    if (retval) {
+         pkiDebug("%s: error from retrieve_certificate_sans()\n", __FUNCTION__);
+         retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
+         goto out;
+     }
++
++    if (princs == NULL && upns == NULL) {
++        TRACE_PKINIT_SERVER_NO_SAN(context);
++        retval = ENOENT;
++        goto out;
++    }
++
+     /* XXX Verify this is consistent with client side XXX */
+ #if 0
+     retval = call_san_checking_plugins(context, plgctx, reqctx, princs,
+@@ -1495,7 +1499,7 @@ pkinit_eku_authorize(krb5_context context, krb5_certauth_moddata moddata,
+         return KRB5KDC_ERR_INCONSISTENT_KEY_PURPOSE;
+     }
+ 
+-    return 0;
++    return KRB5_PLUGIN_NO_HANDLE;
+ }
+ 
+ static krb5_error_code
diff --git a/SOURCES/Fix-in_clock_skew-and-use-it-in-AS-client-code.patch b/SOURCES/Fix-in_clock_skew-and-use-it-in-AS-client-code.patch
new file mode 100644
index 0000000..fb84846
--- /dev/null
+++ b/SOURCES/Fix-in_clock_skew-and-use-it-in-AS-client-code.patch
@@ -0,0 +1,59 @@
+From 7e914206a676fb8f972c8021e97fab86a155488b Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Mon, 24 Apr 2017 02:02:36 -0400
+Subject: [PATCH] Fix in_clock_skew() and use it in AS client code
+
+Add a context parameter to the in_clock_skew() macro so that it isn't
+implicitly relying on a local variable.  Use it in
+get_in_tkt.c:verify_as_reply().
+
+(cherry picked from commit 28a07a6461bb443b7fa75cc5cb859ad0db4cbb5a)
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/lib/krb5/krb/gc_via_tkt.c | 2 +-
+ src/lib/krb5/krb/get_in_tkt.c | 4 ++--
+ src/lib/krb5/krb/int-proto.h  | 3 ++-
+ 3 files changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/src/lib/krb5/krb/gc_via_tkt.c b/src/lib/krb5/krb/gc_via_tkt.c
+index 4c0a1a461..c85d8b8d8 100644
+--- a/src/lib/krb5/krb/gc_via_tkt.c
++++ b/src/lib/krb5/krb/gc_via_tkt.c
+@@ -305,7 +305,7 @@ krb5int_process_tgs_reply(krb5_context context,
+         goto cleanup;
+ 
+     if (!in_cred->times.starttime &&
+-        !in_clock_skew(dec_rep->enc_part2->times.starttime,
++        !in_clock_skew(context, dec_rep->enc_part2->times.starttime,
+                        timestamp)) {
+         retval = KRB5_KDCREP_SKEW;
+         goto cleanup;
+diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
+index 54badbbc3..a058f5bd7 100644
+--- a/src/lib/krb5/krb/get_in_tkt.c
++++ b/src/lib/krb5/krb/get_in_tkt.c
+@@ -287,8 +287,8 @@ verify_as_reply(krb5_context            context,
+             return retval;
+     } else {
+         if ((request->from == 0) &&
+-            (labs(as_reply->enc_part2->times.starttime - time_now)
+-             > context->clockskew))
++            !in_clock_skew(context, as_reply->enc_part2->times.starttime,
++                           time_now))
+             return (KRB5_KDCREP_SKEW);
+     }
+     return 0;
+diff --git a/src/lib/krb5/krb/int-proto.h b/src/lib/krb5/krb/int-proto.h
+index 6da74858e..44eca359f 100644
+--- a/src/lib/krb5/krb/int-proto.h
++++ b/src/lib/krb5/krb/int-proto.h
+@@ -83,7 +83,8 @@ krb5int_construct_matching_creds(krb5_context context, krb5_flags options,
+                                  krb5_creds *in_creds, krb5_creds *mcreds,
+                                  krb5_flags *fields);
+ 
+-#define in_clock_skew(date, now) (labs((date)-(now)) < context->clockskew)
++#define in_clock_skew(context, date, now)               \
++    (labs((date) - (now)) < (context)->clockskew)
+ 
+ #define IS_TGS_PRINC(p) ((p)->length == 2 &&                            \
+                          data_eq_string((p)->data[0], KRB5_TGS_NAME))
diff --git a/SOURCES/Fix-make-certs.sh-for-OpenSSL-1.1.patch b/SOURCES/Fix-make-certs.sh-for-OpenSSL-1.1.patch
new file mode 100644
index 0000000..f02f9c5
--- /dev/null
+++ b/SOURCES/Fix-make-certs.sh-for-OpenSSL-1.1.patch
@@ -0,0 +1,71 @@
+From 7221a9f695016d3e4873bb799f06665ec74387f8 Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Wed, 6 Sep 2017 12:56:37 -0400
+Subject: [PATCH] Fix make-certs.sh for OpenSSL 1.1
+
+The openssl req commands in make-certs.sh contain -subj options which
+were ignored in favor of the config file prior to OpenSSL 1.1.  When
+they are used, they remove elements of the subject which are now
+required by t_pkinit.py.
+
+(cherry picked from commit b0473da67d72e43b9f03b703869069348e872efc)
+[rharwood@redhat.com: remove newer sections in make-certs.sh]
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/tests/dejagnu/pkinit-certs/make-certs.sh | 19 +++++++++----------
+ 1 file changed, 9 insertions(+), 10 deletions(-)
+
+diff --git a/src/tests/dejagnu/pkinit-certs/make-certs.sh b/src/tests/dejagnu/pkinit-certs/make-certs.sh
+index 0f07709b0..0d8c2019a 100755
+--- a/src/tests/dejagnu/pkinit-certs/make-certs.sh
++++ b/src/tests/dejagnu/pkinit-certs/make-certs.sh
+@@ -122,15 +122,14 @@ SUBJECT=ca openssl req -config openssl.cnf -new -x509 -extensions exts_ca \
+     -set_serial 1 -days $DAYS -key privkey.pem -out ca.pem
+ 
+ # Generate a KDC certificate.
+-SUBJECT=kdc openssl req -config openssl.cnf -new -subj /CN=kdc \
+-    -key privkey.pem -out kdc.csr
++SUBJECT=kdc openssl req -config openssl.cnf -new -key privkey.pem -out kdc.csr
+ SUBJECT=kdc openssl x509 -extfile openssl.cnf -extensions exts_kdc \
+     -set_serial 2 -days $DAYS -req -CA ca.pem -CAkey privkey.pem \
+     -out kdc.pem -in kdc.csr
+ 
+ # Generate a client certificate and PKCS#12 bundles.
+-SUBJECT=user openssl req -config openssl.cnf -new -subj /CN=user \
+-    -key privkey.pem -out user.csr
++SUBJECT=user openssl req -config openssl.cnf -new -key privkey.pem \
++    -out user.csr
+ SUBJECT=user openssl x509 -extfile openssl.cnf -extensions exts_client \
+     -set_serial 3 -days $DAYS -req -CA ca.pem -CAkey privkey.pem \
+     -out user.pem -in user.csr
+@@ -140,24 +139,24 @@ openssl pkcs12 -export -in user.pem -inkey privkey.pem -out user-enc.p12 \
+     -passout pass:encrypted
+ 
+ # Generate a client certificate and PKCS#12 bundles with a UPN SAN.
+-SUBJECT=user openssl req -config openssl.cnf -new -subj /CN=user \
+-    -key privkey.pem -out user-upn.csr
++SUBJECT=user openssl req -config openssl.cnf -new -key privkey.pem \
++    -out user-upn.csr
+ SUBJECT=user openssl x509 -extfile openssl.cnf -extensions exts_upn_client \
+     -set_serial 4 -days $DAYS -req -CA ca.pem -CAkey privkey.pem \
+     -out user-upn.pem -in user-upn.csr
+ openssl pkcs12 -export -in user-upn.pem -inkey privkey.pem -out user-upn.p12 \
+     -passout pass:
+ 
+-SUBJECT=user openssl req -config openssl.cnf -new -subj /CN=user \
+-    -key privkey.pem -out user-upn2.csr
++SUBJECT=user openssl req -config openssl.cnf -new -key privkey.pem \
++    -out user-upn2.csr
+ SUBJECT=user openssl x509 -extfile openssl.cnf -extensions exts_upn2_client \
+     -set_serial 5 -days $DAYS -req -CA ca.pem -CAkey privkey.pem \
+     -out user-upn2.pem -in user-upn2.csr
+ openssl pkcs12 -export -in user-upn2.pem -inkey privkey.pem \
+      -out user-upn2.p12 -passout pass:
+ 
+-SUBJECT=user openssl req -config openssl.cnf -new -subj /CN=user \
+-    -key privkey.pem -out user-upn3.csr
++SUBJECT=user openssl req -config openssl.cnf -new -key privkey.pem \
++    -out user-upn3.csr
+ SUBJECT=user openssl x509 -extfile openssl.cnf -extensions exts_upn3_client \
+     -set_serial 6 -days $DAYS -req -CA ca.pem -CAkey privkey.pem \
+     -out user-upn3.pem -in user-upn3.csr
diff --git a/SOURCES/Fix-more-time-manipulations-for-y2038.patch b/SOURCES/Fix-more-time-manipulations-for-y2038.patch
new file mode 100644
index 0000000..44252dc
--- /dev/null
+++ b/SOURCES/Fix-more-time-manipulations-for-y2038.patch
@@ -0,0 +1,84 @@
+From 006c68f6ed266d5ea7a24512349a931f45160cc6 Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Wed, 17 May 2017 14:52:09 -0400
+Subject: [PATCH] Fix more time manipulations for y2038
+
+Use timestamp helper functions to ensure that more operations are safe
+after y2038, and display the current timestamp as unsigned in
+krb5int_trace().
+
+ticket: 8352
+(cherry picked from commit a60db180211a383bd382afe729e9309acb8dcf53)
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/kadmin/server/misc.c   | 2 +-
+ src/kdc/dispatch.c         | 2 +-
+ src/lib/krb5/os/c_ustime.c | 8 ++++----
+ src/lib/krb5/os/trace.c    | 2 +-
+ 4 files changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/src/kadmin/server/misc.c b/src/kadmin/server/misc.c
+index 27a6376af..a75b65a26 100644
+--- a/src/kadmin/server/misc.c
++++ b/src/kadmin/server/misc.c
+@@ -184,7 +184,7 @@ check_min_life(void *server_handle, krb5_principal principal,
+             (void) kadm5_free_principal_ent(handle->lhandle, &princ);
+             return (ret == KADM5_UNK_POLICY) ? 0 : ret;
+         }
+-        if((now - princ.last_pwd_change) < pol.pw_min_life &&
++        if(ts_delta(now, princ.last_pwd_change) < pol.pw_min_life &&
+            !(princ.attributes & KRB5_KDB_REQUIRES_PWCHANGE)) {
+             if (msg_ret != NULL) {
+                 time_t until;
+diff --git a/src/kdc/dispatch.c b/src/kdc/dispatch.c
+index 3a169ebc7..16a35d2be 100644
+--- a/src/kdc/dispatch.c
++++ b/src/kdc/dispatch.c
+@@ -104,7 +104,7 @@ reseed_random(krb5_context kdc_err_context)
+         if (last_os_random == 0)
+             last_os_random = now;
+         /* Grab random data from OS every hour*/
+-        if (now-last_os_random >= 60 * 60) {
++        if (ts_delta(now, last_os_random) >= 60 * 60) {
+             krb5_c_random_os_entropy(kdc_err_context, 0, NULL);
+             last_os_random = now;
+         }
+diff --git a/src/lib/krb5/os/c_ustime.c b/src/lib/krb5/os/c_ustime.c
+index 871d72183..68fb381f4 100644
+--- a/src/lib/krb5/os/c_ustime.c
++++ b/src/lib/krb5/os/c_ustime.c
+@@ -102,17 +102,17 @@ krb5_crypto_us_timeofday(krb5_int32 *seconds, krb5_int32 *microseconds)
+        putting now.sec in the past.  But don't just use '<' because we
+        need to properly handle the case where the administrator intentionally
+        adjusted time backwards. */
+-    if ((now.sec == last_time.sec-1) ||
+-        ((now.sec == last_time.sec) && (now.usec <= last_time.usec))) {
++    if (now.sec == ts_incr(last_time.sec, -1) ||
++        (now.sec == last_time.sec && !ts_after(last_time.usec, now.usec))) {
+         /* Correct 'now' to be exactly one microsecond later than 'last_time'.
+            Note that _because_ we perform this hack, 'now' may be _earlier_
+            than 'last_time', even though the system time is monotonically
+            increasing. */
+ 
+         now.sec = last_time.sec;
+-        now.usec = ++last_time.usec;
++        now.usec = ts_incr(last_time.usec, 1);
+         if (now.usec >= 1000000) {
+-            ++now.sec;
++            now.sec = ts_incr(now.sec, 1);
+             now.usec = 0;
+         }
+     }
+diff --git a/src/lib/krb5/os/trace.c b/src/lib/krb5/os/trace.c
+index a19246128..74c315c90 100644
+--- a/src/lib/krb5/os/trace.c
++++ b/src/lib/krb5/os/trace.c
+@@ -350,7 +350,7 @@ krb5int_trace(krb5_context context, const char *fmt, ...)
+         goto cleanup;
+     if (krb5_crypto_us_timeofday(&sec, &usec) != 0)
+         goto cleanup;
+-    if (asprintf(&msg, "[%d] %d.%d: %s\n", (int) getpid(), (int) sec,
++    if (asprintf(&msg, "[%d] %u.%d: %s\n", (int) getpid(), (unsigned int) sec,
+                  (int) usec, str) < 0)
+         goto cleanup;
+     info.message = msg;
diff --git a/SOURCES/Improve-PKINIT-UPN-SAN-matching.patch b/SOURCES/Improve-PKINIT-UPN-SAN-matching.patch
new file mode 100644
index 0000000..aaf15b6
--- /dev/null
+++ b/SOURCES/Improve-PKINIT-UPN-SAN-matching.patch
@@ -0,0 +1,152 @@
+From 802cf0263965eef725208f00eccb62df0b082319 Mon Sep 17 00:00:00 2001
+From: Matt Rogers <mrogers@redhat.com>
+Date: Mon, 5 Dec 2016 12:17:59 -0500
+Subject: [PATCH] Improve PKINIT UPN SAN matching
+
+Add the match_client() kdcpreauth callback and use it in
+verify_client_san().  match_client() preserves the direct UPN to
+request principal comparison and adds a direct comparison to the
+client principal, falling back to an alias DB search and comparison
+against the client principal.  Change crypto_retreive_X509_sans() to
+parse UPN values as enterprise principals.
+
+[ghudson@mit.edu: use match_client for both kinds of SANs]
+
+ticket: 8528 (new)
+(cherry picked from commit 46ff765e1fb8cbec2bb602b43311269e695dbedc)
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/include/krb5/kdcpreauth_plugin.h               | 13 ++++++++++
+ src/kdc/kdc_preauth.c                              | 28 ++++++++++++++++++++--
+ src/plugins/preauth/pkinit/pkinit_crypto_openssl.c |  4 +++-
+ src/plugins/preauth/pkinit/pkinit_srv.c            | 10 ++++----
+ 4 files changed, 48 insertions(+), 7 deletions(-)
+
+diff --git a/src/include/krb5/kdcpreauth_plugin.h b/src/include/krb5/kdcpreauth_plugin.h
+index f455effae..92aa5a5a5 100644
+--- a/src/include/krb5/kdcpreauth_plugin.h
++++ b/src/include/krb5/kdcpreauth_plugin.h
+@@ -221,6 +221,19 @@ typedef struct krb5_kdcpreauth_callbacks_st {
+ 
+     /* End of version 3 kdcpreauth callbacks. */
+ 
++    /*
++     * Return true if princ matches the principal named in the request or the
++     * client principal (possibly canonicalized).  If princ does not match,
++     * attempt a database lookup of princ with aliases allowed and compare the
++     * result to the client principal, returning true if it matches.
++     * Otherwise, return false.
++     */
++    krb5_boolean (*match_client)(krb5_context context,
++                                 krb5_kdcpreauth_rock rock,
++                                 krb5_principal princ);
++
++    /* End of version 4 kdcpreauth callbacks. */
++
+ } *krb5_kdcpreauth_callbacks;
+ 
+ /* Optional: preauth plugin initialization function. */
+diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c
+index 605fcb7ad..0ce79c667 100644
+--- a/src/kdc/kdc_preauth.c
++++ b/src/kdc/kdc_preauth.c
+@@ -568,8 +568,31 @@ set_cookie(krb5_context context, krb5_kdcpreauth_rock rock,
+     return kdc_fast_set_cookie(rock->rstate, pa_type, data);
+ }
+ 
++static krb5_boolean
++match_client(krb5_context context, krb5_kdcpreauth_rock rock,
++             krb5_principal princ)
++{
++    krb5_db_entry *ent;
++    krb5_boolean match = FALSE;
++    krb5_principal req_client = rock->request->client;
++    krb5_principal client = rock->client->princ;
++
++    /* Check for a direct match against the request principal or
++     * the post-canon client principal. */
++    if (krb5_principal_compare_flags(context, princ, req_client,
++                                     KRB5_PRINCIPAL_COMPARE_ENTERPRISE) ||
++        krb5_principal_compare(context, princ, client))
++        return TRUE;
++
++    if (krb5_db_get_principal(context, princ, KRB5_KDB_FLAG_ALIAS_OK, &ent))
++        return FALSE;
++    match = krb5_principal_compare(context, ent->princ, client);
++    krb5_db_free_principal(context, ent);
++    return match;
++}
++
+ static struct krb5_kdcpreauth_callbacks_st callbacks = {
+-    3,
++    4,
+     max_time_skew,
+     client_keys,
+     free_keys,
+@@ -583,7 +606,8 @@ static struct krb5_kdcpreauth_callbacks_st callbacks = {
+     client_keyblock,
+     add_auth_indicator,
+     get_cookie,
+-    set_cookie
++    set_cookie,
++    match_client
+ };
+ 
+ static krb5_error_code
+diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+index 74fffbf32..bc6e7662e 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+@@ -2190,7 +2190,9 @@ crypto_retrieve_X509_sans(krb5_context context,
+                     /* Prevent abuse of embedded null characters. */
+                     if (memchr(name.data, '\0', name.length))
+                         break;
+-                    ret = krb5_parse_name(context, name.data, &upns[u]);
++                    ret = krb5_parse_name_flags(context, name.data,
++                                                KRB5_PRINCIPAL_PARSE_ENTERPRISE,
++                                                &upns[u]);
+                     if (ret) {
+                         pkiDebug("%s: failed parsing ms-upn san value\n",
+                                  __FUNCTION__);
+diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c
+index 295be25e1..b5638a367 100644
+--- a/src/plugins/preauth/pkinit/pkinit_srv.c
++++ b/src/plugins/preauth/pkinit/pkinit_srv.c
+@@ -121,6 +121,8 @@ static krb5_error_code
+ verify_client_san(krb5_context context,
+                   pkinit_kdc_context plgctx,
+                   pkinit_kdc_req_context reqctx,
++                  krb5_kdcpreauth_callbacks cb,
++                  krb5_kdcpreauth_rock rock,
+                   krb5_principal client,
+                   int *valid_san)
+ {
+@@ -171,7 +173,7 @@ verify_client_san(krb5_context context,
+                  __FUNCTION__, client_string, san_string);
+         krb5_free_unparsed_name(context, san_string);
+ #endif
+-        if (krb5_principal_compare(context, princs[i], client)) {
++        if (cb->match_client(context, rock, princs[i])) {
+             pkiDebug("%s: pkinit san match found\n", __FUNCTION__);
+             *valid_san = 1;
+             retval = 0;
+@@ -199,7 +201,7 @@ verify_client_san(krb5_context context,
+                  __FUNCTION__, client_string, san_string);
+         krb5_free_unparsed_name(context, san_string);
+ #endif
+-        if (krb5_principal_compare(context, upns[i], client)) {
++        if (cb->match_client(context, rock, upns[i])) {
+             pkiDebug("%s: upn san match found\n", __FUNCTION__);
+             *valid_san = 1;
+             retval = 0;
+@@ -387,8 +389,8 @@ pkinit_server_verify_padata(krb5_context context,
+     }
+     if (is_signed) {
+ 
+-        retval = verify_client_san(context, plgctx, reqctx, request->client,
+-                                   &valid_san);
++        retval = verify_client_san(context, plgctx, reqctx, cb, rock,
++                                   request->client, &valid_san);
+         if (retval)
+             goto cleanup;
+         if (!valid_san) {
diff --git a/SOURCES/Make-timestamp-manipulations-y2038-safe.patch b/SOURCES/Make-timestamp-manipulations-y2038-safe.patch
new file mode 100644
index 0000000..8ae5272
--- /dev/null
+++ b/SOURCES/Make-timestamp-manipulations-y2038-safe.patch
@@ -0,0 +1,1845 @@
+From 7c671a869d1fc21b5154c035d568d5b5fd940783 Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Sat, 22 Apr 2017 12:52:17 -0400
+Subject: [PATCH] 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
+(cherry picked from commit a9cbbf0899f270fbb14f63ffbed1b6d542333641)
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/clients/kinit/kinit.c                          |  2 +-
+ src/clients/klist/klist.c                          | 20 ++++-------
+ src/clients/ksu/ccache.c                           | 20 +++--------
+ 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, 230 insertions(+), 255 deletions(-)
+
+diff --git a/src/clients/kinit/kinit.c b/src/clients/kinit/kinit.c
+index f1cd1b73d..50065e32e 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 ba19788a2..ffeecc394 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;
++    char timestring[BUFSIZ], fill = ' ';
+ 
+-    fill = ' ';
+-    if (!krb5_timestamp_to_sfstring((krb5_timestamp) tv,
+-                                    timestring,
+-                                    timestamp_width+1,
+-                                    &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 a0736f2da..236313b7b 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;
++    char fmtbuf[18], fill = ' ';
+ 
+-    /* 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))
++    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 ee8e9d6a0..3bf0bd438 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 4f0c56f7e..0a19c5648 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 c53c677a8..aee5c83b9 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 cad53cfbf..a6fc4ea77 100644
+--- a/src/kadmin/dbutil/dump.c
++++ b/src/kadmin/dbutil/dump.c
+@@ -379,11 +379,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. */
+@@ -717,7 +718,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;
+@@ -773,8 +774,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;
+@@ -782,11 +783,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 7df8cbc83..2efe3176e 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 69a3482ec..fb36b060a 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 a4997c60c..9dde579ef 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 712ccb794..59a39cd30 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 547a41441..aacd2f20d 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 fe627494b..84b5c6ad5 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 9df940219..e05107ef3 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 94a2a1c87..c044a3553 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 29f9dbbf0..778a629e5 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 bcf05fc27..672f94380 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 8da7ac19a..fab39cf88 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 a30cacc66..d0f25d1b7 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 580d08cbf..06967aa27 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 03ee25ec1..362ba9d86 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 450593288..1fdb5a16f 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 652b2604b..8054e4a77 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 2dc4d0c1a..bb1072fe4 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 70f7955ae..8e5cc37fb 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 d2e466e60..cac024da1 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 4e35a0563..e662ae53a 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 ff1c310bc..10848c1df 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 408b0eb31..1680a5504 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 59ed0b975..656dddff5 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 0640b47c4..f4a9a2ad2 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 4adf0fcbb..7f33c7e68 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 a827ca608..889460989 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 4fe3f0d6f..fba710b1b 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 0354575c5..c5425eb3a 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 1314d24bd..1a32e00c8 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 9f44af3d0..6092ee432 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 c31a3f5f0..e631f2051 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 131549ffe..b014abf0b 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 c85d8b8d8..cf1ea361f 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 110abeb2b..be5b2d18c 100644
+--- a/src/lib/krb5/krb/get_creds.c
++++ b/src/lib/krb5/krb/get_creds.c
+@@ -816,7 +816,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 a058f5bd7..40aba1905 100644
+--- a/src/lib/krb5/krb/get_in_tkt.c
++++ b/src/lib/krb5/krb/get_in_tkt.c
+@@ -39,24 +39,6 @@ static krb5_error_code sort_krb5_padata_sequence(krb5_context context,
+                                                  krb5_data *realm,
+                                                  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
+@@ -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;
+@@ -790,15 +772,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;
+@@ -1438,7 +1420,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;
+@@ -1807,6 +1789,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;
+ 
+@@ -1838,7 +1821,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 6f3a29f2c..3565a7c4c 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 44eca359f..48bd9f8f7 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 9098927b5..c70585a9e 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 3ab7eacac..f0a2ae20b 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 60cfb5b15..74ac14d9a 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 d63122183..9e509b2dd 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 9786d63b5..b4878ba38 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 fddb12142..887f24c22 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 456193a41..37bc69f49 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 056357683..1c1b571eb 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 c0f12ed9d..6b043844d 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 db273ec2f..b99cdf1ab 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 7d151b55b..3a4f41821 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 7ba53f959..88a170495 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 0fc56c2fe..1088ecc5a 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 f2805f5cd..26e699fae 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 9577365a7..325dce2e9 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 beab0ea11..5dd37b05a 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 ef2a5a3e0..253ae3f06 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 0f76cc334..8dafb7bed 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 c3325034a..2b4373cc1 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);
diff --git a/SOURCES/Prevent-KDC-unset-status-assertion-failures.patch b/SOURCES/Prevent-KDC-unset-status-assertion-failures.patch
new file mode 100644
index 0000000..084f55e
--- /dev/null
+++ b/SOURCES/Prevent-KDC-unset-status-assertion-failures.patch
@@ -0,0 +1,110 @@
+From 3b2376b47a9f1fc7dfd138d4ecc70e5d8897dc2b Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Thu, 13 Jul 2017 12:14:20 -0400
+Subject: [PATCH] Prevent KDC unset status assertion failures
+
+Assign status values if S4U2Self padata fails to decode, if an
+S4U2Proxy request uses invalid KDC options, or if an S4U2Proxy request
+uses an evidence ticket which does not match the canonicalized request
+server principal name.  Reported by Samuel Cabrero.
+
+If a status value is not assigned during KDC processing, default to
+"UNKNOWN_REASON" rather than failing an assertion.  This change will
+prevent future denial of service bugs due to similar mistakes, and
+will allow us to omit assigning status values for unlikely errors such
+as small memory allocation failures.
+
+CVE-2017-11368:
+
+In MIT krb5 1.7 and later, an authenticated attacker can cause an
+assertion failure in krb5kdc by sending an invalid S4U2Self or
+S4U2Proxy request.
+
+  CVSSv3 Vector: AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H/E:H/RL:O/RC:C
+
+ticket: 8599 (new)
+target_version: 1.15-next
+target_version: 1.14-next
+tags: pullup
+
+(cherry picked from commit ffb35baac6981f9e8914f8f3bffd37f284b85970)
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/kdc/do_as_req.c  |  4 ++--
+ src/kdc/do_tgs_req.c |  3 ++-
+ src/kdc/kdc_util.c   | 10 ++++++++--
+ 3 files changed, 12 insertions(+), 5 deletions(-)
+
+diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c
+index 241b05b40..f5cf8ad89 100644
+--- a/src/kdc/do_as_req.c
++++ b/src/kdc/do_as_req.c
+@@ -372,8 +372,8 @@ finish_process_as_req(struct as_req_state *state, krb5_error_code errcode)
+     did_log = 1;
+ 
+ egress:
+-    if (errcode != 0)
+-        assert (state->status != 0);
++    if (errcode != 0 && state->status == NULL)
++        state->status = "UNKNOWN_REASON";
+ 
+     au_state->status = state->status;
+     au_state->reply = &state->reply;
+diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c
+index 4c722a4a3..0009a9319 100644
+--- a/src/kdc/do_tgs_req.c
++++ b/src/kdc/do_tgs_req.c
+@@ -829,7 +829,8 @@ process_tgs_req(struct server_handle *handle, krb5_data *pkt,
+     free(reply.enc_part.ciphertext.data);
+ 
+ cleanup:
+-    assert(status != NULL);
++    if (status == NULL)
++        status = "UNKNOWN_REASON";
+     if (reply_key)
+         krb5_free_keyblock(kdc_context, reply_key);
+     if (errcode)
+diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
+index 8cbdf2c5b..5455e2a67 100644
+--- a/src/kdc/kdc_util.c
++++ b/src/kdc/kdc_util.c
+@@ -1213,8 +1213,10 @@ kdc_process_for_user(kdc_realm_t *kdc_active_realm,
+     req_data.data = (char *)pa_data->contents;
+ 
+     code = decode_krb5_pa_for_user(&req_data, &for_user);
+-    if (code)
++    if (code) {
++        *status = "DECODE_PA_FOR_USER";
+         return code;
++    }
+ 
+     code = verify_for_user_checksum(kdc_context, tgs_session, for_user);
+     if (code) {
+@@ -1313,8 +1315,10 @@ kdc_process_s4u_x509_user(krb5_context context,
+     req_data.data = (char *)pa_data->contents;
+ 
+     code = decode_krb5_pa_s4u_x509_user(&req_data, s4u_x509_user);
+-    if (code)
++    if (code) {
++        *status = "DECODE_PA_S4U_X509_USER";
+         return code;
++    }
+ 
+     code = verify_s4u_x509_user_checksum(context,
+                                          tgs_subkey ? tgs_subkey :
+@@ -1617,6 +1621,7 @@ kdc_process_s4u2proxy_req(kdc_realm_t *kdc_active_realm,
+      * that is validated previously in validate_tgs_request().
+      */
+     if (request->kdc_options & (NON_TGT_OPTION | KDC_OPT_ENC_TKT_IN_SKEY)) {
++        *status = "INVALID_S4U2PROXY_OPTIONS";
+         return KRB5KDC_ERR_BADOPTION;
+     }
+ 
+@@ -1624,6 +1629,7 @@ kdc_process_s4u2proxy_req(kdc_realm_t *kdc_active_realm,
+     if (!krb5_principal_compare(kdc_context,
+                                 server->princ, /* after canon */
+                                 server_princ)) {
++        *status = "EVIDENCE_TICKET_MISMATCH";
+         return KRB5KDC_ERR_SERVER_NOMATCH;
+     }
+ 
diff --git a/SOURCES/Remove-incomplete-PKINIT-OCSP-support.patch b/SOURCES/Remove-incomplete-PKINIT-OCSP-support.patch
new file mode 100644
index 0000000..94315ea
--- /dev/null
+++ b/SOURCES/Remove-incomplete-PKINIT-OCSP-support.patch
@@ -0,0 +1,135 @@
+From 9ff3ed399f9a5bb0c6101a986798d80ecc7a1b92 Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Mon, 31 Jul 2017 16:03:41 -0400
+Subject: [PATCH] Remove incomplete PKINIT OCSP support
+
+pkinit_kdc_ocsp is non-functional in the PKINIT OpenSSL crypto
+implementation, so remove most traces of it, including its man page
+entry.  If it is present in kdc.conf, error out of PKINIT
+initialization instead of silently ignoring the realm entirely.
+
+ticket: 8603 (new)
+(cherry picked from commit 3ff426b9048a8024e5c175256c63cd0ad0572320)
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ doc/admin/conf_files/kdc_conf.rst            |  3 ---
+ src/man/kdc.conf.man                         |  3 ---
+ src/plugins/preauth/pkinit/pkinit.h          |  2 +-
+ src/plugins/preauth/pkinit/pkinit_identity.c | 11 -----------
+ src/plugins/preauth/pkinit/pkinit_srv.c      | 12 ++++++++++--
+ 5 files changed, 11 insertions(+), 20 deletions(-)
+
+diff --git a/doc/admin/conf_files/kdc_conf.rst b/doc/admin/conf_files/kdc_conf.rst
+index 13077ecf4..a4b2a5432 100644
+--- a/doc/admin/conf_files/kdc_conf.rst
++++ b/doc/admin/conf_files/kdc_conf.rst
+@@ -765,9 +765,6 @@ For information about the syntax of some of these options, see
+     pkinit is used to authenticate.  This option may be specified
+     multiple times.  (New in release 1.14.)
+ 
+-**pkinit_kdc_ocsp**
+-    Specifies the location of the KDC's OCSP.
+-
+ **pkinit_pool**
+     Specifies the location of intermediate certificates which may be
+     used by the KDC to complete the trust chain between a client's
+diff --git a/src/man/kdc.conf.man b/src/man/kdc.conf.man
+index 10b333c38..166e68f9a 100644
+--- a/src/man/kdc.conf.man
++++ b/src/man/kdc.conf.man
+@@ -886,9 +886,6 @@ Specifies an authentication indicator to include in the ticket if
+ pkinit is used to authenticate.  This option may be specified
+ multiple times.  (New in release 1.14.)
+ .TP
+-.B \fBpkinit_kdc_ocsp\fP
+-Specifies the location of the KDC\(aqs OCSP.
+-.TP
+ .B \fBpkinit_pool\fP
+ Specifies the location of intermediate certificates which may be
+ used by the KDC to complete the trust chain between a client\(aqs
+diff --git a/src/plugins/preauth/pkinit/pkinit.h b/src/plugins/preauth/pkinit/pkinit.h
+index 876db94c3..a49f3078e 100644
+--- a/src/plugins/preauth/pkinit/pkinit.h
++++ b/src/plugins/preauth/pkinit/pkinit.h
+@@ -73,6 +73,7 @@
+ #define KRB5_CONF_PKINIT_IDENTITIES             "pkinit_identities"
+ #define KRB5_CONF_PKINIT_IDENTITY               "pkinit_identity"
+ #define KRB5_CONF_PKINIT_KDC_HOSTNAME           "pkinit_kdc_hostname"
++/* pkinit_kdc_ocsp has been removed */
+ #define KRB5_CONF_PKINIT_KDC_OCSP               "pkinit_kdc_ocsp"
+ #define KRB5_CONF_PKINIT_POOL                   "pkinit_pool"
+ #define KRB5_CONF_PKINIT_REQUIRE_CRL_CHECKING   "pkinit_require_crl_checking"
+@@ -173,7 +174,6 @@ typedef struct _pkinit_identity_opts {
+     char **anchors;
+     char **intermediates;
+     char **crls;
+-    char *ocsp;
+     int  idtype;
+     char *cert_filename;
+     char *key_filename;
+diff --git a/src/plugins/preauth/pkinit/pkinit_identity.c b/src/plugins/preauth/pkinit/pkinit_identity.c
+index 177a2cad8..a897efa25 100644
+--- a/src/plugins/preauth/pkinit/pkinit_identity.c
++++ b/src/plugins/preauth/pkinit/pkinit_identity.c
+@@ -125,7 +125,6 @@ pkinit_init_identity_opts(pkinit_identity_opts **idopts)
+     opts->anchors = NULL;
+     opts->intermediates = NULL;
+     opts->crls = NULL;
+-    opts->ocsp = NULL;
+ 
+     opts->cert_filename = NULL;
+     opts->key_filename = NULL;
+@@ -174,12 +173,6 @@ pkinit_dup_identity_opts(pkinit_identity_opts *src_opts,
+     if (retval)
+         goto cleanup;
+ 
+-    if (src_opts->ocsp != NULL) {
+-        newopts->ocsp = strdup(src_opts->ocsp);
+-        if (newopts->ocsp == NULL)
+-            goto cleanup;
+-    }
+-
+     if (src_opts->cert_filename != NULL) {
+         newopts->cert_filename = strdup(src_opts->cert_filename);
+         if (newopts->cert_filename == NULL)
+@@ -674,10 +667,6 @@ pkinit_identity_prompt(krb5_context context,
+         if (retval)
+             goto errout;
+     }
+-    if (idopts->ocsp != NULL) {
+-        retval = ENOTSUP;
+-        goto errout;
+-    }
+ 
+ errout:
+     return retval;
+diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c
+index 731d14eb8..32ca122f2 100644
+--- a/src/plugins/preauth/pkinit/pkinit_srv.c
++++ b/src/plugins/preauth/pkinit/pkinit_srv.c
+@@ -1252,7 +1252,7 @@ static krb5_error_code
+ pkinit_init_kdc_profile(krb5_context context, pkinit_kdc_context plgctx)
+ {
+     krb5_error_code retval;
+-    char *eku_string = NULL;
++    char *eku_string = NULL, *ocsp_check = NULL;
+ 
+     pkiDebug("%s: entered for realm %s\n", __FUNCTION__, plgctx->realmname);
+     retval = pkinit_kdcdefault_string(context, plgctx->realmname,
+@@ -1287,7 +1287,15 @@ pkinit_init_kdc_profile(krb5_context context, pkinit_kdc_context plgctx)
+ 
+     pkinit_kdcdefault_string(context, plgctx->realmname,
+                              KRB5_CONF_PKINIT_KDC_OCSP,
+-                             &plgctx->idopts->ocsp);
++                             &ocsp_check);
++    if (ocsp_check != NULL) {
++        free(ocsp_check);
++        retval = ENOTSUP;
++        krb5_set_error_message(context, retval,
++                               _("OCSP is not supported: (realm: %s)"),
++                               plgctx->realmname);
++        goto errout;
++    }
+ 
+     pkinit_kdcdefault_integer(context, plgctx->realmname,
+                               KRB5_CONF_PKINIT_DH_MIN_BITS,
diff --git a/SOURCES/Use-krb5_timestamp-where-appropriate.patch b/SOURCES/Use-krb5_timestamp-where-appropriate.patch
new file mode 100644
index 0000000..084c698
--- /dev/null
+++ b/SOURCES/Use-krb5_timestamp-where-appropriate.patch
@@ -0,0 +1,328 @@
+From f181bf6ee4ff66489895a8c543521cbec253d1f9 Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Wed, 17 May 2017 15:14:15 -0400
+Subject: [PATCH] Use krb5_timestamp where appropriate
+
+Where krb5_int32 is used to hold the number of seconds since the
+epoch, use krb5_timestamp instead.
+
+(cherry picked from commit ae25f6ec5558140a546db34fea389412d81c0631)
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/clients/klist/klist.c          |  2 +-
+ src/include/k5-int.h               |  2 +-
+ src/kadmin/server/misc.c           |  2 +-
+ src/kdc/dispatch.c                 |  4 ++--
+ src/lib/kadm5/srv/server_acl.c     |  2 +-
+ src/lib/kadm5/srv/server_kdb.c     |  2 +-
+ src/lib/kadm5/srv/svr_principal.c  | 10 +++++-----
+ src/lib/krb5/krb/gen_save_subkey.c |  3 ++-
+ src/lib/krb5/krb/get_in_tkt.c      |  2 +-
+ src/lib/krb5/krb/init_ctx.c        |  3 ++-
+ src/lib/krb5/os/c_ustime.c         |  7 +++++--
+ src/lib/krb5/os/toffset.c          |  3 ++-
+ src/lib/krb5/os/trace.c            |  3 ++-
+ src/lib/krb5/os/ustime.c           |  3 ++-
+ src/lib/krb5/rcache/rc_dfl.c       | 10 +++++-----
+ src/tests/create/kdb5_mkdums.c     |  2 +-
+ 16 files changed, 34 insertions(+), 26 deletions(-)
+
+diff --git a/src/clients/klist/klist.c b/src/clients/klist/klist.c
+index ffeecc394..4334415be 100644
+--- a/src/clients/klist/klist.c
++++ b/src/clients/klist/klist.c
+@@ -56,7 +56,7 @@ int show_adtype = 0, show_all = 0, list_all = 0, use_client_keytab = 0;
+ int show_config = 0;
+ char *defname;
+ char *progname;
+-krb5_int32 now;
++krb5_timestamp now;
+ unsigned int timestamp_width;
+ 
+ krb5_context kcontext;
+diff --git a/src/include/k5-int.h b/src/include/k5-int.h
+index 82ee20760..ed9c7bf75 100644
+--- a/src/include/k5-int.h
++++ b/src/include/k5-int.h
+@@ -721,7 +721,7 @@ krb5_error_code krb5int_c_copy_keyblock_contents(krb5_context context,
+                                                  const krb5_keyblock *from,
+                                                  krb5_keyblock *to);
+ 
+-krb5_error_code krb5_crypto_us_timeofday(krb5_int32 *, krb5_int32 *);
++krb5_error_code krb5_crypto_us_timeofday(krb5_timestamp *, krb5_int32 *);
+ 
+ /*
+  * End "los-proto.h"
+diff --git a/src/kadmin/server/misc.c b/src/kadmin/server/misc.c
+index a75b65a26..ba672d714 100644
+--- a/src/kadmin/server/misc.c
++++ b/src/kadmin/server/misc.c
+@@ -159,7 +159,7 @@ kadm5_ret_t
+ check_min_life(void *server_handle, krb5_principal principal,
+                char *msg_ret, unsigned int msg_len)
+ {
+-    krb5_int32                  now;
++    krb5_timestamp              now;
+     kadm5_ret_t                 ret;
+     kadm5_policy_ent_rec        pol;
+     kadm5_principal_ent_rec     princ;
+diff --git a/src/kdc/dispatch.c b/src/kdc/dispatch.c
+index 16a35d2be..4ecc23481 100644
+--- a/src/kdc/dispatch.c
++++ b/src/kdc/dispatch.c
+@@ -94,8 +94,8 @@ static void
+ reseed_random(krb5_context kdc_err_context)
+ {
+     krb5_error_code retval;
+-    krb5_int32 now, now_usec;
+-    krb5_int32 usec_difference;
++    krb5_timestamp now;
++    krb5_int32 now_usec, usec_difference;
+     krb5_data data;
+ 
+     retval = krb5_crypto_us_timeofday(&now, &now_usec);
+diff --git a/src/lib/kadm5/srv/server_acl.c b/src/lib/kadm5/srv/server_acl.c
+index 656dddff5..c2cf69169 100644
+--- a/src/lib/kadm5/srv/server_acl.c
++++ b/src/lib/kadm5/srv/server_acl.c
+@@ -375,7 +375,7 @@ kadm5int_acl_impose_restrictions(kcontext, recp, maskp, rp)
+     restriction_t              *rp;
+ {
+     krb5_error_code     code;
+-    krb5_int32          now;
++    krb5_timestamp      now;
+ 
+     DPRINT(DEBUG_CALLS, acl_debug_level,
+            ("* kadm5int_acl_impose_restrictions(..., *maskp=0x%08x, rp=0x%08x)\n",
+diff --git a/src/lib/kadm5/srv/server_kdb.c b/src/lib/kadm5/srv/server_kdb.c
+index 612553ba3..f4b8aef2b 100644
+--- a/src/lib/kadm5/srv/server_kdb.c
++++ b/src/lib/kadm5/srv/server_kdb.c
+@@ -365,7 +365,7 @@ kdb_put_entry(kadm5_server_handle_t handle,
+               krb5_db_entry *kdb, osa_princ_ent_rec *adb)
+ {
+     krb5_error_code ret;
+-    krb5_int32 now;
++    krb5_timestamp now;
+     XDR xdrs;
+     krb5_tl_data tl_data;
+ 
+diff --git a/src/lib/kadm5/srv/svr_principal.c b/src/lib/kadm5/srv/svr_principal.c
+index f4a9a2ad2..0d4f0a632 100644
+--- a/src/lib/kadm5/srv/svr_principal.c
++++ b/src/lib/kadm5/srv/svr_principal.c
+@@ -296,7 +296,7 @@ kadm5_create_principal_3(void *server_handle,
+     osa_princ_ent_rec           adb;
+     kadm5_policy_ent_rec        polent;
+     krb5_boolean                have_polent = FALSE;
+-    krb5_int32                  now;
++    krb5_timestamp              now;
+     krb5_tl_data                *tl_data_tail;
+     unsigned int                ret;
+     kadm5_server_handle_t handle = server_handle;
+@@ -1322,7 +1322,7 @@ kadm5_chpass_principal_3(void *server_handle,
+                          int n_ks_tuple, krb5_key_salt_tuple *ks_tuple,
+                          char *password)
+ {
+-    krb5_int32                  now;
++    krb5_timestamp              now;
+     kadm5_policy_ent_rec        pol;
+     osa_princ_ent_rec           adb;
+     krb5_db_entry               *kdb;
+@@ -1544,7 +1544,7 @@ kadm5_randkey_principal_3(void *server_handle,
+ {
+     krb5_db_entry               *kdb;
+     osa_princ_ent_rec           adb;
+-    krb5_int32                  now;
++    krb5_timestamp              now;
+     kadm5_policy_ent_rec        pol;
+     int                         ret, last_pwd, n_new_keys;
+     krb5_boolean                have_pol = FALSE;
+@@ -1686,7 +1686,7 @@ kadm5_setv4key_principal(void *server_handle,
+ {
+     krb5_db_entry               *kdb;
+     osa_princ_ent_rec           adb;
+-    krb5_int32                  now;
++    krb5_timestamp              now;
+     kadm5_policy_ent_rec        pol;
+     krb5_keysalt                keysalt;
+     int                         i, kvno, ret;
+@@ -1888,7 +1888,7 @@ kadm5_setkey_principal_4(void *server_handle, krb5_principal principal,
+ {
+     krb5_db_entry *kdb;
+     osa_princ_ent_rec adb;
+-    krb5_int32 now;
++    krb5_timestamp now;
+     kadm5_policy_ent_rec pol;
+     krb5_key_data *new_key_data = NULL;
+     int i, j, ret, n_new_key_data = 0;
+diff --git a/src/lib/krb5/krb/gen_save_subkey.c b/src/lib/krb5/krb/gen_save_subkey.c
+index 61f36aa36..bc2c46d30 100644
+--- a/src/lib/krb5/krb/gen_save_subkey.c
++++ b/src/lib/krb5/krb/gen_save_subkey.c
+@@ -38,7 +38,8 @@ k5_generate_and_save_subkey(krb5_context context,
+        to guarantee randomness, but to make it less likely that multiple
+        sessions could pick the same subkey.  */
+     struct {
+-        krb5_int32 sec, usec;
++        krb5_timestamp sec;
++        krb5_int32 usec;
+     } rnd_data;
+     krb5_data d;
+     krb5_error_code retval;
+diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
+index 40aba1905..7178bd87b 100644
+--- a/src/lib/krb5/krb/get_in_tkt.c
++++ b/src/lib/krb5/krb/get_in_tkt.c
+@@ -1788,7 +1788,7 @@ k5_populate_gic_opt(krb5_context context, krb5_get_init_creds_opt **out,
+                     krb5_creds *creds)
+ {
+     int i;
+-    krb5_int32 starttime;
++    krb5_timestamp starttime;
+     krb5_deltat lifetime;
+     krb5_get_init_creds_opt *opt;
+     krb5_error_code retval;
+diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c
+index cf226fdba..4246c5dd2 100644
+--- a/src/lib/krb5/krb/init_ctx.c
++++ b/src/lib/krb5/krb/init_ctx.c
+@@ -139,7 +139,8 @@ krb5_init_context_profile(profile_t profile, krb5_flags flags,
+     krb5_context ctx = 0;
+     krb5_error_code retval;
+     struct {
+-        krb5_int32 now, now_usec;
++        krb5_timestamp now;
++        krb5_int32 now_usec;
+         long pid;
+     } seed_data;
+     krb5_data seed;
+diff --git a/src/lib/krb5/os/c_ustime.c b/src/lib/krb5/os/c_ustime.c
+index 68fb381f4..f69f2ea4c 100644
+--- a/src/lib/krb5/os/c_ustime.c
++++ b/src/lib/krb5/os/c_ustime.c
+@@ -29,7 +29,10 @@
+ 
+ k5_mutex_t krb5int_us_time_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
+ 
+-struct time_now { krb5_int32 sec, usec; };
++struct time_now {
++    krb5_timestamp sec;
++    krb5_int32 usec;
++};
+ 
+ #if defined(_WIN32)
+ 
+@@ -73,7 +76,7 @@ get_time_now(struct time_now *n)
+ static struct time_now last_time;
+ 
+ krb5_error_code
+-krb5_crypto_us_timeofday(krb5_int32 *seconds, krb5_int32 *microseconds)
++krb5_crypto_us_timeofday(krb5_timestamp *seconds, krb5_int32 *microseconds)
+ {
+     struct time_now now;
+     krb5_error_code err;
+diff --git a/src/lib/krb5/os/toffset.c b/src/lib/krb5/os/toffset.c
+index 37bc69f49..4bbcdde52 100644
+--- a/src/lib/krb5/os/toffset.c
++++ b/src/lib/krb5/os/toffset.c
+@@ -40,7 +40,8 @@ krb5_error_code KRB5_CALLCONV
+ krb5_set_real_time(krb5_context context, krb5_timestamp seconds, krb5_int32 microseconds)
+ {
+     krb5_os_context os_ctx = &context->os_context;
+-    krb5_int32 sec, usec;
++    krb5_timestamp sec;
++    krb5_int32 usec;
+     krb5_error_code retval;
+ 
+     retval = krb5_crypto_us_timeofday(&sec, &usec);
+diff --git a/src/lib/krb5/os/trace.c b/src/lib/krb5/os/trace.c
+index 74c315c90..8750b7650 100644
+--- a/src/lib/krb5/os/trace.c
++++ b/src/lib/krb5/os/trace.c
+@@ -340,7 +340,8 @@ krb5int_trace(krb5_context context, const char *fmt, ...)
+     va_list ap;
+     krb5_trace_info info;
+     char *str = NULL, *msg = NULL;
+-    krb5_int32 sec, usec;
++    krb5_timestamp sec;
++    krb5_int32 usec;
+ 
+     if (context == NULL || context->trace_callback == NULL)
+         return;
+diff --git a/src/lib/krb5/os/ustime.c b/src/lib/krb5/os/ustime.c
+index 1c1b571eb..a80fdf68c 100644
+--- a/src/lib/krb5/os/ustime.c
++++ b/src/lib/krb5/os/ustime.c
+@@ -40,7 +40,8 @@ krb5_error_code
+ k5_time_with_offset(krb5_timestamp offset, krb5_int32 offset_usec,
+                     krb5_timestamp *time_out, krb5_int32 *usec_out)
+ {
+-    krb5_int32 sec, usec;
++    krb5_timestamp sec;
++    krb5_int32 usec;
+     krb5_error_code retval;
+ 
+     retval = krb5_crypto_us_timeofday(&sec, &usec);
+diff --git a/src/lib/krb5/rcache/rc_dfl.c b/src/lib/krb5/rcache/rc_dfl.c
+index 6b043844d..41ebf94da 100644
+--- a/src/lib/krb5/rcache/rc_dfl.c
++++ b/src/lib/krb5/rcache/rc_dfl.c
+@@ -93,7 +93,7 @@ cmp(krb5_donot_replay *old, krb5_donot_replay *new1, krb5_deltat t)
+ }
+ 
+ static int
+-alive(krb5_int32 mytime, krb5_donot_replay *new1, krb5_deltat t)
++alive(krb5_timestamp mytime, krb5_donot_replay *new1, krb5_deltat t)
+ {
+     if (mytime == 0)
+         return CMP_HOHUM; /* who cares? */
+@@ -129,7 +129,7 @@ struct authlist
+ 
+ static int
+ rc_store(krb5_context context, krb5_rcache id, krb5_donot_replay *rep,
+-         krb5_int32 now, krb5_boolean fromfile)
++         krb5_timestamp now, krb5_boolean fromfile)
+ {
+     struct dfl_data *t = (struct dfl_data *)id->data;
+     unsigned int rephash;
+@@ -536,7 +536,7 @@ krb5_rc_dfl_recover_locked(krb5_context context, krb5_rcache id)
+     krb5_error_code retval;
+     long max_size;
+     int expired_entries = 0;
+-    krb5_int32 now;
++    krb5_timestamp now;
+ 
+     if ((retval = krb5_rc_io_open(context, &t->d, t->name))) {
+         return retval;
+@@ -706,7 +706,7 @@ krb5_rc_dfl_store(krb5_context context, krb5_rcache id, krb5_donot_replay *rep)
+ {
+     krb5_error_code ret;
+     struct dfl_data *t;
+-    krb5_int32 now;
++    krb5_timestamp now;
+ 
+     ret = krb5_timeofday(context, &now);
+     if (ret)
+@@ -762,7 +762,7 @@ krb5_rc_dfl_expunge_locked(krb5_context context, krb5_rcache id)
+     struct authlist **qt;
+     struct authlist *r;
+     struct authlist *rt;
+-    krb5_int32 now;
++    krb5_timestamp now;
+ 
+     if (krb5_timestamp(context, &now))
+         now = 0;
+diff --git a/src/tests/create/kdb5_mkdums.c b/src/tests/create/kdb5_mkdums.c
+index 622f549f9..7c0666601 100644
+--- a/src/tests/create/kdb5_mkdums.c
++++ b/src/tests/create/kdb5_mkdums.c
+@@ -247,7 +247,7 @@ add_princ(context, str_newprinc)
+ 
+     {
+         /* Add mod princ to db entry */
+-        krb5_int32 now;
++        krb5_timestamp now;
+ 
+         retval = krb5_timeofday(context, &now);
+         if (retval) {
diff --git a/SOURCES/Use-the-canonical-client-principal-name-for-OTP.patch b/SOURCES/Use-the-canonical-client-principal-name-for-OTP.patch
new file mode 100644
index 0000000..e77b58a
--- /dev/null
+++ b/SOURCES/Use-the-canonical-client-principal-name-for-OTP.patch
@@ -0,0 +1,30 @@
+From 685698f8d33810ce085da4d75d1d8febe5323fd3 Mon Sep 17 00:00:00 2001
+From: Matt Rogers <mrogers@redhat.com>
+Date: Wed, 5 Apr 2017 16:48:55 -0400
+Subject: [PATCH] Use the canonical client principal name for OTP
+
+In the OTP module, when constructing the RADIUS request, use the
+canonicalized client principal (using the new client_name kdcpreauth
+callback) instead of the request client principal.
+
+ticket: 8571 (new)
+(cherry picked from commit 6411398e35e343cdc4d2d103b079c4d3b9031f7e)
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/plugins/preauth/otp/main.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/src/plugins/preauth/otp/main.c b/src/plugins/preauth/otp/main.c
+index 2649e9a90..a1b681682 100644
+--- a/src/plugins/preauth/otp/main.c
++++ b/src/plugins/preauth/otp/main.c
+@@ -331,7 +331,8 @@ otp_verify(krb5_context context, krb5_data *req_pkt, krb5_kdc_req *request,
+ 
+     /* Send the request. */
+     otp_state_verify((otp_state *)moddata, cb->event_context(context, rock),
+-                     request->client, config, req, on_response, rs);
++                     cb->client_name(context, rock), config, req, on_response,
++                     rs);
+     cb->free_string(context, rock, config);
+ 
+     k5_free_pa_otp_req(context, req);
diff --git a/SOURCES/_kadmind b/SOURCES/_kadmind
new file mode 100644
index 0000000..b073cfb
--- /dev/null
+++ b/SOURCES/_kadmind
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+#  Check for error conditions which the init system expects us to check and
+#  for other common errors, and exit with the expected status codes.
+#
+kadmind=/usr/sbin/kadmind
+if test -f /var/kerberos/krb5kdc/kpropd.acl ; then
+	echo $"Error. This appears to be a slave server, found kpropd.acl"
+	exit 6
+fi
+if ! test -x "$kadmind" ; then
+	exit 5
+fi
+exec "$kadmind" "$@"
diff --git a/SOURCES/_kpropd b/SOURCES/_kpropd
new file mode 100644
index 0000000..1808368
--- /dev/null
+++ b/SOURCES/_kpropd
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+#  Check for error conditions which the init system expects us to check and
+#  for other common errors, and exit with the expected status codes.
+#
+kpropd=/usr/sbin/kpropd
+if ! test -f /var/kerberos/krb5kdc/kpropd.acl ; then
+	echo $"Error. This does not appear to be a slave server, kpropd.acl not found"
+	exit 6
+fi
+if ! test -x "$kpropd" ; then
+	exit 5
+fi
+exec "$kpropd" "$@"
diff --git a/SOURCES/kadm5.acl b/SOURCES/kadm5.acl
new file mode 100644
index 0000000..dc93eb0
--- /dev/null
+++ b/SOURCES/kadm5.acl
@@ -0,0 +1 @@
+*/admin@EXAMPLE.COM	*
diff --git a/SOURCES/kadmin.service b/SOURCES/kadmin.service
new file mode 100644
index 0000000..ede159e
--- /dev/null
+++ b/SOURCES/kadmin.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=Kerberos 5 Password-changing and Administration
+After=syslog.target network.target
+
+[Service]
+Type=forking
+PIDFile=/var/run/kadmind.pid
+EnvironmentFile=-/etc/sysconfig/kadmin
+ExecStart=/usr/sbin/_kadmind -P /var/run/kadmind.pid $KADMIND_ARGS
+ExecReload=/bin/kill -HUP $MAINPID
+
+[Install]
+WantedBy=multi-user.target
diff --git a/SOURCES/kadmin.sysconfig b/SOURCES/kadmin.sysconfig
new file mode 100644
index 0000000..fa72039
--- /dev/null
+++ b/SOURCES/kadmin.sysconfig
@@ -0,0 +1 @@
+KADMIND_ARGS=
diff --git a/SOURCES/kadmind.init b/SOURCES/kadmind.init
new file mode 100755
index 0000000..8915e2b
--- /dev/null
+++ b/SOURCES/kadmind.init
@@ -0,0 +1,108 @@
+#!/bin/bash
+#
+# kadmind      Start and stop the Kerberos 5 administrative server.
+#
+# chkconfig:   - 35 65
+# description: Kerberos 5 is a trusted third-party authentication system.  \
+#	       This script starts and stops the Kerberos 5 administrative \
+#              server, which should only be run on the master server for a \
+#              realm.
+# processname: kadmind
+# config: /etc/sysconfig/kadmin
+# pidfile: /var/run/kadmind.pid
+#
+
+### BEGIN INIT INFO
+# Provides: kadmin
+# Required-Start: $local_fs $network
+# Required-Stop: $local_fs $network
+# Should-Start: portreserve
+# Default-Start:
+# Default-Stop: 0 1 2 3 4 5 6
+# Short-Description: start and stop the Kerberos 5 admin server
+# Description: The kadmind service allows administrators to remotely manage \
+#              the Kerberos 5 realm database.  It should only be run on a \
+#              master KDC.
+### END INIT INFO
+
+# Get config.
+. /etc/sysconfig/network
+
+# Get config.
+[ -r /etc/sysconfig/kadmin ] && . /etc/sysconfig/kadmin
+
+# Source function library.
+. /etc/init.d/functions
+prog="Kerberos 5 Admin Server"
+kadmind=/usr/sbin/kadmind
+pidfile=/var/run/kadmind.pid
+
+RETVAL=0
+
+# Shell functions to cut down on useless shell instances.
+start() {
+  	if [ -f /var/kerberos/krb5kdc/kpropd.acl ] ; then
+	    echo $"Error. This appears to be a slave server, found kpropd.acl"
+	    exit 6
+	else
+	    [ -x $kadmind ] || exit 5
+	fi
+	echo -n $"Starting $prog: "
+	# tell portreserve to release the kerberos-adm port
+	[ -x /sbin/portrelease ] && /sbin/portrelease kerberos-adm &>/dev/null || :
+	daemon ${kadmind} ${KRB5REALM:+-r ${KRB5REALM}} -P $pidfile $KADMIND_ARGS
+	RETVAL=$?
+	echo
+	if test $RETVAL -ne 0 ; then
+	    if status -l kadmin ${kadmind} > /dev/null ; then
+		RETVAL=0
+	    fi
+	fi
+	[ $RETVAL = 0 ] && touch /var/lock/subsys/kadmin
+}
+stop() {
+	echo -n $"Stopping $prog: "
+	killproc ${kadmind}
+	RETVAL=$?
+	echo
+	[ $RETVAL = 0 ] && rm -f /var/lock/subsys/kadmin
+}
+reload() {
+	echo -n $"Reopening $prog log file: "
+	killproc ${kadmind} -HUP
+	RETVAL=$?
+	echo
+}
+
+# See how we were called.
+case "$1" in
+  start)
+	start
+	;;
+  stop)
+	stop
+	;;
+  restart)
+	stop
+	start
+	;;
+  status)
+	status -l kadmin ${kadmind}
+	RETVAL=$?
+	;;
+  reload)
+	reload
+	;;
+  condrestart)
+	if [ -f /var/lock/subsys/kadmin ] ; then
+		stop
+		start
+	fi
+	;;
+  *)
+	echo $"Usage: $0 {start|stop|status|condrestart|reload|restart}"
+	RETVAL=2
+	;;
+esac
+
+exit $RETVAL
diff --git a/SOURCES/kadmind.logrotate b/SOURCES/kadmind.logrotate
new file mode 100644
index 0000000..52a66c4
--- /dev/null
+++ b/SOURCES/kadmind.logrotate
@@ -0,0 +1,9 @@
+/var/log/kadmind.log {
+    missingok
+    notifempty
+    monthly
+    rotate 12
+    postrotate
+	/bin/kill -HUP `cat /var/run/kadmind.pid 2>/dev/null` 2> /dev/null || true
+    endscript
+}
diff --git a/SOURCES/kdc.conf b/SOURCES/kdc.conf
new file mode 100644
index 0000000..e99219a
--- /dev/null
+++ b/SOURCES/kdc.conf
@@ -0,0 +1,12 @@
+[kdcdefaults]
+ kdc_ports = 88
+ kdc_tcp_ports = 88
+
+[realms]
+ EXAMPLE.COM = {
+  #master_key_type = aes256-cts
+  acl_file = /var/kerberos/krb5kdc/kadm5.acl
+  dict_file = /usr/share/dict/words
+  admin_keytab = /var/kerberos/krb5kdc/kadm5.keytab
+  supported_enctypes = aes256-cts:normal aes128-cts:normal des3-hmac-sha1:normal arcfour-hmac:normal camellia256-cts:normal camellia128-cts:normal des-hmac-sha1:normal des-cbc-md5:normal des-cbc-crc:normal
+ }
diff --git a/SOURCES/kerberos-adm.portreserve b/SOURCES/kerberos-adm.portreserve
new file mode 100644
index 0000000..eb6080d
--- /dev/null
+++ b/SOURCES/kerberos-adm.portreserve
@@ -0,0 +1 @@
+kerberos-adm/tcp
diff --git a/SOURCES/kprop.service b/SOURCES/kprop.service
new file mode 100644
index 0000000..da6a6b8
--- /dev/null
+++ b/SOURCES/kprop.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Kerberos 5 Propagation
+After=syslog.target network.target
+
+[Service]
+Type=forking
+EnvironmentFile=-/etc/sysconfig/kprop
+ExecStart=/usr/sbin/_kpropd $KPROPD_ARGS
+
+[Install]
+WantedBy=multi-user.target
diff --git a/SOURCES/kprop.sysconfig b/SOURCES/kprop.sysconfig
new file mode 100644
index 0000000..f43e8bb
--- /dev/null
+++ b/SOURCES/kprop.sysconfig
@@ -0,0 +1 @@
+KPROPD_ARGS=
diff --git a/SOURCES/kpropd.init b/SOURCES/kpropd.init
new file mode 100755
index 0000000..b872ee3
--- /dev/null
+++ b/SOURCES/kpropd.init
@@ -0,0 +1,92 @@
+#!/bin/bash
+#
+# kpropd.init  Start and stop the Kerberos 5 propagation client.
+#
+# chkconfig:   - 35 65
+# description: Kerberos 5 is a trusted third-party authentication system.  \
+#	       This script starts and stops the service that allows this \
+#              KDC to receive updates from your master KDC.
+# processname: kpropd
+#
+
+### BEGIN INIT INFO
+# Provides: kprop
+# Required-Start: $local_fs $network
+# Required-Stop: $local_fs $network
+# Should-Start: portreserve
+# Default-Start:
+# Default-Stop: 0 1 2 3 4 5 6
+# Short-Description: start and stop the Kerberos 5 propagation client
+# Description: The kpropd service accepts database updates pushed to it from \
+#              the master KDC.  It will never be needed on a master KDC.
+### END INIT INFO
+
+# Get config.
+. /etc/sysconfig/network
+
+# Source function library.
+. /etc/init.d/functions
+
+RETVAL=0
+prog="Kerberos 5 Propagation Server"
+kpropd=/usr/sbin/kpropd
+
+# Shell functions to cut down on useless shell instances.
+start() {
+  	[ -f /var/kerberos/krb5kdc/kpropd.acl ] || exit 6
+	[ -x $kpropd ] || exit 5
+	echo -n $"Starting $prog: "
+	# tell portreserve to release the krb5_prop port
+	[ -x /sbin/portrelease ] && /sbin/portrelease krb5_prop &>/dev/null || :
+	daemon ${kpropd} -S
+	RETVAL=$?
+	echo
+	if test $RETVAL -ne 0 ; then
+	    if status -l kprop ${kpropd} > /dev/null ; then
+		RETVAL=0
+	    fi
+	fi
+	[ $RETVAL = 0 ] && touch /var/lock/subsys/kprop
+}
+stop() {
+	echo -n $"Stopping $prog: "
+	killproc ${kpropd}
+	RETVAL=$?
+	echo
+	[ $RETVAL = 0 ] && rm -f /var/lock/subsys/kprop
+}
+
+# See how we were called.
+case "$1" in
+  start)
+	start
+	;;
+  stop)
+	stop
+	;;
+  # We don't really "do" reload, so treat it as a restart.
+  restart|force-reload)
+	stop
+	start
+	;;
+  reload)
+	echo "can't reload configuration, you have to restart it"
+	RETVAL=3
+	;;
+  status)
+	status -l kprop ${kpropd}
+	RETVAL=$?
+	;;
+  condrestart)
+	if [ -f /var/lock/subsys/kprop ] ; then
+		stop
+		start
+	fi
+	;;
+  *)
+	echo $"Usage: $0 {start|stop|restart|condrestart|reload|status|force-reload}"
+	RETVAL=2
+	;;
+esac
+
+exit $RETVAL
diff --git a/SOURCES/krb5-1.11-kpasswdtest.patch b/SOURCES/krb5-1.11-kpasswdtest.patch
new file mode 100644
index 0000000..d58987e
--- /dev/null
+++ b/SOURCES/krb5-1.11-kpasswdtest.patch
@@ -0,0 +1,22 @@
+From c21187b3a9f37fd88230e963275d3242344f8f82 Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Fri, 22 Apr 2016 10:03:40 -0400
+Subject: [PATCH] krb5-1.11-kpasswdtest.patch
+
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/kadmin/testing/proto/krb5.conf.proto | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/kadmin/testing/proto/krb5.conf.proto b/src/kadmin/testing/proto/krb5.conf.proto
+index 00c442978..9c4bc1de7 100644
+--- a/src/kadmin/testing/proto/krb5.conf.proto
++++ b/src/kadmin/testing/proto/krb5.conf.proto
+@@ -9,6 +9,7 @@
+ 	__REALM__ = {
+ 		kdc = __KDCHOST__:1750
+ 		admin_server = __KDCHOST__:1751
++		kpasswd_server = __KDCHOST__:1752
+ 		database_module = foobar_db2_module_blah
+ 	}
+ 
diff --git a/SOURCES/krb5-1.11-run_user_0.patch b/SOURCES/krb5-1.11-run_user_0.patch
new file mode 100644
index 0000000..3093df6
--- /dev/null
+++ b/SOURCES/krb5-1.11-run_user_0.patch
@@ -0,0 +1,42 @@
+From b22fe94f6965ebdd2e0cbf2ac002e0e5f9c11789 Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Fri, 22 Apr 2016 10:03:22 -0400
+Subject: [PATCH] krb5-1.11-run_user_0.patch
+
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/lib/krb5/ccache/cc_dir.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/src/lib/krb5/ccache/cc_dir.c b/src/lib/krb5/ccache/cc_dir.c
+index 73f0fe62d..4850c0d07 100644
+--- a/src/lib/krb5/ccache/cc_dir.c
++++ b/src/lib/krb5/ccache/cc_dir.c
+@@ -61,6 +61,8 @@
+ 
+ #include <dirent.h>
+ 
++#define ROOT_SPECIAL_DCC_PARENT "/run/user/0"
++
+ extern const krb5_cc_ops krb5_dcc_ops;
+ extern const krb5_cc_ops krb5_fcc_ops;
+ 
+@@ -237,6 +239,18 @@ verify_dir(krb5_context context, const char *dirname)
+ 
+     if (stat(dirname, &st) < 0) {
+         if (errno == ENOENT) {
++            if (strncmp(dirname, ROOT_SPECIAL_DCC_PARENT "/",
++                        sizeof(ROOT_SPECIAL_DCC_PARENT)) == 0 &&
++                stat(ROOT_SPECIAL_DCC_PARENT, &st) < 0 &&
++                errno == ENOENT) {
++#ifdef USE_SELINUX
++                selabel = krb5int_push_fscreatecon_for(ROOT_SPECIAL_DCC_PARENT);
++#endif
++                status = mkdir(ROOT_SPECIAL_DCC_PARENT, S_IRWXU);
++#ifdef USE_SELINUX
++                krb5int_pop_fscreatecon(selabel);
++#endif
++            }
+ #ifdef USE_SELINUX
+             selabel = krb5int_push_fscreatecon_for(dirname);
+ #endif
diff --git a/SOURCES/krb5-1.12-api.patch b/SOURCES/krb5-1.12-api.patch
new file mode 100644
index 0000000..e040029
--- /dev/null
+++ b/SOURCES/krb5-1.12-api.patch
@@ -0,0 +1,35 @@
+From a609a605d87b3107de64141cd3d60c2a73c7b38f Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Fri, 22 Apr 2016 09:59:22 -0400
+Subject: [PATCH] krb5-1.12-api.patch
+
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/lib/krb5/krb/princ_comp.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/src/lib/krb5/krb/princ_comp.c b/src/lib/krb5/krb/princ_comp.c
+index a6936107d..0ed78833b 100644
+--- a/src/lib/krb5/krb/princ_comp.c
++++ b/src/lib/krb5/krb/princ_comp.c
+@@ -36,6 +36,10 @@ realm_compare_flags(krb5_context context,
+     const krb5_data *realm1 = &princ1->realm;
+     const krb5_data *realm2 = &princ2->realm;
+ 
++    if (princ1 == NULL || princ2 == NULL)
++        return FALSE;
++    if (realm1 == NULL || realm2 == NULL)
++        return FALSE;
+     if (realm1->length != realm2->length)
+         return FALSE;
+     if (realm1->length == 0)
+@@ -88,6 +92,9 @@ krb5_principal_compare_flags(krb5_context context,
+     krb5_principal upn2 = NULL;
+     krb5_boolean ret = FALSE;
+ 
++    if (princ1 == NULL || princ2 == NULL)
++        return FALSE;
++
+     if (flags & KRB5_PRINCIPAL_COMPARE_ENTERPRISE) {
+         /* Treat UPNs as if they were real principals */
+         if (princ1->type == KRB5_NT_ENTERPRISE_PRINCIPAL) {
diff --git a/SOURCES/krb5-1.12-ksu-path.patch b/SOURCES/krb5-1.12-ksu-path.patch
new file mode 100644
index 0000000..cc4a074
--- /dev/null
+++ b/SOURCES/krb5-1.12-ksu-path.patch
@@ -0,0 +1,22 @@
+From fc004dc501c6fc1f1f423a8d87cdc9137d7f6bbf Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Fri, 22 Apr 2016 09:57:25 -0400
+Subject: [PATCH] krb5-1.12-ksu-path.patch
+
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/clients/ksu/Makefile.in | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/clients/ksu/Makefile.in b/src/clients/ksu/Makefile.in
+index 5755bb58a..9d58f29b5 100644
+--- a/src/clients/ksu/Makefile.in
++++ b/src/clients/ksu/Makefile.in
+@@ -1,6 +1,6 @@
+ mydir=clients$(S)ksu
+ BUILDTOP=$(REL)..$(S)..
+-DEFINES = -DGET_TGT_VIA_PASSWD -DPRINC_LOOK_AHEAD -DCMD_PATH='"/bin /local/bin"'
++DEFINES = -DGET_TGT_VIA_PASSWD -DPRINC_LOOK_AHEAD -DCMD_PATH='"/usr/local/sbin /usr/local/bin /sbin /bin /usr/sbin /usr/bin"'
+ 
+ KSU_LIBS=@KSU_LIBS@
+ PAM_LIBS=@PAM_LIBS@
diff --git a/SOURCES/krb5-1.12-ktany.patch b/SOURCES/krb5-1.12-ktany.patch
new file mode 100644
index 0000000..bae76e2
--- /dev/null
+++ b/SOURCES/krb5-1.12-ktany.patch
@@ -0,0 +1,364 @@
+From 5c9294c37210d01f59c54ea623a66618ed2e0e6e Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Fri, 22 Apr 2016 09:58:00 -0400
+Subject: [PATCH] krb5-1.12-ktany.patch
+
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/lib/krb5/keytab/Makefile.in |   3 +
+ src/lib/krb5/keytab/kt_any.c    | 292 ++++++++++++++++++++++++++++++++++++++++
+ src/lib/krb5/keytab/ktbase.c    |   7 +-
+ 3 files changed, 301 insertions(+), 1 deletion(-)
+ create mode 100644 src/lib/krb5/keytab/kt_any.c
+
+diff --git a/src/lib/krb5/keytab/Makefile.in b/src/lib/krb5/keytab/Makefile.in
+index 2a8fceb00..ffd179fb2 100644
+--- a/src/lib/krb5/keytab/Makefile.in
++++ b/src/lib/krb5/keytab/Makefile.in
+@@ -12,6 +12,7 @@ STLIBOBJS= \
+ 	ktfr_entry.o	\
+ 	ktremove.o	\
+ 	ktfns.o		\
++	kt_any.o	\
+ 	kt_file.o	\
+ 	kt_memory.o	\
+ 	kt_srvtab.o	\
+@@ -24,6 +25,7 @@ OBJS=	\
+ 	$(OUTPRE)ktfr_entry.$(OBJEXT)	\
+ 	$(OUTPRE)ktremove.$(OBJEXT)	\
+ 	$(OUTPRE)ktfns.$(OBJEXT)	\
++	$(OUTPRE)kt_any.$(OBJEXT)	\
+ 	$(OUTPRE)kt_file.$(OBJEXT)	\
+ 	$(OUTPRE)kt_memory.$(OBJEXT)	\
+ 	$(OUTPRE)kt_srvtab.$(OBJEXT)	\
+@@ -36,6 +38,7 @@ SRCS=	\
+ 	$(srcdir)/ktfr_entry.c	\
+ 	$(srcdir)/ktremove.c	\
+ 	$(srcdir)/ktfns.c	\
++	$(srcdir)/kt_any.c	\
+ 	$(srcdir)/kt_file.c	\
+ 	$(srcdir)/kt_memory.c	\
+ 	$(srcdir)/kt_srvtab.c	\
+diff --git a/src/lib/krb5/keytab/kt_any.c b/src/lib/krb5/keytab/kt_any.c
+new file mode 100644
+index 000000000..1b9b7765b
+--- /dev/null
++++ b/src/lib/krb5/keytab/kt_any.c
+@@ -0,0 +1,292 @@
++/*
++ * lib/krb5/keytab/kt_any.c
++ *
++ * Copyright 1998, 1999 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.  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.
++ * 
++ *
++ * krb5_kta_ops
++ */
++
++#include "k5-int.h"
++
++typedef struct _krb5_ktany_data {
++    char *name;
++    krb5_keytab *choices;
++    int nchoices;
++} krb5_ktany_data;
++
++typedef struct _krb5_ktany_cursor_data {
++    int which;
++    krb5_kt_cursor cursor;
++} krb5_ktany_cursor_data;
++
++static krb5_error_code krb5_ktany_resolve
++	          (krb5_context,
++		   const char *,
++		   krb5_keytab *);
++static krb5_error_code krb5_ktany_get_name
++	          (krb5_context context,
++		   krb5_keytab id,
++		   char *name,
++		   unsigned int len);
++static krb5_error_code krb5_ktany_close
++	          (krb5_context context,
++		   krb5_keytab id);
++static krb5_error_code krb5_ktany_get_entry
++	          (krb5_context context,
++		   krb5_keytab id,
++		   krb5_const_principal principal,
++		   krb5_kvno kvno,
++		   krb5_enctype enctype,
++		   krb5_keytab_entry *entry);
++static krb5_error_code krb5_ktany_start_seq_get
++	          (krb5_context context,
++		   krb5_keytab id,
++		   krb5_kt_cursor *cursorp);
++static krb5_error_code krb5_ktany_next_entry
++	          (krb5_context context,
++		   krb5_keytab id,
++		   krb5_keytab_entry *entry,
++		   krb5_kt_cursor *cursor);
++static krb5_error_code krb5_ktany_end_seq_get
++	          (krb5_context context,
++		   krb5_keytab id,
++		   krb5_kt_cursor *cursor);
++static void cleanup
++	          (krb5_context context,
++		   krb5_ktany_data *data,
++		   int nchoices);
++
++struct _krb5_kt_ops krb5_kta_ops = {
++    0,
++    "ANY", 	/* Prefix -- this string should not appear anywhere else! */
++    krb5_ktany_resolve,
++    krb5_ktany_get_name,
++    krb5_ktany_close,
++    krb5_ktany_get_entry,
++    krb5_ktany_start_seq_get,
++    krb5_ktany_next_entry,
++    krb5_ktany_end_seq_get,
++    NULL,
++    NULL,
++    NULL,
++};
++
++static krb5_error_code
++krb5_ktany_resolve(context, name, id)
++    krb5_context context;
++    const char *name;
++    krb5_keytab *id;
++{
++    const char *p, *q;
++    char *copy;
++    krb5_error_code kerror;
++    krb5_ktany_data *data;
++    int i;
++
++    /* Allocate space for our data and remember a copy of the name. */
++    if ((data = (krb5_ktany_data *)malloc(sizeof(krb5_ktany_data))) == NULL)
++	return(ENOMEM);
++    if ((data->name = (char *)malloc(strlen(name) + 1)) == NULL) {
++	free(data);
++	return(ENOMEM);
++    }
++    strcpy(data->name, name);
++
++    /* Count the number of choices and allocate memory for them. */
++    data->nchoices = 1;
++    for (p = name; (q = strchr(p, ',')) != NULL; p = q + 1)
++	data->nchoices++;
++    if ((data->choices = (krb5_keytab *)
++	 malloc(data->nchoices * sizeof(krb5_keytab))) == NULL) {
++	free(data->name);
++	free(data);
++	return(ENOMEM);
++    }
++
++    /* Resolve each of the choices. */
++    i = 0;
++    for (p = name; (q = strchr(p, ',')) != NULL; p = q + 1) {
++	/* Make a copy of the choice name so we can terminate it. */
++	if ((copy = (char *)malloc(q - p + 1)) == NULL) {
++	    cleanup(context, data, i);
++	    return(ENOMEM);
++	}
++	memcpy(copy, p, q - p);
++	copy[q - p] = 0;
++
++	/* Try resolving the choice name. */
++	kerror = krb5_kt_resolve(context, copy, &data->choices[i]);
++	free(copy);
++	if (kerror) {
++	    cleanup(context, data, i);
++	    return(kerror);
++	}
++	i++;
++    }
++    if ((kerror = krb5_kt_resolve(context, p, &data->choices[i]))) {
++	cleanup(context, data, i);
++	return(kerror);
++    }
++
++    /* Allocate and fill in an ID for the caller. */
++    if ((*id = (krb5_keytab)malloc(sizeof(**id))) == NULL) {
++	cleanup(context, data, i);
++	return(ENOMEM);
++    }
++    (*id)->ops = &krb5_kta_ops;
++    (*id)->data = (krb5_pointer)data;
++    (*id)->magic = KV5M_KEYTAB;
++
++    return(0);
++}
++
++static krb5_error_code
++krb5_ktany_get_name(context, id, name, len)
++    krb5_context context;
++    krb5_keytab id;
++    char *name;
++    unsigned int len;
++{
++    krb5_ktany_data *data = (krb5_ktany_data *)id->data;
++
++    if (len < strlen(data->name) + 1)
++	return(KRB5_KT_NAME_TOOLONG);
++    strcpy(name, data->name);
++    return(0);
++}
++
++static krb5_error_code
++krb5_ktany_close(context, id)
++    krb5_context context;
++    krb5_keytab id;
++{
++    krb5_ktany_data *data = (krb5_ktany_data *)id->data;
++
++    cleanup(context, data, data->nchoices);
++    id->ops = 0;
++    free(id);
++    return(0);
++}
++
++static krb5_error_code
++krb5_ktany_get_entry(context, id, principal, kvno, enctype, entry)
++    krb5_context context;
++    krb5_keytab id;
++    krb5_const_principal principal;
++    krb5_kvno kvno;
++    krb5_enctype enctype;
++    krb5_keytab_entry *entry;
++{
++    krb5_ktany_data *data = (krb5_ktany_data *)id->data;
++    krb5_error_code kerror = KRB5_KT_NOTFOUND;
++    int i;
++
++    for (i = 0; i < data->nchoices; i++) {
++	if ((kerror = krb5_kt_get_entry(context, data->choices[i], principal,
++					kvno, enctype, entry)) != ENOENT)
++	    return kerror;
++    }
++    return kerror;
++}
++
++static krb5_error_code
++krb5_ktany_start_seq_get(context, id, cursorp)
++    krb5_context context;
++    krb5_keytab id;
++    krb5_kt_cursor *cursorp;
++{
++    krb5_ktany_data *data = (krb5_ktany_data *)id->data;
++    krb5_ktany_cursor_data *cdata;
++    krb5_error_code kerror = ENOENT;
++    int i;
++
++    if ((cdata = (krb5_ktany_cursor_data *)
++	 malloc(sizeof(krb5_ktany_cursor_data))) == NULL)
++	return(ENOMEM);
++
++    /* Find a choice which can handle the serialization request. */
++    for (i = 0; i < data->nchoices; i++) {
++	if ((kerror = krb5_kt_start_seq_get(context, data->choices[i],
++					    &cdata->cursor)) == 0)
++	    break;
++	else if (kerror != ENOENT) {
++	    free(cdata);
++	    return(kerror);
++	}
++    }
++
++    if (i == data->nchoices) {
++	/* Everyone returned ENOENT, so no go. */
++	free(cdata);
++	return(kerror);
++    }
++
++    cdata->which = i;
++    *cursorp = (krb5_kt_cursor)cdata;
++    return(0);
++}
++
++static krb5_error_code
++krb5_ktany_next_entry(context, id, entry, cursor)
++    krb5_context context;
++    krb5_keytab id;
++    krb5_keytab_entry *entry;
++    krb5_kt_cursor *cursor;
++{
++    krb5_ktany_data *data = (krb5_ktany_data *)id->data;
++    krb5_ktany_cursor_data *cdata = (krb5_ktany_cursor_data *)*cursor;
++    krb5_keytab choice_id;
++
++    choice_id = data->choices[cdata->which];
++    return(krb5_kt_next_entry(context, choice_id, entry, &cdata->cursor));
++}
++
++static krb5_error_code
++krb5_ktany_end_seq_get(context, id, cursor)
++    krb5_context context;
++    krb5_keytab id;
++    krb5_kt_cursor *cursor;
++{
++    krb5_ktany_data *data = (krb5_ktany_data *)id->data;
++    krb5_ktany_cursor_data *cdata = (krb5_ktany_cursor_data *)*cursor;
++    krb5_keytab choice_id;
++    krb5_error_code kerror;
++
++    choice_id = data->choices[cdata->which];
++    kerror = krb5_kt_end_seq_get(context, choice_id, &cdata->cursor);
++    free(cdata);
++    return(kerror);
++}
++
++static void
++cleanup(context, data, nchoices)
++    krb5_context context;
++    krb5_ktany_data *data;
++    int nchoices;
++{
++    int i;
++
++    free(data->name);
++    for (i = 0; i < nchoices; i++)
++	krb5_kt_close(context, data->choices[i]);
++    free(data->choices);
++    free(data);
++}
+diff --git a/src/lib/krb5/keytab/ktbase.c b/src/lib/krb5/keytab/ktbase.c
+index 0d39b2940..6534d7c52 100644
+--- a/src/lib/krb5/keytab/ktbase.c
++++ b/src/lib/krb5/keytab/ktbase.c
+@@ -57,14 +57,19 @@ extern const krb5_kt_ops krb5_ktf_ops;
+ extern const krb5_kt_ops krb5_ktf_writable_ops;
+ extern const krb5_kt_ops krb5_kts_ops;
+ extern const krb5_kt_ops krb5_mkt_ops;
++extern const krb5_kt_ops krb5_kta_ops;
+ 
+ struct krb5_kt_typelist {
+     const krb5_kt_ops *ops;
+     const struct krb5_kt_typelist *next;
+ };
++static struct krb5_kt_typelist krb5_kt_typelist_any = {
++    &krb5_kta_ops,
++    NULL
++};
+ const static struct krb5_kt_typelist krb5_kt_typelist_srvtab = {
+     &krb5_kts_ops,
+-    NULL
++    &krb5_kt_typelist_any
+ };
+ const static struct krb5_kt_typelist krb5_kt_typelist_memory = {
+     &krb5_mkt_ops,
diff --git a/SOURCES/krb5-1.12.1-pam.patch b/SOURCES/krb5-1.12.1-pam.patch
new file mode 100644
index 0000000..7b8d6f5
--- /dev/null
+++ b/SOURCES/krb5-1.12.1-pam.patch
@@ -0,0 +1,758 @@
+From 9a6c3d9c1f4286a1a17cd89a1225712606863da8 Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Mon, 18 Apr 2016 15:57:38 -0400
+Subject: [PATCH] krb5-1.12.1-pam.patch
+
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/aclocal.m4              |  67 ++++++++
+ src/clients/ksu/Makefile.in |   8 +-
+ src/clients/ksu/main.c      |  88 +++++++++-
+ src/clients/ksu/pam.c       | 389 ++++++++++++++++++++++++++++++++++++++++++++
+ src/clients/ksu/pam.h       |  57 +++++++
+ src/configure.in            |   2 +
+ 6 files changed, 608 insertions(+), 3 deletions(-)
+ create mode 100644 src/clients/ksu/pam.c
+ create mode 100644 src/clients/ksu/pam.h
+
+diff --git a/src/aclocal.m4 b/src/aclocal.m4
+index 9c46da4b5..508e5fe90 100644
+--- a/src/aclocal.m4
++++ b/src/aclocal.m4
+@@ -1675,3 +1675,70 @@ AC_DEFUN(KRB5_AC_PERSISTENT_KEYRING,[
+       ]))
+ ])dnl
+ dnl
++dnl
++dnl Use PAM instead of local crypt() compare for checking local passwords,
++dnl and perform PAM account, session management, and password-changing where
++dnl appropriate.
++dnl 
++AC_DEFUN(KRB5_WITH_PAM,[
++AC_ARG_WITH(pam,[AC_HELP_STRING(--with-pam,[compile with PAM support])],
++	    withpam="$withval",withpam=auto)
++AC_ARG_WITH(pam-ksu-service,[AC_HELP_STRING(--with-ksu-service,[PAM service name for ksu ["ksu"]])],
++	    withksupamservice="$withval",withksupamservice=ksu)
++old_LIBS="$LIBS"
++if test "$withpam" != no ; then
++	AC_MSG_RESULT([checking for PAM...])
++	PAM_LIBS=
++
++	AC_CHECK_HEADERS(security/pam_appl.h)
++	if test "x$ac_cv_header_security_pam_appl_h" != xyes ; then
++		if test "$withpam" = auto ; then
++			AC_MSG_RESULT([Unable to locate security/pam_appl.h.])
++			withpam=no
++		else
++			AC_MSG_ERROR([Unable to locate security/pam_appl.h.])
++		fi
++	fi
++
++	LIBS=
++	unset ac_cv_func_pam_start
++	AC_CHECK_FUNCS(putenv pam_start)
++	if test "x$ac_cv_func_pam_start" = xno ; then
++		unset ac_cv_func_pam_start
++		AC_CHECK_LIB(dl,dlopen)
++		AC_CHECK_FUNCS(pam_start)
++		if test "x$ac_cv_func_pam_start" = xno ; then
++			AC_CHECK_LIB(pam,pam_start)
++			unset ac_cv_func_pam_start
++			unset ac_cv_func_pam_getenvlist
++			AC_CHECK_FUNCS(pam_start pam_getenvlist)
++			if test "x$ac_cv_func_pam_start" = xyes ; then
++				PAM_LIBS="$LIBS"
++			else
++				if test "$withpam" = auto ; then
++					AC_MSG_RESULT([Unable to locate libpam.])
++					withpam=no
++				else
++					AC_MSG_ERROR([Unable to locate libpam.])
++				fi
++			fi
++		fi
++	fi
++	if test "$withpam" != no ; then
++		AC_MSG_NOTICE([building with PAM support])
++		AC_DEFINE(USE_PAM,1,[Define if Kerberos-aware tools should support PAM])
++		AC_DEFINE_UNQUOTED(KSU_PAM_SERVICE,"$withksupamservice",
++				   [Define to the name of the PAM service name to be used by ksu.])
++		PAM_LIBS="$LIBS"
++		NON_PAM_MAN=".\\\" "
++		PAM_MAN=
++	else
++		PAM_MAN=".\\\" "
++		NON_PAM_MAN=
++	fi
++fi
++LIBS="$old_LIBS"
++AC_SUBST(PAM_LIBS)
++AC_SUBST(PAM_MAN)
++AC_SUBST(NON_PAM_MAN)
++])dnl
+diff --git a/src/clients/ksu/Makefile.in b/src/clients/ksu/Makefile.in
+index b2fcbf240..5755bb58a 100644
+--- a/src/clients/ksu/Makefile.in
++++ b/src/clients/ksu/Makefile.in
+@@ -3,12 +3,14 @@ BUILDTOP=$(REL)..$(S)..
+ DEFINES = -DGET_TGT_VIA_PASSWD -DPRINC_LOOK_AHEAD -DCMD_PATH='"/bin /local/bin"'
+ 
+ KSU_LIBS=@KSU_LIBS@
++PAM_LIBS=@PAM_LIBS@
+ 
+ SRCS = \
+ 	$(srcdir)/krb_auth_su.c \
+ 	$(srcdir)/ccache.c \
+ 	$(srcdir)/authorization.c \
+ 	$(srcdir)/main.c \
++	$(srcdir)/pam.c \
+ 	$(srcdir)/heuristic.c \
+ 	$(srcdir)/xmalloc.c \
+ 	$(srcdir)/setenv.c
+@@ -17,13 +19,17 @@ OBJS = \
+ 	ccache.o \
+ 	authorization.o \
+ 	main.o \
++	pam.o \
+ 	heuristic.o \
+ 	xmalloc.o @SETENVOBJ@
+ 
+ all: ksu
+ 
+ ksu: $(OBJS) $(KRB5_BASE_DEPLIBS)
+-	$(CC_LINK) -o $@ $(OBJS) $(KRB5_BASE_LIBS) $(KSU_LIBS)
++	$(CC_LINK) -o $@ $(OBJS) $(KRB5_BASE_LIBS) $(KSU_LIBS) $(PAM_LIBS)
++
++pam.o: pam.c
++	$(CC) $(ALL_CFLAGS) -c $<
+ 
+ clean:
+ 	$(RM) ksu
+diff --git a/src/clients/ksu/main.c b/src/clients/ksu/main.c
+index 28342c2d7..cab0c1806 100644
+--- a/src/clients/ksu/main.c
++++ b/src/clients/ksu/main.c
+@@ -26,6 +26,7 @@
+  * KSU was writen by:  Ari Medvinsky, ari@isi.edu
+  */
+ 
++#include "autoconf.h"
+ #include "ksu.h"
+ #include "adm_proto.h"
+ #include <sys/types.h>
+@@ -33,6 +34,10 @@
+ #include <signal.h>
+ #include <grp.h>
+ 
++#ifdef USE_PAM
++#include "pam.h"
++#endif
++
+ /* globals */
+ char * prog_name;
+ int auth_debug =0;
+@@ -40,6 +45,7 @@ char k5login_path[MAXPATHLEN];
+ char k5users_path[MAXPATHLEN];
+ char * gb_err = NULL;
+ int quiet = 0;
++int force_fork = 0;
+ /***********/
+ 
+ #define KS_TEMPORARY_CACHE "MEMORY:_ksu"
+@@ -515,6 +521,23 @@ main (argc, argv)
+                prog_name,target_user,client_name,
+                source_user,ontty());
+ 
++#ifdef USE_PAM
++        if (appl_pam_enabled(ksu_context, "ksu")) {
++            if (appl_pam_acct_mgmt(KSU_PAM_SERVICE, 1, target_user, NULL,
++                                   NULL, source_user,
++                                   ttyname(STDERR_FILENO)) != 0) {
++                fprintf(stderr, "Access denied for %s.\n", target_user);
++                exit(1);
++            }
++            if (appl_pam_requires_chauthtok()) {
++                fprintf(stderr, "Password change required for %s.\n",
++                        target_user);
++                exit(1);
++            }
++            force_fork++;
++        }
++#endif
++
+         /* Run authorization as target.*/
+         if (krb5_seteuid(target_uid)) {
+             com_err(prog_name, errno, _("while switching to target for "
+@@ -575,6 +598,24 @@ main (argc, argv)
+ 
+             exit(1);
+         }
++#ifdef USE_PAM
++    } else {
++        /* we always do PAM account management, even for root */
++        if (appl_pam_enabled(ksu_context, "ksu")) {
++            if (appl_pam_acct_mgmt(KSU_PAM_SERVICE, 1, target_user, NULL,
++                                   NULL, source_user,
++                                   ttyname(STDERR_FILENO)) != 0) {
++                fprintf(stderr, "Access denied for %s.\n", target_user);
++                exit(1);
++            }
++            if (appl_pam_requires_chauthtok()) {
++                fprintf(stderr, "Password change required for %s.\n",
++                        target_user);
++                exit(1);
++            }
++            force_fork++;
++        }
++#endif
+     }
+ 
+     if( some_rest_copy){
+@@ -632,6 +673,30 @@ main (argc, argv)
+         exit(1);
+     }
+ 
++#ifdef USE_PAM
++    if (appl_pam_enabled(ksu_context, "ksu")) {
++        if (appl_pam_session_open() != 0) {
++            fprintf(stderr, "Error opening session for %s.\n", target_user);
++            exit(1);
++        }
++#ifdef DEBUG
++        if (auth_debug){
++            printf(" Opened PAM session.\n");
++        }
++#endif
++        if (appl_pam_cred_init()) {
++            fprintf(stderr, "Error initializing credentials for %s.\n",
++                    target_user);
++            exit(1);
++        }
++#ifdef DEBUG
++        if (auth_debug){
++            printf(" Initialized PAM credentials.\n");
++        }
++#endif
++    }
++#endif
++
+     /* set permissions */
+     if (setgid(target_pwd->pw_gid) < 0) {
+         perror("ksu: setgid");
+@@ -729,7 +794,7 @@ main (argc, argv)
+         fprintf(stderr, "program to be execed %s\n",params[0]);
+     }
+ 
+-    if( keep_target_cache ) {
++    if( keep_target_cache && !force_fork ) {
+         execv(params[0], params);
+         com_err(prog_name, errno, _("while trying to execv %s"), params[0]);
+         sweep_up(ksu_context, cc_target);
+@@ -759,16 +824,35 @@ main (argc, argv)
+             if (ret_pid == -1) {
+                 com_err(prog_name, errno, _("while calling waitpid"));
+             }
+-            sweep_up(ksu_context, cc_target);
++            if( !keep_target_cache ) {
++                sweep_up(ksu_context, cc_target);
++            }
+             exit (statusp);
+         case -1:
+             com_err(prog_name, errno, _("while trying to fork."));
+             sweep_up(ksu_context, cc_target);
+             exit (1);
+         case 0:
++#ifdef USE_PAM
++            if (appl_pam_enabled(ksu_context, "ksu")) {
++                if (appl_pam_setenv() != 0) {
++                    fprintf(stderr, "Error setting up environment for %s.\n",
++                            target_user);
++                    exit (1);
++                }
++#ifdef DEBUG
++                if (auth_debug){
++                    printf(" Set up PAM environment.\n");
++                }
++#endif
++            }
++#endif
+             execv(params[0], params);
+             com_err(prog_name, errno, _("while trying to execv %s"),
+                     params[0]);
++            if( keep_target_cache ) {
++                sweep_up(ksu_context, cc_target);
++            }
+             exit (1);
+         }
+     }
+diff --git a/src/clients/ksu/pam.c b/src/clients/ksu/pam.c
+new file mode 100644
+index 000000000..cbfe48704
+--- /dev/null
++++ b/src/clients/ksu/pam.c
+@@ -0,0 +1,389 @@
++/*
++ * src/clients/ksu/pam.c
++ *
++ * Copyright 2007,2009,2010 Red Hat, Inc.
++ *
++ * All Rights Reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ *
++ *  Redistributions of source code must retain the above copyright notice, this
++ *  list of conditions and the following disclaimer.
++ *
++ *  Redistributions in binary form must reproduce the above copyright notice,
++ *  this list of conditions and the following disclaimer in the documentation
++ *  and/or other materials provided with the distribution.
++ *
++ *  Neither the name of Red Hat, Inc. nor the names of its contributors may be
++ *  used to endorse or promote products derived from this software without
++ *  specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++ * POSSIBILITY OF SUCH DAMAGE.
++ * 
++ * Convenience wrappers for using PAM.
++ */
++
++#include "autoconf.h"
++#ifdef USE_PAM
++#include <sys/types.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++#include "k5-int.h"
++#include "pam.h"
++
++#ifndef MAXPWSIZE
++#define MAXPWSIZE 128
++#endif
++
++static int appl_pam_started;
++static pid_t appl_pam_starter = -1;
++static int appl_pam_session_opened;
++static int appl_pam_creds_initialized;
++static int appl_pam_pwchange_required;
++static pam_handle_t *appl_pamh;
++static struct pam_conv appl_pam_conv;
++static char *appl_pam_user;
++struct appl_pam_non_interactive_args {
++	const char *user;
++	const char *password;
++};
++
++int
++appl_pam_enabled(krb5_context context, const char *section)
++{
++	int enabled = 1;
++	if ((context != NULL) && (context->profile != NULL)) {
++		if (profile_get_boolean(context->profile,
++					section,
++					USE_PAM_CONFIGURATION_KEYWORD,
++					NULL,
++					enabled, &enabled) != 0) {
++			enabled = 1;
++		}
++	}
++	return enabled;
++}
++
++void
++appl_pam_cleanup(void)
++{
++	if (getpid() != appl_pam_starter) {
++		return;
++	}
++#ifdef DEBUG
++	printf("Called to clean up PAM.\n");
++#endif
++	if (appl_pam_creds_initialized) {
++#ifdef DEBUG
++		printf("Deleting PAM credentials.\n");
++#endif
++		pam_setcred(appl_pamh, PAM_DELETE_CRED);
++		appl_pam_creds_initialized = 0;
++	}
++	if (appl_pam_session_opened) {
++#ifdef DEBUG
++		printf("Closing PAM session.\n");
++#endif
++		pam_close_session(appl_pamh, 0);
++		appl_pam_session_opened = 0;
++	}
++	appl_pam_pwchange_required = 0;
++	if (appl_pam_started) {
++#ifdef DEBUG
++		printf("Shutting down PAM.\n");
++#endif
++		pam_end(appl_pamh, 0);
++		appl_pam_started = 0;
++		appl_pam_starter = -1;
++		free(appl_pam_user);
++		appl_pam_user = NULL;
++	}
++}
++static int
++appl_pam_interactive_converse(int num_msg, const struct pam_message **msg,
++			      struct pam_response **presp, void *appdata_ptr)
++{
++	const struct pam_message *message;
++	struct pam_response *resp;
++	int i, code;
++	char *pwstring, pwbuf[MAXPWSIZE];
++	unsigned int pwsize;
++	resp = malloc(sizeof(struct pam_response) * num_msg);
++	if (resp == NULL) {
++		return PAM_BUF_ERR;
++	}
++	memset(resp, 0, sizeof(struct pam_response) * num_msg);
++	code = PAM_SUCCESS;
++	for (i = 0; i < num_msg; i++) {
++		message = &(msg[0][i]); /* XXX */
++		message = msg[i]; /* XXX */
++		pwstring = NULL;
++		switch (message->msg_style) {
++		case PAM_TEXT_INFO:
++		case PAM_ERROR_MSG:
++			printf("[%s]\n", message->msg ? message->msg : "");
++			fflush(stdout);
++			resp[i].resp = NULL;
++			resp[i].resp_retcode = PAM_SUCCESS;
++			break;
++		case PAM_PROMPT_ECHO_ON:
++		case PAM_PROMPT_ECHO_OFF:
++			if (message->msg_style == PAM_PROMPT_ECHO_ON) {
++				if (fgets(pwbuf, sizeof(pwbuf),
++					  stdin) != NULL) {
++					pwbuf[strcspn(pwbuf, "\r\n")] = '\0';
++					pwstring = pwbuf;
++				}
++			} else {
++				pwstring = getpass(message->msg ?
++						   message->msg :
++						   "");
++			}
++			if ((pwstring != NULL) && (pwstring[0] != '\0')) {
++				pwsize = strlen(pwstring);
++				resp[i].resp = malloc(pwsize + 1);
++				if (resp[i].resp == NULL) {
++					resp[i].resp_retcode = PAM_BUF_ERR;
++				} else {
++					memcpy(resp[i].resp, pwstring, pwsize);
++					resp[i].resp[pwsize] = '\0';
++					resp[i].resp_retcode = PAM_SUCCESS;
++				}
++			} else {
++				resp[i].resp_retcode = PAM_CONV_ERR;
++				code = PAM_CONV_ERR;
++			}
++			break;
++		default:
++			break;
++		}
++	}
++	*presp = resp;
++	return code;
++}
++static int
++appl_pam_non_interactive_converse(int num_msg,
++				  const struct pam_message **msg,
++				  struct pam_response **presp,
++				  void *appdata_ptr)
++{
++	const struct pam_message *message;
++	struct pam_response *resp;
++	int i, code;
++	unsigned int pwsize;
++	struct appl_pam_non_interactive_args *args;
++	const char *pwstring;
++	resp = malloc(sizeof(struct pam_response) * num_msg);
++	if (resp == NULL) {
++		return PAM_BUF_ERR;
++	}
++	args = appdata_ptr;
++	memset(resp, 0, sizeof(struct pam_response) * num_msg);
++	code = PAM_SUCCESS;
++	for (i = 0; i < num_msg; i++) {
++		message = &((*msg)[i]);
++		message = msg[i];
++		pwstring = NULL;
++		switch (message->msg_style) {
++		case PAM_TEXT_INFO:
++		case PAM_ERROR_MSG:
++			break;
++		case PAM_PROMPT_ECHO_ON:
++		case PAM_PROMPT_ECHO_OFF:
++			if (message->msg_style == PAM_PROMPT_ECHO_ON) {
++				/* assume "user" */
++				pwstring = args->user;
++			} else {
++				/* assume "password" */
++				pwstring = args->password;
++			}
++			if ((pwstring != NULL) && (pwstring[0] != '\0')) {
++				pwsize = strlen(pwstring);
++				resp[i].resp = malloc(pwsize + 1);
++				if (resp[i].resp == NULL) {
++					resp[i].resp_retcode = PAM_BUF_ERR;
++				} else {
++					memcpy(resp[i].resp, pwstring, pwsize);
++					resp[i].resp[pwsize] = '\0';
++					resp[i].resp_retcode = PAM_SUCCESS;
++				}
++			} else {
++				resp[i].resp_retcode = PAM_CONV_ERR;
++				code = PAM_CONV_ERR;
++			}
++			break;
++		default:
++			break;
++		}
++	}
++	*presp = resp;
++	return code;
++}
++static int
++appl_pam_start(const char *service, int interactive,
++	       const char *login_username,
++	       const char *non_interactive_password,
++	       const char *hostname,
++	       const char *ruser,
++	       const char *tty)
++{
++	static int exit_handler_registered;
++	static struct appl_pam_non_interactive_args args;
++	int ret = 0;
++	if (appl_pam_started &&
++	    (strcmp(login_username, appl_pam_user) != 0)) {
++		appl_pam_cleanup();
++		appl_pam_user = NULL;
++	}
++	if (!appl_pam_started) {
++#ifdef DEBUG
++		printf("Starting PAM up (service=\"%s\",user=\"%s\").\n",
++		       service, login_username);
++#endif
++		memset(&appl_pam_conv, 0, sizeof(appl_pam_conv));
++		appl_pam_conv.conv = interactive ?
++				     &appl_pam_interactive_converse :
++				     &appl_pam_non_interactive_converse;
++		memset(&args, 0, sizeof(args));
++		args.user = strdup(login_username);
++		args.password = non_interactive_password ?
++				strdup(non_interactive_password) :
++				NULL;
++		appl_pam_conv.appdata_ptr = &args;
++		ret = pam_start(service, login_username,
++				&appl_pam_conv, &appl_pamh);
++		if (ret == 0) {
++			if (hostname != NULL) {
++#ifdef DEBUG
++				printf("Setting PAM_RHOST to \"%s\".\n", hostname);
++#endif
++				pam_set_item(appl_pamh, PAM_RHOST, hostname);
++			}
++			if (ruser != NULL) {
++#ifdef DEBUG
++				printf("Setting PAM_RUSER to \"%s\".\n", ruser);
++#endif
++				pam_set_item(appl_pamh, PAM_RUSER, ruser);
++			}
++			if (tty != NULL) {
++#ifdef DEBUG
++				printf("Setting PAM_TTY to \"%s\".\n", tty);
++#endif
++				pam_set_item(appl_pamh, PAM_TTY, tty);
++			}
++			if (!exit_handler_registered &&
++			    (atexit(appl_pam_cleanup) != 0)) {
++				pam_end(appl_pamh, 0);
++				appl_pamh = NULL;
++				ret = -1;
++			} else {
++				appl_pam_started = 1;
++				appl_pam_starter = getpid();
++				appl_pam_user = strdup(login_username);
++				exit_handler_registered = 1;
++			}
++		}
++	}
++	return ret;
++}
++int
++appl_pam_acct_mgmt(const char *service, int interactive,
++		   const char *login_username,
++		   const char *non_interactive_password,
++		   const char *hostname,
++		   const char *ruser,
++		   const char *tty)
++{
++	int ret;
++	appl_pam_pwchange_required = 0;
++	ret = appl_pam_start(service, interactive, login_username,
++			     non_interactive_password, hostname, ruser, tty);
++	if (ret == 0) {
++#ifdef DEBUG
++		printf("Calling pam_acct_mgmt().\n");
++#endif
++		ret = pam_acct_mgmt(appl_pamh, 0);
++		switch (ret) {
++		case PAM_IGNORE:
++			ret = 0;
++			break;
++		case PAM_NEW_AUTHTOK_REQD:
++			appl_pam_pwchange_required = 1;
++			ret = 0;
++			break;
++		default:
++			break;
++		}
++	}
++	return ret;
++}
++int
++appl_pam_requires_chauthtok(void)
++{
++	return appl_pam_pwchange_required;
++}
++int
++appl_pam_session_open(void)
++{
++	int ret = 0;
++	if (appl_pam_started) {
++#ifdef DEBUG
++		printf("Opening PAM session.\n");
++#endif
++		ret = pam_open_session(appl_pamh, 0);
++		if (ret == 0) {
++			appl_pam_session_opened = 1;
++		}
++	}
++	return ret;
++}
++int
++appl_pam_setenv(void)
++{
++	int ret = 0;
++#ifdef HAVE_PAM_GETENVLIST
++#ifdef HAVE_PUTENV
++	int i;
++	char **list;
++	if (appl_pam_started) {
++		list = pam_getenvlist(appl_pamh);
++		for (i = 0; ((list != NULL) && (list[i] != NULL)); i++) {
++#ifdef DEBUG
++			printf("Setting \"%s\" in environment.\n", list[i]);
++#endif
++			putenv(list[i]);
++		}
++	}
++#endif
++#endif
++	return ret;
++}
++int
++appl_pam_cred_init(void)
++{
++	int ret = 0;
++	if (appl_pam_started) {
++#ifdef DEBUG
++		printf("Initializing PAM credentials.\n");
++#endif
++		ret = pam_setcred(appl_pamh, PAM_ESTABLISH_CRED);
++		if (ret == 0) {
++			appl_pam_creds_initialized = 1;
++		}
++	}
++	return ret;
++}
++#endif
+diff --git a/src/clients/ksu/pam.h b/src/clients/ksu/pam.h
+new file mode 100644
+index 000000000..0ab76569c
+--- /dev/null
++++ b/src/clients/ksu/pam.h
+@@ -0,0 +1,57 @@
++/*
++ * src/clients/ksu/pam.h
++ *
++ * Copyright 2007,2009,2010 Red Hat, Inc.
++ *
++ * All Rights Reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ *
++ *  Redistributions of source code must retain the above copyright notice, this
++ *  list of conditions and the following disclaimer.
++ *
++ *  Redistributions in binary form must reproduce the above copyright notice,
++ *  this list of conditions and the following disclaimer in the documentation
++ *  and/or other materials provided with the distribution.
++ *
++ *  Neither the name of Red Hat, Inc. nor the names of its contributors may be
++ *  used to endorse or promote products derived from this software without
++ *  specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++ * POSSIBILITY OF SUCH DAMAGE.
++ * 
++ * Convenience wrappers for using PAM.
++ */
++
++#include <krb5.h>
++#ifdef HAVE_SECURITY_PAM_APPL_H
++#include <security/pam_appl.h>
++#endif
++
++#define USE_PAM_CONFIGURATION_KEYWORD "use_pam"
++
++#ifdef USE_PAM
++int appl_pam_enabled(krb5_context context, const char *section);
++int appl_pam_acct_mgmt(const char *service, int interactive,
++		       const char *local_username,
++		       const char *non_interactive_password,
++		       const char *hostname,
++		       const char *ruser,
++		       const char *tty);
++int appl_pam_requires_chauthtok(void);
++int appl_pam_session_open(void);
++int appl_pam_setenv(void);
++int appl_pam_cred_init(void);
++void appl_pam_cleanup(void);
++#endif
+diff --git a/src/configure.in b/src/configure.in
+index 037c9f316..daabd12c8 100644
+--- a/src/configure.in
++++ b/src/configure.in
+@@ -1336,6 +1336,8 @@ AC_SUBST([VERTO_VERSION])
+ 
+ AC_PATH_PROG(GROFF, groff)
+ 
++KRB5_WITH_PAM
++
+ # Make localedir work in autoconf 2.5x.
+ if test "${localedir+set}" != set; then
+     localedir='$(datadir)/locale'
diff --git a/SOURCES/krb5-1.13-dirsrv-accountlock.patch b/SOURCES/krb5-1.13-dirsrv-accountlock.patch
new file mode 100644
index 0000000..268c859
--- /dev/null
+++ b/SOURCES/krb5-1.13-dirsrv-accountlock.patch
@@ -0,0 +1,74 @@
+From f8404b502015b4a9806894d212462c63c3307fa8 Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Fri, 22 Apr 2016 10:01:15 -0400
+Subject: [PATCH] krb5-1.13-dirsrv-accountlock.patch
+
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/aclocal.m4                                    |  9 +++++++++
+ src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c      | 17 +++++++++++++++++
+ src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c |  3 +++
+ 3 files changed, 29 insertions(+)
+
+diff --git a/src/aclocal.m4 b/src/aclocal.m4
+index f5667c35f..2bfb99496 100644
+--- a/src/aclocal.m4
++++ b/src/aclocal.m4
+@@ -1656,6 +1656,15 @@ if test "$with_ldap" = yes; then
+   AC_MSG_NOTICE(enabling OpenLDAP database backend module support)
+   OPENLDAP_PLUGIN=yes
+ fi
++AC_ARG_WITH([dirsrv-account-locking],
++[  --with-dirsrv-account-locking       compile 389/Red Hat/Fedora/Netscape Directory Server database backend module],
++[case "$withval" in
++    yes | no) ;;
++    *)  AC_MSG_ERROR(Invalid option value --with-dirsrv-account-locking="$withval") ;;
++esac], with_dirsrv_account_locking=no)
++if test $with_dirsrv_account_locking = yes; then
++    AC_DEFINE(HAVE_DIRSRV_ACCOUNT_LOCKING,1,[Define if LDAP KDB interface should heed 389 DS's nsAccountLock attribute.])
++fi
+ ])dnl
+ dnl
+ dnl If libkeyutils exists (on Linux) include it and use keyring ccache
+diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c
+index 32efc4f54..af8b2db7b 100644
+--- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c
++++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c
+@@ -1674,6 +1674,23 @@ populate_krb5_db_entry(krb5_context context, krb5_ldap_context *ldap_context,
+     ret = krb5_dbe_update_tl_data(context, entry, &userinfo_tl_data);
+     if (ret)
+         goto cleanup;
++#ifdef HAVE_DIRSRV_ACCOUNT_LOCKING
++    {
++        krb5_timestamp              expiretime=0;
++        char                        *is_login_disabled=NULL;
++
++        /* LOGIN DISABLED */
++        ret = krb5_ldap_get_string(ld, ent, "nsAccountLock", &is_login_disabled,
++                                   &attr_present);
++        if (ret)
++            goto cleanup;
++        if (attr_present == TRUE) {
++            if (strcasecmp(is_login_disabled, "TRUE")== 0)
++                entry->attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
++            free (is_login_disabled);
++        }
++    }
++#endif
+ 
+     ret = krb5_read_tkt_policy(context, ldap_context, entry, tktpolname);
+     if (ret)
+diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c
+index d722dbfa6..5e8e9a897 100644
+--- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c
++++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c
+@@ -54,6 +54,9 @@ char     *principal_attributes[] = { "krbprincipalname",
+                                      "krbLastFailedAuth",
+                                      "krbLoginFailedCount",
+                                      "krbLastSuccessfulAuth",
++#ifdef HAVE_DIRSRV_ACCOUNT_LOCKING
++                                     "nsAccountLock",
++#endif
+                                      "krbLastPwdChange",
+                                      "krbLastAdminUnlock",
+                                      "krbPrincipalAuthInd",
diff --git a/SOURCES/krb5-1.15-beta1-buildconf.patch b/SOURCES/krb5-1.15-beta1-buildconf.patch
new file mode 100644
index 0000000..71e122d
--- /dev/null
+++ b/SOURCES/krb5-1.15-beta1-buildconf.patch
@@ -0,0 +1,66 @@
+From eda215b5fdf43de6d5e0ee3641bb4bb42728ab11 Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Wed, 4 Jan 2017 13:18:18 -0500
+Subject: [PATCH] krb5-1.15-beta1-buildconf.patch
+
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/build-tools/krb5-config.in | 7 +++++++
+ src/config/pre.in              | 2 +-
+ src/config/shlib.conf          | 5 +++--
+ 3 files changed, 11 insertions(+), 3 deletions(-)
+
+diff --git a/src/build-tools/krb5-config.in b/src/build-tools/krb5-config.in
+index c17cb5eb5..1891dea99 100755
+--- a/src/build-tools/krb5-config.in
++++ b/src/build-tools/krb5-config.in
+@@ -226,6 +226,13 @@ if test -n "$do_libs"; then
+ 	    -e 's#\$(PTHREAD_CFLAGS)#'"$PTHREAD_CFLAGS"'#' \
+ 	    -e 's#\$(CFLAGS)##'`
+ 
++    if test `dirname $libdir` = /usr ; then
++        lib_flags=`echo $lib_flags | sed -e "s#-L$libdir##" -e "s#$RPATH_FLAG$libdir##"`
++    fi
++    lib_flags=`echo $lib_flags | sed -e "s#-fPIE##g" -e "s#-pie##g"`
++    lib_flags=`echo $lib_flags | sed -e "s#-Wl,-z,relro##g"`
++    lib_flags=`echo $lib_flags | sed -e "s#-Wl,-z,now##g"`
++
+     if test $library = 'kdb'; then
+ 	lib_flags="$lib_flags -lkdb5 $KDB5_DB_LIB"
+ 	library=krb5
+diff --git a/src/config/pre.in b/src/config/pre.in
+index fcea229bd..d961b5621 100644
+--- a/src/config/pre.in
++++ b/src/config/pre.in
+@@ -185,7 +185,7 @@ INSTALL_PROGRAM=@INSTALL_PROGRAM@ $(INSTALL_STRIP)
+ INSTALL_SCRIPT=@INSTALL_PROGRAM@
+ INSTALL_DATA=@INSTALL_DATA@
+ INSTALL_SHLIB=@INSTALL_SHLIB@
+-INSTALL_SETUID=$(INSTALL) $(INSTALL_STRIP) -m 4755 -o root
++INSTALL_SETUID=$(INSTALL) $(INSTALL_STRIP) -m 4755
+ ## This is needed because autoconf will sometimes define @exec_prefix@ to be
+ ## ${prefix}.
+ prefix=@prefix@
+diff --git a/src/config/shlib.conf b/src/config/shlib.conf
+index 3e4af6c02..2b20c3fda 100644
+--- a/src/config/shlib.conf
++++ b/src/config/shlib.conf
+@@ -423,7 +423,7 @@ mips-*-netbsd*)
+ 	# Linux ld doesn't default to stuffing the SONAME field...
+ 	# Use objdump -x to examine the fields of the library
+ 	# UNDEF_CHECK is suppressed by --enable-asan
+-	LDCOMBINE='$(CC) -shared -fPIC -Wl,-h,$(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT) $(UNDEF_CHECK)'
++	LDCOMBINE='$(CC) -shared -fPIC -Wl,-h,$(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT) $(UNDEF_CHECK)  -Wl,-z,relro -Wl,--warn-shared-textrel'
+ 	UNDEF_CHECK='-Wl,--no-undefined'
+ 	# $(EXPORT_CHECK) runs export-check.pl when in maintainer mode.
+ 	LDCOMBINE_TAIL='-Wl,--version-script binutils.versions $(EXPORT_CHECK)'
+@@ -435,7 +435,8 @@ mips-*-netbsd*)
+ 	SHLIB_EXPFLAGS='$(SHLIB_RPATH_FLAGS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)'
+ 	PROFFLAGS=-pg
+ 	PROG_RPATH_FLAGS='$(RPATH_FLAG)$(PROG_RPATH)'
+-	CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) $(LDFLAGS)'
++	CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) -pie -Wl,-z,relro -Wl,-z,now $(LDFLAGS)'
++	INSTALL_SHLIB='${INSTALL} -m755'
+ 	CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)'
+ 	CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CXXFLAGS) $(LDFLAGS)'
+ 	CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(LDFLAGS)'
diff --git a/SOURCES/krb5-1.15-beta1-selinux-label.patch b/SOURCES/krb5-1.15-beta1-selinux-label.patch
new file mode 100644
index 0000000..0cc22e8
--- /dev/null
+++ b/SOURCES/krb5-1.15-beta1-selinux-label.patch
@@ -0,0 +1,1034 @@
+From 71fe21b5aeac1834df824ff5c6475e653ceb8b6b Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Wed, 4 Jan 2017 13:17:28 -0500
+Subject: [PATCH] krb5-1.15-beta1-selinux-label.patch
+
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/aclocal.m4                                     |  49 +++
+ src/build-tools/krb5-config.in                     |   3 +-
+ src/config/pre.in                                  |   3 +-
+ src/configure.in                                   |   2 +
+ src/include/k5-int.h                               |   1 +
+ src/include/k5-label.h                             |  32 ++
+ src/include/krb5/krb5.hin                          |   6 +
+ src/kadmin/dbutil/dump.c                           |  11 +-
+ src/kdc/main.c                                     |   2 +-
+ src/lib/kadm5/logger.c                             |   4 +-
+ src/lib/kdb/kdb_log.c                              |   2 +-
+ src/lib/krb5/ccache/cc_dir.c                       |  26 +-
+ src/lib/krb5/keytab/kt_file.c                      |   4 +-
+ src/lib/krb5/os/trace.c                            |   2 +-
+ src/lib/krb5/rcache/rc_dfl.c                       |  13 +
+ src/plugins/kdb/db2/adb_openclose.c                |   2 +-
+ src/plugins/kdb/db2/kdb_db2.c                      |   4 +-
+ src/plugins/kdb/db2/libdb2/btree/bt_open.c         |   3 +-
+ src/plugins/kdb/db2/libdb2/hash/hash.c             |   3 +-
+ src/plugins/kdb/db2/libdb2/recno/rec_open.c        |   4 +-
+ .../kdb/ldap/ldap_util/kdb5_ldap_services.c        |  11 +-
+ src/slave/kpropd.c                                 |   9 +
+ src/util/profile/prof_file.c                       |   3 +-
+ src/util/support/Makefile.in                       |   3 +-
+ src/util/support/selinux.c                         | 406 +++++++++++++++++++++
+ 25 files changed, 587 insertions(+), 21 deletions(-)
+ create mode 100644 src/include/k5-label.h
+ create mode 100644 src/util/support/selinux.c
+
+diff --git a/src/aclocal.m4 b/src/aclocal.m4
+index 508e5fe90..607859f17 100644
+--- a/src/aclocal.m4
++++ b/src/aclocal.m4
+@@ -89,6 +89,7 @@ AC_SUBST_FILE(libnodeps_frag)
+ dnl
+ KRB5_AC_PRAGMA_WEAK_REF
+ WITH_LDAP
++KRB5_WITH_SELINUX
+ KRB5_LIB_PARAMS
+ KRB5_AC_INITFINI
+ KRB5_AC_ENABLE_THREADS
+@@ -1742,3 +1743,51 @@ AC_SUBST(PAM_LIBS)
+ AC_SUBST(PAM_MAN)
+ AC_SUBST(NON_PAM_MAN)
+ ])dnl
++dnl
++dnl Use libselinux to set file contexts on newly-created files.
++dnl
++AC_DEFUN(KRB5_WITH_SELINUX,[
++AC_ARG_WITH(selinux,[AC_HELP_STRING(--with-selinux,[compile with SELinux labeling support])],
++           withselinux="$withval",withselinux=auto)
++old_LIBS="$LIBS"
++if test "$withselinux" != no ; then
++       AC_MSG_RESULT([checking for libselinux...])
++       SELINUX_LIBS=
++       AC_CHECK_HEADERS(selinux/selinux.h selinux/label.h)
++       if test "x$ac_cv_header_selinux_selinux_h" != xyes ; then
++               if test "$withselinux" = auto ; then
++                       AC_MSG_RESULT([Unable to locate selinux/selinux.h.])
++                       withselinux=no
++               else
++                       AC_MSG_ERROR([Unable to locate selinux/selinux.h.])
++               fi
++       fi
++
++       LIBS=
++       unset ac_cv_func_setfscreatecon
++       AC_CHECK_FUNCS(setfscreatecon selabel_open)
++       if test "x$ac_cv_func_setfscreatecon" = xno ; then
++               AC_CHECK_LIB(selinux,setfscreatecon)
++               unset ac_cv_func_setfscreatecon
++               AC_CHECK_FUNCS(setfscreatecon selabel_open)
++               if test "x$ac_cv_func_setfscreatecon" = xyes ; then
++                       SELINUX_LIBS="$LIBS"
++               else
++                       if test "$withselinux" = auto ; then
++                               AC_MSG_RESULT([Unable to locate libselinux.])
++                               withselinux=no
++                       else
++                               AC_MSG_ERROR([Unable to locate libselinux.])
++                       fi
++               fi
++       fi
++       if test "$withselinux" != no ; then
++               AC_MSG_NOTICE([building with SELinux labeling support])
++               AC_DEFINE(USE_SELINUX,1,[Define if Kerberos-aware tools should set SELinux file contexts when creating files.])
++               SELINUX_LIBS="$LIBS"
++		EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS krb5int_labeled_open krb5int_labeled_fopen krb5int_push_fscreatecon_for krb5int_pop_fscreatecon"
++       fi
++fi
++LIBS="$old_LIBS"
++AC_SUBST(SELINUX_LIBS)
++])dnl
+diff --git a/src/build-tools/krb5-config.in b/src/build-tools/krb5-config.in
+index f6184da3f..c17cb5eb5 100755
+--- a/src/build-tools/krb5-config.in
++++ b/src/build-tools/krb5-config.in
+@@ -41,6 +41,7 @@ DL_LIB='@DL_LIB@'
+ DEFCCNAME='@DEFCCNAME@'
+ DEFKTNAME='@DEFKTNAME@'
+ DEFCKTNAME='@DEFCKTNAME@'
++SELINUX_LIBS='@SELINUX_LIBS@'
+ 
+ LIBS='@LIBS@'
+ GEN_LIB=@GEN_LIB@
+@@ -255,7 +256,7 @@ if test -n "$do_libs"; then
+     fi
+ 
+     # If we ever support a flag to generate output suitable for static
+-    # linking, we would output "-lkrb5support $GEN_LIB $LIBS $DL_LIB"
++    # linking, we would output "-lkrb5support $GEN_LIB $LIBS $SELINUX_LIBS $DL_LIB"
+     # here.
+ 
+     echo $lib_flags
+diff --git a/src/config/pre.in b/src/config/pre.in
+index e0626320c..fcea229bd 100644
+--- a/src/config/pre.in
++++ b/src/config/pre.in
+@@ -177,6 +177,7 @@ LD = $(PURE) @LD@
+ KRB_INCLUDES = -I$(BUILDTOP)/include -I$(top_srcdir)/include
+ LDFLAGS = @LDFLAGS@
+ LIBS = @LIBS@
++SELINUX_LIBS=@SELINUX_LIBS@
+ 
+ INSTALL=@INSTALL@
+ INSTALL_STRIP=
+@@ -399,7 +400,7 @@ SUPPORT_LIB			= -l$(SUPPORT_LIBNAME)
+ # HESIOD_LIBS is -lhesiod...
+ HESIOD_LIBS	= @HESIOD_LIBS@
+ 
+-KRB5_BASE_LIBS	= $(KRB5_LIB) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB) $(GEN_LIB) $(LIBS) $(DL_LIB)
++KRB5_BASE_LIBS	= $(KRB5_LIB) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB) $(GEN_LIB) $(LIBS) $(SELINUX_LIBS) $(DL_LIB)
+ KDB5_LIBS	= $(KDB5_LIB) $(GSSRPC_LIBS)
+ GSS_LIBS	= $(GSS_KRB5_LIB)
+ # needs fixing if ever used on Mac OS X!
+diff --git a/src/configure.in b/src/configure.in
+index daabd12c8..acf3a458b 100644
+--- a/src/configure.in
++++ b/src/configure.in
+@@ -1338,6 +1338,8 @@ AC_PATH_PROG(GROFF, groff)
+ 
+ KRB5_WITH_PAM
+ 
++KRB5_WITH_SELINUX
++
+ # Make localedir work in autoconf 2.5x.
+ if test "${localedir+set}" != set; then
+     localedir='$(datadir)/locale'
+diff --git a/src/include/k5-int.h b/src/include/k5-int.h
+index 64991738a..173cb0264 100644
+--- a/src/include/k5-int.h
++++ b/src/include/k5-int.h
+@@ -128,6 +128,7 @@ typedef unsigned char   u_char;
+ 
+ 
+ #include "k5-platform.h"
++#include "k5-label.h"
+ 
+ #define KRB5_KDB_MAX_LIFE       (60*60*24) /* one day */
+ #define KRB5_KDB_MAX_RLIFE      (60*60*24*7) /* one week */
+diff --git a/src/include/k5-label.h b/src/include/k5-label.h
+new file mode 100644
+index 000000000..dfaaa847c
+--- /dev/null
++++ b/src/include/k5-label.h
+@@ -0,0 +1,32 @@
++#ifndef _KRB5_LABEL_H
++#define _KRB5_LABEL_H
++
++#ifdef THREEPARAMOPEN
++#undef THREEPARAMOPEN
++#endif
++#ifdef WRITABLEFOPEN
++#undef WRITABLEFOPEN
++#endif
++
++/* Wrapper functions which help us create files and directories with the right
++ * context labels. */
++#ifdef USE_SELINUX
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <stdio.h>
++#include <unistd.h>
++FILE *krb5int_labeled_fopen(const char *path, const char *mode);
++int krb5int_labeled_creat(const char *path, mode_t mode);
++int krb5int_labeled_open(const char *path, int flags, ...);
++int krb5int_labeled_mkdir(const char *path, mode_t mode);
++int krb5int_labeled_mknod(const char *path, mode_t mode, dev_t device);
++#define THREEPARAMOPEN(x,y,z) krb5int_labeled_open(x,y,z)
++#define WRITABLEFOPEN(x,y) krb5int_labeled_fopen(x,y)
++void *krb5int_push_fscreatecon_for(const char *pathname);
++void krb5int_pop_fscreatecon(void *previous);
++#else
++#define WRITABLEFOPEN(x,y) fopen(x,y)
++#define THREEPARAMOPEN(x,y,z) open(x,y,z)
++#endif
++#endif
+diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
+index ac22f4c55..cf60d6c41 100644
+--- a/src/include/krb5/krb5.hin
++++ b/src/include/krb5/krb5.hin
+@@ -87,6 +87,12 @@
+ #define THREEPARAMOPEN(x,y,z) open(x,y,z)
+ #endif
+ 
++#if KRB5_PRIVATE
++#ifndef WRITABLEFOPEN
++#define WRITABLEFOPEN(x,y) fopen(x,y)
++#endif
++#endif
++
+ #define KRB5_OLD_CRYPTO
+ 
+ #include <stdlib.h>
+diff --git a/src/kadmin/dbutil/dump.c b/src/kadmin/dbutil/dump.c
+index f7889bd23..cad53cfbf 100644
+--- a/src/kadmin/dbutil/dump.c
++++ b/src/kadmin/dbutil/dump.c
+@@ -148,12 +148,21 @@ create_ofile(char *ofile, char **tmpname)
+ {
+     int fd = -1;
+     FILE *f;
++#ifdef USE_SELINUX
++    void *selabel;
++#endif
+ 
+     *tmpname = NULL;
+     if (asprintf(tmpname, "%s-XXXXXX", ofile) < 0)
+         goto error;
+ 
++#ifdef USE_SELINUX
++    selabel = krb5int_push_fscreatecon_for(ofile);
++#endif
+     fd = mkstemp(*tmpname);
++#ifdef USE_SELINUX
++    krb5int_pop_fscreatecon(selabel);
++#endif
+     if (fd == -1)
+         goto error;
+ 
+@@ -194,7 +203,7 @@ prep_ok_file(krb5_context context, char *file_name, int *fd)
+         return 0;
+     }
+ 
+-    *fd = open(file_ok, O_WRONLY | O_CREAT | O_TRUNC, 0600);
++    *fd = THREEPARAMOPEN(file_ok, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+     if (*fd == -1) {
+         com_err(progname, errno, _("while creating 'ok' file, '%s'"), file_ok);
+         exit_status++;
+diff --git a/src/kdc/main.c b/src/kdc/main.c
+index ebc852bba..a4dffb29a 100644
+--- a/src/kdc/main.c
++++ b/src/kdc/main.c
+@@ -872,7 +872,7 @@ write_pid_file(const char *path)
+     FILE *file;
+     unsigned long pid;
+ 
+-    file = fopen(path, "w");
++    file = WRITABLEFOPEN(path, "w");
+     if (file == NULL)
+         return errno;
+     pid = (unsigned long) getpid();
+diff --git a/src/lib/kadm5/logger.c b/src/lib/kadm5/logger.c
+index ce79fabf7..c53a5743f 100644
+--- a/src/lib/kadm5/logger.c
++++ b/src/lib/kadm5/logger.c
+@@ -414,7 +414,7 @@ krb5_klog_init(krb5_context kcontext, char *ename, char *whoami, krb5_boolean do
+                      */
+                     append = (cp[4] == ':') ? O_APPEND : 0;
+                     if (append || cp[4] == '=') {
+-                        fd = open(&cp[5], O_CREAT | O_WRONLY | append,
++                        fd = THREEPARAMOPEN(&cp[5], O_CREAT | O_WRONLY | append,
+                                   S_IRUSR | S_IWUSR | S_IRGRP);
+                         if (fd != -1)
+                             f = fdopen(fd, append ? "a" : "w");
+@@ -918,7 +918,7 @@ krb5_klog_reopen(krb5_context kcontext)
+              * In case the old logfile did not get moved out of the
+              * way, open for append to prevent squashing the old logs.
+              */
+-            f = fopen(log_control.log_entries[lindex].lfu_fname, "a+");
++            f = WRITABLEFOPEN(log_control.log_entries[lindex].lfu_fname, "a+");
+             if (f) {
+                 set_cloexec_file(f);
+                 log_control.log_entries[lindex].lfu_filep = f;
+diff --git a/src/lib/kdb/kdb_log.c b/src/lib/kdb/kdb_log.c
+index 766d3002a..6466417b7 100644
+--- a/src/lib/kdb/kdb_log.c
++++ b/src/lib/kdb/kdb_log.c
+@@ -476,7 +476,7 @@ ulog_map(krb5_context context, const char *logname, uint32_t ulogentries)
+     int ulogfd = -1;
+ 
+     if (stat(logname, &st) == -1) {
+-        ulogfd = open(logname, O_RDWR | O_CREAT, 0600);
++        ulogfd = THREEPARAMOPEN(logname, O_RDWR | O_CREAT, 0600);
+         if (ulogfd == -1)
+             return errno;
+ 
+diff --git a/src/lib/krb5/ccache/cc_dir.c b/src/lib/krb5/ccache/cc_dir.c
+index bba64e516..73f0fe62d 100644
+--- a/src/lib/krb5/ccache/cc_dir.c
++++ b/src/lib/krb5/ccache/cc_dir.c
+@@ -183,10 +183,19 @@ write_primary_file(const char *primary_path, const char *contents)
+     char *newpath = NULL;
+     FILE *fp = NULL;
+     int fd = -1, status;
++#ifdef USE_SELINUX
++    void *selabel;
++#endif
+ 
+     if (asprintf(&newpath, "%s.XXXXXX", primary_path) < 0)
+         return ENOMEM;
++#ifdef USE_SELINUX
++    selabel = krb5int_push_fscreatecon_for(primary_path);
++#endif
+     fd = mkstemp(newpath);
++#ifdef USE_SELINUX
++    krb5int_pop_fscreatecon(selabel);
++#endif
+     if (fd < 0)
+         goto cleanup;
+ #ifdef HAVE_CHMOD
+@@ -221,10 +230,23 @@ static krb5_error_code
+ verify_dir(krb5_context context, const char *dirname)
+ {
+     struct stat st;
++    int status;
++#ifdef USE_SELINUX
++    void *selabel;
++#endif
+ 
+     if (stat(dirname, &st) < 0) {
+-        if (errno == ENOENT && mkdir(dirname, S_IRWXU) == 0)
+-            return 0;
++        if (errno == ENOENT) {
++#ifdef USE_SELINUX
++            selabel = krb5int_push_fscreatecon_for(dirname);
++#endif
++            status = mkdir(dirname, S_IRWXU);
++#ifdef USE_SELINUX
++            krb5int_pop_fscreatecon(selabel);
++#endif
++            if (status == 0)
++                return 0;
++        }
+         k5_setmsg(context, KRB5_FCC_NOFILE,
+                   _("Credential cache directory %s does not exist"),
+                   dirname);
+diff --git a/src/lib/krb5/keytab/kt_file.c b/src/lib/krb5/keytab/kt_file.c
+index 6a42f267d..674d88bab 100644
+--- a/src/lib/krb5/keytab/kt_file.c
++++ b/src/lib/krb5/keytab/kt_file.c
+@@ -1022,14 +1022,14 @@ krb5_ktfileint_open(krb5_context context, krb5_keytab id, int mode)
+ 
+     KTCHECKLOCK(id);
+     errno = 0;
+-    KTFILEP(id) = fopen(KTFILENAME(id),
++    KTFILEP(id) = WRITABLEFOPEN(KTFILENAME(id),
+                         (mode == KRB5_LOCKMODE_EXCLUSIVE) ? "rb+" : "rb");
+     if (!KTFILEP(id)) {
+         if ((mode == KRB5_LOCKMODE_EXCLUSIVE) && (errno == ENOENT)) {
+             /* try making it first time around */
+             k5_create_secure_file(context, KTFILENAME(id));
+             errno = 0;
+-            KTFILEP(id) = fopen(KTFILENAME(id), "rb+");
++            KTFILEP(id) = WRITABLEFOPEN(KTFILENAME(id), "rb+");
+             if (!KTFILEP(id))
+                 goto report_errno;
+             writevno = 1;
+diff --git a/src/lib/krb5/os/trace.c b/src/lib/krb5/os/trace.c
+index 83c8d4db8..a19246128 100644
+--- a/src/lib/krb5/os/trace.c
++++ b/src/lib/krb5/os/trace.c
+@@ -397,7 +397,7 @@ krb5_set_trace_filename(krb5_context context, const char *filename)
+     fd = malloc(sizeof(*fd));
+     if (fd == NULL)
+         return ENOMEM;
+-    *fd = open(filename, O_WRONLY|O_CREAT|O_APPEND, 0600);
++    *fd = THREEPARAMOPEN(filename, O_WRONLY|O_CREAT|O_APPEND, 0600);
+     if (*fd == -1) {
+         free(fd);
+         return errno;
+diff --git a/src/lib/krb5/rcache/rc_dfl.c b/src/lib/krb5/rcache/rc_dfl.c
+index c4d2c744d..c0f12ed9d 100644
+--- a/src/lib/krb5/rcache/rc_dfl.c
++++ b/src/lib/krb5/rcache/rc_dfl.c
+@@ -794,6 +794,9 @@ krb5_rc_dfl_expunge_locked(krb5_context context, krb5_rcache id)
+     krb5_error_code retval = 0;
+     krb5_rcache tmp;
+     krb5_deltat lifespan = t->lifespan;  /* save original lifespan */
++#ifdef USE_SELINUX
++    void *selabel;
++#endif
+ 
+     if (! t->recovering) {
+         name = t->name;
+@@ -815,7 +818,17 @@ krb5_rc_dfl_expunge_locked(krb5_context context, krb5_rcache id)
+     retval = krb5_rc_resolve(context, tmp, 0);
+     if (retval)
+         goto cleanup;
++#ifdef USE_SELINUX
++    if (t->d.fn != NULL)
++        selabel = krb5int_push_fscreatecon_for(t->d.fn);
++    else
++        selabel = NULL;
++#endif
+     retval = krb5_rc_initialize(context, tmp, lifespan);
++#ifdef USE_SELINUX
++    if (selabel != NULL)
++        krb5int_pop_fscreatecon(selabel);
++#endif
+     if (retval)
+         goto cleanup;
+     for (q = t->a; q; q = q->na) {
+diff --git a/src/plugins/kdb/db2/adb_openclose.c b/src/plugins/kdb/db2/adb_openclose.c
+index 7db30a33b..2b9d01921 100644
+--- a/src/plugins/kdb/db2/adb_openclose.c
++++ b/src/plugins/kdb/db2/adb_openclose.c
+@@ -152,7 +152,7 @@ osa_adb_init_db(osa_adb_db_t *dbp, char *filename, char *lockfilename,
+          * needs be open read/write so that write locking can work with
+          * POSIX systems
+          */
+-        if ((lockp->lockinfo.lockfile = fopen(lockfilename, "r+")) == NULL) {
++        if ((lockp->lockinfo.lockfile = WRITABLEFOPEN(lockfilename, "r+")) == NULL) {
+             /*
+              * maybe someone took away write permission so we could only
+              * get shared locks?
+diff --git a/src/plugins/kdb/db2/kdb_db2.c b/src/plugins/kdb/db2/kdb_db2.c
+index 4c4036eb4..d90bdeaba 100644
+--- a/src/plugins/kdb/db2/kdb_db2.c
++++ b/src/plugins/kdb/db2/kdb_db2.c
+@@ -694,8 +694,8 @@ ctx_create_db(krb5_context context, krb5_db2_context *dbc)
+     if (retval)
+         return retval;
+ 
+-    dbc->db_lf_file = open(dbc->db_lf_name, O_CREAT | O_RDWR | O_TRUNC,
+-                           0600);
++    dbc->db_lf_file = THREEPARAMOPEN(dbc->db_lf_name,
++                                     O_CREAT | O_RDWR | O_TRUNC, 0600);
+     if (dbc->db_lf_file < 0) {
+         retval = errno;
+         goto cleanup;
+diff --git a/src/plugins/kdb/db2/libdb2/btree/bt_open.c b/src/plugins/kdb/db2/libdb2/btree/bt_open.c
+index 2977b17f3..d5809a5a9 100644
+--- a/src/plugins/kdb/db2/libdb2/btree/bt_open.c
++++ b/src/plugins/kdb/db2/libdb2/btree/bt_open.c
+@@ -60,6 +60,7 @@ static char sccsid[] = "@(#)bt_open.c	8.11 (Berkeley) 11/2/95";
+ #include <string.h>
+ #include <unistd.h>
+ 
++#include "k5-int.h"
+ #include "db-int.h"
+ #include "btree.h"
+ 
+@@ -203,7 +204,7 @@ __bt_open(fname, flags, mode, openinfo, dflags)
+ 			goto einval;
+ 		}
+ 
+-		if ((t->bt_fd = open(fname, flags | O_BINARY, mode)) < 0)
++		if ((t->bt_fd = THREEPARAMOPEN(fname, flags | O_BINARY, mode)) < 0)
+ 			goto err;
+ 
+ 	} else {
+diff --git a/src/plugins/kdb/db2/libdb2/hash/hash.c b/src/plugins/kdb/db2/libdb2/hash/hash.c
+index 76f5d4709..1fa8b8389 100644
+--- a/src/plugins/kdb/db2/libdb2/hash/hash.c
++++ b/src/plugins/kdb/db2/libdb2/hash/hash.c
+@@ -51,6 +51,7 @@ static char sccsid[] = "@(#)hash.c	8.12 (Berkeley) 11/7/95";
+ #include <assert.h>
+ #endif
+ 
++#include "k5-int.h"
+ #include "db-int.h"
+ #include "hash.h"
+ #include "page.h"
+@@ -140,7 +141,7 @@ __kdb2_hash_open(file, flags, mode, info, dflags)
+ 		new_table = 1;
+ 	}
+ 	if (file) {
+-		if ((hashp->fp = open(file, flags|O_BINARY, mode)) == -1)
++		if ((hashp->fp = THREEPARAMOPEN(file, flags|O_BINARY, mode)) == -1)
+ 			RETURN_ERROR(errno, error0);
+ 		(void)fcntl(hashp->fp, F_SETFD, 1);
+ 	}
+diff --git a/src/plugins/kdb/db2/libdb2/recno/rec_open.c b/src/plugins/kdb/db2/libdb2/recno/rec_open.c
+index d8b26e701..b0daa7c02 100644
+--- a/src/plugins/kdb/db2/libdb2/recno/rec_open.c
++++ b/src/plugins/kdb/db2/libdb2/recno/rec_open.c
+@@ -51,6 +51,7 @@ static char sccsid[] = "@(#)rec_open.c	8.12 (Berkeley) 11/18/94";
+ #include <stdio.h>
+ #include <unistd.h>
+ 
++#include "k5-int.h"
+ #include "db-int.h"
+ #include "recno.h"
+ 
+@@ -68,7 +69,8 @@ __rec_open(fname, flags, mode, openinfo, dflags)
+ 	int rfd = -1, sverrno;
+ 
+ 	/* Open the user's file -- if this fails, we're done. */
+-	if (fname != NULL && (rfd = open(fname, flags | O_BINARY, mode)) < 0)
++	if (fname != NULL &&
++            (rfd = THREEPARAMOPEN(fname, flags | O_BINARY, mode)) < 0)
+ 		return (NULL);
+ 
+ 	if (fname != NULL && fcntl(rfd, F_SETFD, 1) == -1) {
+diff --git a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
+index 022156a5e..3d6994c67 100644
+--- a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
++++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
+@@ -203,7 +203,7 @@ kdb5_ldap_stash_service_password(int argc, char **argv)
+ 
+     /* set password in the file */
+     old_mode = umask(0177);
+-    pfile = fopen(file_name, "a+");
++    pfile = WRITABLEFOPEN(file_name, "a+");
+     if (pfile == NULL) {
+         com_err(me, errno, _("Failed to open file %s: %s"), file_name,
+                 strerror (errno));
+@@ -244,6 +244,9 @@ kdb5_ldap_stash_service_password(int argc, char **argv)
+          * Delete the existing entry and add the new entry
+          */
+         FILE *newfile;
++#ifdef USE_SELINUX
++        void *selabel;
++#endif
+ 
+         mode_t omask;
+ 
+@@ -255,7 +258,13 @@ kdb5_ldap_stash_service_password(int argc, char **argv)
+         }
+ 
+         omask = umask(077);
++#ifdef USE_SELINUX
++        selabel = krb5int_push_fscreatecon_for(file_name);
++#endif
+         newfile = fopen(tmp_file, "w");
++#ifdef USE_SELINUX
++        krb5int_pop_fscreatecon(selabel);
++#endif
+         umask (omask);
+         if (newfile == NULL) {
+             com_err(me, errno, _("Error creating file %s"), tmp_file);
+diff --git a/src/slave/kpropd.c b/src/slave/kpropd.c
+index 056c31a42..b78c3d9e5 100644
+--- a/src/slave/kpropd.c
++++ b/src/slave/kpropd.c
+@@ -464,6 +464,9 @@ doit(int fd)
+     krb5_enctype etype;
+     int database_fd;
+     char host[INET6_ADDRSTRLEN + 1];
++#ifdef USE_SELINUX
++    void *selabel;
++#endif
+ 
+     signal_wrapper(SIGALRM, alarm_handler);
+     alarm(params.iprop_resync_timeout);
+@@ -520,9 +523,15 @@ doit(int fd)
+         free(name);
+         exit(1);
+     }
++#ifdef USE_SELINUX
++    selabel = krb5int_push_fscreatecon_for(file);
++#endif
+     omask = umask(077);
+     lock_fd = open(temp_file_name, O_RDWR | O_CREAT, 0600);
+     (void)umask(omask);
++#ifdef USE_SELINUX
++    krb5int_pop_fscreatecon(selabel);
++#endif
+     retval = krb5_lock_file(kpropd_context, lock_fd,
+                             KRB5_LOCKMODE_EXCLUSIVE | KRB5_LOCKMODE_DONTBLOCK);
+     if (retval) {
+diff --git a/src/util/profile/prof_file.c b/src/util/profile/prof_file.c
+index 907c119bb..0f5462aea 100644
+--- a/src/util/profile/prof_file.c
++++ b/src/util/profile/prof_file.c
+@@ -33,6 +33,7 @@
+ #endif
+ 
+ #include "k5-platform.h"
++#include "k5-label.h"
+ 
+ struct global_shared_profile_data {
+     /* This is the head of the global list of shared trees */
+@@ -423,7 +424,7 @@ static errcode_t write_data_to_file(prf_data_t data, const char *outfile,
+ 
+     errno = 0;
+ 
+-    f = fopen(new_file, "w");
++    f = WRITABLEFOPEN(new_file, "w");
+     if (!f) {
+         retval = errno;
+         if (retval == 0)
+diff --git a/src/util/support/Makefile.in b/src/util/support/Makefile.in
+index 6239e4176..17bcd2a67 100644
+--- a/src/util/support/Makefile.in
++++ b/src/util/support/Makefile.in
+@@ -69,6 +69,7 @@ IPC_SYMS= \
+ 
+ STLIBOBJS= \
+ 	threads.o \
++	selinux.o \
+ 	init-addrinfo.o \
+ 	plugins.o \
+ 	errors.o \
+@@ -148,7 +149,7 @@ SRCS=\
+ 
+ SHLIB_EXPDEPS =
+ # Add -lm if dumping thread stats, for sqrt.
+-SHLIB_EXPLIBS= $(LIBS) $(DL_LIB)
++SHLIB_EXPLIBS= $(LIBS) $(SELINUX_LIBS) $(DL_LIB)
+ 
+ DEPLIBS=
+ 
+diff --git a/src/util/support/selinux.c b/src/util/support/selinux.c
+new file mode 100644
+index 000000000..230263421
+--- /dev/null
++++ b/src/util/support/selinux.c
+@@ -0,0 +1,406 @@
++/*
++ * Copyright 2007,2008,2009,2011,2012,2013,2016 Red Hat, Inc.  All Rights Reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ *
++ *  Redistributions of source code must retain the above copyright notice, this
++ *  list of conditions and the following disclaimer.
++ *
++ *  Redistributions in binary form must reproduce the above copyright notice,
++ *  this list of conditions and the following disclaimer in the documentation
++ *  and/or other materials provided with the distribution.
++ *
++ *  Neither the name of Red Hat, Inc. nor the names of its contributors may be
++ *  used to endorse or promote products derived from this software without
++ *  specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++ * POSSIBILITY OF SUCH DAMAGE.
++ *
++ * File-opening wrappers for creating correctly-labeled files.  So far, we can
++ * assume that this is Linux-specific, so we make many simplifying assumptions.
++ */
++
++#include "../../include/autoconf.h"
++
++#ifdef USE_SELINUX
++
++#include <k5-label.h>
++#include <k5-platform.h>
++
++#include <sys/types.h>
++#include <sys/stat.h>
++
++#include <errno.h>
++#include <fcntl.h>
++#include <limits.h>
++#include <pthread.h>
++#include <stdarg.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++
++#include <selinux/selinux.h>
++#include <selinux/context.h>
++#include <selinux/label.h>
++
++/* #define DEBUG 1 */
++static void
++debug_log(const char *fmt, ...)
++{
++#ifdef DEBUG
++    va_list ap;
++    va_start(ap, str);
++    if (isatty(fileno(stderr))) {
++        vfprintf(stderr, fmt, ap);
++    }
++    va_end(ap);
++#endif
++
++    return;
++}
++
++/* Mutex used to serialize use of the process-global file creation context. */
++k5_mutex_t labeled_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
++
++/* Make sure we finish initializing that mutex before attempting to use it. */
++k5_once_t labeled_once = K5_ONCE_INIT;
++static void
++label_mutex_init(void)
++{
++    k5_mutex_finish_init(&labeled_mutex);
++}
++
++static struct selabel_handle *selabel_ctx;
++static time_t selabel_last_changed;
++
++MAKE_FINI_FUNCTION(cleanup_fscreatecon);
++
++static void
++cleanup_fscreatecon(void)
++{
++    if (selabel_ctx != NULL) {
++        selabel_close(selabel_ctx);
++        selabel_ctx = NULL;
++    }
++}
++
++static security_context_t
++push_fscreatecon(const char *pathname, mode_t mode)
++{
++    security_context_t previous, configuredsc, currentsc, derivedsc;
++    context_t current, derived;
++    const char *fullpath, *currentuser;
++    char *genpath;
++
++    previous = configuredsc = currentsc = derivedsc = NULL;
++    current = derived = NULL;
++    genpath = NULL;
++
++    fullpath = pathname;
++
++    if (!is_selinux_enabled()) {
++        goto fail;
++    }
++
++    if (getfscreatecon(&previous) != 0) {
++        goto fail;
++    }
++
++    /* Canonicalize pathname */
++    if (pathname[0] != '/') {
++        char *wd;
++        size_t len;
++        len = 0;
++
++        wd = getcwd(NULL, len);
++        if (wd == NULL) {
++            goto fail;
++        }
++
++        len = strlen(wd) + 1 + strlen(pathname) + 1;
++        genpath = malloc(len);
++        if (genpath == NULL) {
++            free(wd);
++            goto fail;
++        }
++
++        sprintf(genpath, "%s/%s", wd, pathname);
++        free(wd);
++        fullpath = genpath;
++    }
++
++    debug_log("Looking up context for \"%s\"(%05o).\n", fullpath, mode);
++
++    /* Check whether context file has changed under us */
++    if (selabel_ctx != NULL || selabel_last_changed == 0) {
++        const char *cpath;
++        struct stat st;
++        int i = -1;
++
++        cpath = selinux_file_context_path();
++        if (cpath == NULL || (i = stat(cpath, &st)) != 0 ||
++            st.st_mtime != selabel_last_changed) {
++            cleanup_fscreatecon();
++
++            selabel_last_changed = i ? time(NULL) : st.st_mtime;
++        }
++    }
++
++    if (selabel_ctx == NULL) {
++        selabel_ctx = selabel_open(SELABEL_CTX_FILE, NULL, 0);
++    }
++
++    if (selabel_ctx != NULL &&
++        selabel_lookup(selabel_ctx, &configuredsc, fullpath, mode) != 0) {
++        goto fail;
++    }
++
++    if (genpath != NULL) {
++        free(genpath);
++        genpath = NULL;
++    }
++
++    if (configuredsc == NULL) {
++        goto fail;
++    }
++
++    getcon(&currentsc);
++
++    /* AAAAAAAA */
++    if (currentsc != NULL) {
++        derived = context_new(configuredsc);
++
++        if (derived != NULL) {
++            current = context_new(currentsc);
++
++            if (current != NULL) {
++                currentuser = context_user_get(current);
++
++                if (currentuser != NULL) {
++                    if (context_user_set(derived,
++                                         currentuser) == 0) {
++                        derivedsc = context_str(derived);
++
++                        if (derivedsc != NULL) {
++                            freecon(configuredsc);
++                            configuredsc = strdup(derivedsc);
++                        }
++                    }
++                }
++
++                context_free(current);
++            }
++
++            context_free(derived);
++        }
++
++        freecon(currentsc);
++    }
++
++    debug_log("Setting file creation context to \"%s\".\n", configuredsc);
++    if (setfscreatecon(configuredsc) != 0) {
++        debug_log("Unable to determine current context.\n");
++        goto fail;
++    }
++
++    freecon(configuredsc);
++    return previous;
++
++fail:
++    if (previous != NULL) {
++        freecon(previous);
++    }
++    if (genpath != NULL) {
++        free(genpath);
++    }
++    if (configuredsc != NULL) {
++        freecon(configuredsc);
++    }
++
++    cleanup_fscreatecon();
++    return NULL;
++}
++
++static void
++pop_fscreatecon(security_context_t previous)
++{
++    if (!is_selinux_enabled()) {
++        return;
++    }
++
++    if (previous != NULL) {
++        debug_log("Resetting file creation context to \"%s\".\n", previous);
++    } else {
++        debug_log("Resetting file creation context to default.\n");
++    }
++
++    /* NULL resets to default */
++    setfscreatecon(previous);
++
++    if (previous != NULL) {
++        freecon(previous);
++    }
++
++    /* Need to clean this up here otherwise it leaks */
++    cleanup_fscreatecon();
++}
++
++void *
++krb5int_push_fscreatecon_for(const char *pathname)
++{
++    struct stat st;
++    void *retval;
++
++    k5_once(&labeled_once, label_mutex_init);
++    k5_mutex_lock(&labeled_mutex);
++
++    if (stat(pathname, &st) != 0) {
++        st.st_mode = S_IRUSR | S_IWUSR;
++    }
++
++    retval = push_fscreatecon(pathname, st.st_mode);
++    return retval ? retval : (void *) -1;
++}
++
++void
++krb5int_pop_fscreatecon(void *con)
++{
++    if (con != NULL) {
++        pop_fscreatecon((con == (void *) -1) ? NULL : con);
++        k5_mutex_unlock(&labeled_mutex);
++    }
++}
++
++FILE *
++krb5int_labeled_fopen(const char *path, const char *mode)
++{
++    FILE *fp;
++    int errno_save;
++    security_context_t ctx;
++
++    if ((strcmp(mode, "r") == 0) ||
++        (strcmp(mode, "rb") == 0)) {
++        return fopen(path, mode);
++    }
++
++    k5_once(&labeled_once, label_mutex_init);
++    k5_mutex_lock(&labeled_mutex);
++    ctx = push_fscreatecon(path, 0);
++
++    fp = fopen(path, mode);
++    errno_save = errno;
++
++    pop_fscreatecon(ctx);
++    k5_mutex_unlock(&labeled_mutex);
++
++    errno = errno_save;
++    return fp;
++}
++
++int
++krb5int_labeled_creat(const char *path, mode_t mode)
++{
++    int fd;
++    int errno_save;
++    security_context_t ctx;
++
++    k5_once(&labeled_once, label_mutex_init);
++    k5_mutex_lock(&labeled_mutex);
++    ctx = push_fscreatecon(path, 0);
++
++    fd = creat(path, mode);
++    errno_save = errno;
++
++    pop_fscreatecon(ctx);
++    k5_mutex_unlock(&labeled_mutex);
++
++    errno = errno_save;
++    return fd;
++}
++
++int
++krb5int_labeled_mknod(const char *path, mode_t mode, dev_t dev)
++{
++    int ret;
++    int errno_save;
++    security_context_t ctx;
++
++    k5_once(&labeled_once, label_mutex_init);
++    k5_mutex_lock(&labeled_mutex);
++    ctx = push_fscreatecon(path, mode);
++
++    ret = mknod(path, mode, dev);
++    errno_save = errno;
++
++    pop_fscreatecon(ctx);
++    k5_mutex_unlock(&labeled_mutex);
++
++    errno = errno_save;
++    return ret;
++}
++
++int
++krb5int_labeled_mkdir(const char *path, mode_t mode)
++{
++    int ret;
++    int errno_save;
++    security_context_t ctx;
++
++    k5_once(&labeled_once, label_mutex_init);
++    k5_mutex_lock(&labeled_mutex);
++    ctx = push_fscreatecon(path, S_IFDIR);
++
++    ret = mkdir(path, mode);
++    errno_save = errno;
++
++    pop_fscreatecon(ctx);
++    k5_mutex_unlock(&labeled_mutex);
++
++    errno = errno_save;
++    return ret;
++}
++
++int
++krb5int_labeled_open(const char *path, int flags, ...)
++{
++    int fd;
++    int errno_save;
++    security_context_t ctx;
++    mode_t mode;
++    va_list ap;
++
++    if ((flags & O_CREAT) == 0) {
++        return open(path, flags);
++    }
++
++    k5_once(&labeled_once, label_mutex_init);
++    k5_mutex_lock(&labeled_mutex);
++    ctx = push_fscreatecon(path, 0);
++
++    va_start(ap, flags);
++    mode = va_arg(ap, mode_t);
++    fd = open(path, flags, mode);
++    va_end(ap);
++
++    errno_save = errno;
++
++    pop_fscreatecon(ctx);
++    k5_mutex_unlock(&labeled_mutex);
++
++    errno = errno_save;
++    return fd;
++}
++
++#endif /* USE_SELINUX */
diff --git a/SOURCES/krb5-1.15.1.tar.gz.asc b/SOURCES/krb5-1.15.1.tar.gz.asc
new file mode 100644
index 0000000..15dad17
--- /dev/null
+++ b/SOURCES/krb5-1.15.1.tar.gz.asc
@@ -0,0 +1,17 @@
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1
+
+iQIVAwUAWLmTPQy6CFdfg3LfAQKWgBAAnahZbh9rFKBor8lz8icPdOAPyF7QP9xM
+aDlxANUePQxN7BG68MPNL0A4/kIB1QHVl07t9vEnPBMKuF6RfVS1Sl9LYvxAF5Gf
+pp5nbOOYf8bs5V/isMYjAu61D4Hyr/anKYZsbOTcR+c5CI4UXAB1uaznGcTUT+vL
+MJie3ebWxJOPhv2HhkMU4BMkBxnGs1ONNsmU7yvCnbf6kgxpLaVITDzKGDrjIdQu
+ej6HZQpwidUZDRICFks6pY4ASfSBEzUGswnnhdsq3uvUhxm5F6jn097K+3nIydVT
+SgbJX4sBn5iJBBNumRZZ3OAovwBN+6XKM54ELWgyeQCY3Pk2P8qTojIWaqNJtyuf
+q0FSR16rWKq7ZRxHwgc93YETmzIkdil5WFnTpAtqVR5RFOL/GNGh5Dwn645mC3XY
+WOFBaVhX1libl+GApJjwriIzZ3e+gtaqsYa/A473BGJL+mKCp8xOfeTXeZCTCVgo
+x32NhUcXTxr6RRCq/WTEH6reu4oU+VkostCv3yknHOHatYbzh2DDni+mUVnUpGw8
+WEh3XNjHrjPQ5Vr1F7/aIhmG80QXVKWfJgrVVTwUXjk8+v0enTWudsKYVanvPZDN
+Yo1Jqrgc7tfRJpirVpJKxS0rNt/ES2I4heLkoz8j/DnDNqNmKV718jWVAms6jjuR
+Cunhql8OvtU=
+=Tvr2
+-----END PGP SIGNATURE-----
diff --git a/SOURCES/krb5-1.3.1-dns.patch b/SOURCES/krb5-1.3.1-dns.patch
new file mode 100644
index 0000000..761722f
--- /dev/null
+++ b/SOURCES/krb5-1.3.1-dns.patch
@@ -0,0 +1,22 @@
+From e48799ea02841461af9a97a8f490bcf4f4ac5666 Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Fri, 22 Apr 2016 09:59:05 -0400
+Subject: [PATCH] krb5-1.3.1-dns.patch
+
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/aclocal.m4 | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/aclocal.m4 b/src/aclocal.m4
+index 607859f17..f5667c35f 100644
+--- a/src/aclocal.m4
++++ b/src/aclocal.m4
+@@ -703,6 +703,7 @@ AC_HELP_STRING([--with-netlib=LIBS], use user defined resolver library),
+ 	LIBS="$LIBS $withval"
+ 	AC_MSG_RESULT("netlib will use \'$withval\'")
+   fi
++  KRB5_AC_ENABLE_DNS
+ ],dnl
+ [AC_LIBRARY_NET]
+ )])dnl
diff --git a/SOURCES/krb5-1.9-debuginfo.patch b/SOURCES/krb5-1.9-debuginfo.patch
new file mode 100644
index 0000000..e74a6a9
--- /dev/null
+++ b/SOURCES/krb5-1.9-debuginfo.patch
@@ -0,0 +1,37 @@
+From 502177c9256aa52ee3f7812f5127619475b3c7a5 Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Fri, 22 Apr 2016 10:02:40 -0400
+Subject: [PATCH] krb5-1.9-debuginfo.patch
+
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/kadmin/cli/Makefile.in                 | 5 +++++
+ src/plugins/kdb/ldap/ldap_util/Makefile.in | 2 +-
+ 2 files changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/src/kadmin/cli/Makefile.in b/src/kadmin/cli/Makefile.in
+index adfea6e2b..d1327e400 100644
+--- a/src/kadmin/cli/Makefile.in
++++ b/src/kadmin/cli/Makefile.in
+@@ -37,3 +37,8 @@ clean-unix::
+ # CC_LINK is not meant for compilation and this use may break in the future.
+ datetest: getdate.c
+ 	$(CC_LINK) $(ALL_CFLAGS) -DTEST -o datetest getdate.c
++
++%.c: %.y
++	$(RM) y.tab.c $@
++	$(YACC.y) $< 
++	$(CP) y.tab.c $@
+diff --git a/src/plugins/kdb/ldap/ldap_util/Makefile.in b/src/plugins/kdb/ldap/ldap_util/Makefile.in
+index 8669c2436..a22f23c02 100644
+--- a/src/plugins/kdb/ldap/ldap_util/Makefile.in
++++ b/src/plugins/kdb/ldap/ldap_util/Makefile.in
+@@ -20,7 +20,7 @@ $(PROG): $(OBJS) $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIB) $(GETDATE)
+ getdate.c: $(GETDATE)
+ 	$(RM) getdate.c y.tab.c
+ 	$(YACC) $(GETDATE)
+-	$(MV) y.tab.c getdate.c
++	$(CP) y.tab.c getdate.c
+ 
+ install:
+ 	$(INSTALL_PROGRAM) $(PROG) ${DESTDIR}$(ADMIN_BINDIR)/$(PROG)
diff --git a/SOURCES/krb5-krb5kdc.conf b/SOURCES/krb5-krb5kdc.conf
new file mode 100644
index 0000000..eadeb51
--- /dev/null
+++ b/SOURCES/krb5-krb5kdc.conf
@@ -0,0 +1 @@
+d /var/run/krb5kdc 0755 root root
diff --git a/SOURCES/krb5-kvno-230379.patch b/SOURCES/krb5-kvno-230379.patch
new file mode 100644
index 0000000..2005ab9
--- /dev/null
+++ b/SOURCES/krb5-kvno-230379.patch
@@ -0,0 +1,54 @@
+From 16c9dd3d2f8d74958495674f4906626a74ef8c12 Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Fri, 22 Apr 2016 10:03:07 -0400
+Subject: [PATCH] krb5-kvno-230379.patch
+
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ src/kadmin/ktutil/ktutil.c    | 5 +++--
+ src/lib/krb5/keytab/kt_file.c | 2 +-
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/src/kadmin/ktutil/ktutil.c b/src/kadmin/ktutil/ktutil.c
+index ef16d37a5..64a6d6ab1 100644
+--- a/src/kadmin/ktutil/ktutil.c
++++ b/src/kadmin/ktutil/ktutil.c
+@@ -140,7 +140,7 @@ void ktutil_add_entry(argc, argv)
+     char *princ = NULL;
+     char *enctype = NULL;
+     krb5_kvno kvno = 0;
+-    int use_pass = 0, use_key = 0, i;
++    int use_pass = 0, use_key = 0, use_kvno = 0, i;
+ 
+     for (i = 1; i < argc; i++) {
+         if ((strlen(argv[i]) == 2) && !strncmp(argv[i], "-p", 2)) {
+@@ -149,6 +149,7 @@ void ktutil_add_entry(argc, argv)
+         }
+         if ((strlen(argv[i]) == 2) && !strncmp(argv[i], "-k", 2)) {
+             kvno = (krb5_kvno) atoi(argv[++i]);
++            use_kvno++;
+             continue;
+         }
+         if ((strlen(argv[i]) == 2) && !strncmp(argv[i], "-e", 2)) {
+@@ -165,7 +166,7 @@ void ktutil_add_entry(argc, argv)
+         }
+     }
+ 
+-    if (argc != 8 || !(princ && kvno && enctype) || (use_pass+use_key != 1)) {
++    if (argc != 8 || !(princ && use_kvno && enctype) || (use_pass+use_key != 1)) {
+         fprintf(stderr, _("usage: %s (-key | -password) -p principal "
+                           "-k kvno -e enctype\n"), argv[0]);
+         return;
+diff --git a/src/lib/krb5/keytab/kt_file.c b/src/lib/krb5/keytab/kt_file.c
+index 674d88bab..131549ffe 100644
+--- a/src/lib/krb5/keytab/kt_file.c
++++ b/src/lib/krb5/keytab/kt_file.c
+@@ -377,7 +377,7 @@ krb5_ktfile_get_entry(krb5_context context, krb5_keytab id,
+              * Otherwise, remember that we were here so we can return the right
+              * error, and free the new.
+              */
+-            if (new_entry.vno == kvno) {
++            if (new_entry.vno == kvno || new_entry.vno == IGNORE_VNO) {
+                 krb5_kt_free_entry(context, &cur_entry);
+                 cur_entry = new_entry;
+                 if (new_entry.vno == kvno)
diff --git a/SOURCES/krb5.conf b/SOURCES/krb5.conf
new file mode 100644
index 0000000..77d794a
--- /dev/null
+++ b/SOURCES/krb5.conf
@@ -0,0 +1,25 @@
+# Configuration snippets may be placed in this directory as well
+includedir /etc/krb5.conf.d/
+
+[logging]
+ default = FILE:/var/log/krb5libs.log
+ kdc = FILE:/var/log/krb5kdc.log
+ admin_server = FILE:/var/log/kadmind.log
+
+[libdefaults]
+ dns_lookup_realm = false
+ ticket_lifetime = 24h
+ renew_lifetime = 7d
+ forwardable = true
+ rdns = false
+# default_realm = EXAMPLE.COM
+
+[realms]
+# EXAMPLE.COM = {
+#  kdc = kerberos.example.com
+#  admin_server = kerberos.example.com
+# }
+
+[domain_realm]
+# .example.com = EXAMPLE.COM
+# example.com = EXAMPLE.COM
diff --git a/SOURCES/krb5_prop.portreserve b/SOURCES/krb5_prop.portreserve
new file mode 100644
index 0000000..54eeff2
--- /dev/null
+++ b/SOURCES/krb5_prop.portreserve
@@ -0,0 +1 @@
+krb5_prop/tcp
diff --git a/SOURCES/krb5kdc.init b/SOURCES/krb5kdc.init
new file mode 100755
index 0000000..3462ca6
--- /dev/null
+++ b/SOURCES/krb5kdc.init
@@ -0,0 +1,102 @@
+#!/bin/bash
+#
+# krb5kdc      Start and stop the Kerberos 5 servers.
+#
+# chkconfig:   - 35 65
+# description: Kerberos 5 is a trusted third-party authentication system.  \
+#	       This script starts and stops the server that Kerberos 5 \
+#	       clients need to connect to in order to obtain credentials.
+# processname: krb5kdc
+# config: /etc/sysconfig/krb5kdc
+# pidfile: /var/run/krb5kdc.pid
+#
+
+### BEGIN INIT INFO
+# Provides: krb5kdc
+# Required-Start: $local_fs $network
+# Required-Stop: $local_fs $network
+# Should-Start: portreserve
+# Default-Start:
+# Default-Stop: 0 1 2 3 4 5 6
+# Short-Description: start and stop the Kerberos 5 KDC
+# Description: The krb5kdc is the Kerberos 5 key distribution center, which \
+#              issues credentials to Kerberos 5 clients.
+### END INIT INFO
+
+# Get config.
+. /etc/sysconfig/network
+
+# Get config.
+[ -r /etc/sysconfig/krb5kdc ] && . /etc/sysconfig/krb5kdc
+
+# Source function library.
+. /etc/rc.d/init.d/functions
+
+RETVAL=0
+prog="Kerberos 5 KDC"
+krb5kdc=/usr/sbin/krb5kdc
+pidfile=/var/run/krb5kdc.pid
+PATH=/usr/lib64/krb5:/usr/lib/krb5:"$PATH"
+
+# Shell functions to cut down on useless shell instances.
+start() {
+	[ -x $krb5kdc ] || exit 5
+	echo -n $"Starting $prog: "
+	# tell portreserve to release the kerberos-iv port
+	[ -x /sbin/portrelease ] && /sbin/portrelease kerberos-iv &>/dev/null || :
+	daemon ${krb5kdc} ${KRB5REALM:+-r ${KRB5REALM}} -P $pidfile $KRB5KDC_ARGS
+	RETVAL=$?
+	echo
+	if test $RETVAL -ne 0 ; then
+	    if status ${krb5kdc} > /dev/null ; then
+		RETVAL=0
+	    fi
+	fi
+	[ $RETVAL = 0 ] && touch /var/lock/subsys/krb5kdc
+}
+stop() {
+	echo -n $"Stopping $prog: "
+	killproc ${krb5kdc}
+	RETVAL=$?
+	echo
+	[ $RETVAL = 0 ] && rm -f /var/lock/subsys/krb5kdc
+}
+reload() {
+	echo -n $"Reopening $prog log file: "
+	killproc ${krb5kdc} -HUP
+        RETVAL=$?
+	echo
+}
+
+# See how we were called.
+case "$1" in
+  start)
+	start
+	;;
+  stop)
+	stop
+	;;
+  restart)
+	stop
+	start
+	;;
+  reload)
+        reload
+        ;;
+  status)
+	status ${krb5kdc}
+        RETVAL=$?
+	;;
+  condrestart)
+	if [ -f /var/lock/subsys/krb5kdc ] ; then
+		stop
+		start
+	fi
+	;;
+  *)
+	echo $"Usage: $0 {start|stop|status|reload|restart|condrestart}"
+	RETVAL=2
+	;;
+esac
+
+exit $RETVAL
diff --git a/SOURCES/krb5kdc.logrotate b/SOURCES/krb5kdc.logrotate
new file mode 100644
index 0000000..1100ed3
--- /dev/null
+++ b/SOURCES/krb5kdc.logrotate
@@ -0,0 +1,9 @@
+/var/log/krb5kdc.log {
+    missingok
+    notifempty
+    monthly
+    rotate 12
+    postrotate
+	/bin/kill -HUP `cat /var/run/krb5kdc.pid 2>/dev/null` 2> /dev/null || true
+    endscript
+}
diff --git a/SOURCES/krb5kdc.service b/SOURCES/krb5kdc.service
new file mode 100644
index 0000000..bc49204
--- /dev/null
+++ b/SOURCES/krb5kdc.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=Kerberos 5 KDC
+After=syslog.target network.target
+
+[Service]
+Type=forking
+PIDFile=/var/run/krb5kdc.pid
+EnvironmentFile=-/etc/sysconfig/krb5kdc
+ExecStart=/usr/sbin/krb5kdc -P /var/run/krb5kdc.pid $KRB5KDC_ARGS
+ExecReload=/bin/kill -HUP $MAINPID
+
+[Install]
+WantedBy=multi-user.target
diff --git a/SOURCES/krb5kdc.sysconfig b/SOURCES/krb5kdc.sysconfig
new file mode 100644
index 0000000..791216d
--- /dev/null
+++ b/SOURCES/krb5kdc.sysconfig
@@ -0,0 +1 @@
+KRB5KDC_ARGS=
diff --git a/SOURCES/ksu.pamd b/SOURCES/ksu.pamd
new file mode 100644
index 0000000..66f5b2c
--- /dev/null
+++ b/SOURCES/ksu.pamd
@@ -0,0 +1,4 @@
+#%PAM-1.0
+auth    include  su
+account include  su
+session include  su
diff --git a/SOURCES/noport.c b/SOURCES/noport.c
new file mode 100644
index 0000000..22088eb
--- /dev/null
+++ b/SOURCES/noport.c
@@ -0,0 +1,111 @@
+#define _GNU_SOURCE
+#include <sys/socket.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netinet/in.h>
+
+static int
+port_is_okay(unsigned short port)
+{
+	char *p, *q;
+	long l;
+
+	p = getenv("NOPORT");
+	while ((p != NULL) && (*p != '\0')) {
+		l = strtol(p, &q, 10);
+		if ((q == NULL) || (q == p)) {
+			break;
+		}
+		if ((*q == '\0') || (*q == ',')) {
+			if (port == l) {
+				errno = ECONNREFUSED;
+				return -1;
+			}
+		}
+		p = q;
+		p += strspn(p, ",");
+	}
+	return 0;
+}
+
+int
+connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
+{
+	unsigned short port;
+	static int (*next_connect)(int, const struct sockaddr *, socklen_t);
+
+	if (next_connect == NULL) {
+		next_connect = dlsym(RTLD_NEXT, "connect");
+		if (next_connect == NULL) {
+			errno = ENOSYS;
+			return -1;
+		}
+	}
+
+	if (getenv("NOPORT") == NULL) {
+		return next_connect(sockfd, addr, addrlen);
+	}
+
+	switch (addr->sa_family) {
+	case AF_INET:
+		port = ntohs(((struct sockaddr_in *)addr)->sin_port);
+		if (port_is_okay(port) != 0) {
+			return -1;
+		}
+		break;
+	case AF_INET6:
+		port = ntohs(((struct sockaddr_in6 *)addr)->sin6_port);
+		if (port_is_okay(port) != 0) {
+			return -1;
+		}
+		break;
+	default:
+		break;
+	}
+	return next_connect(sockfd, addr, addrlen);
+}
+
+ssize_t
+sendto(int sockfd, const void *buf, size_t len, int flags,
+       const struct sockaddr *dest_addr, socklen_t addrlen)
+{
+	unsigned short port;
+	static int (*next_sendto)(int, const void *, size_t, int,
+				  const struct sockaddr *, socklen_t);
+
+	if (next_sendto == NULL) {
+		next_sendto = dlsym(RTLD_NEXT, "sendto");
+		if (next_sendto == NULL) {
+			errno = ENOSYS;
+			return -1;
+		}
+	}
+
+	if (getenv("NOPORT") == NULL) {
+		return next_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
+	}
+
+	if (dest_addr != NULL) {
+		switch (dest_addr->sa_family) {
+		case AF_INET:
+			port = ((struct sockaddr_in *)dest_addr)->sin_port;
+			port = ntohs(port);
+			if (port_is_okay(port) != 0) {
+				return -1;
+			}
+			break;
+		case AF_INET6:
+			port = ((struct sockaddr_in6 *)dest_addr)->sin6_port;
+			port = ntohs(port);
+			if (port_is_okay(port) != 0) {
+				return -1;
+			}
+			break;
+		default:
+			break;
+		}
+	}
+	return next_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
+}
diff --git a/SPECS/krb5.spec b/SPECS/krb5.spec
new file mode 100644
index 0000000..e3a5ee2
--- /dev/null
+++ b/SPECS/krb5.spec
@@ -0,0 +1,3563 @@
+%global WITH_DIRSRV 1
+
+# Set this so that find-lang.sh will recognize the .po files.
+%global gettext_domain mit-krb5
+
+# Guess where the -libs subpackage's docs are going to go.
+%define libsdocdir %{?_pkgdocdir:%(echo %{_pkgdocdir} | sed -e s,krb5,krb5-libs,g)}%{!?_pkgdocdir:%{_docdir}/%{name}-libs-%{version}}
+
+# Figure out where the default ccache lives and how we set it.
+%global configured_default_ccache_name KEYRING:persistent:%%{uid}
+
+Summary: The Kerberos network authentication system
+Name: krb5
+Version: 1.15.1
+Release: 18%{?dist}
+
+# - Maybe we should explode from the now-available-to-everybody tarball instead?
+# http://web.mit.edu/kerberos/dist/krb5/1.13/krb5-1.13.2-signed.tar
+# - The sources below are stored in a lookaside cache. Upload with
+# $ rhpkg upload krb5-1.13.2.tar.gz krb5-1.13.2.tar.gz.asc # (and don't
+# remove, otherwise you can't go back or branch from a previous point)
+Source0: krb5-%{version}.tar.gz
+Source1: krb5-%{version}.tar.gz.asc
+Source3: krb5-%{version}-pdfs.tar
+Source2: kprop.service
+Source4: kadmin.service
+Source5: krb5kdc.service
+Source6: krb5.conf
+Source7: _kpropd
+Source8: _kadmind
+Source10: kdc.conf
+Source11: kadm5.acl
+Source19: krb5kdc.sysconfig
+Source20: kadmin.sysconfig
+Source21: kprop.sysconfig
+Source29: ksu.pamd
+Source31: kerberos-adm.portreserve
+Source32: krb5_prop.portreserve
+Source33: krb5kdc.logrotate
+Source34: kadmind.logrotate
+Source36: kpropd.init
+Source37: kadmind.init
+Source38: krb5kdc.init
+Source39: krb5-krb5kdc.conf
+
+BuildRequires: cmake xz
+# Carry this locally until it's available in a packaged form.
+Source100: nss_wrapper-0.0-20140204195100.git3d58327.tar.xz
+Source101: noport.c
+Source102: socket_wrapper-0.0-20140204194748.gitf3b2ece.tar.xz
+
+Patch136: krb5-1.12.1-pam.patch
+Patch137: krb5-1.15-beta1-selinux-label.patch
+Patch138: krb5-1.12-ksu-path.patch
+Patch139: krb5-1.12-ktany.patch
+Patch140: krb5-1.15-beta1-buildconf.patch
+Patch141: krb5-1.3.1-dns.patch
+Patch142: krb5-1.12-api.patch
+Patch143: krb5-1.13-dirsrv-accountlock.patch
+Patch144: krb5-1.9-debuginfo.patch
+Patch145: krb5-kvno-230379.patch
+Patch146: krb5-1.11-run_user_0.patch
+Patch147: krb5-1.11-kpasswdtest.patch
+Patch148: Improve-PKINIT-UPN-SAN-matching.patch
+Patch149: Deindent-crypto_retrieve_X509_sans.patch
+Patch152: Add-certauth-pluggable-interface.patch
+Patch153: Correct-error-handling-bug-in-prior-commit.patch
+Patch154: Add-the-client_name-kdcpreauth-callback.patch
+Patch155: Use-the-canonical-client-principal-name-for-OTP.patch
+Patch156: Remove-incomplete-PKINIT-OCSP-support.patch
+Patch157: Add-support-to-query-the-SSF-of-a-GSS-context.patch
+Patch158: Add-k5test-expected_msg-expected_trace.patch
+Patch159: Add-PKINIT-UPN-tests-to-t_pkinit.py.patch
+Patch160: Add-test-cert-generation-to-make-certs.sh.patch
+Patch161: Fix-make-certs.sh-for-OpenSSL-1.1.patch
+Patch162: Allow-clock-skew-in-krb5-gss_context_time.patch
+Patch163: Fix-in_clock_skew-and-use-it-in-AS-client-code.patch
+Patch164: Add-timestamp-helper-functions.patch
+Patch165: Make-timestamp-manipulations-y2038-safe.patch
+Patch166: Add-timestamp-tests.patch
+Patch167: Add-y2038-documentation.patch
+Patch168: Fix-more-time-manipulations-for-y2038.patch
+Patch169: Use-krb5_timestamp-where-appropriate.patch
+Patch170: Add-KDC-policy-pluggable-interface.patch
+Patch171: Fix-bugs-in-kdcpolicy-commit.patch
+Patch172: Prevent-KDC-unset-status-assertion-failures.patch
+Patch173: Convert-some-pkiDebug-messages-to-TRACE-macros.patch
+Patch174: Fix-certauth-built-in-module-returns.patch
+Patch175: Add-test-cert-with-no-extensions.patch
+Patch176: Expose-context-errors-in-pkinit_server_plugin_init.patch
+
+License: MIT
+URL: http://web.mit.edu/kerberos/www/
+Group: System Environment/Libraries
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+BuildRequires: autoconf, bison, flex, gawk, gettext, pkgconfig, sed
+BuildRequires: libcom_err-devel, libedit-devel, libss-devel
+BuildRequires: gzip, ncurses-devel
+BuildRequires: python-sphinx, texlive-pdftex
+
+# Taken from \usepackage directives produced by sphinx:
+BuildRequires: tex(babel.sty)
+BuildRequires: tex(bookmark.sty)
+BuildRequires: tex(fancybox.sty)
+BuildRequires: tex(fncychap.sty)
+BuildRequires: tex(fontenc.sty)
+BuildRequires: tex(framed.sty)
+BuildRequires: tex(hyperref.sty)
+BuildRequires: tex(ifthen.sty)
+BuildRequires: tex(inputenc.sty)
+BuildRequires: tex(longtable.sty)
+BuildRequires: tex(multirow.sty)
+BuildRequires: tex(times.sty)
+BuildRequires: tex(titlesec.sty)
+BuildRequires: tex(threeparttable.sty)
+BuildRequires: tex(wrapfig.sty)
+BuildRequires: tex(report.cls)
+
+# Typical fonts, and the commands which we need to have present.
+BuildRequires: texlive, texlive-latex, texlive-texmf-fonts
+BuildRequires: /usr/bin/pdflatex /usr/bin/makeindex
+BuildRequires: keyutils, keyutils-libs-devel >= 1.5.8
+BuildRequires: libselinux-devel
+BuildRequires: pam-devel
+BuildRequires: systemd-units
+# For the test framework.
+BuildRequires: perl, dejagnu, tcl-devel
+BuildRequires: net-tools, rpcbind
+BuildRequires: hostname
+BuildRequires: iproute
+
+# someday...
+%if 0%{?fedora} >= 9
+BuildRequires: python-pyrad
+%endif
+%if 0%{?fedora} >= 8
+%ifarch %{ix86} x86_64
+BuildRequires: yasm
+%endif
+%endif
+
+BuildRequires: openldap-devel
+BuildRequires: openssl-devel >= 0.9.8
+BuildRequires: libverto-devel
+
+%description
+Kerberos V5 is a trusted-third-party network authentication system,
+which can improve your network's security by eliminating the insecure
+practice of sending passwords over the network in unencrypted form.
+
+%package devel
+Summary: Development files needed to compile Kerberos 5 programs
+Group: Development/Libraries
+Requires: %{name}-libs%{?_isa} = %{version}-%{release}
+Requires: libkadm5%{?_isa} = %{version}-%{release}
+Requires: libcom_err-devel
+Requires: keyutils-libs-devel, libselinux-devel
+Requires: libverto-devel
+
+%description devel
+Kerberos is a network authentication system. The krb5-devel package
+contains the header files and libraries needed for compiling Kerberos
+5 programs. If you want to develop Kerberos-aware programs, you need
+to install this package.
+
+%package libs
+Summary: The non-admin shared libraries used by Kerberos 5
+Group: System Environment/Libraries
+Requires: coreutils, gawk, grep, sed
+Requires: keyutils-libs >= 1.5.8
+
+%description libs
+Kerberos is a network authentication system. The krb5-libs package
+contains the shared libraries needed by Kerberos 5. If you are using
+Kerberos, you need to install this package.
+
+%package server
+Group: System Environment/Daemons
+Summary: The KDC and related programs for Kerberos 5
+Requires: %{name}-libs%{?_isa} = %{version}-%{release}
+Requires(post): systemd-units
+Requires(preun): systemd-units
+Requires(postun): systemd-units
+# we drop files in its directory, but we don't want to own that directory
+Requires: logrotate
+# we specify /usr/share/dict/words as the default dict_file in kdc.conf
+Requires: /usr/share/dict/words
+# for run-time, and for parts of the test suite
+BuildRequires: libverto-module-base
+Requires: libverto-module-base
+%ifarch x86_64
+Obsoletes: krb5-server-1.11.3-49.el7.i686
+%endif
+%ifarch ppc64
+Obsoletes: krb5-server-1.11.3-49.el7.ppc
+%endif
+%ifarch s390x
+Obsoletes: krb5-server-1.11.3-49.el7.s390
+%endif
+Requires: libkadm5%{?_isa} = %{version}-%{release}
+
+%description server
+Kerberos is a network authentication system. The krb5-server package
+contains the programs that must be installed on a Kerberos 5 key
+distribution center (KDC).  If you are installing a Kerberos 5 KDC,
+you need to install this package (in other words, most people should
+NOT install this package).
+
+%package server-ldap
+Group: System Environment/Daemons
+Summary: The LDAP storage plugin for the Kerberos 5 KDC
+Requires: %{name}-server%{?_isa} = %{version}-%{release}
+Requires: %{name}-libs%{?_isa} = %{version}-%{release}
+Requires: libkadm5%{?_isa} = %{version}-%{release}
+%ifarch x86_64
+Obsoletes: krb5-server-ldap-1.11.3-49.el7.i686
+%endif
+%ifarch ppc64
+Obsoletes: krb5-server-ldap-1.11.3-49.el7.ppc
+%endif
+%ifarch s390x
+Obsoletes: krb5-server-ldap-1.11.3-49.el7.s390
+%endif
+
+%description server-ldap
+Kerberos is a network authentication system. The krb5-server package
+contains the programs that must be installed on a Kerberos 5 key
+distribution center (KDC).  If you are installing a Kerberos 5 KDC,
+and you wish to use a directory server to store the data for your
+realm, you need to install this package.
+
+%package workstation
+Summary: Kerberos 5 programs for use on workstations
+Group: System Environment/Base
+Requires: %{name}-libs%{?_isa} = %{version}-%{release}
+Requires: libkadm5%{?_isa} = %{version}-%{release}
+# mktemp is used by krb5-send-pr
+Requires: coreutils
+
+%description workstation
+Kerberos is a network authentication system. The krb5-workstation
+package contains the basic Kerberos programs (kinit, klist, kdestroy,
+kpasswd). If your network uses Kerberos, this package should be
+installed on every workstation.
+
+%package pkinit
+Summary: The PKINIT module for Kerberos 5
+Group: System Environment/Libraries
+Requires: %{name}-libs%{?_isa} = %{version}-%{release}
+Obsoletes: krb5-pkinit-openssl < %{version}-%{release}
+Provides: krb5-pkinit-openssl = %{version}-%{release}
+
+%description pkinit
+Kerberos is a network authentication system. The krb5-pkinit
+package contains the PKINIT plugin, which allows clients
+to obtain initial credentials from a KDC using a private key and a
+certificate.
+
+%package -n libkadm5
+Summary: Kerberos 5 Administrative libraries
+Group: System Environment/Base
+Requires: %{name}-libs%{?_isa} = %{version}-%{release}
+
+%description -n libkadm5
+Kerberos is a network authentication system. The libkadm5 package
+contains the libkadm5clnt and libkadm5serv shared objects, for use
+ONLY by kerberos itself. Do not depend on this package.
+
+%prep
+# Apply run_user_0 when the hard-wired or configured default location is
+# DIR:/run/user/%%{uid}/krb5cc.
+%setup -q -a 3 -a 100 -a 102
+%patch136 -p1 -b .krb5-1.12.1-pam
+%patch137 -p1 -b .krb5-1.15-beta1-selinux-label
+%patch138 -p1 -b .krb5-1.12-ksu-path
+%patch139 -p1 -b .krb5-1.12-ktany
+%patch140 -p1 -b .krb5-1.15-beta1-buildconf
+%patch141 -p1 -b .krb5-1.3.1-dns
+%patch142 -p1 -b .krb5-1.12-api
+%patch143 -p1 -b .krb5-1.13-dirsrv-accountlock
+%patch144 -p1 -b .krb5-1.9-debuginfo
+%patch145 -p1 -b .krb5-kvno-230379
+%patch146 -p1 -b .krb5-1.11-run_user_0
+%patch147 -p1 -b .krb5-1.11-kpasswdtest
+%patch148 -p1 -b .Improve-PKINIT-UPN-SAN-matching
+%patch149 -p1 -b .Deindent-crypto_retrieve_X509_sans
+%patch152 -p1 -b .Add-certauth-pluggable-interface
+%patch153 -p1 -b .Correct-error-handling-bug-in-prior-commit
+%patch154 -p1 -b .Add-the-client_name-kdcpreauth-callback
+%patch155 -p1 -b .Use-the-canonical-client-principal-name-for-OTP
+%patch156 -p1 -b .Remove-incomplete-PKINIT-OCSP-support
+%patch157 -p1 -b .Add-support-to-query-the-SSF-of-a-GSS-context
+%patch158 -p1 -b .Add-k5test-expected_msg-expected_trace
+%patch159 -p1 -b .Add-PKINIT-UPN-tests-to-t_pkinit.py
+%patch160 -p1 -b .Add-test-cert-generation-to-make-certs.sh
+%patch161 -p1 -b .Fix-make-certs.sh-for-OpenSSL-1.1
+%patch162 -p1 -b .Allow-clock-skew-in-krb5-gss_context_time
+%patch163 -p1 -b .Fix-in_clock_skew-and-use-it-in-AS-client-code
+%patch164 -p1 -b .Add-timestamp-helper-functions
+%patch165 -p1 -b .Make-timestamp-manipulations-y2038-safe
+%patch166 -p1 -b .Add-timestamp-tests
+%patch167 -p1 -b .Add-y2038-documentation
+%patch168 -p1 -b .Fix-more-time-manipulations-for-y2038
+%patch169 -p1 -b .Use-krb5_timestamp-where-appropriate
+%patch170 -p1 -b .Add-KDC-policy-pluggable-interface
+%patch171 -p1 -b .Fix-bugs-in-kdcpolicy-commit
+%patch172 -p1 -b .Prevent-KDC-unset-status-assertion-failures
+%patch173 -p1 -b .Convert-some-pkiDebug-messages-to-TRACE-macros
+%patch174 -p1 -b .Fix-certauth-built-in-module-returns
+%patch175 -p1 -b .Add-test-cert-with-no-extensions
+%patch176 -p1 -b .Expose-context-errors-in-pkinit_server_plugin_init
+
+ln NOTICE LICENSE
+
+chmod u+x src/util/paste-kdcproxy.py
+# Take the execute bit off of documentation.
+chmod -x doc/ccapi/*.html
+
+# Generate an FDS-compatible LDIF file.
+inldif=src/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif
+cat > '60kerberos.ldif' << EOF
+# This is a variation on kerberos.ldif which 389 Directory Server will like.
+dn: cn=schema
+EOF
+egrep -iv '(^$|^dn:|^changetype:|^add:)' $inldif | \
+sed -r 's,^		,                ,g' | \
+sed -r 's,^	,        ,g' >> 60kerberos.ldif
+touch -r $inldif 60kerberos.ldif
+
+# Rebuild the configure scripts.
+pushd src
+autoreconf -fiv
+popd
+
+# Create build spaces for the test wrappers.
+mkdir -p nss_wrapper/build
+mkdir -p socket_wrapper/build
+
+# Mess with some of the default ports that we use for testing, so that multiple
+# builds going on the same host don't step on each other.
+cfg="src/kadmin/testing/proto/kdc.conf.proto \
+     src/kadmin/testing/proto/krb5.conf.proto \
+     src/lib/kadm5/unit-test/api.current/init-v2.exp \
+     src/util/k5test.py"
+LONG_BIT=`getconf LONG_BIT`
+PORT=`expr 61000 + $LONG_BIT - 48`
+sed -i -e s,61000,`expr "$PORT" + 0`,g $cfg
+PORT=`expr 1750 + $LONG_BIT - 48`
+sed -i -e s,1750,`expr "$PORT" + 0`,g $cfg
+sed -i -e s,1751,`expr "$PORT" + 1`,g $cfg
+sed -i -e s,1752,`expr "$PORT" + 2`,g $cfg
+PORT=`expr 8888 + $LONG_BIT - 48`
+sed -i -e s,8888,`expr "$PORT" - 0`,g $cfg
+sed -i -e s,8887,`expr "$PORT" - 1`,g $cfg
+sed -i -e s,8886,`expr "$PORT" - 2`,g $cfg
+PORT=`expr 7777 + $LONG_BIT - 48`
+sed -i -e s,7777,`expr "$PORT" + 0`,g $cfg
+sed -i -e s,7778,`expr "$PORT" + 1`,g $cfg
+
+%build
+# Go ahead and supply tcl info, because configure doesn't know how to find it.
+source %{_libdir}/tclConfig.sh
+pushd src
+
+# Set this so that configure will have a value even if the current version of
+# autoconf doesn't set one.
+runstatedir=%{_localstatedir}/run; export runstatedir
+# Work out the CFLAGS and CPPFLAGS which we intend to use.
+INCLUDES=-I%{_includedir}/et
+CFLAGS="`echo $RPM_OPT_FLAGS $DEFINES $INCLUDES -fPIC -fno-strict-aliasing -fstack-protector-all`"
+CPPFLAGS="`echo $DEFINES $INCLUDES`"
+%configure \
+	CC="%{__cc}" \
+	CFLAGS="$CFLAGS" \
+	CPPFLAGS="$CPPFLAGS" \
+%if 0%{?fedora} >= 7 || 0%{?rhel} >= 6
+	SS_LIB="-lss" \
+%else
+	SS_LIB="-lss -lncurses" \
+%endif
+	--enable-shared \
+	--localstatedir=%{_var}/kerberos \
+	--disable-rpath \
+	--without-krb5-config \
+	--with-system-et \
+	--with-system-ss \
+	--with-netlib=-lresolv \
+	--with-tcl \
+	--enable-dns-for-realm \
+	--with-ldap \
+%if %{WITH_DIRSRV}
+	--with-dirsrv-account-locking \
+%endif
+	--enable-pkinit \
+	--with-pkinit-crypto-impl=openssl \
+	--with-tls-impl=openssl \
+	--with-system-verto \
+	--with-pam \
+	--with-selinux \
+        --with-prng-alg=os
+# Now build it.
+make
+popd
+
+# Sanity check the KDC_RUN_DIR.
+configured_kdcrundir=`grep KDC_RUN_DIR src/include/osconf.h | awk '{print $NF}'`
+configured_kdcrundir=`eval echo $configured_kdcrundir`
+if test "$configured_kdcrundir" != %{_localstatedir}/run/krb5kdc ; then
+	exit 1
+fi
+
+# Build the docs.
+make -C src/doc paths.py version.py
+cp src/doc/paths.py doc/
+mkdir -p build-man build-html build-pdf
+sphinx-build -a -b man   -t pathsubs doc build-man
+sphinx-build -a -b html  -t pathsubs doc build-html
+rm -fr build-html/_sources
+sphinx-build -a -b latex -t pathsubs doc build-pdf
+# Build the PDFs if we didn't have pre-built ones.
+for pdf in admin appdev basic build plugindev user ; do
+	test -s build-pdf/$pdf.pdf || make -C build-pdf
+done
+# new krb5-%{version}-pdf
+tar -cf "krb5-%{version}-pdfs.tar.new" build-pdf/*.pdf
+
+# Build the test wrappers.
+pushd nss_wrapper/build
+cmake ..
+make
+popd
+pushd socket_wrapper/build
+cmake ..
+make
+popd
+
+# We need to cut off any access to locally-running nameservers, too.
+%{__cc} -fPIC -shared -o noport.so -Wall -Wextra $RPM_SOURCE_DIR/noport.c
+
+%check
+# Alright, this much is still a work in progress.
+%if %{?__isa_bits:%{__isa_bits}}%{!?__isa_bits:32} == 64
+if hostname | grep -q build ; then
+	sleep 600
+fi
+%endif
+
+# Set things up to use the test wrappers.
+NSS_WRAPPER_HOSTNAME=test.example.com ; export NSS_WRAPPER_HOSTNAME
+NSS_WRAPPER_HOSTS="`pwd`/nss_wrapper/fakehosts" ; export NSS_WRAPPER_HOSTS
+echo 127.0.0.1 $NSS_WRAPPER_HOSTNAME $NSS_WRAPPER_HOSTNAME localhost localhost >"$NSS_WRAPPER_HOSTS"
+NOPORT=53,111; export NOPORT
+SOCKET_WRAPPER_DIR=`pwd`/sockets; mkdir -p $SOCKET_WRAPPER_DIR; export SOCKET_WRAPPER_DIR
+LD_PRELOAD=`pwd`/noport.so:`pwd`/nss_wrapper/build/src/libnss_wrapper.so:`pwd`/socket_wrapper/build/src/libsocket_wrapper.so ; export LD_PRELOAD
+
+# Run the test suite. We can't actually run the whole thing in the build
+# system, but we can at least run more than we used to.  The build system may
+# give us a revoked session keyring, so run affected tests with a new one.
+make -C src runenv.py
+: make -C src check TMPDIR=%{_tmppath}
+keyctl session - make -C src/lib check TMPDIR=%{_tmppath} OFFLINE=yes
+make -C src/kdc check TMPDIR=%{_tmppath}
+keyctl session - make -C src/appl check TMPDIR=%{_tmppath}
+make -C src/clients check TMPDIR=%{_tmppath}
+keyctl session - make -C src/util check TMPDIR=%{_tmppath}
+
+%install
+[ "$RPM_BUILD_ROOT" != '/' ] && rm -rf -- $RPM_BUILD_ROOT
+
+# Sample KDC config files (bundled kdc.conf and kadm5.acl).
+mkdir -p $RPM_BUILD_ROOT%{_var}/kerberos/krb5kdc
+install -pm 600 %{SOURCE10} $RPM_BUILD_ROOT%{_var}/kerberos/krb5kdc/
+install -pm 600 %{SOURCE11} $RPM_BUILD_ROOT%{_var}/kerberos/krb5kdc/
+
+# Where per-user keytabs live by default.
+mkdir -p $RPM_BUILD_ROOT%{_var}/kerberos/krb5/user
+
+# Default configuration file for everything.
+mkdir -p $RPM_BUILD_ROOT/etc
+install -pm 644 %{SOURCE6} $RPM_BUILD_ROOT/etc/krb5.conf
+
+# Default include on this directory
+mkdir -p $RPM_BUILD_ROOT/etc/krb5.conf.d
+
+# Parent of configuration file for list of loadable GSS mechs ("mechs").  This
+# location is not relative to sysconfdir, but is hard-coded in g_initialize.c.
+mkdir -m 755 -p $RPM_BUILD_ROOT/etc/gss
+# Parent of groups of configuration files for a list of loadable GSS mechs
+# ("mechs").  This location is not relative to sysconfdir, and is also
+# hard-coded in g_initialize.c.
+mkdir -m 755 -p $RPM_BUILD_ROOT/etc/gss/mech.d
+
+# If the default configuration needs to start specifying a default cache
+# location, add it now, then fixup the timestamp so that it looks the same.
+DEFCCNAME="%{configured_default_ccache_name}"; export DEFCCNAME
+awk '{print}
+     /^# default_realm/{print " default_ccache_name =", ENVIRON["DEFCCNAME"]}' \
+     %{SOURCE6} > $RPM_BUILD_ROOT/etc/krb5.conf
+touch -r %{SOURCE6} $RPM_BUILD_ROOT/etc/krb5.conf
+grep default_ccache_name $RPM_BUILD_ROOT/etc/krb5.conf
+
+# Server init scripts (krb5kdc,kadmind,kpropd) and their sysconfig files.
+mkdir -p $RPM_BUILD_ROOT%{_unitdir}
+for unit in \
+	%{SOURCE5}\
+	%{SOURCE4} \
+	%{SOURCE2} ; do
+	# In the past, the init script was supposed to be named after the
+	# service that the started daemon provided.  Changing their names
+	# is an upgrade-time problem I'm in no hurry to deal with.
+	install -pm 644 ${unit} $RPM_BUILD_ROOT%{_unitdir}
+done
+mkdir -p $RPM_BUILD_ROOT%{_sbindir}
+for wrapper in \
+	%{SOURCE7} \
+	%{SOURCE8} ; do
+	install -pm 755 ${wrapper} $RPM_BUILD_ROOT%{_sbindir}/
+done
+mkdir -p $RPM_BUILD_ROOT/%{_tmpfilesdir}
+install -pm 644 %{SOURCE39} $RPM_BUILD_ROOT/%{_tmpfilesdir}/
+mkdir -p $RPM_BUILD_ROOT/%{_localstatedir}/run/krb5kdc
+
+mkdir -p $RPM_BUILD_ROOT/etc/sysconfig
+for sysconfig in \
+	%{SOURCE19}\
+	%{SOURCE20}\
+	%{SOURCE21} ; do
+	install -pm 644 ${sysconfig} \
+	$RPM_BUILD_ROOT/etc/sysconfig/`basename ${sysconfig} .sysconfig`
+done
+
+# logrotate configuration files
+mkdir -p $RPM_BUILD_ROOT/etc/logrotate.d/
+for logrotate in \
+	%{SOURCE33} \
+	%{SOURCE34} ; do
+	install -pm 644 ${logrotate} \
+	$RPM_BUILD_ROOT/etc/logrotate.d/`basename ${logrotate} .logrotate`
+done
+
+# PAM configuration files.
+mkdir -p $RPM_BUILD_ROOT/etc/pam.d/
+for pam in \
+	%{SOURCE29} ; do
+	install -pm 644 ${pam} \
+	$RPM_BUILD_ROOT/etc/pam.d/`basename ${pam} .pamd`
+done
+
+# Plug-in directories.
+install -pdm 755 $RPM_BUILD_ROOT/%{_libdir}/krb5/plugins/preauth
+install -pdm 755 $RPM_BUILD_ROOT/%{_libdir}/krb5/plugins/kdb
+install -pdm 755 $RPM_BUILD_ROOT/%{_libdir}/krb5/plugins/authdata
+
+# The rest of the binaries, headers, libraries, and docs.
+make -C src DESTDIR=$RPM_BUILD_ROOT EXAMPLEDIR=%{libsdocdir}/examples install
+
+# Munge krb5-config yet again.  This is totally wrong for 64-bit, but chunks
+# of the buildconf patch already conspire to strip out /usr/<anything> from the
+# list of link flags, and it helps prevent file conflicts on multilib systems.
+sed -r -i -e 's|^libdir=/usr/lib(64)?$|libdir=/usr/lib|g' $RPM_BUILD_ROOT%{_bindir}/krb5-config
+
+# FIXME: Temporay workaround for RH bug #1204646 ("krb5-config
+# returns wrong -specs path") so that development of krb5
+# dependicies gets unstuck.
+sed -r -i -e "s/-specs=\/.+?\/redhat-hardened-ld//g" $RPM_BUILD_ROOT%{_bindir}/krb5-config
+
+if [[ "$(< $RPM_BUILD_ROOT%{_bindir}/krb5-config )" == *redhat-hardened-ld* ]] ; then
+       printf '# redhat-hardened-ld for krb5-config failed' 1>&2
+       exit 1
+fi
+
+# Install processed man pages.
+for section in 1 5 8 ; do
+	install -m 644 build-man/*.${section} \
+		       $RPM_BUILD_ROOT/%{_mandir}/man${section}/
+done
+
+# This script just tells you to send bug reports to krb5-bugs@mit.edu, but
+# since we don't have a man page for it, just drop it.
+rm -- $RPM_BUILD_ROOT/%{_sbindir}/krb5-send-pr
+
+# These files are already packaged elsewhere
+rm -f -- "$RPM_BUILD_ROOT/%{_docdir}/krb5-libs/examples/kdc.conf"
+rm -f -- "$RPM_BUILD_ROOT/%{_docdir}/krb5-libs/examples/krb5.conf"
+rm -f -- "$RPM_BUILD_ROOT/%{_docdir}/krb5-libs/examples/services.append"
+
+# This is only needed for tests
+rm -- "$RPM_BUILD_ROOT/%{_libdir}/krb5/plugins/preauth/test.so"
+
+%find_lang %{gettext_domain}
+
+%clean
+[ "$RPM_BUILD_ROOT" != '/' ] && rm -rf -- $RPM_BUILD_ROOT
+
+%post libs -p /sbin/ldconfig
+
+%triggerun libs -- krb5-libs < 1.15.1-13
+if ! grep -q 'includedir /etc/krb5.conf.d' /etc/krb5.conf ; then
+    sed -i '1i # Other applications require this directory to perform krb5 configuration.\nincludedir /etc/krb5.conf.d/\n' /etc/krb5.conf
+fi
+
+%postun libs -p /sbin/ldconfig
+
+%post server-ldap -p /sbin/ldconfig
+
+%postun server-ldap -p /sbin/ldconfig
+
+%post server
+# assert sanity.  A cleaner solution probably exists but it is opaque.
+/bin/systemctl daemon-reload
+exit 0
+
+%preun server
+if [ "$1" -eq "0" ] ; then
+	/bin/systemctl --no-reload disable krb5kdc.service > /dev/null 2>&1 || :
+	/bin/systemctl --no-reload disable kadmin.service > /dev/null 2>&1 || :
+	/bin/systemctl --no-reload disable kprop.service > /dev/null 2>&1 || :
+	/bin/systemctl stop krb5kdc.service > /dev/null 2>&1 || :
+	/bin/systemctl stop kadmin.service > /dev/null 2>&1 || :
+	/bin/systemctl stop kprop.service > /dev/null 2>&1 || :
+fi
+exit 0
+
+%postun server
+/bin/systemctl daemon-reload >/dev/null 2>&1 || :
+if [ "$1" -ge 1 ] ; then
+	/bin/systemctl try-restart krb5kdc.service >/dev/null 2>&1 || :
+	/bin/systemctl try-restart kadmin.service >/dev/null 2>&1 || :
+	/bin/systemctl try-restart kprop.service >/dev/null 2>&1 || :
+fi
+exit 0
+
+%post -n libkadm5 -p /sbin/ldconfig
+
+%postun -n libkadm5 -p /sbin/ldconfig
+
+%files workstation
+%defattr(-,root,root,-)
+%doc src/config-files/services.append
+%doc build-html/*
+%doc build-pdf/user.pdf build-pdf/basic.pdf
+%attr(0755,root,root) %doc src/config-files/convert-config-files
+
+# Clients of the KDC, including tools you're likely to need if you're running
+# app servers other than those built from this source package.
+%{_bindir}/kdestroy
+%{_mandir}/man1/kdestroy.1*
+%{_bindir}/kinit
+%{_mandir}/man1/kinit.1*
+%{_bindir}/klist
+%{_mandir}/man1/klist.1*
+%{_bindir}/kpasswd
+%{_mandir}/man1/kpasswd.1*
+%{_bindir}/kswitch
+%{_mandir}/man1/kswitch.1*
+
+%{_bindir}/kvno
+%{_mandir}/man1/kvno.1*
+%{_bindir}/kadmin
+%{_mandir}/man1/kadmin.1*
+%{_bindir}/k5srvutil
+%{_mandir}/man1/k5srvutil.1*
+%{_bindir}/ktutil
+%{_mandir}/man1/ktutil.1*
+
+# Doesn't really fit anywhere else.
+%attr(4755,root,root) %{_bindir}/ksu
+%{_mandir}/man1/ksu.1*
+%config(noreplace) /etc/pam.d/ksu
+
+%files server
+%defattr(-,root,root,-)
+%docdir %{_mandir}
+%doc build-pdf/admin.pdf build-pdf/build.pdf
+%{_unitdir}/krb5kdc.service
+%{_unitdir}/kadmin.service
+%{_unitdir}/kprop.service
+%{_tmpfilesdir}/krb5-krb5kdc.conf
+%dir %{_localstatedir}/run/krb5kdc
+%config(noreplace) /etc/sysconfig/krb5kdc
+%config(noreplace) /etc/sysconfig/kadmin
+%config(noreplace) /etc/sysconfig/kprop
+%config(noreplace) /etc/logrotate.d/krb5kdc
+%config(noreplace) /etc/logrotate.d/kadmind
+
+%dir %{_var}/kerberos
+%dir %{_var}/kerberos/krb5kdc
+%config(noreplace) %{_var}/kerberos/krb5kdc/kdc.conf
+%config(noreplace) %{_var}/kerberos/krb5kdc/kadm5.acl
+
+%dir %{_libdir}/krb5
+%dir %{_libdir}/krb5/plugins
+%dir %{_libdir}/krb5/plugins/kdb
+%dir %{_libdir}/krb5/plugins/preauth
+%dir %{_libdir}/krb5/plugins/authdata
+%{_libdir}/krb5/plugins/preauth/otp.so
+%{_libdir}/krb5/plugins/kdb/db2.so
+
+# KDC binaries and configuration.
+%{_mandir}/man5/kadm5.acl.5*
+%{_mandir}/man5/kdc.conf.5*
+%{_sbindir}/kadmin.local
+%{_mandir}/man8/kadmin.local.8*
+%{_sbindir}/kadmind
+%{_sbindir}/_kadmind
+%{_mandir}/man8/kadmind.8*
+%{_sbindir}/kdb5_util
+%{_mandir}/man8/kdb5_util.8*
+%{_sbindir}/kprop
+%{_mandir}/man8/kprop.8*
+%{_sbindir}/kpropd
+%{_sbindir}/_kpropd
+%{_mandir}/man8/kpropd.8*
+%{_sbindir}/kproplog
+%{_mandir}/man8/kproplog.8*
+%{_sbindir}/krb5kdc
+%{_mandir}/man8/krb5kdc.8*
+
+# This is here for people who want to test their server.  It was formerly also
+# in -devel.
+%{_bindir}/sclient
+%{_mandir}/man1/sclient.1*
+%{_sbindir}/sserver
+%{_mandir}/man8/sserver.8*
+
+%files server-ldap
+%defattr(-,root,root,-)
+%docdir %{_mandir}
+%doc src/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif
+%doc src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema
+%doc 60kerberos.ldif
+%dir %{_libdir}/krb5
+%dir %{_libdir}/krb5/plugins
+%dir %{_libdir}/krb5/plugins/kdb
+%{_libdir}/krb5/plugins/kdb/kldap.so
+%{_libdir}/libkdb_ldap.so
+%{_libdir}/libkdb_ldap.so.*
+%{_mandir}/man8/kdb5_ldap_util.8.gz
+%{_sbindir}/kdb5_ldap_util
+
+%files libs -f %{gettext_domain}.lang
+%defattr(-,root,root,-)
+%doc README NOTICE
+%{!?_licensedir:%global license %%doc}
+%license LICENSE
+%docdir %{_mandir}
+# These are hard-coded, not-dependent-on-the-configure-script paths.
+%dir /etc/gss
+%dir /etc/gss/mech.d
+%dir /etc/krb5.conf.d
+%config(noreplace) /etc/krb5.conf
+/%{_mandir}/man5/.k5identity.5*
+/%{_mandir}/man5/.k5login.5*
+/%{_mandir}/man5/k5identity.5*
+/%{_mandir}/man5/k5login.5*
+/%{_mandir}/man5/krb5.conf.5*
+%{_libdir}/libgssapi_krb5.so.*
+%{_libdir}/libgssrpc.so.*
+%{_libdir}/libk5crypto.so.*
+%{_libdir}/libkdb5.so.*
+%{_libdir}/libkrad.so.*
+%{_libdir}/libkrb5.so.*
+%{_libdir}/libkrb5support.so.*
+%dir %{_libdir}/krb5
+%dir %{_libdir}/krb5/plugins
+%dir %{_libdir}/krb5/plugins/*
+%{_libdir}/krb5/plugins/tls/k5tls.so
+%dir %{_var}/kerberos
+%dir %{_var}/kerberos/krb5
+%dir %{_var}/kerberos/krb5/user
+
+%files pkinit
+%defattr(-,root,root,-)
+%dir %{_libdir}/krb5
+%dir %{_libdir}/krb5/plugins
+%dir %{_libdir}/krb5/plugins/preauth
+%{_libdir}/krb5/plugins/preauth/pkinit.so
+
+%files devel
+%defattr(-,root,root,-)
+%docdir %{_mandir}
+
+%{_includedir}/*
+%{_libdir}/libgssapi_krb5.so
+%{_libdir}/libgssrpc.so
+%{_libdir}/libk5crypto.so
+%{_libdir}/libkdb5.so
+%{_libdir}/libkrad.so
+%{_libdir}/libkrb5.so
+%{_libdir}/libkrb5support.so
+%{_libdir}/pkgconfig/*
+
+%{_bindir}/krb5-config
+%{_mandir}/man1/krb5-config.1*
+
+# Protocol test clients.
+%{_bindir}/sim_client
+%{_bindir}/gss-client
+%{_bindir}/uuclient
+
+# Protocol test servers.
+%{_sbindir}/sim_server
+%{_sbindir}/gss-server
+%{_sbindir}/uuserver
+
+%files -n libkadm5
+%defattr(-,root,root,-)
+%{_libdir}/libkadm5clnt.so
+%{_libdir}/libkadm5clnt_mit.so
+%{_libdir}/libkadm5srv.so
+%{_libdir}/libkadm5srv_mit.so
+%{_libdir}/libkadm5clnt_mit.so.*
+%{_libdir}/libkadm5srv_mit.so.*
+
+%changelog
+* Tue Nov 28 2017 Robbie Harwood <rharwood@redhat.com> - 1.15.1-18
+- Expose context errors in pkinit_server_plugin_init
+- Resolves: #1460089
+
+* Thu Nov 02 2017 Robbie Harwood <rharwood@redhat.com> - 1.15.1-17
+- Drop certauth test changes that prevented runnig it
+- Resolves: #1498767
+
+* Thu Nov 02 2017 Robbie Harwood <rharwood@redhat.com> - 1.15.1-16
+- Drop irrelevant DIR trigger logic
+- Resolves: #1431198
+
+* Thu Oct 05 2017 Robbie Harwood <rharwood@redhat.com> - 1.15.1-15
+- Fix CVE-2017-7562 (certauth eku bypass)
+- Resolves: #1498767
+
+* Thu Oct 05 2017 Robbie Harwood <rharwood@redhat.com> - 1.15.1-14
+- Fix CVE-2017-11368 (s4u2 request assertion failures)
+- Resolves: #1498768
+
+* Tue Oct 03 2017 Robbie Harwood <rharwood@redhat.com> - 1.15.1-13
+- Force-add /etc/krb5.conf.d so we can guarantee it exists
+- Resolves: #1431198
+
+* Tue Sep 26 2017 Robbie Harwood <rharwood@redhat.com> - 1.15.1-12
+- Add krb5 policy plugin interface
+- Remove soname downgrade
+- Resolves: #1462982
+
+* Wed Sep 06 2017 Robbie Harwood <rharwood@redhat.com> - 1.15.1-11
+- Make t_certauth.py runnable
+- Resolves: #1443388
+
+* Tue Sep 05 2017 Robbie Harwood <rharwood@redhat.com> - 1.15.1-10
+- Add context SSF query support
+- Resolves: #1472956
+
+* Thu Aug 17 2017 Robbie Harwood <rharwood@redhat.com> - 1.15.1-9
+- Remove incomplete PKINIT OCSP support
+- Resolves: #1460089
+
+* Fri Apr 28 2017 Robbie Harwood <rharwood@redhat.com> - 1.15.1-8
+- Add kprop.service argument file
+- Resolves: #1389073
+
+* Fri Apr 07 2017 Robbie Harwood <rharwood@redhat.com> - 1.15.1-7
+- Fix enterprise principal forwarding
+- Resolves: #1378440
+
+* Thu Apr 06 2017 Robbie Harwood <rharwood@redhat.com> - 1.15.1-6
+- Fix bug in certauth backport
+- Resolves: #1428484
+
+* Wed Mar 22 2017 Robbie Harwood <rharwood@redhat.com> - 1.15.1-5
+- rubygem-rkerberos still needs us to lie about soname
+- Resolves: #1389073
+
+* Wed Mar 22 2017 Robbie Harwood <rharwood@redhat.com> - 1.15.1-4
+- Backport certauth plugin and related pkinit changes
+- Note: related changes cannot be tested because RHEL does not allow
+  binary git diffs
+- Resolves: #1428484
+
+* Tue Mar 07 2017 Robbie Harwood <rharwood@redhat.com> - 1.15.1-3
+- Remove duplication between subpackages
+- Resolves: #1254640
+
+* Mon Mar 06 2017 Robbie Harwood <rharwood@redhat.com> - 1.15.1-2
+- Add back deleted sources
+- Resolves: #1389073
+
+* Mon Mar 06 2017 Robbie Harwood <rharwood@redhat.com> - 1.15.1-1
+- Bump to krb5-1.15.1 (very small change)
+- Apply some sanity to our patches and ordering
+- Resolves: #1389073
+
+* Mon Jan 23 2017 Robbie Harwood <rharwood@redhat.com> - 1.15-2
+- Reinstate e_data free method; bumps KDB to 6.1
+- Resolves: #1389073
+
+* Wed Jan 04 2017 Robbie Harwood <rharwood@redhat.com> - 1.15-1
+- Rebase to 1.15-final
+- Resolves: #1389073
+- Resolves: #1367169
+- Resolves: #1389072
+- Resolves: #1366863
+
+* Wed Nov 02 2016 Robbie Harwood <rharwood@redhat.com> - 1.14.1-27
+- Properly handle EOF on libkrad sockets
+- Resolves: #1382449
+
+* Wed Aug 17 2016 Robbie Harwood <rharwood@redhat.com> - 1.14.1-26
+- Use responder in non-preauth AS reqs
+- Resolves: #1363690
+
+* Wed Aug 17 2016 Robbie Harwood <rharwood@redhat.com> - 1.14.1-25
+- Fix bad debug_log() call in selinux handling
+- Resolves: #1292153
+
+* Wed Aug 10 2016 Robbie Harwood <rharwood@redhat.com> - 1.14.1-24
+- Fix KKDCPP with TLS SNI by always presenting "Host:" header
+- Resolves: #1364993
+
+* Fri Aug 05 2016 Robbie Harwood <rharwood@redhat.com> - 1.14.1-23
+- Add dependency on libkadm5 to krb5-devel
+- Resolves: #1347403
+
+* Fri Jul 29 2016 Robbie Harwood <rharwood@redhat.com> - 1.14.1-22
+- Builders have new version of mock; adapt.
+- Resolves: #1290239
+
+* Fri Jul 29 2016 Robbie Harwood <rharwood@redhat.com> - 1.14.1-21
+- Fix CVE-2016-3120
+- Resolves: #1361504
+
+* Wed Jul 20 2016 Robbie Harwood <rharwood@redhat.com> - 1.14.1-20
+- Make version dependencies on libkadm5 more explicit to appease rpmdiff
+- Resolves: #1347403
+
+* Wed Jul 20 2016 Robbie Harwood <rharwood@redhat.com> - 1.14.1-19
+- Add in upstream version of kprop port and tests
+- Resolves: #1292795
+
+* Wed Jun 29 2016 Robbie Harwood <rharwood@redhat.com> - 1.14.1-18
+- Fix incorrect recv() size calculation in libkrad
+- Resolves: #1349042
+
+* Wed Jun 15 2016 Robbie Harwood <rharwood@redhat.com> - 1.14.1-17
+- Separate out the kadm5 libs
+- Resolves: #1347403
+
+* Mon Jun 13 2016 Robbie Harwood <rharwood@redhat.com> - 1.14.1-16
+- Fix kprop/iprop handling of default realm
+- Fix t_kprop.py
+- Resolves: #1290561
+- Resolves: #1302967
+- Resolves: #1292795
+
+* Thu Jun 02 2016 Robbie Harwood <rharwood@redhat.com> - 1.14.1-15
+- Fix SPNEGO with NTLM to conform to MS-SPNG section 3.3.5.1
+- Resolves: #1341726
+
+* Sat May 28 2016 Robbie Harwood <rharwood@redhat.com> - 1.14.1-14
+- Do not indicate depricated mechanisms when requested
+- Resolves: #1293908
+
+* Fri May 27 2016 Robbie Harwood <rharwood@redhat.com> - 1.14.1-13
+- Fix OTP module incorrectly overwriting as_key
+- Resolves: #1340304
+
+* Wed May 25 2016 Robbie Harwood <rharwood@redhat.com> - 1.14.1-12
+- Fix CVE-2016-3119 (LDAP NULL dereference)
+- Resolves: #1339562
+
+* Thu Apr 28 2016 Robbie Harwood <rharwood@redhat.com> - 1.14.1-11
+- Make ksu not ask for password without -n
+- Resolves: #1247261
+
+* Wed Apr 20 2016 Robbie Harwood <rharwood@redhat.com> - 1.14.1-10
+- Frob kadm5 soname version so that the rebase does not break things
+- Resolves: #1292153
+
+* Tue Apr 19 2016 Robbie Harwood <rharwood@redhat.com> - 1.14.1-9
+- Revamp selinux patch to not leak memory
+- Resolves: #1313457
+
+* Mon Apr 11 2016 Robbie Harwood <rharwood@redhat.com> - 1.14.1-8
+- Add snippet support in /etc/krb5.conf.d
+- Resolves: #1146945
+
+* Fri Apr 08 2016 Robbie Harwood <rharwood@redhat.com> - 1.14.1-7
+- Skip unnecessary mech calls in gss_inquire_cred
+- Resolves: #1314493
+
+* Thu Apr 07 2016 Robbie Harwood <rharwood@redhat.com> - 1.14.1-6
+- Fix impersonate_name to work with interposers
+- Resolves: #1284987
+
+* Thu Apr 07 2016 Robbie Harwood <rharwood@redhat.com> - 1.14.1-5
+- Fix change tracking of krb5.conf
+- Resolves: #1208243
+
+* Tue Apr 05 2016 Robbie Harwood <rharwood@redhat.com> - 1.14.1-4
+- Ensure log files are not world-readable
+- Resolves: #1256735
+
+* Wed Mar 30 2016 Robbie Harwood <rharwood@redhat.com> - 1.14.1-3
+- Clean up initscript handling in spec file
+- Resolves: #1283902
+- Resolves: #1183058
+
+* Wed Mar 30 2016 Robbie Harwood <rharwood@redhat.com> - 1.14.1-2
+- Backport spec file changes from Fedora
+- Resolves: #1290239
+
+* Thu Mar 10 2016 Robbie Harwood <rharwood@redhat.com> - 1.14.1-1
+- Rebase to new upstream version 1.14.1
+- Remove pax logic
+- Resolves: #1292153
+- Resolves: #1135427
+- Resolves: #1265509
+- Resolves: #1265510
+- Resolves: #1296241
+
+* Fri Feb 12 2016 Robbie Harwood <rharwood@redhat.com> - 1.13.2-12
+- Remove obsolete trigger to enable building of package
+- Resolves: #1306970
+
+* Fri Feb 12 2016 Robbie Harwood <rharwood@redhat.com> - 1.13.2-11
+- Fix CVE-2015-8631, CVE-2015-8630, and CVE-2015-8629
+- Resolves: #1306970
+
+* Fri Sep 04 2015 Robbie Harwood <rharwood@redhat.com> 1.13.2-9
+- Add patch and test case for "KDC does not return proper
+  client principal for client referrals"
+- Resolves: #1259846
+
+* Mon Aug 31 2015 Roland Mainz <rmainz@redhat.com> - 1.13.2-9
+- Ammend patch for RedHat bug #1252454 ('testsuite complains
+  "Lifetime has increased by 32436 sec while 0 sec passed!",
+  while rhel5-libkrb5 passes') to handle the newly introduced
+  valgrind hits.
+
+* Wed Aug 19 2015 Roland Mainz <rmainz@redhat.com> - 1.13.2-8
+- Add a patch to fix RH Bug #1250154 ("[s390x, ppc64, ppc64le]:
+  kadmind does not accept ACL if kadm5.acl does not end with EOL")
+  The code "accidently" works on x86/AMD64 because declaring a
+  variable |char| results in an |unsigned char| by default while
+  most other platforms (e.g. { s390x, ppc64, ppc64le, ...})
+  default to |signed char| (still have to use lint(1) to clean
+  up 38 more instances of this kind of bug).
+
+* Wed Aug 19 2015 Roland Mainz <rmainz@redhat.com> - 1.13.2-7
+- Obsolete multilib versions of server packages to fix RH
+  bug #1251913 ("krb5 should obsolete the multilib versions
+  of krb5-server and krb5-server-ldap").
+  The following packages are declared obsolete:
+  - krb5-server-1.11.3-49.el7.i686
+  - krb5-server-1.11.3-49.el7.ppc
+  - krb5-server-1.11.3-49.el7.s390
+  - krb5-server-ldap-1.11.3-49.el7.i686
+  - krb5-server-ldap-1.11.3-49.el7.ppc
+  - krb5-server-ldap-1.11.3-49.el7.s390
+
+* Wed Aug 19 2015 Roland Mainz <rmainz@redhat.com> - 1.13.2-6
+- Add a patch to fix RedHat bug #1252454 ('testsuite complains
+  "Lifetime has increased by 32436 sec while 0 sec passed!",
+  while rhel5-libkrb5 passes') so that krb5 resolves GSS creds
+  if |time_rec| is requested.
+
+* Fri Aug 7 2015 Roland Mainz <rmainz@redhat.com> - 1.13.2-5
+- Add a patch to fix RedHat bug #1251586 ("KDC sends multiple
+  requests to ipa-otpd for the same authentication") which causes
+  the KDC to send multiple retries to ipa-otpd for TCP transports
+  while it should only be done for UDP.
+
+* Tue Jul 28 2015 Roland Mainz <rmainz@redhat.com> - 1.13.2-4
+- the rebase to krb5 1.13.2 in vers 1.13.2-0 also fixed:
+  - Redhat Bug #1247761 ("RFE: Minor krb5 spec file cleanup and sync
+    with recent Fedora 22/23 changes")
+  - Redhat Bug #1247751 ("krb5-config returns wrong -specs path")
+  - Redhat Bug #1247608 ('Add support for multi-hop preauth mechs
+    via |KDC_ERR_MORE_PREAUTH_DATA_REQUIRED| for RFC 6113 ("A
+    Generalized Framework for Kerberos Pre-Authentication")')
+- Removed "krb5-1.10-kprop-mktemp.patch" and
+  "krb5-1.3.4-send-pr-tempfile.patch", both are no longer used since
+  the rebase to krb5 1.13.1
+
+* Fri May 29 2015 Roland Mainz <rmainz@redhat.com> - 1.13.2-3
+- Add patch to fix Redhat Bug #1222903 ("[SELinux] AVC denials may appear
+  when kadmind starts"). The issue was caused by an unneeded |htons()|
+  which triggered SELinux AVC denials due to the "random" port usage.
+
+* Thu May 21 2015 Roland Mainz <rmainz@redhat.com> - 1.13.2-2
+- Add fix for RedHat Bug #1164304 ("Upstream unit tests loads
+  the installed shared libraries instead the ones from the build")
+
+* Fri May 15 2015 Roland Mainz <rmainz@redhat.com> - 1.13.2-1
+- the rebase to krb5 1.13.1 in vers 1.13.1-0 also fixed:
+  - Bug 1144498 ("Fix the race condition in the libkrb5 replay cache")
+  - Bug 1163402 ("kdb5_ldap_util view_policy does not shows ticket flags on s390x and ppc64")
+  - Bug 1185770 ("Missing upstream test in krb5-1.12.2: src/tests/gssapi/t_invalid.c")
+  - Bug 1204211 ("CVE-2014-5355 krb5: unauthenticated denial of service in recvauth_common() and other")
+
+* Fri May 15 2015 Roland Mainz <rmainz@redhat.com> - 1.13.2-0
+- Update to krb5-1.13.2
+  - drop patch for krb5-1.13.2-CVE_2015_2694_requires_preauth_bypass_in_PKINIT_enabled_KDC, fixed in krb5-1.13.2
+  - drop patch for krb5-1.12.1-CVE_2014_5355_fix_krb5_read_message_handling, fixed in krb5-1.13.2
+
+* Thu May 14 2015 Roland Mainz <rmainz@redhat.com> - 1.13.1-2
+- the rebase to krb5 1.13.1 in vers 1.13.1-0 also fixed RH
+  bug #1156144 ("krb5 upstream test t_kdb.py failure")
+
+* Mon May 4 2015 Roland Mainz <rmainz@redhat.com> - 1.13.1-1
+- fix for CVE-2015-2694 (#1218020) "requires_preauth bypass
+  in PKINIT-enabled KDC".
+  In MIT krb5 1.12 and later, when the KDC is configured with
+  PKINIT support, an unauthenticated remote attacker can
+  bypass the requires_preauth flag on a client principal and
+  obtain a ciphertext encrypted in the principal's long-term
+  key.  This ciphertext could be used to conduct an off-line
+  dictionary attack against the user's password.
+
+* Fri Apr 24 2015 Roland Mainz <rmainz@redhat.com> - 1.13.1-0
+- Update to krb5-1.13.1
+  - patch krb5-1.12-selinux-label was updated and renamed to krb5-1.13-selinux-label
+  - patch krb5-1.11-dirsrv-accountlock was updated and renamed to krb5-1.13-dirsrv-accountlock
+  - drop patch for krb5-1.12-pwdch-fast, fixed in krb5-1.13
+  - drop patch for krb5-1.12ish-kpasswd_tcp, fixed in krb5-1.13
+  - drop patch for krb5-master-rcache-internal-const, no longer needed
+  - drop patch for krb5-master-rcache-acquirecred-cleanup, no longer needed
+  - drop patch for krb5-master-rcache-acquirecred-source, no longer needed
+  - drop patch for krb5-master-rcache-acquirecred-test, no longer needed
+  - drop patch for krb5-master-move-otp-sockets, no longer needed
+  - drop patch for krb5-master-mechd, no longer needed
+  - drop patch for krb5-master-strdupcheck, no longer needed
+  - drop patch for krb5-master-compatible-keys, no longer needed
+  - drop patch for krb5-1.12-system-exts, fixed in krb5-1.13
+  - drop patch for 0001-In-ksu-merge-krb5_ccache_copy-and-_restricted, no longer needed
+  - drop patch for 0002-In-ksu-don-t-stat-not-on-disk-ccache-residuals, no longer needed
+  - drop patch for 0003-Use-an-intermediate-memory-cache-in-ksu, no longer needed
+  - drop patch for 0004-Make-ksu-respect-the-default_ccache_name-setting, no longer needed
+  - drop patch for 0005-Copy-config-entries-to-the-ksu-target-ccache, no longer needed
+  - drop patch for 0006-Use-more-randomness-for-ksu-secondary-cache-names, no longer needed
+  - drop patch for 0007-Make-krb5_cc_new_unique-create-DIR-directories, no longer needed
+  - drop patch for krb5-1.12-kpasswd-skip-address-check, fixed in krb5-1.13
+  - drop patch for 0000-Refactor-cm-functions-in-sendto_kdc.c, no longer needed
+  - drop patch for 0001-Simplify-sendto_kdc.c, no longer needed
+  - drop patch for 0002-Add-helper-to-determine-if-a-KDC-is-the-master, no longer needed
+  - drop patch for 0003-Use-k5_transport-_strategy-enums-for-k5_sendto, no longer needed
+  - drop patch for 0004-Build-support-for-TLS-used-by-HTTPS-proxy-support, no longer needed
+  - drop patch for 0005-Add-ASN.1-codec-for-KKDCP-s-KDC-PROXY-MESSAGE, no longer needed
+  - drop patch for 0006-Dispatch-style-protocol-switching-for-transport, no longer needed
+  - drop patch for 0007-HTTPS-transport-Microsoft-KKDCPP-implementation, no longer needed
+  - drop patch for 0008-Load-custom-anchors-when-using-KKDCP, no longer needed
+  - drop patch for 0009-Check-names-in-the-server-s-cert-when-using-KKDCP, no longer needed
+  - drop patch for 0010-Add-some-longer-form-docs-for-HTTPS, no longer needed
+  - drop patch for 0011-Have-k5test.py-provide-runenv-to-python-tests, no longer needed
+  - drop patch for 0012-Add-a-simple-KDC-proxy-test-server, no longer needed
+  - drop patch for 0013-Add-tests-for-MS-KKDCP-client-support, no longer needed
+  - drop patch for krb5-1.12ish-tls-plugins, fixed in krb5-1.13.1
+  - drop patch for krb5-1.12-nodelete-plugins, fixed in krb5-1.13.1
+  - drop patch for krb5-1.12-ksu-untyped-default-ccache-name, fixed in krb5-1.13.1
+  - drop patch for krb5-1.12-ksu-no-ccache, fixed in krb5-1.13.1
+  - drop patch for krb5-ksu_not_working_with_default_principal, fixed in krb5-1.13.1
+  - drop patch for CVE_2014_5353_fix_LDAP_misused_policy_name_crash, fixed in krb5-1.13.1
+  - drop patch for CVE_2014_5354_support_keyless_principals_in_ldap, fixed in krb5-1.13.1
+  - drop patch for kinit -C loops (MIT/krb5 bug #243), fixed in krb5-1.13.1
+  - drop patch for CVEs { 2014-9421, 2014-9422, 2014-9423, 2014-5352 }, fixed in krb5-1.13.1
+  - added patch krb5-1.14-Support-KDC_ERR_MORE_PREAUTH_DATA_REQUIRED
+  - added patch krb5-1.12.1-CVE_2014_5355_fix_krb5_read_message_handling
+- Minor spec cleanup
+
+* Mon Jan 26 2015 Roland Mainz <rmainz@redhat.com> - 1.12.2-14
+- fix for kinit -C loops (#1184629, MIT/krb5 issue 243, "Do not
+  loop on principal unknown errors").
+
+* Mon Jan 12 2015 Roland Mainz <rmainz@redhat.com> - 1.12.2-13
+- fix for CVE-2014-5352 (#1179856) "gss_process_context_token()
+  incorrectly frees context (MITKRB5-SA-2015-001)"
+- fix for CVE-2014-9421 (#1179857) "kadmind doubly frees partial
+  deserialization results (MITKRB5-SA-2015-001)"
+- fix for CVE-2014-9422 (#1179861) "kadmind incorrectly
+  validates server principal name (MITKRB5-SA-2015-001)"
+- fix for CVE-2014-9423 (#1179863) "libgssrpc server applications
+  leak uninitialized bytes (MITKRB5-SA-2015-001)"
+
+* Mon Dec 22 2014 Roland Mainz <rmainz@redhat.com> - 1.12.2-12
+- fix for CVE-2014-5354 (#1174546) "krb5: NULL pointer
+  dereference when using keyless entries"
+
+* Mon Dec 22 2014 Roland Mainz <rmainz@redhat.com> - 1.12.2-11
+- fix for CVE-2014-5353 (#1174543) "Fix LDAP misused policy
+  name crash"
+
+* Sun Dec 7 2014 Roland Mainz <rmainz@redhat.com> - 1.12.2-10
+- In ksu, without the -e flag, also check .k5users (#1105489)
+  When ksu was explicitly told to spawn a shell, a line in .k5users which
+  listed "*" as the allowed command would cause the principal named on the
+  line to be considered as a candidate for authentication.
+  When ksu was not passed a command to run, which implicitly meant that
+  the invoking user wanted to run the target user's login shell, knowledge
+  that the principal was a valid candidate was ignored, which could cause
+  a less optimal choice of the default target principal.
+  This doesn't impact the authorization checks which we perform later.
+  Patch by Nalin Dahyabhai <nalin@redhat.com>
+
+* Wed Dec 3 2014 Roland Mainz <rmainz@redhat.com> - 1.12.2-9
+- Undo libkadmclnt SONAME change (from 8 to 9) which originally
+  happened in the krb5 1.12 rebase (#1166012) but broke
+  rubygem-rkerberos (sort of ruby language bindings for
+  libkadmclnt&co.) dependicies, as side effect of
+  rubygem-rkerberos using private interfaces in libkadmclnt.
+
+* Mon Sep  8 2014 Nalin Dahyabhai <nalin@redhat.com> - 1.12.2-8
+- fix the problem where the %%license file has been a dangling symlink
+- ksu: pull in fix from pull #206 to avoid breakage when the
+  default_ccache_name doesn't include a cache type as a prefix
+- ksu: pull in a proposed fix for pull #207 to avoid breakage when the
+  invoking user doesn't already have a ccache
+
+* Sat Sep  6 2014 Nalin Dahyabhai <nalin@redhat.com> - 1.12.2-7
+- pull in patch from master to load plugins with RTLD_NODELETE, when
+  defined (RT#7947)
+
+* Fri Sep  5 2014 Nalin Dahyabhai <nalin@redhat.com> - 1.12.2-6
+- backport patch to make the client skip checking the server's reply
+  address when processing responses to password-change requests, which
+  between NAT and upcoming HTTPS support, can cause us to erroneously
+  report an error to the user when the server actually reported success
+  (RT#7886)
+- backport support for accessing KDCs and kpasswd services via HTTPS
+  proxies (marked by being specified as https URIs instead as hostnames
+  or hostname-and-port), such as the one implemented in python-kdcproxy
+  (RT#7929, #109919), and pick up a subsequent patch to build HTTPS
+  as a plugin
+
+* Thu Aug 28 2014 Nalin Dahyabhai <nalin@redhat.com> - 1.12.2-5
+- backport fix for trying all compatible keys when not being strict about
+  acceptor names while reading AP-REQs (RT#7883, #1078888)
+- define _GNU_SOURCE in files where we use EAI_NODATA, to make sure that
+  it's declared (#1059730,#1084068,#1109102)
+
+* Tue Aug 26 2014 Nalin Dahyabhai <nalin@redhat.com> - 1.12.2-4
+- kpropd hasn't bothered with -S since 1.11; stop trying to use that flag
+  in the systemd unit file
+
+* Wed Aug 20 2014 Nalin Dahyabhai <nalin@redhat.com> - 1.12.2-3
+- pull in upstream fix for an incorrect check on the value returned by a
+  strdup() call (#1132062)
+
+* Sun Aug 17 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.12.1-15
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild
+
+* Sun Aug 17 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.12.2-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild
+
+* Fri Aug 15 2014 Nalin Dahyabhai <nalin@redhat.com> - 1.12.2-1
+- update to 1.12.2
+  - drop patch for RT#7820, fixed in 1.12.2
+  - drop patch for #231147, fixed as RT#3277 in 1.12.2
+  - drop patch for RT#7818, fixed in 1.12.2
+  - drop patch for RT#7836, fixed in 1.12.2
+  - drop patch for RT#7858, fixed in 1.12.2
+  - drop patch for RT#7924, fixed in 1.12.2
+  - drop patch for RT#7926, fixed in 1.12.2
+  - drop patches for CVE-2014-4341/CVE-2014-4342, included in 1.12.2
+  - drop patch for CVE-2014-4343, included in 1.12.2
+  - drop patch for CVE-2014-4344, included in 1.12.2
+  - drop patch for CVE-2014-4345, included in 1.12.2
+- replace older proposed changes for ksu with backports of the changes
+  after review and merging upstream (#1015559, #1026099, #1118347)
+
+* Thu Aug  7 2014 Nalin Dahyabhai <nalin@redhat.com> - 1.12.1-14
+- incorporate fix for MITKRB5-SA-2014-001 (CVE-2014-4345)
+
+* Mon Jul 21 2014 Nalin Dahyabhai <nalin@redhat.com> - 1.12.1-13
+- gssapi: pull in upstream fix for a possible NULL dereference
+  in spnego (CVE-2014-4344)
+
+* Wed Jul 16 2014 Nalin Dahyabhai <nalin@redhat.com> - 1.12.1-12
+- gssapi: pull in proposed fix for a double free in initiators (David
+  Woodhouse, CVE-2014-4343, #1117963)
+
+* Sat Jul 12 2014 Tom Callaway <spot@fedoraproject.org> - 1.12.1-11
+- fix license handling
+
+* Mon Jul  7 2014 Nalin Dahyabhai <nalin@redhat.com> - 1.12.1-10
+- pull in fix for denial of service by injection of malformed GSSAPI tokens
+  (CVE-2014-4341, CVE-2014-4342, #1116181)
+
+* Tue Jun 24 2014 Nalin Dahyabhai <nalin@redhat.com> - 1.12.1-9
+- pull in changes from upstream which add processing of the contents of
+  /etc/gss/mech.d/*.conf when loading GSS modules (#1102839)
+
+* Thu Jun 12 2014 Nalin Dahyabhai <nalin@redhat.com> - 1.12.1-8
+- pull in fix for building against tcl 8.6 (#1107061)
+
+* Sun Jun 08 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.12.1-7
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild
+
+* Tue Mar 04 2014 Nathaniel McCallum <npmccallum@redhat.com> - 1.12.1-6
+- Backport fix for change password requests when using FAST (RT#7868)
+
+* Mon Feb 17 2014 Nalin Dahyabhai <nalin@redhat.com> - 1.12.1-5
+- spnego: pull in patch from master to restore preserving the OID of the
+  mechanism the initiator requested when we have multiple OIDs for the same
+  mechanism, so that we reply using the same mechanism OID and the initiator
+  doesn't get confused (#1066000, RT#7858)
+
+* Fri Feb  7 2014 Nalin Dahyabhai <nalin@redhat.com> - 1.12.1-4
+- pull in patch from master to move the default directory which the KDC uses
+  when computing the socket path for a local OTP daemon from the database
+  directory (/var/kerberos/krb5kdc) to the newly-added run directory
+  (/run/krb5kdc), in line with what we're expecting in 1.13 (RT#7859, more
+  of #1040056 as #1063905)
+- add a tmpfiles.d configuration file to have /run/krb5kdc created at
+  boot-time
+- own /var/run/krb5kdc
+
+* Fri Jan 31 2014 Nalin Dahyabhai <nalin@redhat.com> - 1.12.1-3
+- refresh nss_wrapper and add socket_wrapper to the %%check environment
+
+* Fri Jan 31 2014 Nalin Dahyabhai <nalin@redhat.com>
+- add currently-proposed changes to teach ksu about credential cache
+  collections and the default_ccache_name setting (#1015559,#1026099)
+
+* Tue Jan 21 2014 Nalin Dahyabhai <nalin@redhat.com> - 1.12.1-2
+- pull in multiple changes to allow replay caches to be added to a GSS
+  credential store as "rcache"-type credentials (RT#7818/#7819/#7836,
+  #1056078/#1056080)
+
+* Fri Jan 17 2014 Nalin Dahyabhai <nalin@redhat.com> - 1.12.1-1
+- update to 1.12.1
+  - drop patch for RT#7794, included now
+  - drop patch for RT#7797, included now
+  - drop patch for RT#7803, included now
+  - drop patch for RT#7805, included now
+  - drop patch for RT#7807, included now
+  - drop patch for RT#7045, included now
+  - drop patches for RT#7813 and RT#7815, included now
+  - add patch to always retrieve the KDC time offsets from keyring caches,
+    so that we don't mistakenly interpret creds as expired before their
+    time when our clock is ahead of the KDC's (RT#7820, #1030607)
+
+* Mon Jan 13 2014 Nalin Dahyabhai <nalin@redhat.com> - 1.12-11
+- update the PIC patch for iaesx86.s to not use ELF relocations to the version
+  that landed upstream (RT#7815, #1045699)
+
+* Thu Jan  9 2014 Nalin Dahyabhai <nalin@redhat.com>
+- pass -Wl,--warn-shared-textrel to the compiler when we're creating shared
+  libraries
+
+* Thu Jan  9 2014 Nalin Dahyabhai <nalin@redhat.com> - 1.12-10
+- amend the PIC patch for iaesx86.s to also save/restore ebx in the
+  functions where we modify it, because the ELF spec says we need to
+
+* Mon Jan  6 2014 Nalin Dahyabhai <nalin@redhat.com> - 1.12-9
+- grab a more-commented version of the most recent patch from upstream
+  master
+- make a guess at making the 32-bit AES-NI implementation sufficiently
+  position-independent to not require execmod permissions for libk5crypto
+  (more of #1045699)
+
+* Thu Jan  2 2014 Nalin Dahyabhai <nalin@redhat.com> - 1.12-8
+- add patch from Dhiru Kholia for the AES-NI implementations to allow
+  libk5crypto to be properly marked as not needing an executable stack
+  on arches where they're used (#1045699, and so many others)
+
+* Thu Jan  2 2014 Nalin Dahyabhai <nalin@redhat.com> - 1.12-7
+- revert that last change for a bit while sorting out execstack when we
+  use AES-NI (#1045699)
+
+* Thu Dec 19 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.12-6
+- add yasm as a build requirement for AES-NI support, on arches that have
+  yasm and AES-NI
+
+* Thu Dec 19 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.12-5
+- pull in fix from master to make reporting of errors encountered by
+  the SPNEGO mechanism work better (RT#7045, part of #1043962)
+
+* Thu Dec 19 2013 Nalin Dahyabhai <nalin@redhat.com>
+- update a test wrapper to properly handle things that the new libkrad does,
+  and add python-pyrad as a build requirement so that we can run its tests
+
+* Wed Dec 18 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.12-4
+- revise previous patch to initialize one more element
+
+* Wed Dec 18 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.12-3
+- backport fixes to krb5_copy_context (RT#7807, #1044735/#1044739)
+
+* Wed Dec 18 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.12-2
+- pull in fix from master to return a NULL pointer rather than allocating
+  zero bytes of memory if we read a zero-length input token (RT#7794, part of
+  #1043962)
+- pull in fix from master to ignore an empty token from an acceptor if
+  we've already finished authenticating (RT#7797, part of #1043962)
+- pull in fix from master to avoid a memory leak when a mechanism's
+  init_sec_context function fails (RT#7803, part of #1043962)
+- pull in fix from master to avoid a memory leak in a couple of error
+  cases which could occur while obtaining acceptor credentials (RT#7805, part
+  of #1043962)
+
+* Wed Dec 11 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.12-1
+- update to 1.12 final
+
+* Mon Dec  2 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.12-beta2.0
+- update to beta2
+  - drop obsolete backports for storing KDC time offsets and expiration times
+    in keyring credential caches
+
+* Tue Nov 19 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.12-beta1.0
+- rebase to master
+- update to beta1
+  - drop obsolete backport of fix for RT#7706
+
+* Mon Nov 18 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.11.4-2
+- pull in fix to store KDC time offsets in keyring credential caches (RT#7768,
+  #1030607)
+- pull in fix to set expiration times on credentials stored in keyring
+  credential caches (RT#7769, #1031724)
+
+* Tue Nov 12 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.11.4-1
+- update to 1.11.4
+  - drop patch for RT#7650, obsoleted
+  - drop patch for RT#7706, obsoleted as RT#7723
+  - drop patch for CVE-2013-1418/CVE-2013-6800, included in 1.11.4
+
+* Tue Nov 12 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.11.3-31
+- switch to the simplified version of the patch for #1029110 (RT#7764)
+
+* Mon Nov 11 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.11.3-30
+- check more thoroughly for errors when resolving KEYRING ccache names of type
+  "persistent", which should only have a numeric UID as the next part of the
+  name (#1029110)
+
+* Tue Nov  5 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.11.3-29
+- incorporate upstream patch for remote crash of KDCs which serve multiple
+  realms simultaneously (RT#7756, CVE-2013-1418/CVE-2013-6800,
+  #1026997/#1031501)
+
+* Mon Nov  4 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.11.3-28
+- drop patch to add additional access() checks to ksu - they add to breakage
+  when non-FILE: caches are in use (#1026099), shouldn't be resulting in any
+  benefit, and clash with proposed changes to fix its cache handling
+
+* Tue Oct 22 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.11.3-27
+- add some minimal description to the top of the wrapper scripts we use
+  when starting krb5kdc and kadmind to describe why they exist (tooling)
+
+* Thu Oct 17 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.12-alpha1.0
+- initial update to alpha1
+  - drop backport of persistent keyring support
+  - drop backport for RT#7689
+  - drop obsolete patch for fixing a use-before-init in a test program
+  - drop obsolete patch teaching config.guess/config.sub about aarch64-linux
+  - drop backport for RT#7598
+  - drop backport for RT#7172
+  - drop backport for RT#7642
+  - drop backport for RT#7643
+  - drop patches from master to not test GSSRPC-over-UDP and to not
+    depend on the portmapper, which are areas where our build systems
+    often give us trouble, too; obsolete
+  - drop backports for RT#7682
+  - drop backport for RT#7709
+  - drop backport for RT#7590 and partial backport for RT#7680
+  - drop OTP backport
+  - drop backports for RT#7656 and RT#7657
+- BuildRequires: libedit-devel to prefer it
+- BuildRequires: pkgconfig, since configure uses it
+
+* Wed Oct 16 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.11.3-26
+- create and own /etc/gss (#1019937)
+
+* Tue Oct 15 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.11.3-25
+- pull up fix for importing previously-exported credential caches in the
+  gssapi library (RT# 7706, #1019420)
+
+* Mon Oct 14 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.11.3-24
+- backport the callback to use the libkrb5 prompter when we can't load PEM
+  files for PKINIT (RT#7590, includes part of #965721/#1016690)
+- extract the rest of the fix #965721/#1016690 from the changes for RT#7680
+
+* Mon Oct 14 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.11.3-23
+- fix trigger scriptlet's invocation of sed (#1016945)
+
+* Fri Oct  4 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.11.3-22
+- rebuild with keyutils 1.5.8 (part of #1012043)
+
+* Wed Oct  2 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.11.3-21
+- switch to the version of persistent-keyring that was just merged to
+  master (RT#7711), along with related changes to kinit (RT#7689)
+- go back to setting default_ccache_name to a KEYRING type
+
+* Mon Sep 30 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.11.3-20
+- pull up fix for not calling a kdb plugin's check-transited-path
+  method before calling the library's default version, which only knows
+  how to read what's in the configuration file (RT#7709, #1013664)
+
+* Thu Sep 26 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.11.3-19
+- configure --without-krb5-config so that we don't pull in the old default
+  ccache name when we want to stop setting a default ccache name at configure-
+  time
+
+* Wed Sep 25 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.11.3-18
+- fix broken dependency on awk (should be gawk, rdieter)
+
+* Wed Sep 25 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.11.3-17
+- add missing dependency on newer keyutils-libs (#1012034)
+
+* Tue Sep 24 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.11.3-16
+- back out setting default_ccache_name to the new default for now, resetting
+  it to the old default while the kernel/keyutils bits get sorted (sgallagh)
+
+* Mon Sep 23 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.11.3-15
+- add explicit build-time dependency on a version of keyutils that's new
+  enough to include keyctl_get_persistent() (more of #991148)
+
+* Thu Sep 19 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.11.3-14
+- incorporate Simo's updated backport of his updated persistent-keyring changes
+  (more of #991148)
+
+* Fri Sep 13 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.11.3-13
+- don't break during %%check when the session keyring is revoked
+
+* Fri Sep 13 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.11.3-12
+- pull the newer F21 defaults back to F20 (sgallagh)
+
+* Mon Sep  9 2013 Nalin Dahyabhai <nalin@redhat.com>
+- only apply the patch to autocreate /run/user/0 when we're hard-wiring the
+  default ccache location to be under it; otherwise it's unnecessary
+
+* Mon Sep  9 2013 Nalin Dahyabhai <nalin@redhat.com> 1.11.3-11
+- don't let comments intended for one scriptlet become part of the "script"
+  that gets passed to ldconfig as part of another one (Mattias Ellert, #1005675)
+
+* Fri Sep  6 2013 Nalin Dahyabhai <nalin@redhat.com> 1.11.3-10
+- incorporate Simo's backport of his persistent-keyring changes (#991148)
+- restore build-time default DEFCCNAME on Fedora 21 and later and EL, and
+  instead set default_ccache_name in the default krb5.conf's [libdefaults]
+  section (#991148)
+- on releases where we expect krb5.conf to be configured with a
+  default_ccache_name, add it whenever we upgrade from an older version of
+  the package that wouldn't have included it in its default configuration
+  file (#991148)
+
+* Fri Aug 23 2013 Nalin Dahyabhai <nalin@redhat.com> 1.11.3-9
+- take another stab at accounting for UnversionedDocdirs for the -libs
+  subpackage (spotted by ssorce)
+- switch to just the snapshot of nss_wrapper we were using, since we
+  no longer need to carry anything that isn't in the cwrap.org repository
+  (ssorce)
+
+* Thu Aug 15 2013 Nalin Dahyabhai <nalin@redhat.com> 1.11.3-8
+- drop a patch we weren't not applying (build tooling)
+- wrap kadmind and kpropd in scripts which check for the presence/absence
+  of files which dictate particular exit codes before exec'ing the actual
+  binaries, instead of trying to use ConditionPathExists in the unit files
+  to accomplish that, so that we exit with failure properly when what we
+  expect isn't actually in effect on the system (#800343)
+
+* Mon Jul 29 2013 Nalin Dahyabhai <nalin@redhat.com> 1.11.3-7
+- attempt to account for UnversionedDocdirs for the -libs subpackage
+
+* Fri Jul 26 2013 Nalin Dahyabhai <nalin@redhat.com> 1.11.3-6
+- tweak configuration files used during tests to try to reduce the number
+  of conflicts encountered when builds for multiple arches land on the same
+  builder
+
+* Mon Jul 22 2013 Nalin Dahyabhai <nalin@redhat.com> 1.11.3-5
+- pull up changes to allow GSSAPI modules to provide more functions
+  (RT#7682, #986564/#986565)
+
+* Fri Jul 19 2013 Nalin Dahyabhai <nalin@redhat.com> 1.11.3-4
+- use (a bundled, for now, copy of) nss_wrapper to let us run some of the
+  self-tests at build-time in more places than we could previously (#978756)
+- cover inconsistencies in whether or not there's a local caching nameserver
+  that's willing to answer when the build environment doesn't have a
+  resolver configuration, so that nss_wrapper's faking of the local
+  hostname can be complete
+
+* Mon Jul  1 2013 Nalin Dahyabhai <nalin@redhat.com> 1.11.3-3
+- specify dependencies on the same arch of krb5-libs by using the %%{?_isa}
+  suffix, to avoid dragging 32-bit libraries onto 64-bit systems (#980155)
+
+* Thu Jun 13 2013 Nalin Dahyabhai <nalin@redhat.com> 1.11.3-2
+- special-case /run/user/0, attempting to create it when resolving a
+  directory cache below it fails due to ENOENT and we find that it doesn't
+  already exist, either, before attempting to create the directory cache
+  (maybe helping, maybe just making things more confusing for #961235)
+
+* Tue Jun  4 2013 Nalin Dahyabhai <nalin@redhat.com> 1.11.3-1
+- update to 1.11.3
+  - drop patch for RT#7605, fixed in this release
+  - drop patch for CVE-2002-2443, fixed in this release
+  - drop patch for RT#7369, fixed in this release
+- pull upstream fix for breaking t_skew.py by adding the patch for #961221
+
+* Fri May 31 2013 Nalin Dahyabhai <nalin@redhat.com> 1.11.2-10
+- respin with updated version of patch for RT#7650 (#969331)
+
+* Thu May 30 2013 Nalin Dahyabhai <nalin@redhat.com> 1.11.2-9
+- don't forget to set the SELinux label when creating the directory for
+  a DIR: ccache
+- pull in proposed fix for attempts to get initial creds, which end up
+  following referrals, incorrectly trying to always use master KDCs if
+  they talked to a master at any point (should fix RT#7650)
+
+* Thu May 30 2013 Nalin Dahyabhai <nalin@redhat.com> 1.11.2-8
+- pull in patches from master to not test GSSRPC-over-UDP and to not
+  depend on the portmapper, which are areas where our build systems
+  often give us trouble, too
+
+* Tue May 28 2013 Nalin Dahyabhai <nalin@redhat.com> 1.11.2-7
+- backport fix for not being able to verify the list of transited realms
+  in GSS acceptors (RT#7639, #959685)
+- backport fix for not being able to pass an empty password to the
+  get-init-creds APIs and have them actually use it (RT#7642, #960001)
+- add backported proposed fix to use the unauthenticated server time
+  as the basis for computing the requested credential expiration times,
+  rather than the client's idea of the current time, which could be
+  significantly incorrect (#961221)
+
+* Tue May 21 2013 Nalin Dahyabhai <nalin@redhat.com> 1.11.2-6
+- pull in upstream fix to start treating a KRB5CCNAME value that begins
+  with DIR:: the same as it would a DIR: value with just one ccache file
+  in it (RT#7172, #965574)
+
+* Mon May 13 2013 Nalin Dahyabhai <nalin@redhat.com> 1.11.2-5
+- pull up fix for UDP ping-pong flaw in kpasswd service (CVE-2002-2443,
+  #962531,#962534)
+
+* Mon Apr 29 2013 Nathaniel McCallum <npmccallum@redhat.com> 1.11.2-4
+- Update otp patches
+- Merge otp patches into a single patch
+- Add keycheck patch
+
+* Tue Apr 23 2013 Nalin Dahyabhai <nalin@redhat.com> 1.11.2-3
+- pull the changing of the compiled-in default ccache location to
+  DIR:/run/user/%%{uid}/krb5cc back into F19, in line with SSSD and
+  the most recent pam_krb5 build
+
+* Wed Apr 17 2013 Nalin Dahyabhai <nalin@redhat.com> 1.11.2-2
+- correct some configuration file paths which the KDC_DIR patch missed
+
+* Mon Apr 15 2013 Nalin Dahyabhai <nalin@redhat.com> 1.11.2-1
+- update to 1.11.2
+  - drop pulled in patch for RT#7586, included in this release
+  - drop pulled in patch for RT#7592, included in this release
+- pull in fix for keeping track of the message type when parsing FAST requests
+  in the KDC (RT#7605, #951843) (also #951965)
+
+* Fri Apr 12 2013 Nalin Dahyabhai <nalin@redhat.com> 1.11.1-9
+- move the compiled-in default ccache location from the previous default of
+  FILE:/tmp/krb5cc_%%{uid} to DIR:/run/user/%%{uid}/krb5cc (part of #949588)
+
+* Tue Apr 09 2013 Nathaniel McCallum <npmccallum@redhat.com> - 1.11.1-8
+- Update otp backport patches (libk5radius => libkrad)
+
+* Wed Apr  3 2013 Nalin Dahyabhai <nalin@redhat.com> 1.11.1-7
+- when testing the RPC library, treat denials from the local portmapper the
+  same as a portmapper-not-running situation, to allow other library tests
+  to be run while building the package
+
+* Thu Mar 28 2013 Nalin Dahyabhai <nalin@redhat.com> 1.11.1-6
+- create and own /var/kerberos/krb5/user instead of /var/kerberos/kdc/user,
+  since that's what the libraries actually look for
+- add buildrequires on nss-myhostname, in an attempt to get more of the tests
+  to run properly during builds
+- pull in Simo's patch to recognize "client_keytab" as a key type which can
+  be passed in to gss_acquire_cred_from() (RT#7598)
+
+* Tue Mar 26 2013 Nalin Dahyabhai <nalin@redhat.com> 1.11.1-5
+- pull up Simo's patch to mark the correct mechanism on imported GSSAPI
+  contexts (RT#7592)
+- go back to using reconf to run autoconf and autoheader (part of #925640)
+- add temporary patch to use newer config.guess/config.sub (more of #925640)
+
+* Mon Mar 18 2013 Nalin Dahyabhai <nalin@redhat.com>
+- fix a version comparison to expect newer texlive build requirements when
+  %%{_rhel} > 6 rather than when it's > 7
+
+* Mon Mar 11 2013 Nathaniel McCallum <npmccallum@redhat.com> 1.11.1-4
+- Add libverto-devel requires for krb5-devel
+- Add otp support
+
+* Thu Feb 28 2013 Nalin Dahyabhai <nalin@redhat.com> 1.11.1-3
+- fix a memory leak when acquiring credentials using a keytab (RT#7586, #911110)
+
+* Wed Feb 27 2013 Nalin Dahyabhai <nalin@redhat.com> 1.11.1-2
+- prebuild PDF docs to reduce multilib differences (internal tooling, #884065)
+- drop the kerberos-iv portreserve file, and drop the rest on systemd systems
+- escape uses of macros in comments (more of #884065)
+
+* Mon Feb 25 2013 Nalin Dahyabhai <nalin@redhat.com> 1.11.1-1
+- update to 1.11.1
+  - drop patch for noticing negative timeouts being passed to the poll()
+    wrapper in the client transmit functions
+
+* Fri Feb  8 2013 Nalin Dahyabhai <nalin@redhat.com> 1.11-2
+- set "rdns = false" in the default krb5.conf (#908323,#908324)
+
+* Tue Dec 18 2012 Nalin Dahyabhai <nalin@redhat.com> 1.11-1
+- update to 1.11 release
+
+* Thu Dec 13 2012 Nalin Dahyabhai <nalin@redhat.com> 1.11-0.beta2.0
+- update to 1.11 beta 2
+
+* Thu Dec 13 2012 Nalin Dahyabhai <nalin@redhat.com>
+- when building with our bundled copy of libverto, package it in with -libs
+  rather than with -server (#886049)
+
+* Wed Nov 21 2012 Nalin Dahyabhai <nalin@redhat.com> 1.11-0.beta1.0
+- update to 1.11 beta 1
+
+* Fri Nov 16 2012 Nalin Dahyabhai <nalin@redhat.com> 1.11-0.alpha1.1
+- handle releases where texlive packaging wasn't yet as complicated as it
+  is in Fedora 18
+- fix an uninitialized-variable error building one of the test programs
+
+* Fri Nov 16 2012 Nalin Dahyabhai <nalin@redhat.com> 1.11-0.alpha1.0
+- move the rather large pile of html and pdf docs to -workstation, so
+  that just having something that links to the libraries won't drag
+  them onto a system, and we avoid having to sort out hard-coded paths
+  that include %%{_libdir} showing up in docs in multilib packages
+- actually create %%{_var}/kerberos/kdc/user, so that it can be packaged
+- correct the list of packaged man pages
+- don't dummy up required tex stylesheets, require them
+- require pdflatex and makeindex
+
+* Thu Nov 15 2012 Nalin Dahyabhai <nalin@redhat.com>
+- update to 1.11 alpha 1
+  - drop backported patch for RT #7406
+  - drop backported patch for RT #7407
+  - drop backported patch for RT #7408
+  - the new docs system generates PDFs, so stop including them as sources
+  - drop backported patch to allow deltat.y to build with the usual
+    warning flags and the current gcc
+  - drop backported fix for disabling use of a replay cache when verifying
+    initial credentials
+  - drop backported fix for teaching PKINIT clients which trust the KDC's
+    certificate directly to verify signed-data messages that are signed with
+    the KDC's certificate, when the blobs don't include a copy of the KDC's
+    certificate
+  - drop backported patches to make keytab-based authentication attempts
+    work better when the client tells the KDC that it supports a particular
+    cipher, but doesn't have a key for it in the keytab
+  - drop backported fix for avoiding spurious clock skew when a TGT is
+    decrypted long after the KDC sent it to the client which decrypts it
+  - move the cross-referenced HTML docs into the -libs package to avoid
+    broken internal links
+  - drop patches to fixup paths in man pages, shouldn't be needed any more
+
+* Wed Oct 17 2012 Nalin Dahyabhai <nalin@redhat.com> 1.10.3-7
+- tag a couple of other patches which we still need to be applied during
+  %%{?_rawbuild} builds (zmraz)
+
+* Tue Sep 25 2012 Nalin Dahyabhai <nalin@redhat.com> 1.10.3-6
+- actually pull up the patch for RT#7063, and not some other ticket (#773496)
+
+* Mon Sep 10 2012 Nalin Dahyabhai <nalin@redhat.com> 1.10.3-5
+- add patch based on one from Filip Krska to not call poll() with a negative
+  timeout when the caller's intent is for us to just stop calling it (#838548)
+
+* Fri Sep  7 2012 Nalin Dahyabhai <nalin@redhat.com>
+- on EL6, conflict with libsmbclient before 3.5.10-124, which is when it
+  stopped linking with a symbol which we no longer export (#771687)
+- pull up patch for RT#7063, in which not noticing a prompt for a long
+  time throws the client library's idea of the time difference between it
+  and the KDC really far out of whack (#773496)
+- add a backport of more patches to set the client's list of supported enctypes
+  when using a keytab to be the list of types of keys in the keytab, plus the
+  list of other types the client supports but for which it doesn't have keys,
+  in that order, so that KDCs have a better chance of being able to issue
+  tickets with session keys of types that the client can use (#837855)
+
+* Thu Sep  6 2012 Nalin Dahyabhai <nalin@redhat.com> 1.10.3-4
+- cut down the number of times we load SELinux labeling configuration from
+  a minimum of two times to actually one (more of #845125)
+
+* Thu Aug 30 2012 Nalin Dahyabhai <nalin@redhat.com> 1.10.3-3
+- backport patch to disable replay detection in krb5_verify_init_creds()
+  while reading the AP-REQ that's generated in the same function (RT#7229)
+
+* Thu Aug 30 2012 Nalin Dahyabhai <nalin@redhat.com> 1.10.3-2
+- undo rename from krb5-pkinit-openssl to krb5-pkinit on EL6
+- version the Obsoletes: on the krb5-pkinit-openssl to krb5-pkinit rename
+- reintroduce the init scripts for non-systemd releases
+- forward-port %%{?_rawbuild} annotations from EL6 packaging
+
+* Thu Aug  9 2012 Nalin Dahyabhai <nalin@redhat.com> 1.10.3-1
+- update to 1.10.3, rolling in the fixes from MITKRB5-SA-2012-001
+
+* Thu Aug  2 2012 Nalin Dahyabhai <nalin@redhat.com> 1.10.2-7
+- selinux: hang on to the list of selinux contexts, freeing and reloading
+  it only when the file we read it from is modified, freeing it when the
+  shared library is being unloaded (#845125)
+
+* Thu Aug  2 2012 Nalin Dahyabhai <nalin@redhat.com> 1.10.2-6
+- go back to not messing with library file paths on Fedora 17: it breaks
+  file path dependencies in other packages, and since Fedora 17 is already
+  released, breaking that is our fault
+
+* Tue Jul 31 2012 Nalin Dahyabhai <nalin@redhat.com> 1.10.2-5
+- add upstream patch to fix freeing an uninitialized pointer and dereferencing
+  another uninitialized pointer in the KDC (MITKRB5-SA-2012-001, CVE-2012-1014
+  and CVE-2012-1015, #844779 and #844777)
+- fix a thinko in whether or not we mess around with devel .so symlinks on
+  systems without a separate /usr (sbose)
+
+* Fri Jul 27 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.10.2-4
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild
+
+* Fri Jun 22 2012 Nalin Dahyabhai <nalin@redhat.com> 1.10.2-3
+- backport a fix to allow a PKINIT client to handle SignedData from a KDC
+  that's signed with a certificate that isn't in the SignedData, but which
+  is available as an anchor or intermediate on the client (RT#7183)
+
+* Tue Jun  5 2012 Nalin Dahyabhai <nalin@redhat.com> 1.10.2-2
+- back out this labeling change (dwalsh):
+  - when building the new label for a file we're about to create, also mix
+    in the current range, in addition to the current user
+
+* Fri Jun  1 2012 Nalin Dahyabhai <nalin@redhat.com> 1.10.2-1
+- update to 1.10.2
+  - when building the new label for a file we're about to create, also mix
+    in the current range, in addition to the current user
+  - also package the PDF format admin, user, and install guides
+  - drop some PDFs that no longer get built right
+- add a backport of Stef's patch to set the client's list of supported
+  enctypes to match the types of keys that we have when we are using a
+  keytab to try to get initial credentials, so that a KDC won't send us
+  an AS reply that we can't encrypt (RT#2131, #748528)
+- don't shuffle around any shared libraries on releases with no-separate-/usr,
+  since /usr/lib is the same place as /lib
+- add explicit buildrequires: on 'hostname', for the tests, on systems where
+  it's in its own package, and require net-tools, which used to provide the
+  command, everywhere
+
+* Mon May  7 2012 Nalin Dahyabhai <nalin@redhat.com>
+- skip the setfscreatecon() if fopen() is passed "rb" as the open mode (part
+  of #819115)
+
+* Tue May  1 2012 Nalin Dahyabhai <nalin@redhat.com> 1.10.1-3
+- have -server require /usr/share/dict/words, which we set as the default
+  dict_file in kdc.conf (#817089)
+
+* Tue Mar 20 2012 Nalin Dahyabhai <nalin@redhat.com> 1.10.1-2
+- change back dns_lookup_kdc to the default setting (Stef Walter, #805318)
+- comment out example.com examples in default krb5.conf (Stef Walter, #805320)
+
+* Fri Mar  9 2012 Nalin Dahyabhai <nalin@redhat.com> 1.10.1-1
+- update to 1.10.1
+  - drop the KDC crash fix
+  - drop the KDC lookaside cache fix
+  - drop the fix for kadmind RPC ACLs (CVE-2012-1012)
+
+* Wed Mar  7 2012 Nalin Dahyabhai <nalin@redhat.com> 1.10-5
+- when removing -workstation, remove our files from the info index while
+  the file is still there, in %%preun, rather than %%postun, and use the
+  compressed file's name (#801035)
+
+* Tue Feb 21 2012 Nathaniel McCallum <nathaniel@natemccallum.com> - 1.10-4
+- Fix string RPC ACLs (RT#7093); CVE-2012-1012
+
+* Tue Jan 31 2012 Nathaniel McCallum <nathaniel@natemccallum.com> - 1.10-3
+- Add upstream lookaside cache behavior fix (RT#7082)
+
+* Mon Jan 30 2012 Nalin Dahyabhai <nalin@redhat.com> 1.10-2
+- add patch to accept keytab entries with vno==0 as matches when we're
+  searching for an entry with a specific name/kvno (#230382/#782211,RT#3349)
+
+* Mon Jan 30 2012 Nalin Dahyabhai <nalin@redhat.com> 1.10-1
+- update to 1.10 final
+
+* Thu Jan 26 2012 Nathaniel McCallum <nathaniel@natemccallum.com> - 1.10-0.beta1.2
+- Add upstream crashfix patch (RT#7081)
+
+* Thu Jan 12 2012 Nalin Dahyabhai <nalin@redhat.com> 1.10-0.beta1.1
+- update to beta 1
+
+* Wed Jan 11 2012 Peter Robinson <pbrobinson@gmail.com>
+- mktemp was long obsoleted by coreutils
+
+* Wed Jan  4 2012 Nalin Dahyabhai <nalin@redhat.com> 1.10-0.alpha2.2
+- modify the deltat grammar to also tell gcc (4.7) to suppress
+  "maybe-uninitialized" warnings in addition to the "uninitialized" warnings
+  it's already being told to suppress (RT#7080)
+
+* Tue Dec 20 2011 Nalin Dahyabhai <nalin@redhat.com> 1.10-0.alpha2.1
+- update to alpha 2
+- drop a couple of patches which were integrated for alpha 2
+
+* Tue Dec 13 2011 Nalin Dahyabhai <nalin@redhat.com> 1.10-0.alpha1.3
+- pull in patch for RT#7046: tag a ccache containing credentials obtained via
+  S4U2Proxy with the principal name of the proxying principal (part of #761317)
+  so that the default principal name can be set to that of the client for which
+  it is proxying, which results in the ccache looking more normal to consumers
+  of the ccache that don't care that there's proxying going on
+- pull in patch for RT#7047: allow tickets obtained via S4U2Proxy to be cached
+  (more of #761317)
+- pull in patch for RT#7048: allow PAC verification to only bother trying to
+  verify the signature with keys that it's given (still more of #761317)
+
+* Tue Dec  6 2011 Nalin Dahyabhai <nalin@redhat.com> 1.10-0.alpha1.2
+- apply upstream patch to fix a null pointer dereference when processing
+  TGS requests (CVE-2011-1530, #753748)
+
+* Wed Nov 30 2011 Nalin Dahyabhai <nalin@redhat.com> 1.10-0.alpha1.1
+- correct a bug in the fix for #754001 so that the file creation context is
+  consistently reset
+
+* Tue Nov 15 2011 Nalin Dahyabhai <nalin@redhat.com> 1.10-0.alpha1.0
+- update to 1.10 alpha 1
+- on newer releases where we can assume NSS >= 3.13, configure PKINIT to build
+  using NSS
+- on newer releases where we build PKINIT using NSS, configure libk5crypto to
+  build using NSS
+- rename krb5-pkinit-openssl to krb5-pkinit on newer releases where we're
+  expecting to build PKINIT using NSS instead
+- during %%check, run check in the library and kdc subdirectories, which
+  should be able to run inside of the build system without issue
+
+* Wed Oct 26 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.9.1-19
+- Rebuilt for glibc bug#747377
+
+* Tue Oct 18 2011 Nalin Dahyabhai <nalin@redhat.com> 1.9.1-18
+- apply upstream patch to fix a null pointer dereference with the LDAP kdb
+  backend (CVE-2011-1527, #744125), an assertion failure with multiple kdb
+  backends (CVE-2011-1528), and a null pointer dereference with multiple kdb
+  backends (CVE-2011-1529) (#737711)
+
+* Thu Oct 13 2011 Nalin Dahyabhai <nalin@redhat.com> 1.9.1-17
+- pull in patch from trunk to rename krb5int_pac_sign() to krb5_pac_sign() and
+  make it public (#745533)
+
+* Fri Oct  7 2011 Nalin Dahyabhai <nalin@redhat.com> 1.9.1-16
+- kadmin.service: fix #723723 again
+- kadmin.service,krb5kdc.service: remove optional use of $KRB5REALM in command
+  lines, because systemd parsing doesn't handle alternate value shell variable
+  syntax
+- kprop.service: add missing Type=forking so that systemd doesn't assume simple
+- kprop.service: expect the ACL configuration to be there, not absent
+- handle a harder-to-trigger assertion failure that starts cropping up when we
+  exit the transmit loop on time (#739853)
+
+* Sun Oct  2 2011 Tom Callaway <spot@fedoraproject.org> 1.9.1-15
+- hardcode pid file as option in krb5kdc.service
+
+* Fri Sep 30 2011 Tom Callaway <spot@fedoraproject.org> 1.9.1-14
+- fix pid path in krb5kdc.service
+
+* Mon Sep 19 2011 Tom Callaway <spot@fedoraproject.org> 1.9.1-13
+- convert to systemd
+
+* Tue Sep  6 2011 Nalin Dahyabhai <nalin@redhat.com> 1.9.1-12
+- pull in upstream patch for RT#6952, confusion following referrals for
+  cross-realm auth (#734341)
+- pull in build-time deps for the tests
+
+* Thu Sep  1 2011 Nalin Dahyabhai <nalin@redhat.com> 1.9.1-11
+- switch to the upstream patch for #727829
+
+* Wed Aug 31 2011 Nalin Dahyabhai <nalin@redhat.com> 1.9.1-10
+- handle an assertion failure that starts cropping up when the patch for
+  using poll (#701446) meets servers that aren't running KDCs or against
+  which the connection fails for other reasons (#727829, #734172)
+
+* Mon Aug  8 2011 Nalin Dahyabhai <nalin@redhat.com> 1.9.1-9
+- override the default build rules to not delete temporary y.tab.c files,
+  so that they can be packaged, allowing debuginfo files which point to them
+  do so usefully (#729044)
+
+* Fri Jul 22 2011 Nalin Dahyabhai <nalin@redhat.com> 1.9.1-8
+- build shared libraries with partial RELRO support (#723995)
+- filter out potentially multiple instances of -Wl,-z,relro from krb5-config
+  output, now that it's in the buildroot's default LDFLAGS
+- pull in a patch to fix losing track of the replay cache FD, from SVN by
+  way of Kevin Coffman
+
+* Wed Jul 20 2011 Nalin Dahyabhai <nalin@redhat.com> 1.9.1-7
+- kadmind.init: drop the attempt to detect no-database-present errors (#723723),
+  which is too fragile in cases where the database has been manually moved or
+  is accessed through another kdb plugin
+
+* Tue Jul 19 2011 Nalin Dahyabhai <nalin@redhat.com> 1.9.1-6
+- backport fixes to teach libkrb5 to use descriptors higher than FD_SETSIZE
+  to talk to a KDC by using poll() if it's detected at compile-time (#701446,
+  RT#6905)
+
+* Thu Jun 23 2011 Nalin Dahyabhai <nalin@redhat.com> 1.9.1-5
+- pull a fix from SVN to try to avoid triggering a PTR lookup in getaddrinfo()
+  during krb5_sname_to_principal(), and to let getaddrinfo() decide whether or
+  not to ask for an IPv6 address based on the set of configured interfaces
+  (#717378, RT#6922)
+- pull a fix from SVN to use AI_ADDRCONFIG more often (RT#6923)
+
+* Mon Jun 20 2011 Nalin Dahyabhai <nalin@redhat.com> 1.9.1-4
+- apply upstream patch by way of Burt Holzman to fall back to a non-referral
+  method in cases where we might be derailed by a KDC that rejects the
+  canonicalize option (for example, those from the RHEL 2.1 or 3 era) (#715074)
+
+* Tue Jun 14 2011 Nalin Dahyabhai <nalin@redhat.com> 1.9.1-3
+- pull a fix from SVN to get libgssrpc clients (e.g. kadmin) authenticating
+  using the old protocol over IPv4 again (RT#6920)
+
+* Tue Jun 14 2011 Nalin Dahyabhai <nalin@redhat.com>
+- incorporate a fix to teach the file labeling bits about when replay caches
+  are expunged (#576093)
+
+* Thu May 26 2011 Nalin Dahyabhai <nalin@redhat.com>
+- switch to the upstream patch for #707145
+
+* Wed May 25 2011 Nalin Dahyabhai <nalin@redhat.com> 1.9.1-2
+- klist: don't trip over referral entries when invoked with -s (#707145,
+  RT#6915)
+
+* Fri May  6 2011 Nalin Dahyabhai <nalin@redhat.com>
+- fixup URL in a comment
+- when built with NSS, require 3.12.10 rather than 3.12.9
+
+* Thu May  5 2011 Nalin Dahyabhai <nalin@redhat.com> 1.9.1-1
+- update to 1.9.1:
+  - drop no-longer-needed patches for CVE-2010-4022, CVE-2011-0281,
+    CVE-2011-0282, CVE-2011-0283, CVE-2011-0284, CVE-2011-0285
+
+* Wed Apr 13 2011 Nalin Dahyabhai <nalin@redhat.com> 1.9-9
+- kadmind: add upstream patch to fix free() on an invalid pointer (#696343,
+  MITKRB5-SA-2011-004, CVE-2011-0285)
+
+* Mon Apr  4 2011 Nalin Dahyabhai <nalin@redhat.com>
+- don't discard the error code from an error message received in response
+  to a change-password request (#658871, RT#6893)
+
+* Fri Apr  1 2011 Nalin Dahyabhai <nalin@redhat.com>
+- override INSTALL_SETUID at build-time so that ksu is installed into
+  the buildroot with the right permissions (part of #225974)
+
+* Fri Mar 18 2011 Nalin Dahyabhai <nalin@redhat.com> 1.9-8
+- backport change from SVN to fix a computed-value-not-used warning in
+  kpropd (#684065)
+
+* Tue Mar 15 2011 Nalin Dahyabhai <nalin@redhat.com> 1.9-7
+- turn off NSS as the backend for libk5crypto for now to work around its
+  DES string2key not working (#679012)
+- add revised upstream patch to fix double-free in KDC while returning
+  typed-data with errors (MITKRB5-SA-2011-003, CVE-2011-0284, #674325)
+
+* Thu Feb 17 2011 Nalin Dahyabhai <nalin@redhat.com>
+- throw in a not-applied-by-default patch to try to make pkinit debugging
+  into a run-time boolean option named "pkinit_debug"
+
+* Wed Feb 16 2011 Nalin Dahyabhai <nalin@redhat.com> 1.9-6
+- turn on NSS as the backend for libk5crypto, adding nss-devel as a build
+  dependency when that switch is flipped
+
+* Wed Feb  9 2011 Nalin Dahyabhai <nalin@redhat.com> 1.9-5
+- krb5kdc init script: prototype some changes to do a quick spot-check
+  of the TGS and kadmind keys and warn if there aren't any non-weak keys
+  on file for them (to flush out parts of #651466)
+
+* Tue Feb  8 2011 Nalin Dahyabhai <nalin@redhat.com> 1.9-4
+- add upstream patches to fix standalone kpropd exiting if the per-client
+  child process exits with an error (MITKRB5-SA-2011-001), a hang or crash
+  in the KDC when using the LDAP kdb backend, and an uninitialized pointer
+  use in the KDC (MITKRB5-SA-2011-002) (CVE-2010-4022, #664009,
+  CVE-2011-0281, #668719, CVE-2011-0282, #668726, CVE-2011-0283, #676126)
+
+* Mon Feb 07 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.9-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
+
+* Mon Feb  7 2011 Nalin Dahyabhai <nalin@redhat.com>
+- fix a compile error in the SELinux labeling patch when -DDEBUG is used (Sumit
+  Bose)
+
+* Tue Feb  1 2011 Nalin Dahyabhai <nalin@redhat.com>
+- properly advertise that the kpropd init script now supports force-reload
+  (Zbysek Mraz, #630587)
+
+* Wed Jan 26 2011 Nalin Dahyabhai <nalin@redhat.com> 1.9-2
+- pkinit: when verifying signed data, use the CMS APIs for better
+  interoperability (#636985, RT#6851)
+
+* Wed Dec 22 2010 Nalin Dahyabhai <nalin@redhat.com> 1.9-1
+- update to 1.9 final
+
+* Mon Dec 20 2010 Nalin Dahyabhai <nalin@redhat.com> 1.9-0.beta3.1
+- fix link flags and permissions on shared libraries (ausil)
+
+* Thu Dec 16 2010 Nalin Dahyabhai <nalin@redhat.com> 1.9-0.beta3.0
+- update to 1.9 beta 3
+
+* Mon Dec  6 2010 Nalin Dahyabhai <nalin@redhat.com> 1.9-0.beta2.0
+- update to 1.9 beta 2
+
+* Tue Nov  9 2010 Nalin Dahyabhai <nalin@redhat.com> 1.9-0.beta1.1
+- drop not-needed-since-1.8 build dependency on rsh (ssorce)
+
+* Fri Nov  5 2010 Nalin Dahyabhai <nalin@redhat.com> 1.9-0.beta1.0
+- start moving to 1.9 with beta 1
+  - drop patches for RT#5755, RT#6762, RT#6774, RT#6775
+  - drop no-longer-needed backport patch for #539423
+  - drop no-longer-needed patch for CVE-2010-1322
+- if WITH_NSS is set, built with --with-crypto-impl=nss (requires NSS 3.12.9)
+
+* Tue Oct  5 2010 Nalin Dahyabhai <nalin@redhat.com> 1.8.3-8
+- incorporate upstream patch to fix uninitialized pointer crash in the KDC's
+  authorization data handling (CVE-2010-1322, #636335)
+
+* Mon Oct  4 2010 Nalin Dahyabhai <nalin@redhat.com> 1.8.3-7
+- rebuild
+
+* Mon Oct  4 2010 Nalin Dahyabhai <nalin@redhat.com> 1.8.3-6
+- pull down patches from trunk to implement k5login_authoritative and
+  k5login_directory settings for krb5.conf (#539423)
+
+* Wed Sep 29 2010 jkeating - 1.8.3-5
+- Rebuilt for gcc bug 634757
+
+* Wed Sep 15 2010 Nalin Dahyabhai <nalin@redhat.com> 1.8.3-4
+- fix reading of keyUsage extensions when attempting to select pkinit client
+  certs (part of #629022, RT#6775)
+- fix selection of pkinit client certs when one or more don't include a
+  subjectAltName extension (part of #629022, RT#6774)
+
+* Fri Sep  3 2010 Nalin Dahyabhai <nalin@redhat.com> 1.8.3-3
+- build with -fstack-protector-all instead of the default -fstack-protector,
+  so that we add checking to more functions (i.e., all of them) (#629950)
+- also link binaries with -Wl,-z,relro,-z,now (part of #629950)
+
+* Tue Aug 24 2010 Nalin Dahyabhai <nalin@redhat.com> 1.8.3-2
+- fix a logic bug in computing key expiration times (RT#6762, #627022)
+
+* Wed Aug  4 2010 Nalin Dahyabhai <nalin@redhat.com> 1.8.3-1
+- update to 1.8.3
+  - drop backports of fixes for gss context expiration and error table
+    registration/deregistration mismatch
+  - drop patch for upstream #6750
+
+* Wed Jul  7 2010 Nalin Dahyabhai <nalin@redhat.com> 1.8.2-3
+- tell krb5kdc and kadmind to create pid files, since they can
+- add logrotate configuration files for krb5kdc and kadmind (#462658)
+- fix parsing of the pidfile option in the KDC (upstream #6750)
+
+* Mon Jun 21 2010 Nalin Dahyabhai <nalin@redhat.com> 1.8.2-2
+- libgssapi: pull in patch from svn to stop returning context-expired errors
+  when the ticket which was used to set up the context expires (#605366,
+  upstream #6739)
+
+* Mon Jun 21 2010 Nalin Dahyabhai <nalin@redhat.com>
+- pull up fix for upstream #6745, in which the gssapi library would add the
+  wrong error table but subsequently attempt to unload the right one
+
+* Thu Jun 10 2010 Nalin Dahyabhai <nalin@redhat.com> 1.8.2-1
+- update to 1.8.2
+  - drop patches for CVE-2010-1320, CVE-2010-1321
+
+* Tue Jun  1 2010 Nalin Dahyabhai <nalin@redhat.com> 1.8.1-7
+- rebuild
+
+* Thu May 27 2010 Nalin Dahyabhai <nalin@redhat.com>
+- ksu: move session management calls to before we drop privileges, like
+  su does (#596887), and don't skip the PAM account check for root or the
+  same user (more of #540769)
+
+* Mon May 24 2010 Nalin Dahyabhai <nalin@redhat.com> 1.8.1-6
+- make krb5-server-ldap also depend on the same version-release of krb5-libs,
+  as the other subpackages do, if only to make it clearer than it is when we
+  just do it through krb5-server
+- drop explicit linking with libtinfo for applications that use libss, now
+  that readline itself links with libtinfo (as of readline-5.2-3, since
+  fedora 7 or so)
+- go back to building without strict aliasing (compiler warnings in gssrpc)
+
+* Tue May 18 2010 Nalin Dahyabhai <nalin@redhat.com> 1.8.1-5
+- add patch to correct GSSAPI library null pointer dereference which could be
+  triggered by malformed client requests (CVE-2010-1321, #582466)
+
+* Tue May  4 2010 Nalin Dahyabhai <nalin@redhat.com> 1.8.1-4
+- fix output of kprop's init script's "status" and "reload" commands (#588222)
+
+* Tue Apr 20 2010 Nalin Dahyabhai <nalin@redhat.com> 1.8.1-3
+- incorporate patch to fix double-free in the KDC (CVE-2010-1320, #581922)
+
+* Wed Apr 14 2010 Nalin Dahyabhai <nalin@redhat.com> 1.8.1-2
+- fix a typo in kerberos.ldif
+
+* Fri Apr  9 2010 Nalin Dahyabhai <nalin@redhat.com> 1.8.1-1
+- update to 1.8.1
+  - no longer need patches for #555875, #561174, #563431, RT#6661, CVE-2010-0628
+- replace buildrequires on tetex-latex with one on texlive-latex, which is
+  the package that provides it now
+
+* Thu Apr  8 2010 Nalin Dahyabhai <nalin@redhat.com>
+- kdc.conf: no more need to suggest a v4 mode, or listening on the v4 port
+
+* Thu Apr  8 2010 Nalin Dahyabhai <nalin@redhat.com>
+- drop patch to suppress key expiration warnings sent from the KDC in
+  the last-req field, as the KDC is expected to just be configured to either
+  send them or not as a particular key approaches expiration (#556495)
+
+* Tue Mar 23 2010 Nalin Dahyabhai <nalin@redhat.com> - 1.8-5
+- add upstream fix for denial-of-service in SPNEGO (CVE-2010-0628, #576325)
+- kdc.conf: no more need to suggest keeping keys with v4-compatible salting
+
+* Fri Mar 19 2010 Nalin Dahyabhai <nalin@redhat.com> - 1.8-4
+- remove the krb5-appl bits (the -workstation-clients and -workstation-servers
+  subpackages) now that krb5-appl is its own package
+- replace our patch for #563431 (kpasswd doesn't fall back to guessing your
+  principal name using your user name if you don't have a ccache) with the
+  one upstream uses
+
+* Fri Mar 12 2010 Nalin Dahyabhai <nalin@redhat.com> - 1.8-3
+- add documentation for the ticket_lifetime option (#561174)
+
+* Mon Mar  8 2010 Nalin Dahyabhai <nalin@redhat.com> - 1.8-2
+- pull up patch to get the client libraries to correctly perform password
+  changes over IPv6 (Sumit Bose, RT#6661)
+
+* Fri Mar  5 2010 Nalin Dahyabhai <nalin@redhat.com> - 1.8-1
+- update to 1.8
+  - temporarily bundling the krb5-appl package (split upstream as of 1.8)
+    until its package review is complete
+  - profile.d scriptlets are now only needed by -workstation-clients
+  - adjust paths in init scripts
+  - drop upstreamed fix for KDC denial of service (CVE-2010-0283)
+  - drop patch to check the user's password correctly using crypt(), which
+    isn't a code path we hit when we're using PAM
+
+* Wed Mar  3 2010 Nalin Dahyabhai <nalin@redhat.com> - 1.7.1-6
+- fix a null pointer dereference and crash introduced in our PAM patch that
+  would happen if ftpd was given the name of a user who wasn't known to the
+  local system, limited to being triggerable by gssapi-authenticated clients by
+  the default xinetd config (Olivier Fourdan, #569472)
+
+* Tue Mar  2 2010 Nalin Dahyabhai <nalin@redhat.com> - 1.7.1-5
+- fix a regression (not labeling a kdb database lock file correctly, #569902)
+
+* Thu Feb 25 2010 Nalin Dahyabhai <nalin@redhat.com> - 1.7.1-4
+- move the package changelog to the end to match the usual style (jdennis)
+- scrub out references to $RPM_SOURCE_DIR (jdennis)
+- include a symlink to the readme with the name LICENSE so that people can
+  find it more easily (jdennis)
+
+* Wed Feb 17 2010 Nalin Dahyabhai <nalin@redhat.com> - 1.7.1-3
+- pull up the change to make kpasswd's behavior better match the docs
+  when there's no ccache (#563431)
+
+* Tue Feb 16 2010 Nalin Dahyabhai <nalin@redhat.com> - 1.7.1-2
+- apply patch from upstream to fix KDC denial of service (CVE-2010-0283,
+  #566002)
+
+* Wed Feb  3 2010 Nalin Dahyabhai <nalin@redhat.com> - 1.7.1-1
+- update to 1.7.1
+  - don't trip AD lockout on wrong password (#542687, #554351)
+  - incorporates fixes for CVE-2009-4212 and CVE-2009-3295
+  - fixes gss_krb5_copy_ccache() when SPNEGO is used
+- move sim_client/sim_server, gss-client/gss-server, uuclient/uuserver to
+  the devel subpackage, better lining up with the expected krb5/krb5-appl
+  split in 1.8
+- drop kvno,kadmin,k5srvutil,ktutil from -workstation-servers, as it already
+  depends on -workstation which also includes them
+
+* Mon Jan 25 2010 Nalin Dahyabhai <nalin@redhat.com> - 1.7-23
+- tighten up default permissions on kdc.conf and kadm5.acl (#558343)
+
+* Fri Jan 22 2010 Nalin Dahyabhai <nalin@redhat.com> - 1.7-22
+- use portreserve correctly -- portrelease takes the basename of the file
+  whose entries should be released, so we need three files, not one
+
+* Mon Jan 18 2010 Nalin Dahyabhai <nalin@redhat.com> - 1.7-21
+- suppress warnings of impending password expiration if expiration is more than
+  seven days away when the KDC reports it via the last-req field, just as we
+  already do when it reports expiration via the key-expiration field (#556495)
+- link with libtinfo rather than libncurses, when we can, in future RHEL
+
+* Fri Jan 15 2010 Nalin Dahyabhai <nalin@redhat.com> - 1.7-20
+- krb5_get_init_creds_password: check opte->flags instead of options->flags
+  when checking whether or not we get to use the prompter callback (#555875)
+
+* Thu Jan 14 2010 Nalin Dahyabhai <nalin@redhat.com> - 1.7-19
+- use portreserve to make sure the KDC can always bind to the kerberos-iv
+  port, kpropd can always bind to the krb5_prop port, and that kadmind can
+  always bind to the kerberos-adm port (#555279)
+- correct inadvertent use of macros in the changelog (rpmlint)
+
+* Tue Jan 12 2010 Nalin Dahyabhai <nalin@redhat.com> - 1.7-18
+- add upstream patch for integer underflow during AES and RC4 decryption
+  (CVE-2009-4212), via Tom Yu (#545015)
+
+* Wed Jan  6 2010 Nalin Dahyabhai <nalin@redhat.com> - 1.7-17
+- put the conditional back for the -devel subpackage
+- back down to the earlier version of the patch for #551764; the backported
+  alternate version was incomplete
+
+* Tue Jan  5 2010 Nalin Dahyabhai <nalin@redhat.com> - 1.7-16
+- use %%global instead of %%define
+- pull up proposed patch for creating previously-not-there lock files for
+  kdb databases when 'kdb5_util' is called to 'load' (#551764)
+
+* Mon Jan  4 2010 Dennis Gregorovic <dgregor@redhat.com>
+- fix conditional for future RHEL
+
+* Mon Jan  4 2010 Nalin Dahyabhai <nalin@redhat.com> - 1.7-15
+- add upstream patch for KDC crash during referral processing (CVE-2009-3295),
+  via Tom Yu (#545002)
+
+* Mon Dec 21 2009 Nalin Dahyabhai <nalin@redhat.com> - 1.7-14
+- refresh patch for #542868 from trunk
+
+* Thu Dec 10 2009 Nalin Dahyabhai <nalin@redhat.com>
+- move man pages that live in the -libs subpackage into the regular
+  %%{_mandir} tree where they'll still be found if that package is the
+  only one installed (#529319)
+
+* Wed Dec  9 2009 Nalin Dahyabhai <nalin@redhat.com> - 1.7-13
+- and put it back in
+
+* Tue Dec  8 2009 Nalin Dahyabhai <nalin@redhat.com>
+- back that last change out
+
+* Tue Dec  8 2009 Nalin Dahyabhai <nalin@redhat.com> - 1.7-12
+- try to make gss_krb5_copy_ccache() work correctly for spnego (#542868)
+
+* Fri Dec  4 2009 Nalin Dahyabhai <nalin@redhat.com>
+- make krb5-config suppress CFLAGS output when called with --libs (#544391)
+
+* Thu Dec  3 2009 Nalin Dahyabhai <nalin@redhat.com> - 1.7-11
+- ksu: move account management checks to before we drop privileges, like
+  su does (#540769)
+- selinux: set the user part of file creation contexts to match the current
+  context instead of what we looked up
+- configure with --enable-dns-for-realm instead of --enable-dns, which isn't
+  recognized any more
+
+* Fri Nov 20 2009 Nalin Dahyabhai <nalin@redhat.com> - 1.7-10
+- move /etc/pam.d/ksu from krb5-workstation-servers to krb5-workstation,
+  where it's actually needed (#538703)
+
+* Fri Oct 23 2009 Nalin Dahyabhai <nalin@redhat.com> - 1.7-9
+- add some conditional logic to simplify building on older Fedora releases
+
+* Tue Oct 13 2009 Nalin Dahyabhai <nalin@redhat.com>
+- don't forget the README
+
+* Mon Sep 14 2009 Nalin Dahyabhai <nalin@redhat.com> - 1.7-8
+- specify the location of the subsystem lock when using the status() function
+  in the kadmind and kpropd init scripts, so that we get the right error when
+  we're dead but have a lock file - requires initscripts 8.99 (#521772)
+
+* Tue Sep  8 2009 Nalin Dahyabhai <nalin@redhat.com>
+- if the init script fails to start krb5kdc/kadmind/kpropd because it's already
+  running (according to status()), return 0 (part of #521772)
+
+* Mon Aug 24 2009 Nalin Dahyabhai <nalin@redhat.com> - 1.7-7
+- work around a compile problem with new openssl
+
+* Fri Aug 21 2009 Tomas Mraz <tmraz@redhat.com> - 1.7-6
+- rebuilt with new openssl
+
+* Fri Jul 24 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.7-5
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild
+
+* Tue Jul  7 2009 Nalin Dahyabhai <nalin@redhat.com> 1.7-5
+- rebuild to pick up the current forms of various patches
+
+* Mon Jul  6 2009 Nalin Dahyabhai <nalin@redhat.com>
+- simplify the man pages patch by only preprocessing the files we care about
+  and moving shared configure.in logic into a shared function
+- catch the case of ftpd printing file sizes using %%i, when they might be
+  bigger than an int now
+
+* Tue Jun 30 2009 Nalin Dahyabhai <nalin@redhat.com> 1.7-4
+- try to merge and clean up all the large file support for ftp and rcp
+  - ftpd no longer prints a negative length when sending a large file
+    from a 32-bit host
+
+* Tue Jun 30 2009 Nalin Dahyabhai <nalin@redhat.com>
+- pam_rhosts_auth.so's been gone, use pam_rhosts.so instead
+
+* Mon Jun 29 2009 Nalin Dahyabhai <nalin@redhat.com> 1.7-3
+- switch buildrequires: and requires: on e2fsprogs-devel into
+  buildrequires: and requires: on libss-devel, libcom_err-devel, per
+  sandeen on fedora-devel-list
+
+* Fri Jun 26 2009 Nalin Dahyabhai <nalin@redhat.com>
+- fix a type mismatch in krb5_copy_error_message()
+- ftp: fix some odd use of strlen()
+- selinux labeling: use selabel_open() family of functions rather than
+  matchpathcon(), bail on it if attempting to get the mutex lock fails
+
+* Tue Jun 16 2009 Nalin Dahyabhai <nalin@redhat.com>
+- compile with %%{?_smp_mflags} (Steve Grubb)
+- drop the bit where we munge part of the error table header, as it's not
+  needed any more
+
+* Fri Jun  5 2009 Nalin Dahyabhai <nalin@redhat.com> 1.7-2
+- add and own %%{_libdir}/krb5/plugins/authdata
+
+* Thu Jun  4 2009 Nalin Dahyabhai <nalin@redhat.com> 1.7-1
+- update to 1.7
+  - no need to work around build issues with ASN1BUF_OMIT_INLINE_FUNCS
+  - configure recognizes --enable/--disable-pkinit now
+  - configure can take --disable-rpath now
+  - no more libdes425, krb524d, krb425.info
+  - kadmin/k5srvutil/ktutil are user commands now
+  - new kproplog
+  - FAST encrypted-challenge plugin is new
+- drop static build logic
+- drop pam_krb5-specific configuration from the default krb5.conf
+- drop only-use-v5 flags being passed to various things started by xinetd
+- put %%{krb5prefix}/sbin in everyone's path, too (#504525)
+
+* Tue May 19 2009 Nalin Dahyabhai <nalin@redhat.com> 1.6.3-106
+- add an auth stack to ksu's PAM configuration so that pam_setcred() calls
+  won't just fail
+
+* Mon May 11 2009 Nalin Dahyabhai <nalin@redhat.com> 1.6.3-105
+- make PAM support for ksu also set PAM_RUSER
+
+* Thu Apr 23 2009 Nalin Dahyabhai <nalin@redhat.com> 1.6.3-104
+- extend PAM support to ksu: perform account and session management for the
+  target user
+- pull up and merge James Leddy's changes to also set PAM_RHOST in PAM-aware
+  network-facing services
+
+* Tue Apr 21 2009 Nalin Dahyabhai <nalin@redhat.com> 1.6.3-103
+- fix a typo in a ksu error message (Marek Mahut)
+- "rev" works the way the test suite expects now, so don't disable tests
+  that use it
+
+* Mon Apr 20 2009 Nalin Dahyabhai <nalin@redhat.com> 1.6.3-102
+- add LSB-style init script info
+
+* Fri Apr 17 2009 Nalin Dahyabhai <nalin@redhat.com>
+- explicitly run the pdf generation script using sh (part of #225974)
+
+* Tue Apr  7 2009 Nalin Dahyabhai <nalin@redhat.com> 1.6.3-101
+- add patches for read overflow and null pointer dereference in the
+  implementation of the SPNEGO mechanism (CVE-2009-0844, CVE-2009-0845)
+- add patch for attempt to free uninitialized pointer in libkrb5
+  (CVE-2009-0846)
+- add patch to fix length validation bug in libkrb5 (CVE-2009-0847)
+- put the krb5-user .info file into just -workstation and not also
+  -workstation-clients
+
+* Mon Apr  6 2009 Nalin Dahyabhai <nalin@redhat.com> 1.6.3-100
+- turn off krb4 support (it won't be part of the 1.7 release, but do it now)
+- use triggeruns to properly shut down and disable krb524d when -server and
+  -workstation-servers gets upgraded, because it's gone now
+- move the libraries to /%%{_lib}, but leave --libdir alone so that plugins
+  get installed and are searched for in the same locations (#473333)
+- clean up buildprereq/prereqs, explicit mktemp requires, and add the
+  ldconfig for the -server-ldap subpackage (part of #225974)
+- escape possible macros in the changelog (part of #225974)
+- fixup summary texts (part of #225974)
+- take the execute bit off of the protocol docs (part of #225974)
+- unflag init scripts as configuration files (part of #225974)
+- make the kpropd init script treat 'reload' as 'restart' (part of #225974)
+
+* Tue Mar 17 2009 Nalin Dahyabhai <nalin@redhat.com> 1.6.3-19
+- libgssapi_krb5: backport fix for some errors which can occur when
+  we fail to set up the server half of a context (CVE-2009-0845)
+
+* Wed Feb 25 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.6.3-18
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild
+
+* Fri Jan 16 2009 Nalin Dahyabhai <nalin@redhat.com> 1.6.3-17
+- rebuild
+
+* Thu Sep  4 2008 Nalin Dahyabhai <nalin@redhat.com>
+- if we successfully change the user's password during an attempt to get
+  initial credentials, but then fail to get initial creds from a non-master
+  using the new password, retry against the master (#432334)
+
+* Tue Aug  5 2008 Tom "spot" Callaway <tcallawa@redhat.com> 1.6.3-16
+- fix license tag
+
+* Wed Jul 16 2008 Nalin Dahyabhai <nalin@redhat.com>
+- clear fuzz out of patches, dropping a man page patch which is no longer
+  necessary
+- quote %%{__cc} where needed because it includes whitespace now
+- define ASN1BUF_OMIT_INLINE_FUNCS at compile-time (for now) to keep building
+
+* Fri Jul 11 2008 Nalin Dahyabhai <nalin@redhat.com> 1.6.3-15
+- build with -fno-strict-aliasing, which is needed because the library
+  triggers these warnings
+- don't forget to label principal database lock files
+- fix the labeling patch so that it doesn't break bootstrapping
+
+* Sat Jun 14 2008 Tom "spot" Callaway <tcallawa@redhat.com> 1.6.3-14
+- generate src/include/krb5/krb5.h before building
+- fix conditional for sparcv9
+
+* Wed Apr 16 2008 Nalin Dahyabhai <nalin@redhat.com> 1.6.3-13
+- ftp: use the correct local filename during mget when the 'case' option is
+  enabled (#442713)
+
+* Fri Apr  4 2008 Nalin Dahyabhai <nalin@redhat.com> 1.6.3-12
+- stop exporting kadmin keys to a keytab file when kadmind starts -- the
+  daemon's been able to use the database directly for a long long time now
+- belatedly add aes128,aes256 to the default set of supported key types
+
+* Tue Apr  1 2008 Nalin Dahyabhai <nalin@redhat.com> 1.6.3-11
+- libgssapi_krb5: properly export the acceptor subkey when creating a lucid
+  context (Kevin Coffman, via the nfs4 mailing list)
+
+* Tue Mar 18 2008 Nalin Dahyabhai <nalin@redhat.com> 1.6.3-10
+- add fixes from MITKRB5-SA-2008-001 for use of null or dangling pointer
+  when v4 compatibility is enabled on the KDC (CVE-2008-0062, CVE-2008-0063,
+  #432620, #432621)
+- add fixes from MITKRB5-SA-2008-002 for array out-of-bounds accesses when
+  high-numbered descriptors are used (CVE-2008-0947, #433596)
+- add backport bug fix for an attempt to free non-heap memory in
+  libgssapi_krb5 (CVE-2007-5901, #415321)
+- add backport bug fix for a double-free in out-of-memory situations in
+  libgssapi_krb5 (CVE-2007-5971, #415351)
+
+* Tue Mar 18 2008 Nalin Dahyabhai <nalin@redhat.com> 1.6.3-9
+- rework file labeling patch to not depend on fragile preprocessor trickery,
+  in another attempt at fixing #428355 and friends
+
+* Tue Feb 26 2008 Nalin Dahyabhai <nalin@redhat.com> 1.6.3-8
+- ftp: add patch to fix "runique on" case when globbing fixes applied
+- stop adding a redundant but harmless call to initialize the gssapi internals
+
+* Mon Feb 25 2008 Nalin Dahyabhai <nalin@redhat.com>
+- add patch to suppress double-processing of /etc/krb5.conf when we build
+  with --sysconfdir=/etc, thereby suppressing double-logging (#231147)
+
+* Mon Feb 25 2008 Nalin Dahyabhai <nalin@redhat.com>
+- remove a patch, to fix problems with interfaces which are "up" but which
+  have no address assigned, which conflicted with a different fix for the same
+  problem in 1.5 (#200979)
+
+* Mon Feb 25 2008 Nalin Dahyabhai <nalin@redhat.com>
+- ftp: don't lose track of a descriptor on passive get when the server fails to
+  open a file
+
+* Mon Feb 25 2008 Nalin Dahyabhai <nalin@redhat.com>
+- in login, allow PAM to interact with the user when they've been strongly
+  authenticated
+- in login, signal PAM when we're changing an expired password that it's an
+  expired password, so that when cracklib flags a password as being weak it's
+  treated as an error even if we're running as root
+
+* Mon Feb 18 2008 Nalin Dahyabhai <nalin@redhat.com> 1.6.3-7
+- drop netdb patch
+- kdb_ldap: add patch to treat 'nsAccountLock: true' as an indication that
+  the DISALLOW_ALL_TIX flag is set on an entry, for better interop with Fedora,
+  Netscape, Red Hat Directory Server (Simo Sorce)
+
+* Wed Feb 13 2008 Nalin Dahyabhai <nalin@redhat.com> 1.6.3-6
+- patch to avoid depending on <netdb.h> to define NI_MAXHOST and NI_MAXSERV
+
+* Tue Feb 12 2008 Nalin Dahyabhai <nalin@redhat.com> 1.6.3-5
+- enable patch for key-expiration reporting
+- enable patch to make kpasswd fall back to TCP if UDP fails (#251206)
+- enable patch to make kpasswd use the right sequence number on retransmit
+- enable patch to allow mech-specific creds delegated under spnego to be found
+  when searching for creds
+
+* Wed Jan  2 2008 Nalin Dahyabhai <nalin@redhat.com> 1.6.3-4
+- some init script cleanups
+  - drop unquoted check and silent exit for "$NETWORKING" (#426852, #242502)
+  - krb524: don't barf on missing database if it looks like we're using kldap,
+    same as for kadmin
+  - return non-zero status for missing files which cause startup to
+    fail (#242502)
+
+* Tue Dec 18 2007 Nalin Dahyabhai <nalin@redhat.com> 1.6.3-3
+- allocate space for the nul-terminator in the local pathname when looking up
+  a file context, and properly free a previous context (Jose Plans, #426085)
+
+* Wed Dec  5 2007 Nalin Dahyabhai <nalin@redhat.com> 1.6.3-2
+- rebuild
+
+* Tue Oct 23 2007 Nalin Dahyabhai <nalin@redhat.com> 1.6.3-1
+- update to 1.6.3, dropping now-integrated patches for CVE-2007-3999
+  and CVE-2007-4000 (the new pkinit module is built conditionally and goes
+  into the -pkinit-openssl package, at least for now, to make a buildreq
+  loop with openssl avoidable)
+
+* Wed Oct 17 2007 Nalin Dahyabhai <nalin@redhat.com> 1.6.2-10
+- make proper use of pam_loginuid and pam_selinux in rshd and ftpd
+
+* Fri Oct 12 2007 Nalin Dahyabhai <nalin@redhat.com>
+- make krb5.conf %%verify(not md5 size mtime) in addition to
+  %%config(noreplace), like /etc/nsswitch.conf (#329811)
+
+* Mon Oct  1 2007 Nalin Dahyabhai <nalin@redhat.com> 1.6.2-9
+- apply the fix for CVE-2007-4000 instead of the experimental patch for
+  setting ok-as-delegate flags
+
+* Tue Sep 11 2007 Nalin Dahyabhai <nalin@redhat.com> 1.6.2-8
+- move the db2 kdb plugin from -server to -libs, because a multilib libkdb
+  might need it
+
+* Tue Sep 11 2007 Nalin Dahyabhai <nalin@redhat.com> 1.6.2-7
+- also perform PAM session and credential management when ftpd accepts a
+  client using strong authentication, missed earlier
+- also label kadmind log files and files created by the db2 plugin
+
+* Thu Sep  6 2007 Nalin Dahyabhai <nalin@redhat.com> 1.6.2-6
+- incorporate updated fix for CVE-2007-3999 (CVE-2007-4743)
+- fix incorrect call to "test" in the kadmin init script (#252322,#287291)
+
+* Tue Sep  4 2007 Nalin Dahyabhai <nalin@redhat.com> 1.6.2-5
+- incorporate fixes for MITKRB5-SA-2007-006 (CVE-2007-3999, CVE-2007-4000)
+
+* Sat Aug 25 2007 Nalin Dahyabhai <nalin@redhat.com> 1.6.2-4
+- cover more cases in labeling files on creation
+- add missing gawk build dependency
+
+* Thu Aug 23 2007 Nalin Dahyabhai <nalin@redhat.com> 1.6.2-3
+- rebuild
+
+* Thu Jul 26 2007 Nalin Dahyabhai <nalin@redhat.com> 1.6.2-2
+- kdc.conf: default to listening for TCP clients, too (#248415)
+
+* Thu Jul 19 2007 Nalin Dahyabhai <nalin@redhat.com> 1.6.2-1
+- update to 1.6.2
+- add "buildrequires: texinfo-tex" to get texi2pdf
+
+* Wed Jun 27 2007 Nalin Dahyabhai <nalin@redhat.com> 1.6.1-8
+- incorporate fixes for MITKRB5-SA-2007-004 (CVE-2007-2442,CVE-2007-2443)
+  and MITKRB5-SA-2007-005 (CVE-2007-2798)
+
+* Mon Jun 25 2007 Nalin Dahyabhai <nalin@redhat.com> 1.6.1-7
+- reintroduce missing %%postun for the non-split_workstation case
+
+* Mon Jun 25 2007 Nalin Dahyabhai <nalin@redhat.com> 1.6.1-6
+- rebuild
+
+* Mon Jun 25 2007 Nalin Dahyabhai <nalin@redhat.com> 1.6.1-5.1
+- rebuild
+
+* Sun Jun 24 2007 Nalin Dahyabhai <nalin@redhat.com> 1.6.1-5
+- add missing pam-devel build requirement, force selinux-or-fail build
+
+* Sun Jun 24 2007 Nalin Dahyabhai <nalin@redhat.com> 1.6.1-4
+- rebuild
+
+* Sun Jun 24 2007 Nalin Dahyabhai <nalin@redhat.com> 1.6.1-3
+- label all files at creation-time according to the SELinux policy (#228157)
+
+* Fri Jun 22 2007 Nalin Dahyabhai <nalin@redhat.com>
+- perform PAM account / session management in krshd (#182195,#195922)
+- perform PAM authentication and account / session management in ftpd
+- perform PAM authentication, account / session management, and password-
+  changing in login.krb5 (#182195,#195922)
+
+* Fri Jun 22 2007 Nalin Dahyabhai <nalin@redhat.com>
+- preprocess kerberos.ldif into a format FDS will like better, and include
+  that as a doc file as well
+
+* Fri Jun 22 2007 Nalin Dahyabhai <nalin@redhat.com>
+- switch man pages to being generated with the right paths in them
+- drop old, incomplete SELinux patch
+- add patch from Greg Hudson to make srvtab routines report missing-file errors
+  at same point that keytab routines do (#241805)
+
+* Thu May 24 2007 Nalin Dahyabhai <nalin@redhat.com> 1.6.1-2
+- pull patch from svn to undo unintentional chattiness in ftp
+- pull patch from svn to handle NULL krb5_get_init_creds_opt structures
+  better in a couple of places where they're expected
+
+* Wed May 23 2007 Nalin Dahyabhai <nalin@redhat.com> 1.6.1-1
+- update to 1.6.1
+  - drop no-longer-needed patches for CVE-2007-0956,CVE-2007-0957,CVE-2007-1216
+  - drop patch for sendto bug in 1.6, fixed in 1.6.1
+
+* Fri May 18 2007 Nalin Dahyabhai <nalin@redhat.com>
+- kadmind.init: don't fail outright if the default principal database
+  isn't there if it looks like we might be using the kldap plugin
+- kadmind.init: attempt to extract the key for the host-specific kadmin
+  service when we try to create the keytab
+
+* Wed May 16 2007 Nalin Dahyabhai <nalin@redhat.com> 1.6-6
+- omit dependent libraries from the krb5-config --libs output, as using
+  shared libraries (no more static libraries) makes them unnecessary and
+  they're not part of the libkrb5 interface (patch by Rex Dieter, #240220)
+  (strips out libkeyutils, libresolv, libdl)
+
+* Fri May  4 2007 Nalin Dahyabhai <nalin@redhat.com> 1.6-5
+- pull in keyutils as a build requirement to get the "KEYRING:" ccache type,
+  because we've merged
+
+* Fri May  4 2007 Nalin Dahyabhai <nalin@redhat.com> 1.6-4
+- fix an uninitialized length value which could cause a crash when parsing
+  key data coming from a directory server
+- correct a typo in the krb5.conf man page ("ldap_server"->"ldap_servers")
+
+* Fri Apr 13 2007 Nalin Dahyabhai <nalin@redhat.com>
+- move the default acl_file, dict_file, and admin_keytab settings to
+  the part of the default/example kdc.conf where they'll actually have
+  an effect (#236417)
+
+* Thu Apr  5 2007 Nalin Dahyabhai <nalin@redhat.com> 1.5-24
+- merge security fixes from RHSA-2007:0095
+
+* Tue Apr  3 2007 Nalin Dahyabhai <nalin@redhat.com> 1.6-3
+- add patch to correct unauthorized access via krb5-aware telnet
+  daemon (#229782, CVE-2007-0956)
+- add patch to fix buffer overflow in krb5kdc and kadmind
+  (#231528, CVE-2007-0957)
+- add patch to fix double-free in kadmind (#231537, CVE-2007-1216)
+
+* Thu Mar 22 2007 Nalin Dahyabhai <nalin@redhat.com>
+- back out buildrequires: keyutils-libs-devel for now
+
+* Thu Mar 22 2007 Nalin Dahyabhai <nalin@redhat.com> 1.6-2
+- add buildrequires: on keyutils-libs-devel to enable use of keyring ccaches,
+  dragging keyutils-libs in as a dependency
+
+* Mon Mar 19 2007 Nalin Dahyabhai <nalin@redhat.com> 1.5-23
+- fix bug ID in changelog
+
+* Thu Mar 15 2007 Nalin Dahyabhai <nalin@redhat.com> 1.5-22
+
+* Thu Mar 15 2007 Nalin Dahyabhai <nalin@redhat.com> 1.5-21
+- add preliminary patch to fix buffer overflow in krb5kdc and kadmind
+  (#231528, CVE-2007-0957)
+- add preliminary patch to fix double-free in kadmind (#231537, CVE-2007-1216)
+
+* Wed Feb 28 2007 Nalin Dahyabhai <nalin@redhat.com>
+- add patch to build semi-useful static libraries, but don't apply it unless
+  we need them
+
+* Tue Feb 27 2007 Nalin Dahyabhai <nalin@redhat.com> - 1.5-20
+- temporarily back out %%post changes, fix for #143289 for security update
+- add preliminary patch to correct unauthorized access via krb5-aware telnet
+
+* Mon Feb 19 2007 Nalin Dahyabhai <nalin@redhat.com>
+- make profile.d scriptlets mode 644 instead of 755 (part of #225974)
+
+* Tue Jan 30 2007 Nalin Dahyabhai <nalin@redhat.com> 1.6-1
+- clean up quoting of command-line arguments passed to the krsh/krlogin
+  wrapper scripts
+
+* Mon Jan 22 2007 Nalin Dahyabhai <nalin@redhat.com>
+- initial update to 1.6, pre-package-reorg
+- move workstation daemons to a new subpackage (#81836, #216356, #217301), and
+  make the new subpackage require xinetd (#211885)
+
+* Mon Jan 22 2007 Nalin Dahyabhai <nalin@redhat.com> - 1.5-18
+- make use of install-info more failsafe (Ville Skyttä, #223704)
+- preserve timestamps on shell scriptlets at %%install-time
+
+* Tue Jan 16 2007 Nalin Dahyabhai <nalin@redhat.com> - 1.5-17
+- move to using pregenerated PDF docs to cure multilib conflicts (#222721)
+
+* Fri Jan 12 2007 Nalin Dahyabhai <nalin@redhat.com> - 1.5-16
+- update backport of the preauth module interface (part of #194654)
+
+* Tue Jan  9 2007 Nalin Dahyabhai <nalin@redhat.com> - 1.5-14
+- apply fixes from Tom Yu for MITKRB5-SA-2006-002 (CVE-2006-6143) (#218456)
+- apply fixes from Tom Yu for MITKRB5-SA-2006-003 (CVE-2006-6144) (#218456)
+
+* Wed Dec 20 2006 Nalin Dahyabhai <nalin@redhat.com> - 1.5-12
+- update backport of the preauth module interface
+
+* Mon Oct 30 2006 Nalin Dahyabhai <nalin@redhat.com>
+- update backport of the preauth module interface
+- add proposed patches 4566, 4567
+- add proposed edata reporting interface for KDC
+- add temporary placeholder for module global context fixes
+
+* Mon Oct 23 2006 Nalin Dahyabhai <nalin@redhat.com> - 1.5-11
+- don't bail from the KDC init script if there's no database, it may be in
+  a different location than the default (fenlason)
+- remove the [kdc] section from the default krb5.conf -- doesn't seem to have
+  been applicable for a while
+
+* Wed Oct 18 2006 Nalin Dahyabhai <nalin@redhat.com> - 1.5-10
+- rename krb5.sh and krb5.csh so that they don't overlap (#210623)
+- way-late application of added error info in kadmind.init (#65853)
+
+* Wed Oct 18 2006 Nalin Dahyabhai <nalin@redhat.com> - 1.5-9.pal_18695
+- add backport of in-development preauth module interface (#208643)
+
+* Mon Oct  9 2006 Nalin Dahyabhai <nalin@redhat.com> - 1.5-9
+- provide docs in PDF format instead of as tex source (Enrico Scholz, #209943)
+
+* Wed Oct  4 2006 Nalin Dahyabhai <nalin@redhat.com> - 1.5-8
+- add missing shebang headers to krsh and krlogin wrapper scripts (#209238)
+
+* Wed Sep  6 2006 Nalin Dahyabhai <nalin@redhat.com> - 1.5-7
+- set SS_LIB at configure-time so that libss-using apps get working readline
+  support (#197044)
+
+* Fri Aug 18 2006 Nalin Dahyabhai <nalin@redhat.com> - 1.5-6
+- switch to the updated patch for MITKRB-SA-2006-001
+
+* Tue Aug  8 2006 Nalin Dahyabhai <nalin@redhat.com> - 1.5-5
+- apply patch to address MITKRB-SA-2006-001 (CVE-2006-3084)
+
+* Mon Aug  7 2006 Nalin Dahyabhai <nalin@redhat.com> - 1.5-4
+- ensure that the gssapi library's been initialized before walking the
+  internal mechanism list in gss_release_oid(), needed if called from
+  gss_release_name() right after a gss_import_name() (#198092)
+
+* Tue Jul 25 2006 Nalin Dahyabhai <nalin@redhat.com> - 1.5-3
+- rebuild
+
+* Tue Jul 25 2006 Nalin Dahyabhai <nalin@redhat.com> - 1.5-2
+- pull up latest revision of patch to reduce lockups in rsh/rshd
+
+* Mon Jul 17 2006 Nalin Dahyabhai <nalin@redhat.com> - 1.5-1.2
+- rebuild
+
+* Wed Jul 12 2006 Jesse Keating <jkeating@redhat.com> - 1.5-1.1
+- rebuild
+
+* Thu Jul  6 2006 Nalin Dahyabhai <nalin@redhat.com> 1.5-1
+- build
+
+* Wed Jul  5 2006 Nalin Dahyabhai <nalin@redhat.com> 1.5-0
+- update to 1.5
+
+* Fri Jun 23 2006 Nalin Dahyabhai <nalin@redhat.com> 1.4.3-9
+- mark profile.d config files noreplace (Laurent Rineau, #196447)
+
+* Thu Jun  8 2006 Nalin Dahyabhai <nalin@redhat.com> 1.4.3-8
+- add buildprereq for autoconf
+
+* Mon May 22 2006 Nalin Dahyabhai <nalin@redhat.com> 1.4.3-7
+- further munge krb5-config so that 'libdir=/usr/lib' is given even on 64-bit
+  architectures, to avoid multilib conflicts; other changes will conspire to
+  strip out the -L flag which uses this, so it should be harmless (#192692)
+
+* Fri Apr 28 2006 Nalin Dahyabhai <nalin@redhat.com> 1.4.3-6
+- adjust the patch which removes the use of rpath to also produce a
+  krb5-config which is okay in multilib environments (#190118)
+- make the name-of-the-tempfile comment which compile_et adds to error code
+  headers always list the same file to avoid conflicts on multilib installations
+- strip SIZEOF_LONG out of krb5.h so that it doesn't conflict on multilib boxes
+- strip GSS_SIZEOF_LONG out of gssapi.h so that it doesn't conflict on mulitlib
+  boxes
+
+* Fri Apr 14 2006 Stepan Kasal <skasal@redhat.com> 1.4.3-5
+- Fix formatting typo in kinit.1 (krb5-kinit-man-typo.patch)
+
+* Fri Feb 10 2006 Jesse Keating <jkeating@redhat.com> 1.4.3-4.1
+- bump again for double-long bug on ppc(64)
+
+* Mon Feb  6 2006 Nalin Dahyabhai <nalin@redhat.com> 1.4.3-4
+- give a little bit more information to the user when kinit gets the catch-all
+  I/O error (#180175)
+
+* Thu Jan 19 2006 Nalin Dahyabhai <nalin@redhat.com> 1.4.3-3
+- rebuild properly when pthread_mutexattr_setrobust_np() is defined but not
+  declared, such as with recent glibc when _GNU_SOURCE isn't being used
+
+* Thu Jan 19 2006 Matthias Clasen <mclasen@redhat.com> 1.4.3-2
+- Use full paths in krb5.sh to avoid path lookups
+
+* Fri Dec 09 2005 Jesse Keating <jkeating@redhat.com>
+- rebuilt
+
+* Thu Dec  1 2005 Nalin Dahyabhai <nalin@redhat.com>
+- login: don't truncate passwords before passing them into crypt(), in
+  case they're significant (#149476)
+
+* Thu Nov 17 2005 Nalin Dahyabhai <nalin@redhat.com> 1.4.3-1
+- update to 1.4.3
+- make ksu setuid again (#137934, others)
+
+* Tue Sep 13 2005 Nalin Dahyabhai <nalin@redhat.com> 1.4.2-4
+- mark %%{krb5prefix}/man so that files which are packaged within it are
+  flagged as %%doc (#168163)
+
+* Tue Sep  6 2005 Nalin Dahyabhai <nalin@redhat.com> 1.4.2-3
+- add an xinetd configuration file for encryption-only telnetd, parallelling
+  the kshell/ekshell pair (#167535)
+
+* Wed Aug 31 2005 Nalin Dahyabhai <nalin@redhat.com> 1.4.2-2
+- change the default configured encryption type for KDC databases to the
+  compiled-in default of des3-hmac-sha1 (#57847)
+
+* Thu Aug 11 2005 Nalin Dahyabhai <nalin@redhat.com> 1.4.2-1
+- update to 1.4.2, incorporating the fixes for MIT-KRB5-SA-2005-002 and
+  MIT-KRB5-SA-2005-003
+
+* Wed Jun 29 2005 Nalin Dahyabhai <nalin@redhat.com> 1.4.1-6
+- rebuild
+
+* Wed Jun 29 2005 Nalin Dahyabhai <nalin@redhat.com> 1.4.1-5
+- fix telnet client environment variable disclosure the same way NetKit's
+  telnet client did (CAN-2005-0488) (#159305)
+- keep apps which call krb5_principal_compare() or krb5_realm_compare() with
+  malformed or NULL principal structures from crashing outright (Thomas Biege)
+  (#161475)
+
+* Tue Jun 28 2005 Nalin Dahyabhai <nalin@redhat.com>
+- apply fixes from draft of MIT-KRB5-SA-2005-002 (CAN-2005-1174,CAN-2005-1175)
+  (#157104)
+- apply fixes from draft of MIT-KRB5-SA-2005-003 (CAN-2005-1689) (#159755)
+
+* Fri Jun 24 2005 Nalin Dahyabhai <nalin@redhat.com> 1.4.1-4
+- fix double-close in keytab handling
+- add port of fixes for CAN-2004-0175 to krb5-aware rcp (#151612)
+
+* Fri May 13 2005 Nalin Dahyabhai <nalin@redhat.com> 1.4.1-3
+- prevent spurious EBADF in krshd when stdin is closed by the client while
+  the command is running (#151111)
+
+* Fri May 13 2005 Martin Stransky <stransky@redhat.com> 1.4.1-2
+- add deadlock patch, removed old patch
+
+* Fri May  6 2005 Nalin Dahyabhai <nalin@redhat.com> 1.4.1-1
+- update to 1.4.1, incorporating fixes for CAN-2005-0468 and CAN-2005-0469
+- when starting the KDC or kadmind, if KRB5REALM is set via the /etc/sysconfig
+  file for the service, pass it as an argument for the -r flag
+
+* Wed Mar 23 2005 Nalin Dahyabhai <nalin@redhat.com> 1.4-3
+- drop krshd patch for now
+
+* Thu Mar 17 2005 Nalin Dahyabhai <nalin@redhat.com>
+- add draft fix from Tom Yu for slc_add_reply() buffer overflow (CAN-2005-0469)
+- add draft fix from Tom Yu for env_opt_add() buffer overflow (CAN-2005-0468)
+
+* Wed Mar 16 2005 Nalin Dahyabhai <nalin@redhat.com> 1.4-2
+- don't include <term.h> into the telnet client when we're not using curses
+
+* Thu Feb 24 2005 Nalin Dahyabhai <nalin@redhat.com> 1.4-1
+- update to 1.4
+  - v1.4 kadmin client requires a v1.4 kadmind on the server, or use the "-O"
+    flag to specify that it should communicate with the server using the older
+    protocol
+  - new libkrb5support library
+  - v5passwdd and kadmind4 are gone
+  - versioned symbols
+- pick up $KRB5KDC_ARGS from /etc/sysconfig/krb5kdc, if it exists, and pass
+  it on to krb5kdc
+- pick up $KADMIND_ARGS from /etc/sysconfig/kadmin, if it exists, and pass
+  it on to kadmind
+- pick up $KRB524D_ARGS from /etc/sysconfig/krb524, if it exists, and pass
+  it on to krb524d *instead of* "-m"
+- set "forwardable" in [libdefaults] in the default krb5.conf to match the
+  default setting which we supply for pam_krb5
+- set a default of 24h for "ticket_lifetime" in [libdefaults], reflecting the
+  compiled-in default
+
+* Mon Dec 20 2004 Nalin Dahyabhai <nalin@redhat.com> 1.3.6-3
+- rebuild
+
+* Mon Dec 20 2004 Nalin Dahyabhai <nalin@redhat.com> 1.3.6-2
+- rebuild
+
+* Mon Dec 20 2004 Nalin Dahyabhai <nalin@redhat.com> 1.3.6-1
+- update to 1.3.6, which includes the previous fix
+
+* Mon Dec 20 2004 Nalin Dahyabhai <nalin@redhat.com> 1.3.5-8
+- apply fix from Tom Yu for MITKRB5-SA-2004-004 (CAN-2004-1189)
+
+* Fri Dec 17 2004 Martin Stransky <stransky@redhat.com> 1.3.5-7
+- fix deadlock during file transfer via rsync/krsh
+- thanks goes to James Antill for hint
+
+* Fri Nov 26 2004 Nalin Dahyabhai <nalin@redhat.com> 1.3.5-6
+- rebuild
+
+* Mon Nov 22 2004 Nalin Dahyabhai <nalin@redhat.com> 1.3.5-3
+- fix predictable-tempfile-name bug in krb5-send-pr (CAN-2004-0971, #140036)
+
+* Tue Nov 16 2004 Nalin Dahyabhai <nalin@redhat.com>
+- silence compiler warning in kprop by using an in-memory ccache with a fixed
+  name instead of an on-disk ccache with a name generated by tmpnam()
+
+* Tue Nov 16 2004 Nalin Dahyabhai <nalin@redhat.com> 1.3.5-2
+- fix globbing patch port mode (#139075)
+
+* Mon Nov  1 2004 Nalin Dahyabhai <nalin@redhat.com> 1.3.5-1
+- fix segfault in telnet due to incorrect checking of gethostbyname_r result
+  codes (#129059)
+
+* Fri Oct 15 2004 Nalin Dahyabhai <nalin@redhat.com>
+- remove rc4-hmac:norealm and rc4-hmac:onlyrealm from the default list of
+  supported keytypes in kdc.conf -- they produce exactly the same keys as
+  rc4-hmac:normal because rc4 string-to-key ignores salts
+- nuke kdcrotate -- there are better ways to balance the load on KDCs, and
+  the SELinux policy for it would have been scary-looking
+- update to 1.3.5, mainly to include MITKRB5SA 2004-002 and 2004-003
+
+* Tue Aug 31 2004 Nalin Dahyabhai <nalin@redhat.com> 1.3.4-7
+- rebuild
+
+* Tue Aug 24 2004 Nalin Dahyabhai <nalin@redhat.com> 1.3.4-6
+- rebuild
+
+* Tue Aug 24 2004 Nalin Dahyabhai <nalin@redhat.com> 1.3.4-5
+- incorporate revised fixes from Tom Yu for CAN-2004-0642, CAN-2004-0644,
+  CAN-2004-0772
+
+* Mon Aug 23 2004 Nalin Dahyabhai <nalin@redhat.com> 1.3.4-4
+- rebuild
+
+* Mon Aug 23 2004 Nalin Dahyabhai <nalin@redhat.com> 1.3.4-3
+- incorporate fixes from Tom Yu for CAN-2004-0642, CAN-2004-0772
+  (MITKRB5-SA-2004-002, #130732)
+- incorporate fixes from Tom Yu for CAN-2004-0644 (MITKRB5-SA-2004-003, #130732)
+
+* Tue Jul 27 2004 Nalin Dahyabhai <nalin@redhat.com> 1.3.4-2
+- fix indexing error in server sorting patch (#127336)
+
+* Tue Jun 15 2004 Elliot Lee <sopwith@redhat.com>
+- rebuilt
+
+* Mon Jun 14 2004 Nalin Dahyabhai <nalin@redhat.com> 1.3.4-0.1
+- update to 1.3.4 final
+
+* Mon Jun  7 2004 Nalin Dahyabhai <nalin@redhat.com> 1.3.4-0
+- update to 1.3.4 beta1
+- remove MITKRB5-SA-2004-001, included in 1.3.4
+
+* Mon Jun  7 2004 Nalin Dahyabhai <nalin@redhat.com> 1.3.3-8
+- rebuild
+
+* Fri Jun  4 2004 Nalin Dahyabhai <nalin@redhat.com> 1.3.3-7
+- rebuild
+
+* Fri Jun  4 2004 Nalin Dahyabhai <nalin@redhat.com> 1.3.3-6
+- apply updated patch from MITKRB5-SA-2004-001 (revision 2004-06-02)
+
+* Tue Jun  1 2004 Nalin Dahyabhai <nalin@redhat.com> 1.3.3-5
+- rebuild
+
+* Tue Jun  1 2004 Nalin Dahyabhai <nalin@redhat.com> 1.3.3-4
+- apply patch from MITKRB5-SA-2004-001 (#125001)
+
+* Wed May 12 2004 Thomas Woerner <twoerner@redhat.com> 1.3.3-3
+- removed rpath
+
+* Thu Apr 15 2004 Nalin Dahyabhai <nalin@redhat.com> 1.3.3-2
+- re-enable large file support, fell out in 1.3-1
+- patch rcp to use long long and %%lld format specifiers when reporting file
+  sizes on large files
+
+* Tue Apr 13 2004 Nalin Dahyabhai <nalin@redhat.com> 1.3.3-1
+- update to 1.3.3
+
+* Wed Mar 10 2004 Nalin Dahyabhai <nalin@redhat.com> 1.3.2-1
+- update to 1.3.2
+
+* Mon Mar  8 2004 Nalin Dahyabhai <nalin@redhat.com> 1.3.1-12
+- rebuild
+
+* Tue Mar 02 2004 Elliot Lee <sopwith@redhat.com> 1.3.1-11.1
+- rebuilt
+
+* Fri Feb 13 2004 Elliot Lee <sopwith@redhat.com> 1.3.1-11
+- rebuilt
+
+* Mon Feb  9 2004 Nalin Dahyabhai <nalin@redhat.com> 1.3.1-10
+- catch krb4 send_to_kdc cases in kdc preference patch
+
+* Mon Feb  2 2004 Nalin Dahyabhai <nalin@redhat.com> 1.3.1-9
+- remove patch to set TERM in klogind which, combined with the upstream fix in
+  1.3.1, actually produces the bug now (#114762)
+
+* Mon Jan 19 2004 Nalin Dahyabhai <nalin@redhat.com> 1.3.1-8
+- when iterating over lists of interfaces which are "up" from getifaddrs(),
+  skip over those which have no address (#113347)
+
+* Mon Jan 12 2004 Nalin Dahyabhai <nalin@redhat.com>
+- prefer the kdc which last replied to a request when sending requests to kdcs
+
+* Mon Nov 24 2003 Nalin Dahyabhai <nalin@redhat.com> 1.3.1-7
+- fix combination of --with-netlib and --enable-dns (#82176)
+
+* Tue Nov 18 2003 Nalin Dahyabhai <nalin@redhat.com>
+- remove libdefault ticket_lifetime option from the default krb5.conf, it is
+  ignored by libkrb5
+
+* Thu Sep 25 2003 Nalin Dahyabhai <nalin@redhat.com> 1.3.1-6
+- fix bug in patch to make rlogind start login with a clean environment a la
+  netkit rlogin, spotted and fixed by Scott McClung
+
+* Tue Sep 23 2003 Nalin Dahyabhai <nalin@redhat.com> 1.3.1-5
+- include profile.d scriptlets in krb5-devel so that krb5-config will be in
+  the path if krb5-workstation isn't installed, reported by Kir Kolyshkin
+
+* Mon Sep  8 2003 Nalin Dahyabhai <nalin@redhat.com>
+- add more etypes (arcfour) to the default enctype list in kdc.conf
+- don't apply previous patch, refused upstream
+
+* Fri Sep  5 2003 Nalin Dahyabhai <nalin@redhat.com> 1.3.1-4
+- fix 32/64-bit bug storing and retrieving the issue_date in v4 credentials
+
+* Wed Sep 3 2003 Dan Walsh <dwalsh@redhat.com> 1.3.1-3
+- Don't check for write access on /etc/krb5.conf if SELinux
+
+* Tue Aug 26 2003 Nalin Dahyabhai <nalin@redhat.com> 1.3.1-2
+- fixup some int/pointer varargs wackiness
+
+* Tue Aug  5 2003 Nalin Dahyabhai <nalin@redhat.com> 1.3.1-1
+- rebuild
+
+* Mon Aug  4 2003 Nalin Dahyabhai <nalin@redhat.com> 1.3.1-0
+- update to 1.3.1
+
+* Thu Jul 24 2003 Nalin Dahyabhai <nalin@redhat.com> 1.3-2
+- pull fix for non-compliant encoding of salt field in etype-info2 preauth
+  data from 1.3.1 beta 1, until 1.3.1 is released.
+
+* Mon Jul 21 2003 Nalin Dahyabhai <nalin@redhat.com> 1.3-1
+- update to 1.3
+
+* Mon Jul  7 2003 Nalin Dahyabhai <nalin@redhat.com> 1.2.8-4
+- correctly use stdargs
+
+* Wed Jun 18 2003 Nalin Dahyabhai <nalin@redhat.com> 1.3-0.beta.4
+- test update to 1.3 beta 4
+- ditch statglue build option
+- krb5-devel requires e2fsprogs-devel, which now provides libss and libcom_err
+
+* Wed Jun 04 2003 Elliot Lee <sopwith@redhat.com>
+- rebuilt
+
+* Wed May 21 2003 Jeremy Katz <katzj@redhat.com> 1.2.8-2
+- gcc 3.3 doesn't implement varargs.h, include stdarg.h instead
+
+* Wed Apr  9 2003 Nalin Dahyabhai <nalin@redhat.com> 1.2.8-1
+- update to 1.2.8
+
+* Mon Mar 31 2003 Nalin Dahyabhai <nalin@redhat.com> 1.2.7-14
+- fix double-free of enc_part2 in krb524d
+
+* Fri Mar 21 2003 Nalin Dahyabhai <nalin@redhat.com> 1.2.7-13
+- update to latest patch kit for MITKRB5-SA-2003-004
+
+* Wed Mar 19 2003 Nalin Dahyabhai <nalin@redhat.com> 1.2.7-12
+- add patch included in MITKRB5-SA-2003-003 (CAN-2003-0028)
+
+* Mon Mar 17 2003 Nalin Dahyabhai <nalin@redhat.com> 1.2.7-11
+- add patches from patchkit from MITKRB5-SA-2003-004 (CAN-2003-0138 and
+  CAN-2003-0139)
+
+* Thu Mar  6 2003 Nalin Dahyabhai <nalin@redhat.com> 1.2.7-10
+- rebuild
+
+* Thu Mar  6 2003 Nalin Dahyabhai <nalin@redhat.com> 1.2.7-9
+- fix buffer underrun in unparsing certain principals (CAN-2003-0082)
+
+* Tue Feb  4 2003 Nalin Dahyabhai <nalin@redhat.com> 1.2.7-8
+- add patch to document the reject-bad-transited option in kdc.conf
+
+* Mon Feb  3 2003 Nalin Dahyabhai <nalin@redhat.com>
+- add patch to fix server-side crashes when principals have no
+  components (CAN-2003-0072)
+
+* Thu Jan 23 2003 Nalin Dahyabhai <nalin@redhat.com> 1.2.7-7
+- add patch from Mark Cox for exploitable bugs in ftp client
+
+* Wed Jan 22 2003 Tim Powers <timp@redhat.com>
+- rebuilt
+
+* Wed Jan 15 2003 Nalin Dahyabhai <nalin@redhat.com> 1.2.7-5
+- use PICFLAGS when building code from the ktany patch
+
+* Thu Jan  9 2003 Bill Nottingham <notting@redhat.com> 1.2.7-4
+- debloat
+
+* Tue Jan  7 2003 Jeremy Katz <katzj@redhat.com> 1.2.7-3
+- include .so.* symlinks as well as .so.*.*
+
+* Mon Dec  9 2002 Jakub Jelinek <jakub@redhat.com> 1.2.7-2
+- always #include <errno.h> to access errno, never do it directly
+- enable LFS on a bunch of other 32-bit arches
+
+* Wed Dec  4 2002 Nalin Dahyabhai <nalin@redhat.com>
+- increase the maximum name length allowed by kuserok() to the higher value
+  used in development versions
+
+* Mon Dec  2 2002 Nalin Dahyabhai <nalin@redhat.com>
+- install src/krb524/README as README.krb524 in the -servers package,
+  includes information about converting for AFS principals
+
+* Fri Nov 15 2002 Nalin Dahyabhai <nalin@redhat.com> 1.2.7-1
+- update to 1.2.7
+- disable use of tcl
+
+* Mon Nov 11 2002 Nalin Dahyabhai <nalin@redhat.com>
+- update to 1.2.7-beta2 (internal only, not for release), dropping dnsparse
+  and kadmind4 fixes
+
+* Wed Oct 23 2002 Nalin Dahyabhai <nalin@redhat.com> 1.2.6-5
+- add patch for buffer overflow in kadmind4 (not used by default)
+
+* Fri Oct 11 2002 Nalin Dahyabhai <nalin@redhat.com> 1.2.6-4
+- drop a hunk from the dnsparse patch which is actually redundant (thanks to
+  Tom Yu)
+
+* Wed Oct  9 2002 Nalin Dahyabhai <nalin@redhat.com> 1.2.6-3
+- patch to handle truncated dns responses
+
+* Mon Oct  7 2002 Nalin Dahyabhai <nalin@redhat.com> 1.2.6-2
+- remove hashless key types from the default kdc.conf, they're not supposed to
+  be there, noted by Sam Hartman on krbdev
+
+* Fri Sep 27 2002 Nalin Dahyabhai <nalin@redhat.com> 1.2.6-1
+- update to 1.2.6
+
+* Fri Sep 13 2002 Nalin Dahyabhai <nalin@redhat.com> 1.2.5-7
+- use %%{_lib} for the sake of multilib systems
+
+* Fri Aug  2 2002 Nalin Dahyabhai <nalin@redhat.com> 1.2.5-6
+- add patch from Tom Yu for exploitable bugs in rpc code used in kadmind
+
+* Tue Jul 23 2002 Nalin Dahyabhai <nalin@redhat.com> 1.2.5-5
+- fix bug in krb5.csh which would cause the path check to always succeed
+
+* Fri Jul 19 2002 Jakub Jelinek <jakub@redhat.com> 1.2.5-4
+- build even libdb.a with -fPIC and $RPM_OPT_FLAGS.
+
+* Fri Jun 21 2002 Tim Powers <timp@redhat.com>
+- automated rebuild
+
+* Sun May 26 2002 Tim Powers <timp@redhat.com>
+- automated rebuild
+
+* Wed May  1 2002 Nalin Dahyabhai <nalin@redhat.com> 1.2.5-1
+- update to 1.2.5
+- disable statglue
+
+* Fri Mar  1 2002 Nalin Dahyabhai <nalin@redhat.com> 1.2.4-1
+- update to 1.2.4
+
+* Wed Feb 20 2002 Nalin Dahyabhai <nalin@redhat.com> 1.2.3-5
+- rebuild in new environment
+- reenable statglue
+
+* Sat Jan 26 2002 Florian La Roche <Florian.LaRoche@redhat.de>
+- prereq chkconfig for the server subpackage
+
+* Wed Jan 16 2002 Nalin Dahyabhai <nalin@redhat.com> 1.2.3-3
+- build without -g3, which gives us large static libraries in -devel
+
+* Tue Jan 15 2002 Nalin Dahyabhai <nalin@redhat.com> 1.2.3-2
+- reintroduce ld.so.conf munging in the -libs %%post
+
+* Thu Jan 10 2002 Nalin Dahyabhai <nalin@redhat.com> 1.2.3-1
+- rename the krb5 package back to krb5-libs; the previous rename caused
+  something of an uproar
+- update to 1.2.3, which includes the FTP and telnetd fixes
+- configure without --enable-dns-for-kdc --enable-dns-for-realm, which now set
+  the default behavior instead of enabling the feature (the feature is enabled
+  by --enable-dns, which we still use)
+- reenable optimizations on Alpha
+- support more encryption types in the default kdc.conf (heads-up from post
+  to comp.protocols.kerberos by Jason Heiss)
+
+* Fri Aug  3 2001 Nalin Dahyabhai <nalin@redhat.com> 1.2.2-14
+- rename the krb5-libs package to krb5 (naming a subpackage -libs when there
+  is no main package is silly)
+- move defaults for PAM to the appdefaults section of krb5.conf -- this is
+  the area where the krb5_appdefault_* functions look for settings)
+- disable statglue (warning: breaks binary compatibility with previous
+  packages, but has to be broken at some point to work correctly with
+  unpatched versions built with newer versions of glibc)
+
+* Fri Aug  3 2001 Nalin Dahyabhai <nalin@redhat.com> 1.2.2-13
+- bump release number and rebuild
+
+* Wed Aug  1 2001 Nalin Dahyabhai <nalin@redhat.com>
+- add patch to fix telnetd vulnerability
+
+* Fri Jul 20 2001 Nalin Dahyabhai <nalin@redhat.com>
+- tweak statglue.c to fix stat/stat64 aliasing problems
+- be cleaner in use of gcc to build shlibs
+
+* Wed Jul 11 2001 Nalin Dahyabhai <nalin@redhat.com>
+- use gcc to build shared libraries
+
+* Wed Jun 27 2001 Nalin Dahyabhai <nalin@redhat.com>
+- add patch to support "ANY" keytab type (i.e.,
+  "default_keytab_name = ANY:FILE:/etc/krb5.keytab,SRVTAB:/etc/srvtab"
+  patch from Gerald Britton, #42551)
+- build with -D_FILE_OFFSET_BITS=64 to get large file I/O in ftpd (#30697)
+- patch ftpd to use long long and %%lld format specifiers to support the SIZE
+  command on large files (also #30697)
+- don't use LOG_AUTH as an option value when calling openlog() in ksu (#45965)
+- implement reload in krb5kdc and kadmind init scripts (#41911)
+- lose the krb5server init script (not using it any more)
+
+* Sun Jun 24 2001 Elliot Lee <sopwith@redhat.com>
+- Bump release + rebuild.
+
+* Tue May 29 2001 Nalin Dahyabhai <nalin@redhat.com>
+- pass some structures by address instead of on the stack in krb5kdc
+
+* Tue May 22 2001 Nalin Dahyabhai <nalin@redhat.com>
+- rebuild in new environment
+
+* Thu Apr 26 2001 Nalin Dahyabhai <nalin@redhat.com>
+- add patch from Tom Yu to fix ftpd overflows (#37731)
+
+* Wed Apr 18 2001 Than Ngo <than@redhat.com>
+- disable optimizations on the alpha again
+
+* Fri Mar 30 2001 Nalin Dahyabhai <nalin@redhat.com>
+- add in glue code to make sure that libkrb5 continues to provide a
+  weak copy of stat()
+
+* Thu Mar 15 2001 Nalin Dahyabhai <nalin@redhat.com>
+- build alpha with -O0 for now
+
+* Thu Mar  8 2001 Nalin Dahyabhai <nalin@redhat.com>
+- fix the kpropd init script
+
+* Mon Mar  5 2001 Nalin Dahyabhai <nalin@redhat.com>
+- update to 1.2.2, which fixes some bugs relating to empty ETYPE-INFO
+- re-enable optimization on Alpha
+
+* Thu Feb  8 2001 Nalin Dahyabhai <nalin@redhat.com>
+- build alpha with -O0 for now
+- own %%{_var}/kerberos
+
+* Tue Feb  6 2001 Nalin Dahyabhai <nalin@redhat.com>
+- own the directories which are created for each package (#26342)
+
+* Tue Jan 23 2001 Nalin Dahyabhai <nalin@redhat.com>
+- gettextize init scripts
+
+* Fri Jan 19 2001 Nalin Dahyabhai <nalin@redhat.com>
+- add some comments to the ksu patches for the curious
+- re-enable optimization on alphas
+
+* Mon Jan 15 2001 Nalin Dahyabhai <nalin@redhat.com>
+- fix krb5-send-pr (#18932) and move it from -server to -workstation
+- buildprereq libtermcap-devel
+- temporariliy disable optimization on alphas
+- gettextize init scripts
+
+* Tue Dec  5 2000 Nalin Dahyabhai <nalin@redhat.com>
+- force -fPIC
+
+* Fri Dec  1 2000 Nalin Dahyabhai <nalin@redhat.com>
+- rebuild in new environment
+
+* Tue Oct 31 2000 Nalin Dahyabhai <nalin@redhat.com>
+- add bison as a BuildPrereq (#20091)
+
+* Mon Oct 30 2000 Nalin Dahyabhai <nalin@redhat.com>
+- change /usr/dict/words to /usr/share/dict/words in default kdc.conf (#20000)
+
+* Thu Oct  5 2000 Nalin Dahyabhai <nalin@redhat.com>
+- apply kpasswd bug fixes from David Wragg
+
+* Wed Oct  4 2000 Nalin Dahyabhai <nalin@redhat.com>
+- make krb5-libs obsolete the old krb5-configs package (#18351)
+- don't quit from the kpropd init script if there's no principal database so
+  that you can propagate the first time without running kpropd manually
+- don't complain if /etc/ld.so.conf doesn't exist in the -libs %%post
+
+* Tue Sep 12 2000 Nalin Dahyabhai <nalin@redhat.com>
+- fix credential forwarding problem in klogind (goof in KRB5CCNAME handling)
+  (#11588)
+- fix heap corruption bug in FTP client (#14301)
+
+* Wed Aug 16 2000 Nalin Dahyabhai <nalin@redhat.com>
+- fix summaries and descriptions
+- switched the default transfer protocol from PORT to PASV as proposed on
+  bugzilla (#16134), and to match the regular ftp package's behavior
+
+* Wed Jul 19 2000 Jeff Johnson <jbj@redhat.com>
+- rebuild to compress man pages.
+
+* Sat Jul 15 2000 Bill Nottingham <notting@redhat.com>
+- move initscript back
+
+* Fri Jul 14 2000 Nalin Dahyabhai <nalin@redhat.com>
+- disable servers by default to keep linuxconf from thinking they need to be
+  started when they don't
+
+* Thu Jul 13 2000 Prospector <bugzilla@redhat.com>
+- automatic rebuild
+
+* Mon Jul 10 2000 Nalin Dahyabhai <nalin@redhat.com>
+- change cleanup code in post to not tickle chkconfig
+- add grep as a Prereq: for -libs
+
+* Thu Jul  6 2000 Nalin Dahyabhai <nalin@redhat.com>
+- move condrestarts to postun
+- make xinetd configs noreplace
+- add descriptions to xinetd configs
+- add /etc/init.d as a prereq for the -server package
+- patch to properly truncate $TERM in krlogind
+
+* Fri Jun 30 2000 Nalin Dahyabhai <nalin@redhat.com>
+- update to 1.2.1
+- back out Tom Yu's patch, which is a big chunk of the 1.2 -> 1.2.1 update
+- start using the official source tarball instead of its contents
+
+* Thu Jun 29 2000 Nalin Dahyabhai <nalin@redhat.com>
+- Tom Yu's patch to fix compatibility between 1.2 kadmin and 1.1.1 kadmind
+- pull out 6.2 options in the spec file (sonames changing in 1.2 means it's not
+  compatible with other stuff in 6.2, so no need)
+
+* Wed Jun 28 2000 Nalin Dahyabhai <nalin@redhat.com>
+- tweak graceful start/stop logic in post and preun
+
+* Mon Jun 26 2000 Nalin Dahyabhai <nalin@redhat.com>
+- update to the 1.2 release
+- ditch a lot of our patches which went upstream
+- enable use of DNS to look up things at build-time
+- disable use of DNS to look up things at run-time in default krb5.conf
+- change ownership of the convert-config-files script to root.root
+- compress PS docs
+- fix some typos in the kinit man page
+- run condrestart in server post, and shut down in preun
+
+* Mon Jun 19 2000 Nalin Dahyabhai <nalin@redhat.com>
+- only remove old krb5server init script links if the init script is there
+
+* Sat Jun 17 2000 Nalin Dahyabhai <nalin@redhat.com>
+- disable kshell and eklogin by default
+
+* Thu Jun 15 2000 Nalin Dahyabhai <nalin@redhat.com>
+- patch mkdir/rmdir problem in ftpcmd.y
+- add condrestart option to init script
+- split the server init script into three pieces and add one for kpropd
+
+* Wed Jun 14 2000 Nalin Dahyabhai <nalin@redhat.com>
+- make sure workstation servers are all disabled by default
+- clean up krb5server init script
+
+* Fri Jun  9 2000 Nalin Dahyabhai <nalin@redhat.com>
+- apply second set of buffer overflow fixes from Tom Yu
+- fix from Dirk Husung for a bug in buffer cleanups in the test suite
+- work around possibly broken rev binary in running test suite
+- move default realm configs from /var/kerberos to %%{_var}/kerberos
+
+* Tue Jun  6 2000 Nalin Dahyabhai <nalin@redhat.com>
+- make ksu and v4rcp owned by root
+
+* Sat Jun  3 2000 Nalin Dahyabhai <nalin@redhat.com>
+- use %%{_infodir} to better comply with FHS
+- move .so files to -devel subpackage
+- tweak xinetd config files (bugs #11833, #11835, #11836, #11840)
+- fix package descriptions again
+
+* Wed May 24 2000 Nalin Dahyabhai <nalin@redhat.com>
+- change a LINE_MAX to 1024, fix from Ken Raeburn
+- add fix for login vulnerability in case anyone rebuilds without krb4 compat
+- add tweaks for byte-swapping macros in krb.h, also from Ken
+- add xinetd config files
+- make rsh and rlogin quieter
+- build with debug to fix credential forwarding
+- add rsh as a build-time req because the configure scripts look for it to
+  determine paths
+
+* Wed May 17 2000 Nalin Dahyabhai <nalin@redhat.com>
+- fix config_subpackage logic
+
+* Tue May 16 2000 Nalin Dahyabhai <nalin@redhat.com>
+- remove setuid bit on v4rcp and ksu in case the checks previously added
+  don't close all of the problems in ksu
+- apply patches from Jeffrey Schiller to fix overruns Chris Evans found
+- reintroduce configs subpackage for use in the errata
+- add PreReq: sh-utils
+
+* Mon May 15 2000 Nalin Dahyabhai <nalin@redhat.com>
+- fix double-free in the kdc (patch merged into MIT tree)
+- include convert-config-files script as a documentation file
+
+* Wed May 03 2000 Nalin Dahyabhai <nalin@redhat.com>
+- patch ksu man page because the -C option never works
+- add access() checks and disable debug mode in ksu
+- modify default ksu build arguments to specify more directories in CMD_PATH
+  and to use getusershell()
+
+* Wed May 03 2000 Bill Nottingham <notting@redhat.com>
+- fix configure stuff for ia64
+
+* Mon Apr 10 2000 Nalin Dahyabhai <nalin@redhat.com>
+- add LDCOMBINE=-lc to configure invocation to use libc versioning (bug #10653)
+- change Requires: for/in subpackages to include %%{version}
+
+* Wed Apr 05 2000 Nalin Dahyabhai <nalin@redhat.com>
+- add man pages for kerberos(1), kvno(1), .k5login(5)
+- add kvno to -workstation
+
+* Mon Apr 03 2000 Nalin Dahyabhai <nalin@redhat.com>
+- Merge krb5-configs back into krb5-libs.  The krb5.conf file is marked as
+  a %%config file anyway.
+- Make krb5.conf a noreplace config file.
+
+* Thu Mar 30 2000 Nalin Dahyabhai <nalin@redhat.com>
+- Make klogind pass a clean environment to children, like NetKit's rlogind does.
+
+* Wed Mar 08 2000 Nalin Dahyabhai <nalin@redhat.com>
+- Don't enable the server by default.
+- Compress info pages.
+- Add defaults for the PAM module to krb5.conf
+
+* Mon Mar 06 2000 Nalin Dahyabhai <nalin@redhat.com>
+- Correct copyright: it's exportable now, provided the proper paperwork is
+  filed with the government.
+
+* Fri Mar 03 2000 Nalin Dahyabhai <nalin@redhat.com>
+- apply Mike Friedman's patch to fix format string problems
+- don't strip off argv[0] when invoking regular rsh/rlogin
+
+* Thu Mar 02 2000 Nalin Dahyabhai <nalin@redhat.com>
+- run kadmin.local correctly at startup
+
+* Mon Feb 28 2000 Nalin Dahyabhai <nalin@redhat.com>
+- pass absolute path to kadm5.keytab if/when extracting keys at startup
+
+* Sat Feb 19 2000 Nalin Dahyabhai <nalin@redhat.com>
+- fix info page insertions
+
+* Wed Feb  9 2000 Nalin Dahyabhai <nalin@redhat.com>
+- tweak server init script to automatically extract kadm5 keys if
+  /var/kerberos/krb5kdc/kadm5.keytab doesn't exist yet
+- adjust package descriptions
+
+* Thu Feb  3 2000 Nalin Dahyabhai <nalin@redhat.com>
+- fix for potentially gzipped man pages
+
+* Fri Jan 21 2000 Nalin Dahyabhai <nalin@redhat.com>
+- fix comments in krb5-configs
+
+* Fri Jan  7 2000 Nalin Dahyabhai <nalin@redhat.com>
+- move /usr/kerberos/bin to end of PATH
+
+* Tue Dec 28 1999 Nalin Dahyabhai <nalin@redhat.com>
+- install kadmin header files
+
+* Tue Dec 21 1999 Nalin Dahyabhai <nalin@redhat.com>
+- patch around TIOCGTLC defined on alpha and remove warnings from libpty.h
+- add installation of info docs
+- remove krb4 compat patch because it doesn't fix workstation-side servers
+
+* Mon Dec 20 1999 Nalin Dahyabhai <nalin@redhat.com>
+- remove hesiod dependency at build-time
+
+* Sun Dec 19 1999 Nalin Dahyabhai <nsdahya1@eos.ncsu.edu>
+- rebuild on 1.1.1
+
+* Thu Oct  7 1999 Nalin Dahyabhai <nsdahya1@eos.ncsu.edu>
+- clean up init script for server, verify that it works [jlkatz]
+- clean up rotation script so that rc likes it better
+- add clean stanza
+
+* Mon Oct  4 1999 Nalin Dahyabhai <nsdahya1@eos.ncsu.edu>
+- backed out ncurses and makeshlib patches
+- update for krb5-1.1
+- add KDC rotation to rc.boot, based on ideas from Michael's C version
+
+* Mon Sep 27 1999 Nalin Dahyabhai <nsdahya1@eos.ncsu.edu>
+- added -lncurses to telnet and telnetd makefiles
+
+* Mon Jul  5 1999 Nalin Dahyabhai <nsdahya1@eos.ncsu.edu>
+- added krb5.csh and krb5.sh to /etc/profile.d
+
+* Tue Jun 22 1999 Nalin Dahyabhai <nsdahya1@eos.ncsu.edu>
+- broke out configuration files
+
+* Mon Jun 14 1999 Nalin Dahyabhai <nsdahya1@eos.ncsu.edu>
+- fixed server package so that it works now
+
+* Sat May 15 1999 Nalin Dahyabhai <nsdahya1@eos.ncsu.edu>
+- started changelog (previous package from zedz.net)
+- updated existing 1.0.5 RPM from Eos Linux to krb5 1.0.6
+- added --force to makeinfo commands to skip errors during build