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/SOURCES/Add-German-translation.patch b/SOURCES/Add-German-translation.patch
new file mode 100644
index 0000000..98c6404
--- /dev/null
+++ b/SOURCES/Add-German-translation.patch
@@ -0,0 +1,9333 @@
+From eb32be474036aa25a14aca5f457d09ce1f2804ec Mon Sep 17 00:00:00 2001
+From: Chris Leick <c.leick@vollbio.de>
+Date: Wed, 6 Apr 2016 18:14:40 -0400
+Subject: [PATCH] Add German translation
+
+ticket: 8515 (new)
+(cherry picked from commit 0c9a4d9734c29a77d3c7ac267e8e885a75f44b4f)
+---
+ src/po/Makefile.in |    2 +-
+ src/po/de.po       | 9301 ++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 9302 insertions(+), 1 deletion(-)
+ create mode 100644 src/po/de.po
+
+diff --git a/src/po/Makefile.in b/src/po/Makefile.in
+index fdaf872a1..6753447dc 100644
+--- a/src/po/Makefile.in
++++ b/src/po/Makefile.in
+@@ -18,7 +18,7 @@ ETSRCS=	$(BUILDTOP)/lib/gssapi/generic/gssapi_err_generic.c \
+ 	$(BUILDTOP)/lib/krb5/error_tables/kv5m_err.c \
+ 	$(BUILDTOP)/lib/krb5/error_tables/krb524_err.c
+ # This is a placeholder until we have an actual translation.
+-CATALOGS=en_US.mo
++CATALOGS=en_US.mo de.mo
+ 
+ .SUFFIXES: .po .mo
+ .po.mo:
+diff --git a/src/po/de.po b/src/po/de.po
+new file mode 100644
+index 000000000..2144d7833
+--- /dev/null
++++ b/src/po/de.po
+@@ -0,0 +1,9301 @@
++# German translation of mit-krb5.
++# This file is distributed under the same license as the mit-krb5 package.
++# Copyright (C) 1985-2013 by the Massachusetts Institute of Technology.
++# Copyright (C) of this file 2014-2016 Chris Leick <c.leick@vollbio.de>.
++#
++msgid ""
++msgstr ""
++"Project-Id-Version: mit-krb5 13.2\n"
++"Report-Msgid-Bugs-To: krbdev@mit.edu\n"
++"POT-Creation-Date: 2015-05-06 14:59-0400\n"
++"PO-Revision-Date: 2016-04-07 08:15+0200\n"
++"Last-Translator: Chris Leick <c.leick@vollbio.de>\n"
++"Language-Team: German <debian-l10n-german@lists.debian.org>\n"
++"Language: de\n"
++"MIME-Version: 1.0\n"
++"Content-Type: text/plain; charset=UTF-8\n"
++"Content-Transfer-Encoding: 8bit\n"
++"Plural-Forms: nplurals=2; plural=n != 1;\n"
++
++#: ../../src/clients/kdestroy/kdestroy.c:62
++#, c-format
++msgid "Usage: %s [-A] [-q] [-c cache_name]\n"
++msgstr "Aufruf: %s [-A] [-q] [-c Zwischenspeichername]\n"
++
++#: ../../src/clients/kdestroy/kdestroy.c:63
++#, c-format
++msgid "\t-A destroy all credential caches in collection\n"
++msgstr "\t-A vernichtet alle Anmeldedatenzwischenspeicher in der Sammlung.\n"
++
++#: ../../src/clients/kdestroy/kdestroy.c:64
++#, c-format
++msgid "\t-q quiet mode\n"
++msgstr "\t-q stiller Modus\n"
++
++#: ../../src/clients/kdestroy/kdestroy.c:65
++#: ../../src/clients/kswitch/kswitch.c:45
++#, c-format
++msgid "\t-c specify name of credentials cache\n"
++msgstr "\t-c gibt den Namen des Zwischenspeichers für Anmeldedaten an.\n"
++
++#: ../../src/clients/kdestroy/kdestroy.c:98
++#: ../../src/clients/kinit/kinit.c:383 ../../src/clients/ksu/main.c:284
++#, c-format
++msgid "Only one -c option allowed\n"
++msgstr "Nur eine »-c«-Option ist erlaubt.\n"
++
++#: ../../src/clients/kdestroy/kdestroy.c:105
++#: ../../src/clients/kinit/kinit.c:412 ../../src/clients/klist/klist.c:182
++#, c-format
++msgid "Kerberos 4 is no longer supported\n"
++msgstr "Kerberos 4 wird nicht mehr unterstützt.\n"
++
++#: ../../src/clients/kdestroy/kdestroy.c:126
++#: ../../src/clients/klist/klist.c:253 ../../src/clients/ksu/main.c:131
++#: ../../src/clients/ksu/main.c:137 ../../src/clients/kswitch/kswitch.c:97
++#: ../../src/kadmin/ktutil/ktutil.c:52 ../../src/kdc/main.c:926
++#: ../../src/slave/kprop.c:102 ../../src/slave/kpropd.c:1052
++msgid "while initializing krb5"
++msgstr "beim Initialisieren von Krb5"
++
++#: ../../src/clients/kdestroy/kdestroy.c:133
++msgid "while listing credential caches"
++msgstr "beim Auflisten der Anmeldedatenzwischenspeicher"
++
++#: ../../src/clients/kdestroy/kdestroy.c:140
++msgid "composing ccache name"
++msgstr "Ccache-Name wird zusammengesetzt."
++
++#: ../../src/clients/kdestroy/kdestroy.c:145
++#, c-format
++msgid "while destroying cache %s"
++msgstr "beim Zerstören des Zwischenspeichers %s"
++
++#: ../../src/clients/kdestroy/kdestroy.c:157
++#: ../../src/clients/kswitch/kswitch.c:104
++#, c-format
++msgid "while resolving %s"
++msgstr "beim Auflösen von %s"
++
++#: ../../src/clients/kdestroy/kdestroy.c:163
++#: ../../src/clients/kinit/kinit.c:501 ../../src/clients/klist/klist.c:460
++msgid "while getting default ccache"
++msgstr "beim Holen des Standard-Ccaches"
++
++#: ../../src/clients/kdestroy/kdestroy.c:170 ../../src/clients/ksu/main.c:986
++msgid "while destroying cache"
++msgstr "beim Zerstören des Zwischenspeichers"
++
++#: ../../src/clients/kdestroy/kdestroy.c:173
++#, c-format
++msgid "Ticket cache NOT destroyed!\n"
++msgstr "Ticketzwischenspeicher NICHT vernichtet!\n"
++
++#: ../../src/clients/kdestroy/kdestroy.c:175
++#, c-format
++msgid "Ticket cache %cNOT%c destroyed!\n"
++msgstr "Ticketzwischenspeicher %cNICHT%c vernichtet!\n"
++
++#: ../../src/clients/kinit/kinit.c:213
++#, c-format
++msgid "\t-V verbose\n"
++msgstr "\t-V detaillierte Ausgabe\n"
++
++#: ../../src/clients/kinit/kinit.c:214
++#, c-format
++msgid "\t-l lifetime\n"
++msgstr "\t-l Lebensdauer\n"
++
++#: ../../src/clients/kinit/kinit.c:215
++#, c-format
++msgid "\t-s start time\n"
++msgstr "\t-s Startzeit\n"
++
++#: ../../src/clients/kinit/kinit.c:216
++#, c-format
++msgid "\t-r renewable lifetime\n"
++msgstr "\t-r verlängerbare Lebensdauer\n"
++
++#: ../../src/clients/kinit/kinit.c:217
++#, c-format
++msgid "\t-f forwardable\n"
++msgstr "\t-f weiterleitbar\n"
++
++#: ../../src/clients/kinit/kinit.c:218
++#, c-format
++msgid "\t-F not forwardable\n"
++msgstr "\t-F nicht weiterleitbar\n"
++
++#: ../../src/clients/kinit/kinit.c:219
++#, c-format
++msgid "\t-p proxiable\n"
++msgstr "\t-p Proxy nutzbar\n"
++
++#: ../../src/clients/kinit/kinit.c:220
++#, c-format
++msgid "\t-P not proxiable\n"
++msgstr "\t-P Proxy nicht nutzbar\n"
++
++#: ../../src/clients/kinit/kinit.c:221
++#, c-format
++msgid "\t-n anonymous\n"
++msgstr "\t-n anonym\n"
++
++#: ../../src/clients/kinit/kinit.c:222
++#, c-format
++msgid "\t-a include addresses\n"
++msgstr "\t-a bezieht Adressen ein.\n"
++
++#: ../../src/clients/kinit/kinit.c:223
++#, c-format
++msgid "\t-A do not include addresses\n"
++msgstr "\t-a bezieht Adressen nicht ein.\n"
++
++#: ../../src/clients/kinit/kinit.c:224
++#, c-format
++msgid "\t-v validate\n"
++msgstr "\t-v überprüft\n"
++
++#: ../../src/clients/kinit/kinit.c:225
++#, c-format
++msgid "\t-R renew\n"
++msgstr "\t-R erneuert\n"
++
++#: ../../src/clients/kinit/kinit.c:226
++#, c-format
++msgid "\t-C canonicalize\n"
++msgstr "\t-C bringt in Normalform\n"
++
++#: ../../src/clients/kinit/kinit.c:227
++#, c-format
++msgid "\t-E client is enterprise principal name\n"
++msgstr "\t-E Client ist der Principal-Name des Unternehmens\n"
++
++#: ../../src/clients/kinit/kinit.c:228
++#, c-format
++msgid "\t-k use keytab\n"
++msgstr "\t-k verwendet Schlüsseltabelle\n"
++
++#: ../../src/clients/kinit/kinit.c:229
++#, c-format
++msgid "\t-i use default client keytab (with -k)\n"
++msgstr "\t-i verwendet die Standardschlüsseltabelle des Clients (mit -k).\n"
++
++#: ../../src/clients/kinit/kinit.c:230
++#, c-format
++msgid "\t-t filename of keytab to use\n"
++msgstr "\t-t Dateiname der zu verwendenden Schlüsseltabelle\n"
++
++#: ../../src/clients/kinit/kinit.c:231
++#, c-format
++msgid "\t-c Kerberos 5 cache name\n"
++msgstr "\t-c Kerberos-5-Zwischenspeichername\n"
++
++#: ../../src/clients/kinit/kinit.c:232
++#, c-format
++msgid "\t-S service\n"
++msgstr "\t-S Dienst\n"
++
++#: ../../src/clients/kinit/kinit.c:233
++#, c-format
++msgid "\t-T armor credential cache\n"
++msgstr "\t-T gehärteter Anmeldedatenzwischenspeicher\n"
++
++#: ../../src/clients/kinit/kinit.c:234
++#, c-format
++msgid "\t-X <attribute>[=<value>]\n"
++msgstr "\t-X <Attribut>[=<Wert>]\n"
++
++#: ../../src/clients/kinit/kinit.c:301 ../../src/clients/kinit/kinit.c:309
++#, c-format
++msgid "Bad lifetime value %s\n"
++msgstr "falscher Wert für die Lebensdauer %s\n"
++
++#: ../../src/clients/kinit/kinit.c:343
++#, c-format
++msgid "Bad start time value %s\n"
++msgstr "falscher Wert für die Startzeit %s\n"
++
++#: ../../src/clients/kinit/kinit.c:362
++#, c-format
++msgid "Only one -t option allowed.\n"
++msgstr "Nur eine -t-Option ist erlaubt.\n"
++
++#: ../../src/clients/kinit/kinit.c:370
++#, c-format
++msgid "Only one armor_ccache\n"
++msgstr "nur ein gehärteter Ccache\n"
++
++#: ../../src/clients/kinit/kinit.c:391
++#, c-format
++msgid "Only one -I option allowed\n"
++msgstr "Nur eine -I-Option ist erlaubt.\n"
++
++#: ../../src/clients/kinit/kinit.c:401
++msgid "while adding preauth option"
++msgstr "beim Hinzufügen der Option »preauth«"
++
++#: ../../src/clients/kinit/kinit.c:425
++#, c-format
++msgid "Only one of -f and -F allowed\n"
++msgstr "Nur eine der Optionen -f und -F ist erlaubt.\n"
++
++#: ../../src/clients/kinit/kinit.c:430
++#, c-format
++msgid "Only one of -p and -P allowed\n"
++msgstr "Nur eine der Optionen -p und -P ist erlaubt.\n"
++
++#: ../../src/clients/kinit/kinit.c:435
++#, c-format
++msgid "Only one of -a and -A allowed\n"
++msgstr "Nur eine der Optionen -a und -A ist erlaubt.\n"
++
++#: ../../src/clients/kinit/kinit.c:440
++#, c-format
++msgid "Only one of -t and -i allowed\n"
++msgstr "Nur eine der Optionen -t und-i ist erlaubt.\n"
++
++#: ../../src/clients/kinit/kinit.c:447
++#, c-format
++msgid "keytab specified, forcing -k\n"
++msgstr "Schlüsseltabelle angegeben, -k wird erzwungen\n"
++
++#: ../../src/clients/kinit/kinit.c:451 ../../src/clients/klist/klist.c:221
++#, c-format
++msgid "Extra arguments (starting with \"%s\").\n"
++msgstr "zusätzliche Argumente (beginnend mit »%s«)\n"
++
++#: ../../src/clients/kinit/kinit.c:480
++msgid "while initializing Kerberos 5 library"
++msgstr "beim Initialisieren der Kerberos-5-Bibliothek"
++
++#: ../../src/clients/kinit/kinit.c:488 ../../src/clients/kinit/kinit.c:644
++#, c-format
++msgid "resolving ccache %s"
++msgstr "Ccache %s wird ermittelt"
++
++#: ../../src/clients/kinit/kinit.c:493
++#, c-format
++msgid "Using specified cache: %s\n"
++msgstr "Angegebener Zwischenspeicher wird verwendet: %s\n"
++
++#: ../../src/clients/kinit/kinit.c:515 ../../src/clients/kinit/kinit.c:595
++#: ../../src/clients/kpasswd/kpasswd.c:28 ../../src/clients/ksu/main.c:238
++#, c-format
++msgid "when parsing name %s"
++msgstr "wenn der Name %s ausgewertet wird"
++
++#: ../../src/clients/kinit/kinit.c:523 ../../src/kadmin/dbutil/kdb5_util.c:307
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:391
++#: ../../src/slave/kprop.c:203
++msgid "while getting default realm"
++msgstr "beim Holen des Standard-Realms"
++
++#: ../../src/clients/kinit/kinit.c:535
++msgid "while building principal"
++msgstr "beim Erstellen des Principals"
++
++#: ../../src/clients/kinit/kinit.c:543
++msgid "When resolving the default client keytab"
++msgstr "beim Auflösen der Standardschlüsseltabelle des Clients"
++
++#: ../../src/clients/kinit/kinit.c:550
++msgid "When determining client principal name from keytab"
++msgstr "beim Bestimmen des Dienst-Principal-Namens anhand der Schlüsseltabelle"
++
++#: ../../src/clients/kinit/kinit.c:559
++msgid "when creating default server principal name"
++msgstr "wenn der Standard-Principal-Name des Servers erstellt wird"
++
++#: ../../src/clients/kinit/kinit.c:566
++#, c-format
++msgid "(principal %s)"
++msgstr "(Principal %s)"
++
++#: ../../src/clients/kinit/kinit.c:569
++msgid "for local services"
++msgstr "für lokale Dienste"
++
++#: ../../src/clients/kinit/kinit.c:590 ../../src/clients/kpasswd/kpasswd.c:42
++#, c-format
++msgid "Unable to identify user\n"
++msgstr "Benutzer kann nicht identifiziert werden\n"
++
++#: ../../src/clients/kinit/kinit.c:605 ../../src/clients/kswitch/kswitch.c:116
++#, c-format
++msgid "while searching for ccache for %s"
++msgstr "beim Suchen nach Ccache für %s"
++
++#: ../../src/clients/kinit/kinit.c:611
++#, c-format
++msgid "Using existing cache: %s\n"
++msgstr "Existierender Zwischenspeicher wird verwendet: %s\n"
++
++#: ../../src/clients/kinit/kinit.c:620
++msgid "while generating new ccache"
++msgstr "beim Erstellen von neuem Ccache"
++
++#: ../../src/clients/kinit/kinit.c:624
++#, c-format
++msgid "Using new cache: %s\n"
++msgstr "Neuer Zwischenspeicher wird verwendet: %s\n"
++
++#: ../../src/clients/kinit/kinit.c:636
++#, c-format
++msgid "Using default cache: %s\n"
++msgstr "Standardzwischenspeicher wird verwendet: %s\n"
++
++#: ../../src/clients/kinit/kinit.c:649
++#, c-format
++msgid "Using specified input cache: %s\n"
++msgstr "Angegebener Eingabezwischenspeicher wird verwendet: %s\n"
++
++#: ../../src/clients/kinit/kinit.c:657 ../../src/clients/ksu/krb_auth_su.c:160
++msgid "when unparsing name"
++msgstr "beim Rückgängigmachen der Auswertung des Namens"
++
++#: ../../src/clients/kinit/kinit.c:661
++#, c-format
++msgid "Using principal: %s\n"
++msgstr "verwendeter Principal: %s\n"
++
++#: ../../src/clients/kinit/kinit.c:752
++msgid "getting local addresses"
++msgstr "Lokale Adressen werden geholt."
++
++#: ../../src/clients/kinit/kinit.c:771
++#, c-format
++msgid "while setting up KDB keytab for realm %s"
++msgstr "beim Einrichten der KDB-Schlüsseltabelle für Realm %s"
++
++#: ../../src/clients/kinit/kinit.c:780 ../../src/clients/kvno/kvno.c:201
++#, c-format
++msgid "resolving keytab %s"
++msgstr "Schlüsseltabelle wird ermittelt: %s"
++
++#: ../../src/clients/kinit/kinit.c:785
++#, c-format
++msgid "Using keytab: %s\n"
++msgstr "Schlüsseltabelle wird verwendet: %s\n"
++
++#: ../../src/clients/kinit/kinit.c:789
++msgid "resolving default client keytab"
++msgstr "Standardschlüsseltabelle des Clients wird ermittelt."
++
++#: ../../src/clients/kinit/kinit.c:799
++#, c-format
++msgid "while setting '%s'='%s'"
++msgstr "beim Setzen von »%s«=»%s«"
++
++#: ../../src/clients/kinit/kinit.c:804
++#, c-format
++msgid "PA Option %s = %s\n"
++msgstr "PA-Option %s = %s\n"
++
++#: ../../src/clients/kinit/kinit.c:849
++msgid "getting initial credentials"
++msgstr "Anfängliche Anmeldedaten werden geholt."
++
++#: ../../src/clients/kinit/kinit.c:852
++msgid "validating credentials"
++msgstr "Anmeldedaten werden geprüft."
++
++#: ../../src/clients/kinit/kinit.c:855
++msgid "renewing credentials"
++msgstr "Anmeldedaten werden erneuert."
++
++#: ../../src/clients/kinit/kinit.c:860
++#, c-format
++msgid "%s: Password incorrect while %s\n"
++msgstr "%s: Passwort bei %s falsch\n"
++
++#: ../../src/clients/kinit/kinit.c:863
++#, c-format
++msgid "while %s"
++msgstr "bei %s"
++
++#: ../../src/clients/kinit/kinit.c:871 ../../src/slave/kprop.c:224
++#, c-format
++msgid "when initializing cache %s"
++msgstr "beim Initialisieren des Zwischenspeichers %s"
++
++#: ../../src/clients/kinit/kinit.c:876
++#, c-format
++msgid "Initialized cache\n"
++msgstr "initialisierter Zwischenspeicher\n"
++
++#: ../../src/clients/kinit/kinit.c:880
++msgid "while storing credentials"
++msgstr "beim Speichern der Anmeldedaten"
++
++#: ../../src/clients/kinit/kinit.c:884
++#, c-format
++msgid "Stored credentials\n"
++msgstr "gespeicherte Anmeldedaten\n"
++
++#: ../../src/clients/kinit/kinit.c:891
++msgid "while switching to new ccache"
++msgstr "beim Wechsel zum neuen Ccache"
++
++#: ../../src/clients/kinit/kinit.c:946
++#, c-format
++msgid "Authenticated to Kerberos v5\n"
++msgstr "Authentifiziert für Kerberos v5\n"
++
++#: ../../src/clients/klist/klist.c:91
++#, c-format
++msgid ""
++"Usage: %s [-e] [-V] [[-c] [-l] [-A] [-d] [-f] [-s] [-a [-n]]] [-k [-t] [-K]] "
++"[name]\n"
++msgstr ""
++"Aufruf: %s [-e] [-V] [[-c] [-l] [-A] [-d] [-f] [-s] [-a [-n]]] [-k [-t] [-"
++"K]] [Name]\n"
++
++#: ../../src/clients/klist/klist.c:93
++#, c-format
++msgid "\t-c specifies credentials cache\n"
++msgstr "\t-c gibt den Anmeldedatenzwischenspeicher an\n"
++
++#: ../../src/clients/klist/klist.c:94
++#, c-format
++msgid "\t-k specifies keytab\n"
++msgstr "\t-k gibt die Schlüsseltabelle an.\n"
++
++#: ../../src/clients/klist/klist.c:95
++#, c-format
++msgid "\t   (Default is credentials cache)\n"
++msgstr "\t   (Voreinstellung ist Anmeldedatenzwischenspeicher)\n"
++
++#: ../../src/clients/klist/klist.c:96
++#, c-format
++msgid "\t-i uses default client keytab if no name given\n"
++msgstr ""
++"\t-i verwendet die Standardschlüsseltabelle des Clients, falls kein Name "
++"angegeben wurde.\n"
++
++#: ../../src/clients/klist/klist.c:97
++#, c-format
++msgid "\t-l lists credential caches in collection\n"
++msgstr "\t-l listet gesammelte Anmeldedatenzwischenspeicher auf.\n"
++
++#: ../../src/clients/klist/klist.c:98
++#, c-format
++msgid "\t-A shows content of all credential caches\n"
++msgstr "\t-A zeigt den Inhalt aller Anmeldedatenzwischenspeicher an.\n"
++
++#: ../../src/clients/klist/klist.c:99
++#, c-format
++msgid "\t-e shows the encryption type\n"
++msgstr "\t-e zeigt den Verschlüsselungstyp.\n"
++
++#: ../../src/clients/klist/klist.c:100
++#, c-format
++msgid "\t-V shows the Kerberos version and exits\n"
++msgstr "\t-V zeigt die Kerberos-Version und wird beendet.\n"
++
++#: ../../src/clients/klist/klist.c:101
++#, c-format
++msgid "\toptions for credential caches:\n"
++msgstr "\tOptionen für Anmeldedatenzwischenspeicher:\n"
++
++#: ../../src/clients/klist/klist.c:102
++#, c-format
++msgid "\t\t-d shows the submitted authorization data types\n"
++msgstr "\t\t-d zeigt die übertragenen Autorisierungsdatentypen.\n"
++
++#: ../../src/clients/klist/klist.c:104
++#, c-format
++msgid "\t\t-f shows credentials flags\n"
++msgstr "t\t-f zeigt die Anmeldedatenschalter.\n"
++
++#: ../../src/clients/klist/klist.c:105
++#, c-format
++msgid "\t\t-s sets exit status based on valid tgt existence\n"
++msgstr ""
++"\t\t-s setzt den Exit-Status auf Basis der Existenz eines gültigen TGTs.\n"
++
++#: ../../src/clients/klist/klist.c:107
++#, c-format
++msgid "\t\t-a displays the address list\n"
++msgstr "\t\t-a zeigt die Adressliste.\n"
++
++#: ../../src/clients/klist/klist.c:108
++#, c-format
++msgid "\t\t\t-n do not reverse-resolve\n"
++msgstr "\t\t\t-n löst nicht rückwärts auf.\n"
++
++#: ../../src/clients/klist/klist.c:109
++#, c-format
++msgid "\toptions for keytabs:\n"
++msgstr "\tOptionen für Schlüsseltabellen:\n"
++
++#: ../../src/clients/klist/klist.c:110
++#, c-format
++msgid "\t\t-t shows keytab entry timestamps\n"
++msgstr "\t\t-t zeigt die Zeitstempel der Schlüsseltabelleneinträge.\n"
++
++#: ../../src/clients/klist/klist.c:111
++#, c-format
++msgid "\t\t-K shows keytab entry keys\n"
++msgstr "\t\t-K zeigt die Schlüssel der Schlüsseltabelleneinträge.\n"
++
++#: ../../src/clients/klist/klist.c:230
++#, c-format
++msgid "%s version %s\n"
++msgstr "%s Version %s\n"
++
++#: ../../src/clients/klist/klist.c:282
++msgid "while getting default client keytab"
++msgstr "beim Holen der Standardschlüsseltabelle des Clients"
++
++#: ../../src/clients/klist/klist.c:287
++msgid "while getting default keytab"
++msgstr "beim Holen der Standardschlüsseltabelle"
++
++#: ../../src/clients/klist/klist.c:292 ../../src/kadmin/cli/keytab.c:108
++#, c-format
++msgid "while resolving keytab %s"
++msgstr "beim Ermitteln der Schlüsseltabelle %s"
++
++#: ../../src/clients/klist/klist.c:298 ../../src/kadmin/cli/keytab.c:92
++msgid "while getting keytab name"
++msgstr "beim Holen des Schlüsseltabellennamens"
++
++#: ../../src/clients/klist/klist.c:305 ../../src/kadmin/cli/keytab.c:399
++msgid "while starting keytab scan"
++msgstr "beim Start des Schlüsseltabellen-Scans"
++
++#: ../../src/clients/klist/klist.c:326 ../../src/clients/klist/klist.c:500
++#: ../../src/clients/ksu/ccache.c:465 ../../src/kadmin/dbutil/dump.c:550
++msgid "while unparsing principal name"
++msgstr "beim Rückgängigmachen des Auswertens des Principal-Namens"
++
++#: ../../src/clients/klist/klist.c:350 ../../src/kadmin/cli/keytab.c:443
++msgid "while scanning keytab"
++msgstr "beim Scannen der Schlüsseltabelle"
++
++#: ../../src/clients/klist/klist.c:354 ../../src/kadmin/cli/keytab.c:448
++msgid "while ending keytab scan"
++msgstr "beim Beenden des Schlüsseltabellen-Scans"
++
++#: ../../src/clients/klist/klist.c:371 ../../src/clients/klist/klist.c:434
++msgid "while listing ccache collection"
++msgstr "beim Aufführen der Ccache-Sammlung"
++
++#: ../../src/clients/klist/klist.c:411
++msgid "(Expired)"
++msgstr "(abgelaufen)"
++
++#: ../../src/clients/klist/klist.c:466
++#, c-format
++msgid "while resolving ccache %s"
++msgstr "beim Ermitteln des Ccaches %s"
++
++#: ../../src/clients/klist/klist.c:504
++#, c-format
++msgid ""
++"Ticket cache: %s:%s\n"
++"Default principal: %s\n"
++"\n"
++msgstr ""
++"Ticketzwischenspeicher: %s:%s\n"
++"Standard-Principal: %s\n"
++"\n"
++
++#: ../../src/clients/klist/klist.c:518
++msgid "while starting to retrieve tickets"
++msgstr "während das Abfragen der Tickets beginnt"
++
++#: ../../src/clients/klist/klist.c:539
++msgid "while finishing ticket retrieval"
++msgstr "während das Abfragem der Tickets endet"
++
++#: ../../src/clients/klist/klist.c:545
++msgid "while closing ccache"
++msgstr "beim Schließen des Ccaches"
++
++#: ../../src/clients/klist/klist.c:555
++msgid "while retrieving a ticket"
++msgstr "beim Abfragen eines Tickets"
++
++#: ../../src/clients/klist/klist.c:667 ../../src/clients/ksu/ccache.c:450
++#: ../../src/slave/kpropd.c:1225 ../../src/slave/kpropd.c:1285
++msgid "while unparsing client name"
++msgstr "beim Rückgängigmachen des Auswertens des Client-Namens"
++
++#: ../../src/clients/klist/klist.c:672 ../../src/clients/ksu/ccache.c:455
++#: ../../src/slave/kprop.c:240
++msgid "while unparsing server name"
++msgstr "beim Rückgängigmachen des Auswertens des Server-Namens"
++
++#: ../../src/clients/klist/klist.c:701 ../../src/clients/ksu/ccache.c:480
++#, c-format
++msgid "\tfor client %s"
++msgstr "\tfür Client %s"
++
++#: ../../src/clients/klist/klist.c:713 ../../src/clients/ksu/ccache.c:489
++msgid "renew until "
++msgstr "erneuern bis "
++
++#: ../../src/clients/klist/klist.c:730 ../../src/clients/ksu/ccache.c:499
++#, c-format
++msgid "Flags: %s"
++msgstr "Schalter: %s"
++
++#: ../../src/clients/klist/klist.c:749
++#, c-format
++msgid "Etype (skey, tkt): %s, "
++msgstr "Etype (Skey, TKT): %s, "
++
++#: ../../src/clients/klist/klist.c:766
++#, c-format
++msgid "AD types: "
++msgstr "AD-Typen"
++
++#: ../../src/clients/klist/klist.c:783
++#, c-format
++msgid "\tAddresses: (none)\n"
++msgstr "\tAdressen: (keine)\n"
++
++#: ../../src/clients/klist/klist.c:785
++#, c-format
++msgid "\tAddresses: "
++msgstr "\tAdressen: "
++
++#: ../../src/clients/klist/klist.c:818
++#, c-format
++msgid "broken address (type %d length %d)"
++msgstr "kaputte Adresse (Typ %d Länge %d)"
++
++#: ../../src/clients/klist/klist.c:838
++#, c-format
++msgid "unknown addrtype %d"
++msgstr "unbekannter »addrtype« %d"
++
++#: ../../src/clients/klist/klist.c:847
++#, c-format
++msgid "unprintable address (type %d, error %d %s)"
++msgstr "nicht druckbare Adresse (Typ %d Fehler %d %s)"
++
++#: ../../src/clients/kpasswd/kpasswd.c:12 ../../src/lib/krb5/krb/gic_pwd.c:396
++msgid "Enter new password"
++msgstr "Geben Sie ein neues Passwort ein."
++
++#: ../../src/clients/kpasswd/kpasswd.c:13 ../../src/lib/krb5/krb/gic_pwd.c:404
++msgid "Enter it again"
++msgstr "Geben Sie es erneut ein."
++
++#: ../../src/clients/kpasswd/kpasswd.c:33
++#, c-format
++msgid "Unable to identify user from password file\n"
++msgstr ""
++"Der Benutzer kann nicht anhand der Passwortdatei identifiziert werden.\n"
++
++#: ../../src/clients/kpasswd/kpasswd.c:65
++#, c-format
++msgid "usage: %s [principal]\n"
++msgstr "Aufruf: %s [Principal]\n"
++
++#: ../../src/clients/kpasswd/kpasswd.c:73
++msgid "initializing kerberos library"
++msgstr "Kerberos-Bibliothek wird initialisiert."
++
++#: ../../src/clients/kpasswd/kpasswd.c:77
++msgid "allocating krb5_get_init_creds_opt"
++msgstr "krb5_get_init_creds_opt wird reserviert."
++
++#: ../../src/clients/kpasswd/kpasswd.c:92
++msgid "opening default ccache"
++msgstr "Standard-Ccache wird geöffnet."
++
++#: ../../src/clients/kpasswd/kpasswd.c:97
++msgid "getting principal from ccache"
++msgstr "Principal wird vom Ccache geholt."
++
++#: ../../src/clients/kpasswd/kpasswd.c:104
++msgid "while setting FAST ccache"
++msgstr "beim Setzen des FAST-Ccaches"
++
++#: ../../src/clients/kpasswd/kpasswd.c:111
++msgid "closing ccache"
++msgstr "Ccache wird geschlossen."
++
++#: ../../src/clients/kpasswd/kpasswd.c:118
++msgid "parsing client name"
++msgstr "Client-Name wird ausgewertet."
++
++#: ../../src/clients/kpasswd/kpasswd.c:135
++msgid "Password incorrect while getting initial ticket"
++msgstr "Passwort beim Holen des anfänglichen Tickets falsch"
++
++#: ../../src/clients/kpasswd/kpasswd.c:137
++msgid "getting initial ticket"
++msgstr "Anfängliches Ticket wird geholt."
++
++#: ../../src/clients/kpasswd/kpasswd.c:144
++msgid "while reading password"
++msgstr "beim Lesen des Passworts"
++
++#: ../../src/clients/kpasswd/kpasswd.c:152
++msgid "changing password"
++msgstr "Passwort wird geändert."
++
++#: ../../src/clients/kpasswd/kpasswd.c:174
++#: ../lib/kadm5/chpass_util_strings.c:30
++#, c-format
++msgid "Password changed.\n"
++msgstr "Passwort geändert\n"
++
++#: ../../src/clients/ksu/authorization.c:369
++#, c-format
++msgid ""
++"Error: bad entry - %s in %s file, must be either full path or just the cmd "
++"name\n"
++msgstr ""
++"Fehler: falscher Eintrag – %s in Datei %s muss entweder ein vollständiger "
++"Pfad oder nur ein Befehlsname sein.\n"
++
++#: ../../src/clients/ksu/authorization.c:377
++#, c-format
++msgid ""
++"Error: bad entry - %s in %s file, since %s is just the cmd name, CMD_PATH "
++"must be defined \n"
++msgstr ""
++"Fehler: falscher Eintrag – %s in Datei %s. Da %s nur ein Befehlsname ist, "
++"muss CMD_PATH definiert sein.\n"
++
++#: ../../src/clients/ksu/authorization.c:392
++#, c-format
++msgid "Error: bad entry - %s in %s file, CMD_PATH contains no paths \n"
++msgstr ""
++"Fehler: falscher Eintrag – %s in Datei %s. CMD_PATH enthält keine Pfade.\n"
++
++#: ../../src/clients/ksu/authorization.c:401
++#, c-format
++msgid "Error: bad path %s in CMD_PATH for %s must start with '/' \n"
++msgstr "Fehler: falscher Pfad %s in CMD_PATH für %s muss mit »/« beginnen\n"
++
++#: ../../src/clients/ksu/authorization.c:517
++msgid "Error: not found -> "
++msgstr "Fehler: nicht gefunden -> "
++
++#: ../../src/clients/ksu/authorization.c:723
++#, c-format
++msgid "home directory name `%s' too long, can't search for .k5login\n"
++msgstr ""
++"Name des Home-Verzeichnisses »%s« ist zu lang, Suche nach .k5login nicht "
++"möglich\n"
++
++#: ../../src/clients/ksu/ccache.c:368
++#, c-format
++msgid "home directory path for %s too long\n"
++msgstr "Home-Verzeichnispfad für %s zu lang\n"
++
++#: ../../src/clients/ksu/ccache.c:461
++msgid "while retrieving principal name"
++msgstr "beim Abfragen des Principal-Namens"
++
++#: ../../src/clients/ksu/krb_auth_su.c:57
++#: ../../src/clients/ksu/krb_auth_su.c:62 ../../src/slave/kprop.c:247
++msgid "while copying client principal"
++msgstr "beim Kopieren des Client-Principals"
++
++#: ../../src/clients/ksu/krb_auth_su.c:69
++msgid "while creating tgt for local realm"
++msgstr "beim Erstellen des TGTs für lokalen Realm"
++
++#: ../../src/clients/ksu/krb_auth_su.c:84
++msgid "while retrieving creds from cache"
++msgstr "beim Abfragen der Anmeldedaten aus dem Zwischenspeicher"
++
++#: ../../src/clients/ksu/krb_auth_su.c:95
++msgid "while switching to target uid"
++msgstr "beim Umschalten auf die Ziel-UID"
++
++#: ../../src/clients/ksu/krb_auth_su.c:100
++#, c-format
++msgid ""
++"WARNING: Your password may be exposed if you enter it here and are logged \n"
++msgstr ""
++"WARNUNG: Ihr Passwort könnte offengelegt werden, falls Sie es hier eingeben "
++"und\n"
++
++#: ../../src/clients/ksu/krb_auth_su.c:102
++#, c-format
++msgid "         in remotely using an unsecure (non-encrypted) channel. \n"
++msgstr ""
++"         in der Ferne mittels eines unsicheren (unverschlüsselten) Kanals\n"
++"         angemeldet sind.\n"
++
++#: ../../src/clients/ksu/krb_auth_su.c:114 ../../src/clients/ksu/main.c:464
++msgid "while reclaiming root uid"
++msgstr "beim erneuten Beanspruchen der Root-UID"
++
++#: ../../src/clients/ksu/krb_auth_su.c:121
++#, c-format
++msgid "does not have any appropriate tickets in the cache.\n"
++msgstr "hat keine geeigneten Tickets im Zwischenspeicher.\n"
++
++#: ../../src/clients/ksu/krb_auth_su.c:133
++msgid "while verifying ticket for server"
++msgstr "beim Prüfen des Tickets für Server"
++
++#: ../../src/clients/ksu/krb_auth_su.c:167
++msgid "while getting time of day"
++msgstr "beim Holen der Tageszeit"
++
++#: ../../src/clients/ksu/krb_auth_su.c:171
++#, c-format
++msgid "Kerberos password for %s: "
++msgstr "Kerberos-Passwort für %s: "
++
++#: ../../src/clients/ksu/krb_auth_su.c:175
++#, c-format
++msgid "principal name %s too long for internal buffer space\n"
++msgstr "Principal-Name %s für den internen Pufferbereich zu groß\n"
++
++#: ../../src/clients/ksu/krb_auth_su.c:184
++#, c-format
++msgid "while reading password for '%s'\n"
++msgstr "beim Lesen des Passworts für »%s«\n"
++
++#: ../../src/clients/ksu/krb_auth_su.c:191
++#, c-format
++msgid "No password given\n"
++msgstr "kein Passwort angegeben\n"
++
++#: ../../src/clients/ksu/krb_auth_su.c:204
++#, c-format
++msgid "%s: Password incorrect\n"
++msgstr "%s: Passwort falsch\n"
++
++#: ../../src/clients/ksu/krb_auth_su.c:206
++msgid "while getting initial credentials"
++msgstr "beim Holen der Anfangsanmeldedaten"
++
++#: ../../src/clients/ksu/krb_auth_su.c:226
++#: ../../src/clients/ksu/krb_auth_su.c:240
++#, c-format
++msgid " %s while unparsing name\n"
++msgstr "%s beim Rückgängigmachen der Namensauswertung\n"
++
++#: ../../src/clients/ksu/main.c:68
++#, c-format
++msgid ""
++"Usage: %s [target user] [-n principal] [-c source cachename] [-k] [-D] [-r "
++"time] [-pf] [-l lifetime] [-zZ] [-q] [-e command [args... ] ] [-a "
++"[args... ] ]\n"
++msgstr ""
++"Aufruf: %s [Zielbenutzer] [-n Principal] [-c Quellenzwischenspeichername] [-"
++"k] [-D] [-r Zeit] [-pf] [-l Lebensdauer] [-zZ] [-q] [-e Befehl [Argumente "
++"…] ] [-a [Argumente …] ]\n"
++
++#: ../../src/clients/ksu/main.c:147
++msgid ""
++"program name too long - quitting to avoid triggering system logging bugs"
++msgstr ""
++"Programmname zu lang – wird beendet, um das Auslösen von "
++"Systemprotokollierungsfehlern zu vermeiden"
++
++#: ../../src/clients/ksu/main.c:173
++msgid "while allocating memory"
++msgstr "bei Reservieren von Speicher"
++
++#: ../../src/clients/ksu/main.c:186
++msgid "while setting euid to source user"
++msgstr "beim Setzen der EUID auf dem Quellbenutzer"
++
++#: ../../src/clients/ksu/main.c:196 ../../src/clients/ksu/main.c:231
++#, c-format
++msgid "Bad lifetime value (%s hours?)\n"
++msgstr "falscher Wert für Lebensdauer (%s Stunden?)\n"
++
++#: ../../src/clients/ksu/main.c:208 ../../src/clients/ksu/main.c:292
++msgid "when gathering parameters"
++msgstr "beim Zusammenstellen der Parameter"
++
++#: ../../src/clients/ksu/main.c:251
++#, c-format
++msgid "-z option is mutually exclusive with -Z.\n"
++msgstr "Die Optionen -z und -Z schließen sich gegenseitig aus.\n"
++
++#: ../../src/clients/ksu/main.c:259
++#, c-format
++msgid "-Z option is mutually exclusive with -z.\n"
++msgstr "Die Optionen -Z und -z schließen sich gegenseitig aus.\n"
++
++#: ../../src/clients/ksu/main.c:272
++#, c-format
++msgid "while looking for credentials cache %s"
++msgstr "beim Suchen nach dem Anmeldedatenzwischenspeicher %s"
++
++#: ../../src/clients/ksu/main.c:278
++#, c-format
++msgid "malformed credential cache name %s\n"
++msgstr "falsch gebildeter Anmeldedatenzwischenspeichername %s\n"
++
++# ksu ist eine Kerberos-Variante von su
++#: ../../src/clients/ksu/main.c:336
++#, c-format
++msgid "ksu: who are you?\n"
++msgstr "ksu: Wer sind Sie?\n"
++
++#: ../../src/clients/ksu/main.c:340
++#, c-format
++msgid "Your uid doesn't match your passwd entry?!\n"
++msgstr "Ihre UID passt nicht zu Ihrem Passworteintrag.\n"
++
++#: ../../src/clients/ksu/main.c:355
++#, c-format
++msgid "ksu: unknown login %s\n"
++msgstr "ksu: unbekannter Anmeldename %s\n"
++
++#: ../../src/clients/ksu/main.c:375
++msgid "while getting source cache"
++msgstr "beim Holen des Quellenzwischenspeichers"
++
++#: ../../src/clients/ksu/main.c:381 ../../src/clients/kvno/kvno.c:194
++msgid "while opening ccache"
++msgstr "beim Öffnen des Ccaches"
++
++#: ../../src/clients/ksu/main.c:389
++msgid "while selecting the best principal"
++msgstr "beim Auswählen des besten Principals"
++
++#: ../../src/clients/ksu/main.c:397
++msgid "while returning to source uid after finding best principal"
++msgstr ""
++"bei der Rückkehr zur Quell-UID, nachdem der beste Principal gefunden wurde"
++
++#: ../../src/clients/ksu/main.c:417
++#, c-format
++msgid "account %s: authorization failed\n"
++msgstr "Konto %s: Autorisierung fehlgeschlagen\n"
++
++#: ../../src/clients/ksu/main.c:442
++msgid "while parsing temporary name"
++msgstr "beim Auswertens des temporären Namens"
++
++#: ../../src/clients/ksu/main.c:447
++msgid "while creating temporary cache"
++msgstr "bei Erstellen des temporären Zwischenspeichers"
++
++#: ../../src/clients/ksu/main.c:453 ../../src/clients/ksu/main.c:693
++#, c-format
++msgid "while copying cache %s to %s"
++msgstr "beim Kopieren des Zwischenspeichers %s nach %s"
++
++#: ../../src/clients/ksu/main.c:471
++#, c-format
++msgid ""
++"WARNING: Your password may be exposed if you enter it here and are logged\n"
++msgstr ""
++"WARNUNG: Ihr Passwort könnte offengelegt werden, falls Sie es hier eingeben "
++"und\n"
++
++#: ../../src/clients/ksu/main.c:473
++#, c-format
++msgid "         in remotely using an unsecure (non-encrypted) channel.\n"
++msgstr ""
++"         in der Ferne über einen unsicheren (unverschlüsselten) Kanal "
++"angemeldet\n"
++"sind.\n"
++
++#: ../../src/clients/ksu/main.c:479
++#, c-format
++msgid "Goodbye\n"
++msgstr "Auf Wiedersehen\n"
++
++#: ../../src/clients/ksu/main.c:483
++#, c-format
++msgid "Could not get a tgt for "
++msgstr "Es konnte kein TGT geholt werden für "
++
++#: ../../src/clients/ksu/main.c:505
++#, c-format
++msgid "Authentication failed.\n"
++msgstr "Authentifizierung fehlgeschlagen.\n"
++
++#: ../../src/clients/ksu/main.c:513
++msgid "When unparsing name"
++msgstr "beim Rückgängigmachen der Namensauswertung"
++
++#: ../../src/clients/ksu/main.c:517
++#, c-format
++msgid "Authenticated %s\n"
++msgstr "Authentifiziert %s\n"
++
++#: ../../src/clients/ksu/main.c:524
++msgid "while switching to target for authorization check"
++msgstr "beim Wechsel des Ziels der Autorisierungsprüfung"
++
++#: ../../src/clients/ksu/main.c:531
++msgid "while checking authorization"
++msgstr "beim Prüfen der Autorisierung"
++
++#: ../../src/clients/ksu/main.c:537
++msgid "while switching back from target after authorization check"
++msgstr "beim Zurückwechsel vom Ziel nach der Autorisierungsprüfung"
++
++#: ../../src/clients/ksu/main.c:544
++#, c-format
++msgid "Account %s: authorization for %s for execution of\n"
++msgstr "Konto %s: Autorisierung für %s zum Ausführen von\n"
++
++#: ../../src/clients/ksu/main.c:546
++#, c-format
++msgid "               %s successful\n"
++msgstr "               %s erfolgreich\n"
++
++#: ../../src/clients/ksu/main.c:552
++#, c-format
++msgid "Account %s: authorization for %s successful\n"
++msgstr "Konto %s: Autorisierung für %s erfolgreich\n"
++
++#: ../../src/clients/ksu/main.c:564
++#, c-format
++msgid "Account %s: authorization for %s for execution of %s failed\n"
++msgstr "Konto %s: Autorisierung für %s zum Ausführen von %s fehlgeschlagen\n"
++
++#: ../../src/clients/ksu/main.c:572
++#, c-format
++msgid "Account %s: authorization of %s failed\n"
++msgstr "Konto %s: Autorisierung von %s fehlgeschlagen\n"
++
++#: ../../src/clients/ksu/main.c:587
++msgid "while calling cc_filter"
++msgstr "beim Aufruf von »cc_filter«"
++
++#: ../../src/clients/ksu/main.c:595
++msgid "while erasing target cache"
++msgstr "bei Löschen des Zielzwischenspeichers"
++
++#: ../../src/clients/ksu/main.c:615
++#, c-format
++msgid "ksu: permission denied (shell).\n"
++msgstr "ksu: Zugriff verweigert (Shell)\n"
++
++#: ../../src/clients/ksu/main.c:624
++#, c-format
++msgid "ksu: couldn't set environment variable USER\n"
++msgstr "ksu: Umgebungsvariable USER kann nicht gesetzt werden\n"
++
++#: ../../src/clients/ksu/main.c:630
++#, c-format
++msgid "ksu: couldn't set environment variable HOME\n"
++msgstr "ksu: Umgebungsvariable HOME kann nicht gesetzt werden\n"
++
++#: ../../src/clients/ksu/main.c:635
++#, c-format
++msgid "ksu: couldn't set environment variable SHELL\n"
++msgstr "ksu: Umgebungsvariable SHELL kann nicht gesetzt werden\n"
++
++#: ../../src/clients/ksu/main.c:646
++#, c-format
++msgid "ksu: initgroups failed.\n"
++msgstr "ksu: »initgroups« fehlgeschlagen\n"
++
++#: ../../src/clients/ksu/main.c:651
++#, c-format
++msgid "Leaving uid as %s (%ld)\n"
++msgstr "UID bleibt %s (%ld)\n"
++
++#: ../../src/clients/ksu/main.c:654
++#, c-format
++msgid "Changing uid to %s (%ld)\n"
++msgstr "UID wird zu %s (%ld) geändert\n"
++
++#: ../../src/clients/ksu/main.c:680
++msgid "while getting name of target ccache"
++msgstr "beim Holen des Ziel-Ccache-Namens"
++
++#: ../../src/clients/ksu/main.c:700
++#, c-format
++msgid "%s does not have correct permissions for %s, %s aborted"
++msgstr "%s hat nicht die korrekten Rechte für %s, %s wird abgebrochen."
++
++#: ../../src/clients/ksu/main.c:721
++#, c-format
++msgid "Internal error: command %s did not get resolved\n"
++msgstr "Interner Fehler: Befehl %s wurde nicht aufgelöst\n"
++
++#: ../../src/clients/ksu/main.c:738 ../../src/clients/ksu/main.c:774
++#, c-format
++msgid "while trying to execv %s"
++msgstr "beim Versuch von »execv %s«"
++
++#: ../../src/clients/ksu/main.c:764
++msgid "while calling waitpid"
++msgstr "beim Aufruf von »waitpid«"
++
++#: ../../src/clients/ksu/main.c:769
++msgid "while trying to fork."
++msgstr "beim Versuch zu verzweigen."
++
++#: ../../src/clients/ksu/main.c:791
++msgid "while reading cache name from ccache"
++msgstr "beim Lesen des Zwischenspeichernamens aus dem Ccache"
++
++#: ../../src/clients/ksu/main.c:797
++#, c-format
++msgid "ksu: couldn't set environment variable %s\n"
++msgstr "ksu: Umgebungsvariable %s kann nicht gesetzt werden\n"
++
++#: ../../src/clients/ksu/main.c:820
++#, c-format
++msgid "while clearing the value of %s"
++msgstr "beim Leeren des Werts von %s"
++
++#: ../../src/clients/ksu/main.c:828
++msgid "while resetting target ccache name"
++msgstr "beim Zurücksetzen des Ziel-Ccache-Namens"
++
++#: ../../src/clients/ksu/main.c:842
++msgid "while determining target ccache name"
++msgstr "beim Bestimmen des Ziel-Ccache-Namens"
++
++#: ../../src/clients/ksu/main.c:881
++msgid "while generating part of the target ccache name"
++msgstr "beim Erzeugen eines Teils des Ziel-Ccache-Namens"
++
++#: ../../src/clients/ksu/main.c:887
++msgid "while allocating memory for the target ccache name"
++msgstr "beim Reservieren von Speicher für den Ziel-Ccache-Namen"
++
++#: ../../src/clients/ksu/main.c:906
++msgid "while creating new target ccache"
++msgstr "bei Erstellen von neuem Ziel-Ccache"
++
++#: ../../src/clients/ksu/main.c:912
++msgid "while initializing target cache"
++msgstr "beim Initialisieren des Zielzwischenspeichers"
++
++#: ../../src/clients/ksu/main.c:952
++#, c-format
++msgid "terminal name %s too long\n"
++msgstr "Terminal-Name %s ist zu lang.\n"
++
++#: ../../src/clients/ksu/main.c:980
++msgid "while changing to target uid for destroying ccache"
++msgstr "beim Ändern der Ziel-UID für das Zerstören von Ccache"
++
++#: ../../src/clients/kswitch/kswitch.c:44
++#, c-format
++msgid "Usage: %s {-c cache_name | -p principal}\n"
++msgstr "Aufruf: %s {-c Zwischenspeichername | -p Principal}\n"
++
++#: ../../src/clients/kswitch/kswitch.c:46
++#, c-format
++msgid "\t-p specify name of principal\n"
++msgstr "\t-p gibt den Namen des Principals an.\n"
++
++#: ../../src/clients/kswitch/kswitch.c:69
++#, c-format
++msgid "Only one -c or -p option allowed\n"
++msgstr "Nur eine der Optionen -c oder -p ist erlaubt.\n"
++
++#: ../../src/clients/kswitch/kswitch.c:88
++#, c-format
++msgid "One of -c or -p must be specified\n"
++msgstr "Entweder -c oder -p muss angegeben werden.\n"
++
++#: ../../src/clients/kswitch/kswitch.c:110 ../../src/clients/kvno/kvno.c:211
++#: ../../src/clients/kvno/kvno.c:245 ../../src/kadmin/cli/keytab.c:350
++#: ../../src/kadmin/dbutil/kdb5_util.c:576
++#, c-format
++msgid "while parsing principal name %s"
++msgstr "beim Auswerten des Principal-Namens %s"
++
++#: ../../src/clients/kswitch/kswitch.c:124
++msgid "while switching to credential cache"
++msgstr "beim Wechsel auf den Anmeldedatenzwischenspeicher"
++
++#: ../../src/clients/kvno/kvno.c:46
++#, c-format
++msgid "usage: %s [-C] [-u] [-c ccache] [-e etype]\n"
++msgstr "Aufruf: %s [-C] [-u] [-c Ccache] [-e Etype]\n"
++
++#: ../../src/clients/kvno/kvno.c:47
++#, c-format
++msgid "\t[-k keytab] [-S sname] [-U for_user [-P]]\n"
++msgstr "\t[-k Schlüsseltabelle] [-S Sname] [-U für_Benutzer [-P]]\n"
++
++#: ../../src/clients/kvno/kvno.c:48
++#, c-format
++msgid "\tservice1 service2 ...\n"
++msgstr "\tDienst1 Dienst2 …\n"
++
++#: ../../src/clients/kvno/kvno.c:103 ../../src/clients/kvno/kvno.c:111
++#, c-format
++msgid "Options -u and -S are mutually exclusive\n"
++msgstr "Die Optionen -u und -S schließen sich gegenseitig aus.\n"
++
++#: ../../src/clients/kvno/kvno.c:126
++#, c-format
++msgid "Option -P (constrained delegation) requires keytab to be specified\n"
++msgstr ""
++"Die Option -P (eingeschränkte Abtretung) erfordert zur Angabe eine "
++"Schlüsseltabelle.\n"
++
++#: ../../src/clients/kvno/kvno.c:130
++#, c-format
++msgid ""
++"Option -P (constrained delegation) requires option -U (protocol transition)\n"
++msgstr ""
++"Die Option -P (eingeschränkte Abtretung) erfordert die Option -U "
++"(Protokollübergang)\n"
++
++#: ../../src/clients/kvno/kvno.c:175 ../../src/kadmin/cli/kadmin.c:280
++msgid "while initializing krb5 library"
++msgstr "beim Initialisieren der Krb5-Bibliothek"
++
++#: ../../src/clients/kvno/kvno.c:182
++msgid "while converting etype"
++msgstr "bei der Etype-Umwandlung"
++
++#: ../../src/clients/kvno/kvno.c:218
++msgid "while getting client principal name"
++msgstr "beim Holen des Client-Principal-Namens"
++
++#: ../../src/clients/kvno/kvno.c:256
++#, c-format
++msgid "while formatting parsed principal name for '%s'"
++msgstr "beim Formatieren des ausgewerteten Principal-Namens für »%s«"
++
++#: ../../src/clients/kvno/kvno.c:267
++msgid "client and server principal names must match"
++msgstr "Die Principal-Namen von Client und Server müssen übereinstimmen."
++
++#: ../../src/clients/kvno/kvno.c:284
++#, c-format
++msgid "while getting credentials for %s"
++msgstr "beim Holen der Anmeldedaten für %s"
++
++#: ../../src/clients/kvno/kvno.c:291
++#, c-format
++msgid "while decoding ticket for %s"
++msgstr "beim Dekodieren des Tickets für %s"
++
++#: ../../src/clients/kvno/kvno.c:302
++#, c-format
++msgid "while decrypting ticket for %s"
++msgstr "beim Entschlüsseln des Tickets für %s"
++
++#: ../../src/clients/kvno/kvno.c:306
++#, c-format
++msgid "%s: kvno = %d, keytab entry valid\n"
++msgstr "%s: KVNO = %d, Schlüsseltabelleneintrag gültig\n"
++
++#: ../../src/clients/kvno/kvno.c:324
++#, c-format
++msgid "%s: constrained delegation failed"
++msgstr "%s: eingeschränkte Abtretung fehlgeschlagen"
++
++#: ../../src/clients/kvno/kvno.c:330
++#, c-format
++msgid "%s: kvno = %d\n"
++msgstr "%s: KVNO = %d\n"
++
++#: ../../src/kadmin/cli/kadmin.c:118
++#, c-format
++msgid ""
++"Usage: %s [-r realm] [-p principal] [-q query] [clnt|local args]\n"
++"\tclnt args: [-s admin_server[:port]] [[-c ccache]|[-k [-t keytab]]]|[-n]\n"
++"\tlocal args: [-x db_args]* [-d dbname] [-e \"enc:salt ...\"] [-m]\n"
++"where,\n"
++"\t[-x db_args]* - any number of database specific arguments.\n"
++"\t\t\tLook at each database documentation for supported arguments\n"
++msgstr ""
++"Aufruf: %s [-r Realm] [-p Principal] [-q Abfrage] [clnt|lokale Argumente]\n"
++"\tclnt Argumente: [-s Admin-Server[:Port]] [[-c Ccache]|\n"
++"\t[-k [-t Schlüsseltabelle]]]|[-n] lokale Argumente: [-x DB-Argumente]*\n"
++"\t[-d Datenbankname] [-e \"enc:Salt …\"] [-m]\n"
++"wobei\n"
++"\t[-x DB-Argumente]* - eine beliebige Anzahl datenbankspezifischer "
++"Argumente\n"
++"\tist. Die unterstützten Argumente finden Sie in den jeweiligen "
++"\tDatenbankdokumentationen\n"
++
++#: ../../src/kadmin/cli/kadmin.c:292 ../../src/kadmin/cli/kadmin.c:333
++#, c-format
++msgid "%s: Cannot initialize. Not enough memory\n"
++msgstr "%s: Zu wenig Speicher zum Initialisieren\n"
++
++#: ../../src/kadmin/cli/kadmin.c:353 ../../src/kadmin/cli/kadmin.c:804
++#: ../../src/kadmin/cli/kadmin.c:1084 ../../src/kadmin/cli/kadmin.c:1634
++#: ../../src/kadmin/cli/keytab.c:159 ../../src/kadmin/dbutil/kdb5_util.c:591
++#, c-format
++msgid "while parsing keysalts %s"
++msgstr "beim Auswerten der Schlüssel-Salts %s"
++
++#: ../../src/kadmin/cli/kadmin.c:376
++#, c-format
++msgid "%s: unable to get default realm\n"
++msgstr "%s: Standard-Realm kann nicht geholt werden\n"
++
++#: ../../src/kadmin/cli/kadmin.c:396
++msgid "while opening default credentials cache"
++msgstr "beim Öffnen des Standardanmeldedatenzwischenspeichers"
++
++#: ../../src/kadmin/cli/kadmin.c:402
++#, c-format
++msgid "while opening credentials cache %s"
++msgstr "beim Öffnen des Anmeldedatenzwischenspeichers %s"
++
++#: ../../src/kadmin/cli/kadmin.c:424 ../../src/kadmin/cli/kadmin.c:479
++#: ../../src/kadmin/cli/kadmin.c:487 ../../src/kadmin/cli/kadmin.c:494
++#, c-format
++msgid "%s: out of memory\n"
++msgstr "%s: Speicherplatz reicht nicht aus\n"
++
++#: ../../src/kadmin/cli/kadmin.c:433 ../../src/kadmin/cli/kadmin.c:448
++#: ../../src/slave/kpropd.c:681
++msgid "while canonicalizing principal name"
++msgstr "während der Principal-Name in die normale Form gebracht wird"
++
++#: ../../src/kadmin/cli/kadmin.c:442
++msgid "creating host service principal"
++msgstr "Principal des Rechnerdienstes wird erstellt"
++
++#: ../../src/kadmin/cli/kadmin.c:455
++#, c-format
++msgid "%s: unable to canonicalize principal\n"
++msgstr "%s: Principal kann nicht in die normale Form gebracht werden\n"
++
++#: ../../src/kadmin/cli/kadmin.c:499
++#, c-format
++msgid "%s: unable to figure out a principal name\n"
++msgstr "%s: Es kann kein Principal-Name herausgefunden werden.\n"
++
++#: ../../src/kadmin/cli/kadmin.c:507
++msgid "while setting up logging"
++msgstr "beim Einrichten der Protokollierung"
++
++#: ../../src/kadmin/cli/kadmin.c:516
++#, c-format
++msgid "Authenticating as principal %s with existing credentials.\n"
++msgstr "Authentifizierung als Principal %s mit existierenden Anmeldedaten\n"
++
++#: ../../src/kadmin/cli/kadmin.c:522
++#, c-format
++msgid "Authenticating as principal %s with password; anonymous requested.\n"
++msgstr ""
++"Authentifizierung als Principal %s mit Passwort; Anonymität erwünscht\n"
++
++#: ../../src/kadmin/cli/kadmin.c:529
++#, c-format
++msgid "Authenticating as principal %s with keytab %s.\n"
++msgstr "Authentifizierung als Principal %s mit Schlüsseltabelle %s\n"
++
++#: ../../src/kadmin/cli/kadmin.c:532
++#, c-format
++msgid "Authenticating as principal %s with default keytab.\n"
++msgstr "Authentifizierung als Principal %s mit Standardschlüsseltabelle\n"
++
++#: ../../src/kadmin/cli/kadmin.c:538
++#, c-format
++msgid "Authenticating as principal %s with password.\n"
++msgstr "Authentifizierung als Principal %s mit Passwort\n"
++
++#: ../../src/kadmin/cli/kadmin.c:546 ../../src/slave/kpropd.c:728
++#, c-format
++msgid "while initializing %s interface"
++msgstr "beim Initialisieren der Schnittstelle %s"
++
++#: ../../src/kadmin/cli/kadmin.c:560
++#, c-format
++msgid "while closing ccache %s"
++msgstr "beim Schließen von Ccache %s"
++
++#: ../../src/kadmin/cli/kadmin.c:566
++msgid "while mapping update log"
++msgstr "beim Abbilden des Aktualisierungsprotokolls"
++
++#: ../../src/kadmin/cli/kadmin.c:581
++msgid "while unlocking locked database"
++msgstr "beim Entsperren der Datenbank"
++
++#: ../../src/kadmin/cli/kadmin.c:590
++msgid "Administration credentials NOT DESTROYED.\n"
++msgstr "Verwaltungsanmeldedaten NICHT VERNICHTET\n"
++
++#: ../../src/kadmin/cli/kadmin.c:639
++#, c-format
++msgid "usage: delete_principal [-force] principal\n"
++msgstr "Aufruf: delete_principal [-force] Principal\n"
++
++#: ../../src/kadmin/cli/kadmin.c:644 ../../src/kadmin/cli/kadmin.c:819
++msgid "while parsing principal name"
++msgstr "beim Auswerten des Principal-Namens"
++
++#: ../../src/kadmin/cli/kadmin.c:650 ../../src/kadmin/cli/kadmin.c:825
++#: ../../src/kadmin/cli/kadmin.c:1217 ../../src/kadmin/cli/kadmin.c:1339
++#: ../../src/kadmin/cli/kadmin.c:1409 ../../src/kadmin/cli/kadmin.c:1858
++#: ../../src/kadmin/cli/kadmin.c:1902 ../../src/kadmin/cli/kadmin.c:1948
++#: ../../src/kadmin/cli/kadmin.c:1988
++msgid "while canonicalizing principal"
++msgstr "während der Principal in die normale Form gebracht wird"
++
++#: ../../src/kadmin/cli/kadmin.c:654
++#, c-format
++msgid "Are you sure you want to delete the principal \"%s\"? (yes/no): "
++msgstr ""
++"Sind Sie sicher, dass Sie den Principal »%s« löschen möchten? (yes/no): "
++
++#: ../../src/kadmin/cli/kadmin.c:658
++#, c-format
++msgid "Principal \"%s\" not deleted\n"
++msgstr "Principal »%s« nicht gelöscht\n"
++
++#: ../../src/kadmin/cli/kadmin.c:665
++#, c-format
++msgid "while deleting principal \"%s\""
++msgstr "beim Löschen von Principal »%s«"
++
++#: ../../src/kadmin/cli/kadmin.c:668
++#, c-format
++msgid "Principal \"%s\" deleted.\n"
++msgstr "Principal »%s« gelöscht\n"
++
++#: ../../src/kadmin/cli/kadmin.c:669
++#, c-format
++msgid ""
++"Make sure that you have removed this principal from all ACLs before "
++"reusing.\n"
++msgstr ""
++"Stellen Sie sicher, dass Sie diesen Principal aus allen ACLs entfernt haben, "
++"bevor Sie ihn erneut benutzen.\n"
++
++#: ../../src/kadmin/cli/kadmin.c:686
++#, c-format
++msgid "usage: rename_principal [-force] old_principal new_principal\n"
++msgstr "Aufruf: rename_principal [-force] alter_Principal neuer_Principal\n"
++
++#: ../../src/kadmin/cli/kadmin.c:693
++msgid "while parsing old principal name"
++msgstr "beim Auswerten des alten Principal-Namens"
++
++#: ../../src/kadmin/cli/kadmin.c:699
++msgid "while parsing new principal name"
++msgstr "beim Auswerten des neuen Principal-Namens"
++
++#: ../../src/kadmin/cli/kadmin.c:705
++msgid "while canonicalizing old principal"
++msgstr "während der alte Principal in die normale Form gebracht wird"
++
++#: ../../src/kadmin/cli/kadmin.c:711
++msgid "while canonicalizing new principal"
++msgstr "während der neue Principal in die normale Form gebracht wird"
++
++#: ../../src/kadmin/cli/kadmin.c:715
++#, c-format
++msgid ""
++"Are you sure you want to rename the principal \"%s\" to \"%s\"? (yes/no): "
++msgstr ""
++"Sind Sie sicher, dass Sie den Principal »%s« in »%s« umbenennen möchten? "
++"(yes/no): "
++
++#: ../../src/kadmin/cli/kadmin.c:719
++#, c-format
++msgid "Principal \"%s\" not renamed\n"
++msgstr "Principal »%s« wurde nicht umbenannt.\n"
++
++#: ../../src/kadmin/cli/kadmin.c:726
++#, c-format
++msgid "while renaming principal \"%s\" to \"%s\""
++msgstr "beim Umbenennen von Principal »%s« in »%s«"
++
++#: ../../src/kadmin/cli/kadmin.c:730
++#, c-format
++msgid "Principal \"%s\" renamed to \"%s\".\n"
++msgstr "Principal »%s« wurde in »%s« umbenannt.\n"
++
++#: ../../src/kadmin/cli/kadmin.c:731
++#, c-format
++msgid ""
++"Make sure that you have removed the old principal from all ACLs before "
++"reusing.\n"
++msgstr ""
++"Stellen Sie sicher, dass Sie den alten Principal aus allen ACLs entfernt "
++"haben, bevor Sie ihn erneut benutzen.\n"
++
++#: ../../src/kadmin/cli/kadmin.c:746
++#, c-format
++msgid ""
++"usage: change_password [-randkey] [-keepold] [-e keysaltlist] [-pw password] "
++"principal\n"
++msgstr ""
++"Aufruf: change_password [-randkey] [-keepold] [-e Schlüssel-Salt-Liste] [-pw "
++"Passwort] Principal\n"
++
++#: ../../src/kadmin/cli/kadmin.c:772
++msgid "change_password: missing db argument"
++msgstr "change_password: fehlendes Datenbankargument"
++
++#: ../../src/kadmin/cli/kadmin.c:778
++#, c-format
++msgid "change_password: Not enough memory\n"
++msgstr "change_password: zu wenig Speicher\n"
++
++#: ../../src/kadmin/cli/kadmin.c:786
++msgid "change_password: missing password arg"
++msgstr "change_password: fehlendes Passwortargument"
++
++#: ../../src/kadmin/cli/kadmin.c:797
++msgid "change_password: missing keysaltlist arg"
++msgstr "change_password: fehlendes Schlüssel-Salt-Listenargument"
++
++#: ../../src/kadmin/cli/kadmin.c:813
++msgid "missing principal name"
++msgstr "fehlender Principal-Name"
++
++#: ../../src/kadmin/cli/kadmin.c:837 ../../src/kadmin/cli/kadmin.c:874
++#, c-format
++msgid "while changing password for \"%s\"."
++msgstr "beim Ändern des Passworts von »%s«."
++
++#: ../../src/kadmin/cli/kadmin.c:840 ../../src/kadmin/cli/kadmin.c:877
++#, c-format
++msgid "Password for \"%s\" changed.\n"
++msgstr "Passwort von »%s« geändert\n"
++
++#: ../../src/kadmin/cli/kadmin.c:846 ../../src/kadmin/cli/kadmin.c:1290
++#, c-format
++msgid "while randomizing key for \"%s\"."
++msgstr "beim Erzeugen eines zufälligen Schlüssels für »%s«."
++
++#: ../../src/kadmin/cli/kadmin.c:849
++#, c-format
++msgid "Key for \"%s\" randomized.\n"
++msgstr "Es wurde ein zufälliger Schlüssel für %s erzeugt\n"
++
++#: ../../src/kadmin/cli/kadmin.c:854 ../../src/kadmin/cli/kadmin.c:1250
++#, c-format
++msgid "Enter password for principal \"%s\""
++msgstr "Geben Sie das Passwort für Principal »%s« ein."
++
++#: ../../src/kadmin/cli/kadmin.c:856 ../../src/kadmin/cli/kadmin.c:1252
++#, c-format
++msgid "Re-enter password for principal \"%s\""
++msgstr "Geben Sie das Passwort für Principal »%s« erneut ein."
++
++#: ../../src/kadmin/cli/kadmin.c:861 ../../src/kadmin/cli/kadmin.c:1256
++#, c-format
++msgid "while reading password for \"%s\"."
++msgstr "beim Lesen des Passworts von »%s«."
++
++#: ../../src/kadmin/cli/kadmin.c:915
++#, c-format
++msgid "Not enough memory\n"
++msgstr "Speicher reicht nicht aus\n"
++
++#: ../../src/kadmin/cli/kadmin.c:945 ../../src/kadmin/dbutil/kdb5_util.c:623
++msgid "while getting time"
++msgstr "beim Holen der Zeit"
++
++#: ../../src/kadmin/cli/kadmin.c:994 ../../src/kadmin/cli/kadmin.c:1007
++#: ../../src/kadmin/cli/kadmin.c:1020 ../../src/kadmin/cli/kadmin.c:1033
++#: ../../src/kadmin/cli/kadmin.c:1546 ../../src/kadmin/cli/kadmin.c:1558
++#: ../../src/kadmin/cli/kadmin.c:1601 ../../src/kadmin/cli/kadmin.c:1618
++#, c-format
++msgid "Invalid date specification \"%s\".\n"
++msgstr "ungültige Datumsangabe »%s«\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1118 ../../src/kadmin/cli/kadmin.c:1333
++#: ../../src/kadmin/cli/kadmin.c:1404 ../../src/kadmin/cli/kadmin.c:1852
++#: ../../src/kadmin/cli/kadmin.c:1896 ../../src/kadmin/cli/kadmin.c:1942
++#: ../../src/kadmin/cli/kadmin.c:1982
++msgid "while parsing principal"
++msgstr "beim Auswerten des Principals"
++
++#: ../../src/kadmin/cli/kadmin.c:1127
++#, c-format
++msgid "usage: add_principal [options] principal\n"
++msgstr "Aufruf: add_principal [Optionen] Principal\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1128 ../../src/kadmin/cli/kadmin.c:1155
++#: ../../src/kadmin/cli/kadmin.c:1657
++#, c-format
++msgid "\toptions are:\n"
++msgstr "\tEs gibt folgende Optionen:\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1130
++#, c-format
++msgid ""
++"\t\t[-randkey|-nokey] [-x db_princ_args]* [-expire expdate] [-pwexpire "
++"pwexpdate] [-maxlife maxtixlife]\n"
++"\t\t[-kvno kvno] [-policy policy] [-clearpolicy]\n"
++"\t\t[-pw password] [-maxrenewlife maxrenewlife]\n"
++"\t\t[-e keysaltlist]\n"
++"\t\t[{+|-}attribute]\n"
++msgstr ""
++"\t\t[-randkey|-nokey] [-x DB-Principal-Argumente]* [-expire Ablaufdatum] [-"
++"pwexpire Passwortablaufdatum] [-maxlife maximale_Ticketlebensdauer]\n"
++"\t\t[-kvno KVNO] [-policy Richtlinie] [-clearpolicy]\n"
++"\t\t[-pw Passwort] [-maxrenewlife maximale_Dauer_bis_zum_Erneuern]\n"
++"\t\t[-e Schlüssel-Salt-Liste]\n"
++"\t\t[{+|-}Attribut]\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1136
++#, c-format
++msgid "\tattributes are:\n"
++msgstr "\tEs gibt folgende Attribute:\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1138 ../../src/kadmin/cli/kadmin.c:1164
++#, c-format
++msgid ""
++"\t\tallow_postdated allow_forwardable allow_tgs_req allow_renewable\n"
++"\t\tallow_proxiable allow_dup_skey allow_tix requires_preauth\n"
++"\t\trequires_hwauth needchange allow_svr password_changing_service\n"
++"\t\tok_as_delegate ok_to_auth_as_delegate no_auth_data_required\n"
++"\n"
++"where,\n"
++"\t[-x db_princ_args]* - any number of database specific arguments.\n"
++"\t\t\tLook at each database documentation for supported arguments\n"
++msgstr ""
++"\t\tallow_postdated allow_forwardable allow_tgs_req allow_renewable\n"
++"\t\tallow_proxiable allow_dup_skey allow_tix requires_preauth\n"
++"\t\trequires_hwauth needchange allow_svr password_changing_service\n"
++"\t\tok_as_delegate ok_to_auth_as_delegate no_auth_data_required\n"
++"\n"
++"wobei\n"
++"\t[-x DB-Principal-Argumente]* - eine beliebige Zahl\n"
++"\tdatenbankspezifischer Argumente ist.\n"
++"\t\t\tDie unterstützten Argumente finden Sie in der jeweiligen\n"
++"Datenbankdokumentation.\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1154
++#, c-format
++msgid "usage: modify_principal [options] principal\n"
++msgstr "Aufruf: modify_principal [Optionen] Principal\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1157
++#, c-format
++msgid ""
++"\t\t[-x db_princ_args]* [-expire expdate] [-pwexpire pwexpdate] [-maxlife "
++"maxtixlife]\n"
++"\t\t[-kvno kvno] [-policy policy] [-clearpolicy]\n"
++"\t\t[-maxrenewlife maxrenewlife] [-unlock] [{+|-}attribute]\n"
++msgstr ""
++"\t\t[-x DB-Principal-Argumente]* [-expire Ablaufdatum] [-pwexpire "
++"Passwortablaufdatum] [-maxlife maximale_Ticketlebensdauer]\n"
++"\t\t[-kvno KVNO] [-policy Richtlinie] [-clearpolicy]\n"
++"\t\t[-maxrenewlife maximale_Dauer_bis_zum_Erneuern] [-unlock] [{+|-}"
++"Attribut]\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1224 ../../src/kadmin/cli/kadmin.c:1362
++#, c-format
++msgid "WARNING: policy \"%s\" does not exist\n"
++msgstr "WARNUNG: Richtlinie »%s« existiert nicht.\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1230
++#, c-format
++msgid "NOTICE: no policy specified for %s; assigning \"default\"\n"
++msgstr ""
++"HINWEIS: Für %s wurde keine Richtlinie angegeben, es wird »default« "
++"zugewiesen\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1235
++#, c-format
++msgid "WARNING: no policy specified for %s; defaulting to no policy\n"
++msgstr ""
++"WARNUNG: Für %s wurde keine Richtlinie angegeben, es wird die Vorgabe "
++"»keine\n"
++"Richtlinie« verwandt.\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1276
++#, c-format
++msgid "Admin server does not support -nokey while creating \"%s\"\n"
++msgstr ""
++"Der Administrationsrechner unterstützt beim Erstellen von »%s« kein -nokey\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1298
++#, c-format
++msgid "while clearing DISALLOW_ALL_TIX for \"%s\"."
++msgstr "beim Löschen von DISALLOW_ALL_TIX für »%s«."
++
++#: ../../src/kadmin/cli/kadmin.c:1345
++#, c-format
++msgid "while getting \"%s\"."
++msgstr "beim Holen von »%s«."
++
++#: ../../src/kadmin/cli/kadmin.c:1371
++#, c-format
++msgid "while modifying \"%s\"."
++msgstr "beim Ändern von »%s«."
++
++#: ../../src/kadmin/cli/kadmin.c:1375
++#, c-format
++msgid "Principal \"%s\" modified.\n"
++msgstr "Principal »%s« wurde geändert.\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1396
++#, c-format
++msgid "usage: get_principal [-terse] principal\n"
++msgstr "Aufruf: get_principal [-terse] Principal\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1415
++#, c-format
++msgid "while retrieving \"%s\"."
++msgstr "beim Abfragen von »%s«."
++
++#: ../../src/kadmin/cli/kadmin.c:1420 ../../src/kadmin/cli/kadmin.c:1425
++msgid "while unparsing principal"
++msgstr "beim Rückgängigmachen der Auswertung des Principals"
++
++#: ../../src/kadmin/cli/kadmin.c:1429
++#, c-format
++msgid "Principal: %s\n"
++msgstr "Principal: %s\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1430
++#, c-format
++msgid "Expiration date: %s\n"
++msgstr "Ablaufdatum: %s\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1431 ../../src/kadmin/cli/kadmin.c:1433
++#: ../../src/kadmin/cli/kadmin.c:1444
++msgid "[never]"
++msgstr "[niemals]"
++
++#: ../../src/kadmin/cli/kadmin.c:1432
++#, c-format
++msgid "Last password change: %s\n"
++msgstr "Letzte Passwortänderung: %s\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1434
++#, c-format
++msgid "Password expiration date: %s\n"
++msgstr "Passwortablaufdatum: %s\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1436 ../../src/kadmin/cli/kadmin.c:1478
++msgid "[none]"
++msgstr "[keins]"
++
++#: ../../src/kadmin/cli/kadmin.c:1437
++#, c-format
++msgid "Maximum ticket life: %s\n"
++msgstr "maximale Ticketlebensdauer: %s\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1438
++#, c-format
++msgid "Maximum renewable life: %s\n"
++msgstr "maximale verlängerbare Lebensdauer: %s\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1440
++#, c-format
++msgid "Last modified: %s (%s)\n"
++msgstr "zuletzt geändert: %s (%s)\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1442
++#, c-format
++msgid "Last successful authentication: %s\n"
++msgstr "letzte erfolgreiche Authentifizierung: %s\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1448
++#, c-format
++msgid "Failed password attempts: %d\n"
++msgstr "Fehlgeschlagene Anmeldeversuche: %d\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1450
++#, c-format
++msgid "Number of keys: %d\n"
++msgstr "Anzahl der Schlüssel: %d\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1457
++#, c-format
++msgid "<Encryption type 0x%x>"
++msgstr "<Verschlüsselungstyp 0x%x>"
++
++#: ../../src/kadmin/cli/kadmin.c:1464
++#, c-format
++msgid "<Salt type 0x%x>"
++msgstr "<Salt-Typ 0x%x>"
++
++#: ../../src/kadmin/cli/kadmin.c:1470
++#, c-format
++msgid "MKey: vno %d\n"
++msgstr "MKey: vno %d\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1472
++#, c-format
++msgid "Attributes:"
++msgstr "Attribute:"
++
++#: ../../src/kadmin/cli/kadmin.c:1480
++msgid " [does not exist]"
++msgstr " [existiert nicht]"
++
++#: ../../src/kadmin/cli/kadmin.c:1481
++#, c-format
++msgid "Policy: %s%s\n"
++msgstr "Richtlinie: %s%s\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1517
++#, c-format
++msgid "usage: get_principals [expression]\n"
++msgstr "Aufruf: get_principals [Ausdruck]\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1522 ../../src/kadmin/cli/kadmin.c:1794
++msgid "while retrieving list."
++msgstr "beim Abfragen der Liste."
++
++#: ../../src/kadmin/cli/kadmin.c:1647
++#, c-format
++msgid "%s: parser lost count!\n"
++msgstr "%s: Auswertungsprogramm verlor Anzahl!\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1656
++#, c-format
++msgid "usage; %s [options] policy\n"
++msgstr "Aufruf: %s [Optionen] Richtlinie\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1659
++#, c-format
++msgid ""
++"\t\t[-maxlife time] [-minlife time] [-minlength length]\n"
++"\t\t[-minclasses number] [-history number]\n"
++"\t\t[-maxfailure number] [-failurecountinterval time]\n"
++"\t\t[-allowedkeysalts keysalts]\n"
++msgstr ""
++"\t\t[-maxlife Zeit] [-minlife Zeit] [-minlength Länge]\n"
++"\t\t[-minclasses Anzahl] [-history Nummer]\n"
++"\t\t[-maxfailure Anzahl] [-failurecountinterval Zeit]\n"
++"\t\t[-allowedkeysalts Schlüssel-Salts]\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1663
++#, c-format
++msgid "\t\t[-lockoutduration time]\n"
++msgstr "\t\t[-lockoutduration Dauer]\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1682
++#, c-format
++msgid "while creating policy \"%s\"."
++msgstr "beim Erstellen der Richtlinie »%s«"
++
++#: ../../src/kadmin/cli/kadmin.c:1703
++#, c-format
++msgid "while modifying policy \"%s\"."
++msgstr "beim Ändern der Richtlinie »%s«"
++
++#: ../../src/kadmin/cli/kadmin.c:1715
++#, c-format
++msgid "usage: delete_policy [-force] policy\n"
++msgstr "Aufruf: delete_policy [-force] Richtlinie\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1719
++#, c-format
++msgid "Are you sure you want to delete the policy \"%s\"? (yes/no): "
++msgstr ""
++"Sind Sie sicher, dass Sie die Richtlinie »%s« löschen möchten? (yes/no): "
++
++#: ../../src/kadmin/cli/kadmin.c:1723
++#, c-format
++msgid "Policy \"%s\" not deleted.\n"
++msgstr "Richtlinie »%s« nicht gelöscht\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1729
++#, c-format
++msgid "while deleting policy \"%s\""
++msgstr "bei Löschen der Richtlinie »%s«"
++
++#: ../../src/kadmin/cli/kadmin.c:1741
++#, c-format
++msgid "usage: get_policy [-terse] policy\n"
++msgstr "Aufruf: get_policy [-terse] Richtlinie\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1746
++#, c-format
++msgid "while retrieving policy \"%s\"."
++msgstr "beim Abfragen der Richtlinie »%s«."
++
++#: ../../src/kadmin/cli/kadmin.c:1751
++#, c-format
++msgid "Policy: %s\n"
++msgstr "Richtlinie: »%s«\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1752
++#, c-format
++msgid "Maximum password life: %ld\n"
++msgstr "maximale Passwortlebensdauer: %ld\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1753
++#, c-format
++msgid "Minimum password life: %ld\n"
++msgstr "minimale Passwortlebensdauer: %ld\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1754
++#, c-format
++msgid "Minimum password length: %ld\n"
++msgstr "minimale Passwortlänge: %ld\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1755
++#, c-format
++msgid "Minimum number of password character classes: %ld\n"
++msgstr "minimale Anzahl von Passwortzeichenklassen: %ld\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1757
++#, c-format
++msgid "Number of old keys kept: %ld\n"
++msgstr "Anzahl aufbewahrter alter Schlüssel: %ld\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1758
++#, c-format
++msgid "Maximum password failures before lockout: %lu\n"
++msgstr "maximale Anzahl falscher Passworteingaben vor dem Sperren: %lu\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1760
++#, c-format
++msgid "Password failure count reset interval: %s\n"
++msgstr "Rücksetzintervall für zu viele falsch eingebene Passwörter: %s\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1762
++#, c-format
++msgid "Password lockout duration: %s\n"
++msgstr "Passwortsperrdauer: %s\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1765
++#, c-format
++msgid "Allowed key/salt types: %s\n"
++msgstr "erlaubte Schlüssel-/Salt-Typen: %s\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1789
++#, c-format
++msgid "usage: get_policies [expression]\n"
++msgstr "Aufruf: get_policies [Ausdruck]\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1811
++#, c-format
++msgid "usage: get_privs\n"
++msgstr "Aufruf: get_privs\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1816
++msgid "while retrieving privileges"
++msgstr "beim Abfragen von Rechten"
++
++#: ../../src/kadmin/cli/kadmin.c:1819
++#, c-format
++msgid "current privileges:"
++msgstr "aktuelle Rechte:"
++
++#: ../../src/kadmin/cli/kadmin.c:1845
++#, c-format
++msgid "usage: purgekeys [-all|-keepkvno oldest_kvno_to_keep] principal\n"
++msgstr ""
++"Aufruf: purgekeys [-all|-keepkvno älteste_KVNO_die_behalten_wird] Principal\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1865
++#, c-format
++msgid "while purging keys for principal \"%s\""
++msgstr "beim vollständigen Löschen der Schlüssel für Principal »%s«"
++
++#: ../../src/kadmin/cli/kadmin.c:1870
++#, c-format
++msgid "All keys for principal \"%s\" removed.\n"
++msgstr "Alle Schlüssel für Principal »%s« wurden entfernt.\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1872
++#, c-format
++msgid "Old keys for principal \"%s\" purged.\n"
++msgstr "Alte Schlüssel für Principal »%s« wurden entfernt.\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1889
++#, c-format
++msgid "usage: get_strings principal\n"
++msgstr "Aufruf: get_strings Principal\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1909
++#, c-format
++msgid "while getting attributes for principal \"%s\""
++msgstr "beim Holen von Attributen für Principal »%s«"
++
++#: ../../src/kadmin/cli/kadmin.c:1914
++#, c-format
++msgid "(No string attributes.)\n"
++msgstr "(keine Zeichenkettenattribute)\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1933
++#, c-format
++msgid "usage: set_string principal key value\n"
++msgstr "Aufruf: set_string Principal Schlüssel Wert\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1955
++#, c-format
++msgid "while setting attribute on principal \"%s\""
++msgstr "beim Setzen eines Attributes für Principal »%s«"
++
++#: ../../src/kadmin/cli/kadmin.c:1959
++#, c-format
++msgid "Attribute set for principal \"%s\".\n"
++msgstr "Attribute für Principal »%s« wurden gesetzt.\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1974
++#, c-format
++msgid "usage: del_string principal key\n"
++msgstr "Aufruf: del_string Principal Schlüssel\n"
++
++#: ../../src/kadmin/cli/kadmin.c:1995
++#, c-format
++msgid "while deleting attribute from principal \"%s\""
++msgstr "beim Löschen eines Attributs von Principal »%s«"
++
++#: ../../src/kadmin/cli/kadmin.c:1999
++#, c-format
++msgid "Attribute removed from principal \"%s\".\n"
++msgstr "Attribut von Principal »%s« wurde gelöscht.\n"
++
++#: ../../src/kadmin/cli/keytab.c:56
++#, c-format
++msgid ""
++"Usage: ktadd [-k[eytab] keytab] [-q] [-e keysaltlist] [-norandkey] "
++"[principal | -glob princ-exp] [...]\n"
++msgstr ""
++"Aufruf: ktadd [-k[eytab] Schlüsseltabelle] [-q] [-e Schlüssel-Salt-Liste] [-"
++"norandkey] [Principal | -glob Principal-Ausdruck] […]\n"
++
++#: ../../src/kadmin/cli/keytab.c:59
++#, c-format
++msgid ""
++"Usage: ktadd [-k[eytab] keytab] [-q] [-e keysaltlist] [principal | -glob "
++"princ-exp] [...]\n"
++msgstr ""
++"Aufruf: ktadd [-k[eytab] Schlüsseltabelle] [-q] [-e Schlüssel-Salt-Liste] "
++"[Principal | -glob Principal-Ausdruck] […]\n"
++
++#: ../../src/kadmin/cli/keytab.c:67
++#, c-format
++msgid ""
++"Usage: ktremove [-k[eytab] keytab] [-q] principal [kvno|\"all\"|\"old\"]\n"
++msgstr ""
++"Aufruf: ktremove [-k[eytab] Schlüsseltabelle] [-q] Principal "
++"[kvno|»all«|»old«]\n"
++
++#: ../../src/kadmin/cli/keytab.c:81 ../../src/kadmin/cli/keytab.c:102
++msgid "while creating keytab name"
++msgstr "beim Erstellen des Schlüsseltabellennamens"
++
++#: ../../src/kadmin/cli/keytab.c:86
++msgid "while opening default keytab"
++msgstr "beim Öffnen der Standardschlüsseltabelle"
++
++#: ../../src/kadmin/cli/keytab.c:147
++#, c-format
++msgid "-norandkey option only valid for kadmin.local\n"
++msgstr "Die Option »-norandkey« ist nur für »kadmin.local« gültig.\n"
++
++#: ../../src/kadmin/cli/keytab.c:176
++#, c-format
++msgid "cannot specify keysaltlist when not changing key\n"
++msgstr ""
++"Schlüssel-Salt-Liste kann nicht angegeben werden, wenn der Schlüssel nicht "
++"geändert wird\n"
++
++#: ../../src/kadmin/cli/keytab.c:192
++#, c-format
++msgid "while expanding expression \"%s\"."
++msgstr "beim Expandieren des Ausdrucks »%s«."
++
++#: ../../src/kadmin/cli/keytab.c:211 ../../src/kadmin/cli/keytab.c:251
++msgid "while closing keytab"
++msgstr "beim Schließen der Schlüsseltabelle"
++
++#: ../../src/kadmin/cli/keytab.c:275
++#, c-format
++msgid "while parsing -add principal name %s"
++msgstr "beim Auswerten von »-add Principal-Name %s«"
++
++#: ../../src/kadmin/cli/keytab.c:289
++#, c-format
++msgid "%s: Principal %s does not exist.\n"
++msgstr "%s: Principal %s existiert nicht.\n"
++
++#: ../../src/kadmin/cli/keytab.c:292
++#, c-format
++msgid "while changing %s's key"
++msgstr "beim Ändern des Schlüssels von %s"
++
++#: ../../src/kadmin/cli/keytab.c:299
++msgid "while retrieving principal"
++msgstr "beim Abfragen des Principals"
++
++#: ../../src/kadmin/cli/keytab.c:311
++msgid "while adding key to keytab"
++msgstr "beim Hinzufügen des Schlüssels zur Schlüsseltabelle"
++
++#: ../../src/kadmin/cli/keytab.c:317
++#, c-format
++msgid ""
++"Entry for principal %s with kvno %d, encryption type %s added to keytab %s.\n"
++msgstr ""
++"Der Eintrag für Principal %s mit KVNO %d und Verschlüsselungstyp %s wurde "
++"der Schlüsseltabelle %s hinzugefügt.\n"
++
++#: ../../src/kadmin/cli/keytab.c:326
++msgid "while freeing principal entry"
++msgstr "beim Freigeben des Principal-Eintrags"
++
++#: ../../src/kadmin/cli/keytab.c:373
++#, c-format
++msgid "%s: Keytab %s does not exist.\n"
++msgstr "%s: Schlüsseltabelle %s existiert nicht.\n"
++
++#: ../../src/kadmin/cli/keytab.c:377
++#, c-format
++msgid "%s: No entry for principal %s exists in keytab %s\n"
++msgstr ""
++"%s: Für Principal %s existiert kein Eintrag in der Schlüsseltabelle %s.\n"
++
++#: ../../src/kadmin/cli/keytab.c:381
++#, c-format
++msgid "%s: No entry for principal %s with kvno %d exists in keytab %s\n"
++msgstr ""
++"%s: Für den Principal %s mit der KVNO %d existiert kein Eintrag in der "
++"Schlüsseltabelle %s.\n"
++
++#: ../../src/kadmin/cli/keytab.c:387
++msgid "while retrieving highest kvno from keytab"
++msgstr "beim Abfragen der höchsten KVNO der Schlüsseltabelle"
++
++#: ../../src/kadmin/cli/keytab.c:420
++msgid "while temporarily ending keytab scan"
++msgstr "beim Unterbrechen des Schlüsseltabellen-Scans"
++
++#: ../../src/kadmin/cli/keytab.c:425
++msgid "while deleting entry from keytab"
++msgstr "beim Löschen eines Eintrags aus der Schlüsseltabelle"
++
++#: ../../src/kadmin/cli/keytab.c:430
++msgid "while restarting keytab scan"
++msgstr "bei der Wiederaufnahme des Schlüsseltabellen-Scans"
++
++#: ../../src/kadmin/cli/keytab.c:436
++#, c-format
++msgid "Entry for principal %s with kvno %d removed from keytab %s.\n"
++msgstr ""
++"Der Eintrag für Principal %s mit KVNO %d wurde aus der Schlüsseltabelle %s "
++"entfernt.\n"
++
++#: ../../src/kadmin/cli/keytab.c:458
++#, c-format
++msgid "%s: There is only one entry for principal %s in keytab %s\n"
++msgstr ""
++"%s: Es gibt nur einen Eintrag für Principal %s in der Schlüsseltabelle %s.\n"
++
++#: ../../src/kadmin/cli/ss_wrapper.c:49 ../../src/kadmin/ktutil/ktutil.c:58
++msgid "creating invocation"
++msgstr "Aufruf wird erstellt"
++
++#: ../../src/kadmin/dbutil/dump.c:165
++msgid "while allocating temporary filename dump"
++msgstr "beim Reservieren des temporären Dateinamenspeicherauszugs"
++
++#: ../../src/kadmin/dbutil/dump.c:176
++msgid "while renaming dump file into place"
++msgstr "während das Umbenennen der Auszugsdateien Gestalt annimmt"
++
++#: ../../src/kadmin/dbutil/dump.c:192
++msgid "while allocating dump_ok filename"
++msgstr "beim Reservieren des »dump_ok«-Dateinamens"
++
++#: ../../src/kadmin/dbutil/dump.c:199
++#, c-format
++msgid "while creating 'ok' file, '%s'"
++msgstr "beim Erstellen der Datei »ok«, »%s«"
++
++#: ../../src/kadmin/dbutil/dump.c:206
++#, c-format
++msgid "while locking 'ok' file, '%s'"
++msgstr "beim Sperren der Datei »ok«, »%s«"
++
++#: ../../src/kadmin/dbutil/dump.c:248 ../../src/kadmin/dbutil/dump.c:277
++#, c-format
++msgid "%s: regular expression error: %s\n"
++msgstr "%s: Fehler im regulären Ausdruck: %s\n"
++
++#: ../../src/kadmin/dbutil/dump.c:260
++#, c-format
++msgid "%s: regular expression match error: %s\n"
++msgstr "%s: Fehler beim Abgleich mit regulärem Ausdruck: %s\n"
++
++#: ../../src/kadmin/dbutil/dump.c:361
++#, c-format
++msgid "%s: tagged data list inconsistency for %s (counted %d, stored %d)\n"
++msgstr ""
++"%s: Unstimmigkeit in der markierten Datenliste für %s (%d gezählt, %d "
++"gespeichert)\n"
++
++#: ../../src/kadmin/dbutil/dump.c:519
++#, c-format
++msgid ""
++"Warning!  Multiple DES-CBC-CRC keys for principal %s; skipping duplicates.\n"
++msgstr ""
++"Warnung! Mehrere DES-CBC-CRC-Schlüssel für Principal %s, Duplikate werden "
++"übersprungen.\n"
++
++#: ../../src/kadmin/dbutil/dump.c:530
++#, c-format
++msgid ""
++"Warning!  No DES-CBC-CRC key for principal %s, cannot generate OV-compatible "
++"record; skipping\n"
++msgstr ""
++"Warnung! Kein DES-CBC-CRC-Schlüssel für Principal %s, es kann kein OV-"
++"kompatibler Datensatz erzeugt werden, wird übersprungen\n"
++
++#: ../../src/kadmin/dbutil/dump.c:558
++#, c-format
++msgid "while converting %s to new master key"
++msgstr "beim Umwandeln von %s in den neuen Hauptschlüssel"
++
++#: ../../src/kadmin/dbutil/dump.c:579
++#, c-format
++msgid "%s(%d): %s\n"
++msgstr "%s(%d): %s\n"
++
++#: ../../src/kadmin/dbutil/dump.c:622
++#, c-format
++msgid "%s(%d): ignoring trash at end of line: "
++msgstr "%s(%d): Müll am Zeilenende wird ignoriert: "
++
++#: ../../src/kadmin/dbutil/dump.c:685
++msgid "cannot read tagged data type and length"
++msgstr "Markierter Datentyp und Länge können nicht gelesen werden."
++
++#: ../../src/kadmin/dbutil/dump.c:692
++msgid "cannot read tagged data contents"
++msgstr "Inhalt der markierten Daten kann nicht gelesen werden."
++
++#: ../../src/kadmin/dbutil/dump.c:726
++msgid "cannot match size tokens"
++msgstr "Größenmerkmale können nicht zugeordnet werden."
++
++#: ../../src/kadmin/dbutil/dump.c:755
++msgid "cannot read name string"
++msgstr "Namenszeichenkette kann nicht gelesen werden."
++
++#: ../../src/kadmin/dbutil/dump.c:760
++#, c-format
++msgid "while parsing name %s"
++msgstr "beim Auswerten des Namens %s"
++
++#: ../../src/kadmin/dbutil/dump.c:768
++msgid "cannot read principal attributes"
++msgstr "Principal-Attribute können nicht gelesen werden."
++
++#: ../../src/kadmin/dbutil/dump.c:821
++msgid "cannot read key size and version"
++msgstr "Schlüssellänge und -version können nicht gelesen werden."
++
++#: ../../src/kadmin/dbutil/dump.c:832
++msgid "cannot read key type and length"
++msgstr "Schlüsseltyp und -länge können nicht gelesen werden."
++
++#: ../../src/kadmin/dbutil/dump.c:838
++msgid "cannot read key data"
++msgstr "Schlüsseldaten können nicht gelesen werden."
++
++#: ../../src/kadmin/dbutil/dump.c:848
++msgid "cannot read extra data"
++msgstr "Zusätzliche Daten können nicht gelesen werden."
++
++#: ../../src/kadmin/dbutil/dump.c:857
++#, c-format
++msgid "while storing %s"
++msgstr "beim Speichern von %s"
++
++#: ../../src/kadmin/dbutil/dump.c:896 ../../src/kadmin/dbutil/dump.c:935
++#: ../../src/kadmin/dbutil/dump.c:981
++#, c-format
++msgid "cannot parse policy (%d read)\n"
++msgstr "Richtlinie kann nicht ausgewertet werden (%d gelesen)\n"
++
++#: ../../src/kadmin/dbutil/dump.c:904 ../../src/kadmin/dbutil/dump.c:943
++#: ../../src/kadmin/dbutil/dump.c:1001
++msgid "while creating policy"
++msgstr "beim Erstellen der Richtlinie"
++
++#: ../../src/kadmin/dbutil/dump.c:908
++#, c-format
++msgid "created policy %s\n"
++msgstr "erstellte Richtlinie %s\n"
++
++#: ../../src/kadmin/dbutil/dump.c:1038
++#, c-format
++msgid "unknown record type \"%s\"\n"
++msgstr "unbekannter Datensatztyp »%s«\n"
++
++#: ../../src/kadmin/dbutil/dump.c:1167
++#, c-format
++msgid "%s: Unknown iprop dump version %d\n"
++msgstr "%s: unbekannte Iprop-Auszugsversion %d\n"
++
++#: ../../src/kadmin/dbutil/dump.c:1270 ../../src/kadmin/dbutil/dump.c:1498
++#, c-format
++msgid "Iprop not enabled\n"
++msgstr "Iprop nicht aktiviert\n"
++
++#: ../../src/kadmin/dbutil/dump.c:1308
++msgid "Conditional dump is an undocumented option for use only for iprop dumps"
++msgstr ""
++"Bedingter Auszug ist eine nicht dokumentierte Option, die nur für Iprop-"
++"Auszüge benutzt wird."
++
++#: ../../src/kadmin/dbutil/dump.c:1321
++msgid "Database not currently opened!"
++msgstr "Die Datenbank ist zur Zeit nicht geöffnet!"
++
++#: ../../src/kadmin/dbutil/dump.c:1335
++#: ../../src/kadmin/dbutil/kdb5_stash.c:116
++#: ../../src/kadmin/dbutil/kdb5_util.c:479
++msgid "while reading master key"
++msgstr "beim Lesen des Hauptschlüssels"
++
++#: ../../src/kadmin/dbutil/dump.c:1341
++msgid "while verifying master key"
++msgstr "beim Prüfen des Hauptschlüssels"
++
++#: ../../src/kadmin/dbutil/dump.c:1360 ../../src/kadmin/dbutil/dump.c:1370
++msgid "while reading new master key"
++msgstr "beim Lesen des neuen Hauptschlüssels"
++
++#: ../../src/kadmin/dbutil/dump.c:1364
++#, c-format
++msgid "Please enter new master key....\n"
++msgstr "Bitte geben Sie den neuen Hauptschlüssel ein …\n"
++
++#: ../../src/kadmin/dbutil/dump.c:1388
++#, c-format
++msgid "while opening %s for writing"
++msgstr "beim Öffnen von %s zum Schreiben"
++
++#: ../../src/kadmin/dbutil/dump.c:1403
++msgid "while reading update log header"
++msgstr "beim Lesen der Aktualisierungsprotokollkopfzeilen"
++
++#: ../../src/kadmin/dbutil/dump.c:1418 ../../src/kadmin/dbutil/dump.c:1425
++#, c-format
++msgid "performing %s dump"
++msgstr "Auszug von %s wird durchgeführt"
++
++#: ../../src/kadmin/dbutil/dump.c:1455
++#, c-format
++msgid "%s: error processing line %d of %s\n"
++msgstr "%s: Fehler beim Verarbeiten von Zeile %d von %s\n"
++
++#: ../../src/kadmin/dbutil/dump.c:1507
++msgid "while parsing options"
++msgstr "beim Auswerten der Optionen"
++
++#: ../../src/kadmin/dbutil/dump.c:1522
++#, c-format
++msgid "while opening %s"
++msgstr "beim Öffnen von %s"
++
++#: ../../src/kadmin/dbutil/dump.c:1527 ../../src/kadmin/dbutil/dump.c:1626
++msgid "standard input"
++msgstr "Standardeingabe"
++
++#: ../../src/kadmin/dbutil/dump.c:1532
++#, c-format
++msgid "%s: can't read dump header in %s\n"
++msgstr "%s: Kopfzeilen des Auszugs in %s können nicht gelesen werden.\n"
++
++#: ../../src/kadmin/dbutil/dump.c:1540 ../../src/kadmin/dbutil/dump.c:1557
++#, c-format
++msgid "%s: dump header bad in %s\n"
++msgstr "%s: falsche Kopfzeilen des Auszugs in %s\n"
++
++#: ../../src/kadmin/dbutil/dump.c:1566
++#, c-format
++msgid "Could not open iprop ulog\n"
++msgstr "Iprop-Ulog kann nicht geöffnet werden.\n"
++
++#: ../../src/kadmin/dbutil/dump.c:1571
++#, c-format
++msgid "%s: dump version %s can only be loaded with the -update flag\n"
++msgstr ""
++"%s: Die Auszugsversion %s kann nur mit dem Schalter -update geladen werden.\n"
++
++#: ../../src/kadmin/dbutil/dump.c:1580 ../../src/kadmin/dbutil/dump.c:1585
++msgid "computing parameters for database"
++msgstr "Parameter für die Datenbank werden berechnet."
++
++#: ../../src/kadmin/dbutil/dump.c:1591
++msgid "while creating database"
++msgstr "beim Erstellen der Datenbank"
++
++#: ../../src/kadmin/dbutil/dump.c:1600
++msgid "while opening database"
++msgstr "beim Öffnen der Datenbank"
++
++#: ../../src/kadmin/dbutil/dump.c:1610
++msgid "while permanently locking database"
++msgstr "beim dauerhaften Sperren der Datenbank"
++
++#: ../../src/kadmin/dbutil/dump.c:1628
++#, c-format
++msgid "%s: %s restore failed\n"
++msgstr "%s: Wiederherstellen von %s fehlgeschlagen\n"
++
++#: ../../src/kadmin/dbutil/dump.c:1633
++msgid "while unlocking database"
++msgstr "beim Aufheben der Datenbanksperre"
++
++#: ../../src/kadmin/dbutil/dump.c:1643 ../../src/kadmin/dbutil/dump.c:1662
++msgid "while reinitializing update log"
++msgstr "beim erneuten Initialisieren des Aktualisierungsprotokolls"
++
++#: ../../src/kadmin/dbutil/dump.c:1653
++msgid "while making newly loaded database live"
++msgstr "beim Aktivieren der neu geladenen Datenbank"
++
++#: ../../src/kadmin/dbutil/dump.c:1669
++msgid "while writing update log header"
++msgstr "beim Schreiben der Aktualisierungsprotokollkopfzeilen"
++
++#: ../../src/kadmin/dbutil/dump.c:1683
++#, c-format
++msgid "while deleting bad database %s"
++msgstr "beim Löschen der falschen Datenbank %s"
++
++#: ../../src/kadmin/dbutil/kadm5_create.c:84
++msgid "while looking up the Kerberos configuration"
++msgstr "beim Nachschlagen der Kerberos-Konfiguration"
++
++#: ../../src/kadmin/dbutil/kadm5_create.c:111
++msgid "while initializing the Kerberos admin interface"
++msgstr "beim Initialisieren der Kerberos-Administrationsoberfläche"
++
++#: ../../src/kadmin/dbutil/kadm5_create.c:169
++#, c-format
++msgid "getaddrinfo(%s): Cannot determine canonical hostname.\n"
++msgstr ""
++"getaddrinfo(%s): Die Normalform des Rechnernamens kann nicht bestimmt "
++"werden.\n"
++
++#: ../../src/kadmin/dbutil/kadm5_create.c:190
++#: ../../src/kadmin/dbutil/kadm5_create.c:196
++#, c-format
++msgid "Out of memory\n"
++msgstr "Speicherplatz reicht nicht aus.\n"
++
++#: ../../src/kadmin/dbutil/kadm5_create.c:270
++msgid "while appending realm to principal"
++msgstr "beim Anhängen des Realms an den Principal"
++
++#: ../../src/kadmin/dbutil/kadm5_create.c:275
++msgid "while parsing admin principal name"
++msgstr "beim Auswerten des Principal-Namens des Administrators"
++
++#: ../../src/kadmin/dbutil/kadm5_create.c:286
++#, c-format
++msgid "while creating principal %s"
++msgstr "beim Erstellen des Principals %s"
++
++#: ../../src/kadmin/dbutil/kdb5_create.c:175
++#: ../../src/kadmin/dbutil/kdb5_util.c:241
++#: ../../src/kadmin/dbutil/kdb5_util.c:248
++msgid "while parsing command arguments\n"
++msgstr "beim Auswerten der Befehlsargumente\n"
++
++#: ../../src/kadmin/dbutil/kdb5_create.c:198
++#, c-format
++msgid "Loading random data\n"
++msgstr "Zufällige Daten werden geladen.\n"
++
++#: ../../src/kadmin/dbutil/kdb5_create.c:201
++msgid "Loading random data"
++msgstr "Zufällige Daten werden geladen."
++
++#: ../../src/kadmin/dbutil/kdb5_create.c:211
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:242
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:435
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:591
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1149
++#: ../../src/kadmin/dbutil/kdb5_util.c:423
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:606
++msgid "while setting up master key name"
++msgstr "beim Einrichten des Hauptschlüsselnamens"
++
++#: ../../src/kadmin/dbutil/kdb5_create.c:222
++#, c-format
++msgid ""
++"Initializing database '%s' for realm '%s',\n"
++"master key name '%s'\n"
++msgstr ""
++"Datenbank »%s« für Realm »%s« wird initialisiert,\n"
++"Hauptschlüsselname »%s«\n"
++
++#: ../../src/kadmin/dbutil/kdb5_create.c:227
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:516
++#, c-format
++msgid "You will be prompted for the database Master Password.\n"
++msgstr "Sie werden nach dem Master-Passwort der Datenbank gefragt.\n"
++
++#: ../../src/kadmin/dbutil/kdb5_create.c:228
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:260
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:517
++#, c-format
++msgid "It is important that you NOT FORGET this password.\n"
++msgstr "Es ist wichtig, dass Sie dieses Passwort NICHT VERGESSEN.\n"
++
++#: ../../src/kadmin/dbutil/kdb5_create.c:234
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:266
++msgid "while creating new master key"
++msgstr "beim Erstellen des neuen Hauptschlüssels"
++
++#: ../../src/kadmin/dbutil/kdb5_create.c:242
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:527
++msgid "while reading master key from keyboard"
++msgstr "beim Lesen des Hauptschlüssels von der Tastatur"
++
++#: ../../src/kadmin/dbutil/kdb5_create.c:252
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:285
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:618
++msgid "while calculating master key salt"
++msgstr "beim Berechnen des Hauptschlüssel-Salts"
++
++#: ../../src/kadmin/dbutil/kdb5_create.c:260
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:294
++#: ../../src/kadmin/dbutil/kdb5_util.c:465
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:630
++msgid "while transforming master key from password"
++msgstr "beim Umwandeln des Hauptschlüssels vom Passwort"
++
++#: ../../src/kadmin/dbutil/kdb5_create.c:270
++msgid "while initializing random key generator"
++msgstr "beim Initialisieren des Zufallsschlüsselgenerators"
++
++#: ../../src/kadmin/dbutil/kdb5_create.c:275
++#, c-format
++msgid "while creating database '%s'"
++msgstr "beim Erstellen der Datenbank »%s«"
++
++#: ../../src/kadmin/dbutil/kdb5_create.c:293
++msgid "while creating update log"
++msgstr "beim Erstellen des Aktualisierungsprotokolls"
++
++#: ../../src/kadmin/dbutil/kdb5_create.c:304
++msgid "while initializing update log"
++msgstr "beim Initialisieren des Aktualisierungsprotokolls"
++
++#: ../../src/kadmin/dbutil/kdb5_create.c:320
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:642
++msgid "while adding entries to the database"
++msgstr "beim Hinzufügen von Einträgen in die Datenbank"
++
++#: ../../src/kadmin/dbutil/kdb5_create.c:348
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:339
++#: ../../src/kadmin/dbutil/kdb5_stash.c:133
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:667
++msgid "while storing key"
++msgstr "beim Speichern des Schlüssels"
++
++#: ../../src/kadmin/dbutil/kdb5_create.c:349
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:340
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:668
++#, c-format
++msgid "Warning: couldn't stash master key.\n"
++msgstr "Warnung: Hauptschlüssel kann nicht gelagert werden.\n"
++
++#: ../../src/kadmin/dbutil/kdb5_destroy.c:57
++msgid "while initializing krb5_context"
++msgstr "beim Initialisieren von »krb5_context«"
++
++#: ../../src/kadmin/dbutil/kdb5_destroy.c:63
++#: ../../src/kadmin/dbutil/kdb5_util.c:259
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:291
++msgid "while setting default realm name"
++msgstr "beim Einstellen des Standard-Realm-Namens"
++
++#: ../../src/kadmin/dbutil/kdb5_destroy.c:83
++#, c-format
++msgid "Deleting KDC database stored in '%s', are you sure?\n"
++msgstr ""
++"Die in »%s« gespeicherte KDC-Datenbank wird gelöscht. Sind Sie sicher?\n"
++
++#: ../../src/kadmin/dbutil/kdb5_destroy.c:85
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1166
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:360
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1482
++#, c-format
++msgid "(type 'yes' to confirm)? "
++msgstr "(Geben Sie als Bestätigung »yes« ein)? "
++
++#: ../../src/kadmin/dbutil/kdb5_destroy.c:92
++#, c-format
++msgid "OK, deleting database '%s'...\n"
++msgstr "OK, Datenbank »%s« wird gelöscht …\n"
++
++#: ../../src/kadmin/dbutil/kdb5_destroy.c:97
++#, c-format
++msgid "deleting database '%s'"
++msgstr "Datenbank »%s« wird gelöscht."
++
++#: ../../src/kadmin/dbutil/kdb5_destroy.c:106
++#, c-format
++msgid "** Database '%s' destroyed.\n"
++msgstr "** Datenbank »%s« vernichtet\n"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:218
++#, c-format
++msgid "%s is an invalid enctype"
++msgstr "%s ist ein ungültiger Verschlüsselungstyp"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:250
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:443
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:599
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:986
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1157
++#, c-format
++msgid "while getting master key principal %s"
++msgstr "beim Holen des Hauptschlüssels von Principal %s"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:256
++#, c-format
++msgid "Creating new master key for master key principal '%s'\n"
++msgstr ""
++"Es wird ein neuer Hauptschlüssel für den Hauptschlüssel-Principal »%s« "
++"erstellt.\n"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:259
++#, c-format
++msgid "You will be prompted for a new database Master Password.\n"
++msgstr "Sie werden nach einem neuen Datenbank-Master-Passwort gefragt.\n"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:275
++msgid "while reading new master key from keyboard"
++msgstr "beim Lesen des neuen Hauptschlüssels von der Tastatur"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:304
++msgid "adding new master key to master principal"
++msgstr "dem Haupt-Principal wird ein neuer Hauptschlüssel hinzugefügt"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:310
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:402
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:843
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1356
++msgid "while getting current time"
++msgstr "beim Holen der aktuellen Zeit"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:317
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:544
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1363
++msgid "while updating the master key principal modification time"
++msgstr "beim Aktulisieren der Änderungszeit des Hauptschlüssel-Principals"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:325
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:553
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1374
++msgid "while adding master key entry to the database"
++msgstr "beim Hinzufügen des Hauptschlüsseleintrags zur Datenbank"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:383
++msgid "0 is an invalid KVNO value"
++msgstr "0 ist kein gültiger KVNO-Wert"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:394
++#, c-format
++msgid "%d is an invalid KVNO value"
++msgstr "%d ist kein gültiger KVNO-Wert"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:410
++#, c-format
++msgid "could not parse date-time string '%s'"
++msgstr "»date-time«-Zeichenkette »%s« konnte nicht ausgewertet werden"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:452
++msgid "while looking up active version of master key"
++msgstr "beim Nachschlagen der aktiven Version des Hauptschlüssels"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:491
++msgid "while adding new master key"
++msgstr "beim Hinzufügen eines neuen Hauptschlüssels"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:529
++msgid "there must be one master key currently active"
++msgstr "ein Hauptschlüssel muss derzeit aktiv sein"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:537
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1342
++msgid "while updating actkvno data for master principal entry"
++msgstr "beim Aktualisieren der Actkvno-Daten für den Haupt-Principal-Eintrag"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:581
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:948
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1116
++msgid "master keylist not initialized"
++msgstr "Hauptschlüsselliste ist nicht initialisiert"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:607
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:994
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1254
++msgid "while looking up active kvno list"
++msgstr "beim Nachschlagen der Liste aktiver KVNOs"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:615
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1002
++msgid "while looking up active master key"
++msgstr "beim Nachschlagen des aktiven Hauptschlüssels"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:627
++msgid "while getting enctype description"
++msgstr "beim Holen des Verschlüsselungsbeschreibung"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:644
++#, c-format
++msgid "KVNO: %d, Enctype: %s, Active on: %s *\n"
++msgstr "KVNO: %d, Verschlüsselungstyp: %s, aktiviert auf: %s *\n"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:649
++#, c-format
++msgid "KVNO: %d, Enctype: %s, Active on: %s\n"
++msgstr "KVNO: %d, Verschlüsselungstyp: %s, aktiviert auf: %s\n"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:653
++#, c-format
++msgid "KVNO: %d, Enctype: %s, No activate time set\n"
++msgstr "KVNO: %d, Verschlüsselungstyp: %s, keine Aktivierungszeit gesetzt\n"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:658
++msgid "asprintf could not allocate enough memory to hold output"
++msgstr ""
++"Asprintf konnte nicht genug Speicher reservieren, um die Ausgabe "
++"bereitzuhalten"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:793
++msgid "getting string representation of principal name"
++msgstr "Principal-Name wird im Klartext geholt"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:817
++#, c-format
++msgid "determining master key used for principal '%s'"
++msgstr "Hauptschlüssel, der für Principal »%s« benutzt wird, wird bestimmt"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:823
++#, c-format
++msgid "would skip:   %s\n"
++msgstr "würde übersprungen:   %s\n"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:825
++#, c-format
++msgid "skipping: %s\n"
++msgstr "wird übersprungen: %s\n"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:831
++#, c-format
++msgid "would update: %s\n"
++msgstr "würde aktualisiert: %s\n"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:835
++#, c-format
++msgid "updating: %s\n"
++msgstr "wird aktualisiert: %s\n"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:839
++#, c-format
++msgid "error re-encrypting key for principal '%s'"
++msgstr "Fehler beim erneuten Verschlüsseln des Schlüssels für Principal »%s«"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:850
++#, c-format
++msgid "while updating principal '%s' modification time"
++msgstr "beim Aktualisieren der Änderungszeit von Principal »%s«"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:857
++#, c-format
++msgid "while updating principal '%s' key data in the database"
++msgstr ""
++"beim Aktualisieren der Schlüsseldaten von Principal »%s« in der Datenbank"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:889
++#, c-format
++msgid ""
++"\n"
++"(type 'yes' to confirm)? "
++msgstr ""
++"\n"
++"(Geben Sie als Bestätigung »yes« ein) "
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:942
++msgid "while formatting master principal name"
++msgstr "beim Formatieren des Haupt-Principal-Namens"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:959
++#, c-format
++msgid "converting glob pattern '%s' to regular expression"
++msgstr "Platzhalter »%s« wird in einen regulären Ausdruck umgewandelt"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:977
++#, c-format
++msgid "error compiling converted regexp '%s'"
++msgstr "Fehler beim Kompilieren des umgewandelten regulären Ausdrucks »%s«"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1010
++#, c-format
++msgid "Re-encrypt all keys not using master key vno %u?"
++msgstr ""
++"Sollen alle Schlüssel neu verschlüsselt werden, die nicht die Hauptschlüssel-"
++"VNO %u verwenden?"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1012
++#, c-format
++msgid "OK, doing nothing.\n"
++msgstr "Ok, es wird nichts getan.\n"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1018
++#, c-format
++msgid "Principals whose keys WOULD BE re-encrypted to master key vno %u:\n"
++msgstr ""
++"Principals, deren Schlüssel mit dem Hauptschlüssel VNO %u neu verschlüsselt "
++"WÜRDEN:\n"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1021
++#, c-format
++msgid ""
++"Principals whose keys are being re-encrypted to master key vno %u if "
++"necessary:\n"
++msgstr ""
++"Principals, deren Schlüssel mit dem Hauptschlüssel VNO %u neu verschlüsselt "
++"werden, falls nötig:\n"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1037
++msgid "trying to process principal database"
++msgstr "es wird versucht, die Principal-Datenbank zu verarbeiten"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1042
++#, c-format
++msgid "%u principals processed: %u would be updated, %u already current\n"
++msgstr ""
++"%u Principals verarbeitet: %u würden aktualisiert, %u bereits aktuell\n"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1046
++#, c-format
++msgid "%u principals processed: %u updated, %u already current\n"
++msgstr "%u Principals verarbeitet: %u aktualisiert, %u bereits aktuell\n"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1164
++#, c-format
++msgid ""
++"Will purge all unused master keys stored in the '%s' principal, are you "
++"sure?\n"
++msgstr ""
++"Sind Sie sicher, dass alle nicht verwendeten Hauptschlüssel, die für "
++"Principal »%s« gespeichert sind, vollständig entfernt werden sollen?\n"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1175
++#, c-format
++msgid "OK, purging unused master keys from '%s'...\n"
++msgstr ""
++"Ok, die nicht verwendeten Hauptschlüssel von »%s« werden vollständig "
++"entfernt …\n"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1183
++#, c-format
++msgid "There is only one master key which can not be purged.\n"
++msgstr ""
++"Es gibt nur einen einzigen Hauptschlüssel, der nicht vollständig entfernt "
++"werden kann.\n"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1192
++msgid "while allocating args.kvnos"
++msgstr "beim Reservieren von »args.kvnos«"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1208
++msgid "while finding master keys in use"
++msgstr "bei der Suche nach den gerade verwendeten Hauptschlüsseln"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1217
++#, c-format
++msgid "Would purge the following master key(s) from %s:\n"
++msgstr ""
++"Der/Die folgende(n) Hauptschlüssel würden/würde von %s vollständig "
++"entfernt:\n"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1220
++#, c-format
++msgid "Purging the following master key(s) from %s:\n"
++msgstr ""
++"Der/Die folgende(n) Hauptschlüssel werden/wird von %s vollständig entfernt:\n"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1232
++msgid "master key stash file needs updating, command aborting"
++msgstr ""
++"Ablagedatei des Hauptschlüssels erfordert Aktualisierung, Befehl abgebrochen"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1238
++#, c-format
++msgid "KVNO: %d\n"
++msgstr "KVNO: %d\n"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1243
++#, c-format
++msgid "All keys in use, nothing purged.\n"
++msgstr "Alle Schlüssel sind in Gebrauch, keiner wurde vollständig entfernt.\n"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1248
++#, c-format
++msgid "%d key(s) would be purged.\n"
++msgstr "%d Schlüssel würde(n) vollständig entfernt.\n"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1261
++msgid "while looking up mkey aux data list"
++msgstr "beim Nachschlagen der Mkey-Aux-Datenliste"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1269
++msgid "while allocating key_data"
++msgstr "beim Reservieren von »key_data«"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1350
++msgid "while updating mkey_aux data for master principal entry"
++msgstr "beim Aktualisieren der Mkey-Aux-Daten für den Haupt-Principal-Eintrag"
++
++#: ../../src/kadmin/dbutil/kdb5_mkey.c:1378
++#, c-format
++msgid "%d key(s) purged.\n"
++msgstr "%d Schlüssel vollständig entfernt\n"
++
++#: ../../src/kadmin/dbutil/kdb5_stash.c:97
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:538
++#, c-format
++msgid "while setting up enctype %d"
++msgstr "beim Einrichten des Verschlüsselungstyps %d"
++
++#: ../../src/kadmin/dbutil/kdb5_stash.c:123
++msgid "while getting master key list"
++msgstr "beim Holen der Hauptschlüsselliste"
++
++#: ../../src/kadmin/dbutil/kdb5_stash.c:127
++#, c-format
++msgid "Using existing stashed keys to update stash file.\n"
++msgstr ""
++"Zur Aktualisierung der Ablagedatei werden existierende gelagert Schlüssel "
++"verwendet.\n"
++
++#: ../../src/kadmin/dbutil/kdb5_util.c:80
++#, c-format
++msgid ""
++"Usage: kdb5_util [-x db_args]* [-r realm] [-d dbname] [-k mkeytype] [-M "
++"mkeyname]\n"
++"\t        [-kv mkeyVNO] [-sf stashfilename] [-m] cmd [cmd_options]\n"
++"\tcreate  [-s]\n"
++"\tdestroy [-f]\n"
++"\tstash   [-f keyfile]\n"
++"\tdump    [-old|-ov|-b6|-b7|-r13|-r18] [-verbose]\n"
++"\t        [-mkey_convert] [-new_mkey_file mkey_file]\n"
++"\t        [-rev] [-recurse] [filename [princs...]]\n"
++"\tload    [-old|-ov|-b6|-b7|-r13|-r18] [-verbose] [-update] filename\n"
++"\tark     [-e etype_list] principal\n"
++"\tadd_mkey [-e etype] [-s]\n"
++"\tuse_mkey kvno [time]\n"
++"\tlist_mkeys\n"
++msgstr ""
++"Aufruf: kdb5_util [-x Datenbankargumente]* [-r Realm] [-d Datenbankname] [-k "
++"Mkeytype] [-M Mkeyname]\n"
++"\t        [-kv MkeyVNO] [-sf Ablagedateiname] [-m] Befehl [Befehlsoptionen]\n"
++"\tcreate  [-s]\n"
++"\tdestroy [-f]\n"
++"\tstash   [-f Schlüsseldatei]\n"
++"\tdump    [-old|-ov|-b6|-b7|-r13|-r18] [-verbose]\n"
++"\t        [-mkey_convert] [-new_mkey_file mkey-Datei]\n"
++"\t        [-rev] [-recurse] [Dateiname [Principals …]]\n"
++"\tload    [-old|-ov|-b6|-b7|-r13|-r18] [-verbose] [-update] Dateiname\n"
++"\tark     [-e Etype-Liste] Principal\n"
++"\tadd_mkey [-e Etype] [-s]\n"
++"\tuse_mkey kvno [Zeit]\n"
++"\tlist_mkeys\n"
++
++#: ../../src/kadmin/dbutil/kdb5_util.c:98
++#, c-format
++msgid ""
++"\tupdate_princ_encryption [-f] [-n] [-v] [princ-pattern]\n"
++"\tpurge_mkeys [-f] [-n] [-v]\n"
++"\n"
++"where,\n"
++"\t[-x db_args]* - any number of database specific arguments.\n"
++"\t\t\tLook at each database documentation for supported arguments\n"
++msgstr ""
++"\tupdate_princ_encryption [-f] [-n] [-v] [Principal-Muster]\n"
++"\tpurge_mkeys [-f] [-n] [-v]\n"
++"\n"
++"dabei sind\n"
++"\t[-x Datenbankargumente]* - eine beliebige Anzahl datenbankspezifischer "
++"Argumente.\n"
++"\t\t\tWelche Argumente unterstützt werden, finden Sie in der Dokumentation "
++"der jeweiligen Datenbank.\n"
++
++#: ../../src/kadmin/dbutil/kdb5_util.c:211
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:260
++msgid "while initializing Kerberos code"
++msgstr "beim Initialisieren von Kerberos-Code"
++
++#: ../../src/kadmin/dbutil/kdb5_util.c:217
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:267
++msgid "while creating sub-command arguments"
++msgstr "beim Erstellen von Unterbefehlsargumenten"
++
++#: ../../src/kadmin/dbutil/kdb5_util.c:235
++msgid "while parsing command arguments"
++msgstr "beim Auswerten von Befehlsargumenten"
++
++#: ../../src/kadmin/dbutil/kdb5_util.c:264
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:298
++#, c-format
++msgid ": %s is an invalid enctype"
++msgstr ": %s ist kein gültiger Verschlüsselungstyp"
++
++#: ../../src/kadmin/dbutil/kdb5_util.c:272
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:307
++#, c-format
++msgid ": %s is an invalid mkeyVNO"
++msgstr ": %s ist kein gültiger MkeyVNO"
++
++# FIXME s/retreiving/retrieving/
++#: ../../src/kadmin/dbutil/kdb5_util.c:317
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:431
++msgid "while retreiving configuration parameters"
++msgstr "beim Abfragen der Konfigurationsparameter"
++
++#: ../../src/kadmin/dbutil/kdb5_util.c:368
++msgid "Too few arguments"
++msgstr "zu wenige Argumente"
++
++#: ../../src/kadmin/dbutil/kdb5_util.c:369
++#, c-format
++msgid "Usage: %s dbpathname realmname"
++msgstr "Aufruf: %s Datenbankpfadname Realm-Name"
++
++#: ../../src/kadmin/dbutil/kdb5_util.c:375
++msgid "while closing previous database"
++msgstr "beim Schließen der vorherigen Datenbank"
++
++#: ../../src/kadmin/dbutil/kdb5_util.c:412
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:877
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1497
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:564
++msgid "while initializing database"
++msgstr "beim Initialisieren der Datenbank"
++
++#: ../../src/kadmin/dbutil/kdb5_util.c:429
++msgid "while retrieving master entry"
++msgstr "beim Abfragen des Haupteintrags"
++
++#: ../../src/kadmin/dbutil/kdb5_util.c:448
++msgid "while calculated master key salt"
++msgstr "beim Berechnen des Hauptschlüssel-Salts"
++
++#: ../../src/kadmin/dbutil/kdb5_util.c:480
++msgid "Warning: proceeding without master key"
++msgstr "Warnung: Es wird ohne Hauptschlüssel fortgefahren"
++
++#: ../../src/kadmin/dbutil/kdb5_util.c:498
++msgid "while seeding random number generator"
++msgstr "beim Erzeugen des Startwerts des Zufallszahlengenerators"
++
++#: ../../src/kadmin/dbutil/kdb5_util.c:508
++#, c-format
++msgid "%s: Could not map log\n"
++msgstr "%s: Protokolldatei konnte nicht abgebildet werden\n"
++
++#: ../../src/kadmin/dbutil/kdb5_util.c:535
++msgid "while closing database"
++msgstr "beim Schließen der Datenbank"
++
++#: ../../src/kadmin/dbutil/kdb5_util.c:582
++#, c-format
++msgid "while fetching principal %s"
++msgstr "beim Abrufen von Principal %s"
++
++#: ../../src/kadmin/dbutil/kdb5_util.c:605
++msgid "while finding mkey"
++msgstr "beim Suchen nach Mkey"
++
++#: ../../src/kadmin/dbutil/kdb5_util.c:630
++msgid "while setting changetime"
++msgstr "beim Setzen der Änderungszeit der Datei"
++
++#: ../../src/kadmin/dbutil/kdb5_util.c:638
++#, c-format
++msgid "while saving principal %s"
++msgstr "beim Speichern von Principal %s"
++
++#: ../../src/kadmin/dbutil/kdb5_util.c:642
++#, c-format
++msgid "%s changed\n"
++msgstr "%s geändert\n"
++
++#: ../../src/kadmin/ktutil/ktutil.c:73
++#, c-format
++msgid "%s: invalid arguments\n"
++msgstr "%s: ungültige Argumente\n"
++
++#: ../../src/kadmin/ktutil/ktutil.c:78
++msgid "while freeing ktlist"
++msgstr "beim Freigeben von »ktlist«"
++
++#: ../../src/kadmin/ktutil/ktutil.c:89
++#, c-format
++msgid "%s: must specify keytab to read\n"
++msgstr ""
++"%s: Die Schlüsseltabelle, die gelesen werden soll, muss angegeben werden.\n"
++
++#: ../../src/kadmin/ktutil/ktutil.c:94
++#, c-format
++msgid "while reading keytab \"%s\""
++msgstr "beim Lesen der Schlüsseltabelle »%s«"
++
++#: ../../src/kadmin/ktutil/ktutil.c:104
++#, c-format
++msgid "%s: must specify the srvtab to read\n"
++msgstr "%s: Die zu lesende Dienstschlüsseltabelle muss angegeben werden.\n"
++
++#: ../../src/kadmin/ktutil/ktutil.c:109
++#, c-format
++msgid "while reading srvtab \"%s\""
++msgstr "beim Lesen der Dienstschlüsseltabelle »%s«"
++
++#: ../../src/kadmin/ktutil/ktutil.c:119
++#, c-format
++msgid "%s: must specify keytab to write\n"
++msgstr "%s: Die zu schreibende Schlüsseltabelle muss angegeben werden.\n"
++
++#: ../../src/kadmin/ktutil/ktutil.c:124
++#, c-format
++msgid "while writing keytab \"%s\""
++msgstr "beim Schreiben der Schlüsseltabelle »%s«"
++
++#: ../../src/kadmin/ktutil/ktutil.c:131
++#, c-format
++msgid "%s: writing srvtabs is no longer supported\n"
++msgstr ""
++"%s: Schreiben der Dienstschlüsseltabelle wird nicht länger unterstützt\n"
++
++#: ../../src/kadmin/ktutil/ktutil.c:169
++#, c-format
++msgid "usage: %s (-key | -password) -p principal -k kvno -e enctype\n"
++msgstr ""
++"Aufruf: %s (-key | -password) -p Principal -k KVNO -e Verschlüsselungstyp\n"
++
++#: ../../src/kadmin/ktutil/ktutil.c:176
++msgid "while adding new entry"
++msgstr "beim Hinzufügen eines neuen Eintrags"
++
++#: ../../src/kadmin/ktutil/ktutil.c:186
++#, c-format
++msgid "%s: must specify entry to delete\n"
++msgstr "%s: zu löschender Eintrag muss angegeben werden\n"
++
++#: ../../src/kadmin/ktutil/ktutil.c:191
++#, c-format
++msgid "while deleting entry %d"
++msgstr "beim Löschen von Eintrag %d"
++
++#: ../../src/kadmin/ktutil/ktutil.c:219
++#, c-format
++msgid "%s: usage: %s [-t] [-k] [-e]\n"
++msgstr "%s: Aufruf: %s [-t] [-k] [-e]\n"
++
++#: ../../src/kadmin/ktutil/ktutil.c:259
++msgid "While converting enctype to string"
++msgstr "beim Umwandeln des Verschlüsselungstyps in eine Zeichenkette"
++
++#: ../../src/kadmin/ktutil/ktutil_funcs.c:162
++#, c-format
++msgid "Password for %.1000s"
++msgstr "Passwort für %.1000s"
++
++#: ../../src/kadmin/ktutil/ktutil_funcs.c:179
++#, c-format
++msgid "Key for %s (hex): "
++msgstr "Schlüssel für %s (hexadezimal): "
++
++#: ../../src/kadmin/ktutil/ktutil_funcs.c:191
++#, c-format
++msgid "addent: Error reading key.\n"
++msgstr "addent: Fehler beim Lesen des Schlüssels\n"
++
++#: ../../src/kadmin/ktutil/ktutil_funcs.c:206
++#, c-format
++msgid "addent: Illegal character in key.\n"
++msgstr "addent: unerlaubtes Zeichen im Schlüssel\n"
++
++#: ../../src/kadmin/server/ipropd_svc.c:48
++#, c-format
++msgid "Unauthorized request: %s, client=%s, service=%s, addr=%s"
++msgstr "unberechtigte Anfrage: %s, Client=%s, Dienst=%s, Adresse=%s"
++
++#: ../../src/kadmin/server/ipropd_svc.c:49
++#: ../../src/kadmin/server/ipropd_svc.c:212
++#, c-format
++msgid "Request: %s, %s, %s, client=%s, service=%s, addr=%s"
++msgstr "Anfrage: %s, %s, %s, Client=%s, Dienst=%s, Adresse=%s"
++
++#: ../../src/kadmin/server/ipropd_svc.c:146
++#: ../../src/kadmin/server/ipropd_svc.c:271
++#, c-format
++msgid "%s: server handle is NULL"
++msgstr "%s: Server-Identifikator ist NULL"
++
++#: ../../src/kadmin/server/ipropd_svc.c:156
++#: ../../src/kadmin/server/ipropd_svc.c:284
++#, c-format
++msgid "%s: setup_gss_names failed"
++msgstr "%s: setup_gss_names fehlgeschlagen"
++
++#: ../../src/kadmin/server/ipropd_svc.c:166
++#: ../../src/kadmin/server/ipropd_svc.c:295
++#, c-format
++msgid "%s: out of memory recording principal names"
++msgstr "%s: Speicher reicht nicht zur Aufzeichnung der Principal-Namen aus"
++
++#: ../../src/kadmin/server/ipropd_svc.c:195
++#, c-format
++msgid "%s; Incoming SerialNo=%lu; Outgoing SerialNo=%lu"
++msgstr "%s; eingehende Seriennummer=%lu; ausgehende Seriennummer=%lu"
++
++#: ../../src/kadmin/server/ipropd_svc.c:201
++#, c-format
++msgid "%s; Incoming SerialNo=%lu; Outgoing SerialNo=N/A"
++msgstr "%s; eingehende Seriennummer=%lu; ausgehende Seriennummer=N/A"
++
++#: ../../src/kadmin/server/ipropd_svc.c:320
++#, c-format
++msgid "%s: getclhoststr failed"
++msgstr "%s: getclhoststr fehlgeschlagen"
++
++#: ../../src/kadmin/server/ipropd_svc.c:342
++#, c-format
++msgid "%s: cannot construct kdb5 util dump string too long; out of memory"
++msgstr ""
++"Ausgabenzeichenkette des KDB5-Hilfswerkzeugs nicht konstruierbar, da zu "
++"lang; Speicher reicht nicht aus.%s: Die Ausgabezeichenkette des KDB5-"
++"Hilfswerkzeugs kann nicht erstellt werden, weil sie zu lang ist. Der "
++"Speicherplatz reicht nicht aus."
++
++#: ../../src/kadmin/server/ipropd_svc.c:362
++#, c-format
++msgid "%s: fork failed: %s"
++msgstr "%s: Verzweigen fehlgeschlagen: %s"
++
++#: ../../src/kadmin/server/ipropd_svc.c:374
++#, c-format
++msgid "%s: popen failed: %s"
++msgstr "%s: popen fehlgeschlagen: %s"
++
++#: ../../src/kadmin/server/ipropd_svc.c:388
++#, c-format
++msgid "%s: pclose(popen) failed: %s"
++msgstr "%s: pclose(popen) fehlgeschlagen: %s"
++
++#: ../../src/kadmin/server/ipropd_svc.c:405
++#, c-format
++msgid "%s: exec failed: %s"
++msgstr "%s: exec fehlgeschlagen: %s"
++
++#: ../../src/kadmin/server/ipropd_svc.c:421
++#, c-format
++msgid "Request: %s, spawned resync process %d, client=%s, service=%s, addr=%s"
++msgstr ""
++"Anfrage: %s, hervorgebrachter Neusynchronisationsprozess %d, Client=%s, "
++"Dienst=%s, Adresse=%s"
++
++#: ../../src/kadmin/server/ipropd_svc.c:485
++#: ../../src/kadmin/server/kadm_rpc_svc.c:275
++#, c-format
++msgid "check_rpcsec_auth: failed inquire_context, stat=%u"
++msgstr "check_rpcsec_auth: inquire_context fehlgeschlagen, Stat=%u"
++
++#: ../../src/kadmin/server/ipropd_svc.c:515
++#: ../../src/kadmin/server/kadm_rpc_svc.c:304
++#, c-format
++msgid "bad service principal %.*s%s"
++msgstr "falscher Dienst-Principal %.*s%s"
++
++#: ../../src/kadmin/server/ipropd_svc.c:538
++#, c-format
++msgid "authentication attempt failed: %s, RPC authentication flavor %d"
++msgstr ""
++"Authentifizierungsversuche gescheitert: %s, PRC-Authentifizierungsvariante %d"
++
++#: ../../src/kadmin/server/ipropd_svc.c:572
++#, c-format
++msgid "RPC unknown request: %d (%s)"
++msgstr "unbekannte PRC-Anfrage: %d (%s)"
++
++#: ../../src/kadmin/server/ipropd_svc.c:580
++#, c-format
++msgid "RPC svc_getargs failed (%s)"
++msgstr "RPC-»svc_getargs« fehlgeschlagen (%s)"
++
++#: ../../src/kadmin/server/ipropd_svc.c:590
++#, c-format
++msgid "RPC svc_sendreply failed (%s)"
++msgstr "RPC-»svc_sendreply« fehlgeschlagen (%s)"
++
++#: ../../src/kadmin/server/ipropd_svc.c:596
++#, c-format
++msgid "RPC svc_freeargs failed (%s)"
++msgstr "RPC-»svc_freeargs« fehlgeschlagen (%s)"
++
++#: ../../src/kadmin/server/kadm_rpc_svc.c:325
++#, c-format
++msgid "gss_to_krb5_name: failed display_name status %d"
++msgstr "gss_to_krb5_name: display_name fehlgeschlagen, Status %d"
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:86
++#, c-format
++msgid ""
++"Usage: kadmind [-x db_args]* [-r realm] [-m] [-nofork] [-port port-number]\n"
++"\t\t[-proponly] [-p path-to-kdb5_util] [-F dump-file]\n"
++"\t\t[-K path-to-kprop] [-P pid_file]\n"
++"\n"
++"where,\n"
++"\t[-x db_args]* - any number of database specific arguments.\n"
++"\t\t\tLook at each database documentation for supported arguments\n"
++msgstr ""
++"Aufruf: kadmind [-x Datenbankargumente]* [-r Realm] [-m] [-nofork]\n"
++"\t\t[-port Portummer] [-p Pfad_zum_KDB5-Hilfswerkzeug] [-F Auszugsdatei]\n"
++"\t\t[-K Pfad_zu_Kprop] [-P PID-Datei]\n"
++"\n"
++"dabei sind\n"
++"\t[-x Datenbankargumente]* - eine beliebige Anzahl datenbankspezifischer "
++"Argumente.\n"
++"\t\t\tWelche Argumente unterstützt werden, finden Sie in der Dokumentation "
++"der jeweiligen Datenbank.\n"
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:111
++#, c-format
++msgid "%s: %s while %s, aborting\n"
++msgstr "%s: %s bei %s, wird abgebrochen\n"
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:113
++#, c-format
++msgid "%s while %s, aborting\n"
++msgstr "%s bei %s, wird abgebrochen\n"
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:115
++#, c-format
++msgid "%s: %s, aborting\n"
++msgstr "%s: %s, wird abgebrochen\n"
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:116
++#, c-format
++msgid "%s, aborting"
++msgstr "%s, wird abgebrochen"
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:282
++#, c-format
++msgid ""
++"WARNING! Forged/garbled request: %s, claimed client = %.*s%s, server = %.*s"
++"%s, addr = %s"
++msgstr ""
++"WARNUNG! Gefälschte/verstümmelte Anfrage: %s, geforderter Client = %.*s%s, "
++"Server = %.*s%s, Adresse = %s"
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:288
++#, c-format
++msgid ""
++"WARNING! Forged/garbled request: %d, claimed client = %.*s%s, server = %.*s"
++"%s, addr = %s"
++msgstr ""
++"WARNUNG! Gefälschte/verstümmelte Anfrage: %d,   Client = %.*s%s, Server = "
++"%.*s%s, Adresse = %s"
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:302
++#, c-format
++msgid "Miscellaneous RPC error: %s, %s"
++msgstr "sonstiger PRC-Fehler: %s, %s"
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:318
++#, c-format
++msgid "%s Cannot decode status %d"
++msgstr "%s: Status %d kann nicht dekodiert werden"
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:336
++#, c-format
++msgid "Authentication attempt failed: %s, GSS-API error strings are:"
++msgstr "Authentifizierungsversuch fehlgeschlagen: %s, GSS-API-Fehlermeldungen:"
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:341
++msgid "   GSS-API error strings complete."
++msgstr "   GSS-API-Fehlermeldungen vollständig"
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:378
++#, c-format
++msgid "%s: cannot initialize. Not enough memory\n"
++msgstr "%s: kann nicht initialisiert werden: Speicher reicht nicht aus.\n"
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:445
++#, c-format
++msgid "%s: %s while initializing context, aborting\n"
++msgstr "%s: %s beim Initialisieren des Kontextes, wird abgebrochen\n"
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:456
++msgid "initializing"
++msgstr "wird initialisiert"
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:460
++msgid "getting config parameters"
++msgstr "beim Holen der Konfigurationsparameter"
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:462
++msgid "Missing required realm configuration"
++msgstr "erforderliche Realm-Konfiguration fehlt"
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:464
++msgid "Missing required ACL file configuration"
++msgstr "erforderliche ACL-Dateikonfiguration fehlt"
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:468
++msgid "initializing network"
++msgstr "Netzwerk wird initialisiert"
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:473
++msgid "Cannot build GSSAPI auth names"
++msgstr "GSS-API-Authentifizierungsnamen können nicht gebildet werden."
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:477
++msgid "Cannot set up KDB keytab"
++msgstr "Die KDB-Schlüsseltabelle kann nicht eingerichtet werden."
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:480
++msgid "Cannot set GSSAPI authentication names"
++msgstr "GSS-API-Authentifizierungsnamen können nicht gesetzt werden."
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:497
++msgid "Cannot initialize GSSAPI service name"
++msgstr "GSSAPI-Dienstname kann nicht initialisiert werden"
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:501
++msgid "initializing ACL file"
++msgstr "ACL-Datei wird initialisiert"
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:504
++msgid "spawning daemon process"
++msgstr "Daemon-Prozess wird erzeugt"
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:508
++msgid "creating PID file"
++msgstr "PID-Datei wird erstellt"
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:511
++msgid "Seeding random number generator"
++msgstr "Startwert des Zufallszahlengenerators wird erzeugt"
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:514
++msgid "getting random seed"
++msgstr "Zufallsstartwert wird geholt"
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:521
++msgid "mapping update log"
++msgstr "Aktualisierungsprotokoll wird abgebildet"
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:525
++#, c-format
++msgid "%s: create IPROP svc (PROG=%d, VERS=%d)\n"
++msgstr "%s: IPROP-Dienst wird erstellt (PROG=%d, VERS=%d)\n"
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:530
++msgid "starting"
++msgstr "startet"
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:532 ../../src/kdc/main.c:1061
++#, c-format
++msgid "%s: starting...\n"
++msgstr "%s: startet …\n"
++
++#: ../../src/kadmin/server/ovsec_kadmd.c:535
++msgid "finished, exiting"
++msgstr "fertig, wird beendet"
++
++#: ../../src/kadmin/server/schpw.c:282
++#, c-format
++msgid "setpw request from %s by %.*s%s for %.*s%s: %s"
++msgstr "»setpw«-Anfrage von %s durch %.*s%s für %.*s%s: %s"
++
++#: ../../src/kadmin/server/schpw.c:287
++#, c-format
++msgid "chpw request from %s for %.*s%s: %s"
++msgstr "»chpw«-Anfrage von %s für %.*s%s: %s"
++
++#: ../../src/kadmin/server/schpw.c:464
++#, c-format
++msgid "chpw: Couldn't open admin keytab %s"
++msgstr "chpw«: Administratorschlüsseltabelle %s konnte nicht geöffnet werden"
++
++#: ../../src/kadmin/server/server_stubs.c:293
++#, c-format
++msgid ""
++"Unauthorized request: %s, %.*s%s, client=%.*s%s, service=%.*s%s, addr=%s"
++msgstr ""
++"Unauthorisierte Anfrage: %s, %.*s%s, Client=%.*s%s, Dienst=%.*s%s, Adresse=%s"
++
++#: ../../src/kadmin/server/server_stubs.c:314
++#: ../../src/kadmin/server/server_stubs.c:649
++#: ../../src/kadmin/server/server_stubs.c:1792
++msgid "success"
++msgstr "erfolgreich"
++
++#: ../../src/kadmin/server/server_stubs.c:324
++#, c-format
++msgid "Request: %s, %.*s%s, %s, client=%.*s%s, service=%.*s%s, addr=%s"
++msgstr "Anfrage: %s, %.*s%s, %s, Client=%.*s%s, Dienst=%.*s%s, Adresse=%s"
++
++#: ../../src/kadmin/server/server_stubs.c:628
++#, c-format
++msgid ""
++"Unauthorized request: kadm5_rename_principal, %.*s%s to %.*s%s, client=%.*s"
++"%s, service=%.*s%s, addr=%s"
++msgstr ""
++"Unauthorisierte Anfrage: kadm5_rename_principal, %.*s%s bis %.*s%s, Client="
++"%.*s%s, Dienst=%.*s%s, Adresse=%s"
++
++#: ../../src/kadmin/server/server_stubs.c:644
++#, c-format
++msgid ""
++"Request: kadm5_rename_principal, %.*s%s to %.*s%s, %s, client=%.*s%s, "
++"service=%.*s%s, addr=%s"
++msgstr ""
++"Anfrage: kadm5_rename_principal, %.*s%s bis %.*s%s, %s, Client=%.*s%s, "
++"Dienst=%.*s%s, Adresse=%s"
++
++#: ../../src/kadmin/server/server_stubs.c:1788
++#, c-format
++msgid ""
++"Request: kadm5_init, %.*s%s, %s, client=%.*s%s, service=%.*s%s, addr=%s, "
++"vers=%d, flavor=%d"
++msgstr ""
++"Anfrage: kadm5_init, %.*s%s, %s, Client=%.*s%s, Dienst=%.*s%s, Adresse=%s, "
++"Version=%d, Variante=%d"
++
++#: ../../src/kdc/do_as_req.c:273
++#, c-format
++msgid "AS_REQ : handle_authdata (%d)"
++msgstr "AS_REQ: handle_authdata (%d)"
++
++#: ../../src/kdc/do_tgs_req.c:593
++#, c-format
++msgid "TGS_REQ : handle_authdata (%d)"
++msgstr "TGS_REQ: handle_authdata (%d)"
++
++#: ../../src/kdc/do_tgs_req.c:655
++msgid "not checking transit path"
++msgstr "Übergangspfad wird nicht geprüft"
++
++#: ../../src/kdc/fast_util.c:62
++#, c-format
++msgid "%s while handling ap-request armor"
++msgstr "%s bei der Handhabung des »ap-request«-Schutzes"
++
++#: ../../src/kdc/fast_util.c:71
++msgid "ap-request armor for something other than the local TGS"
++msgstr "»ap-request«-Schutz für etwas anderes als den lokalen TGS"
++
++#: ../../src/kdc/fast_util.c:80
++msgid "ap-request armor without subkey"
++msgstr "»ap-request«-Schutz ohne Unterschlüssel"
++
++#: ../../src/kdc/fast_util.c:162
++msgid "Ap-request armor not permitted with TGS"
++msgstr "»ap-request«-Schutz nicht mit TGS gestattet"
++
++#: ../../src/kdc/fast_util.c:169
++#, c-format
++msgid "Unknown FAST armor type %d"
++msgstr "unbekanntet FAST-Schutztyp %d"
++
++#: ../../src/kdc/fast_util.c:183
++msgid "No armor key but FAST armored request present"
++msgstr "Es gibt keinen Schutzschlüssel aber eine FAST-geschützte Anfrage"
++
++#: ../../src/kdc/fast_util.c:219
++msgid "FAST req_checksum invalid; request modified"
++msgstr "FAST-»req_checksum« ungültig; Anfrage geändert"
++
++#: ../../src/kdc/fast_util.c:225
++msgid "Unkeyed checksum used in fast_req"
++msgstr "in fast_req wurde eine Prüfsumme ohne Schlüssel benutzt"
++
++#: ../../src/kdc/kdc_audit.c:110
++#, c-format
++msgid "audit plugin %s failed to open. error=%i"
++msgstr "Öffnen der Audit-Erweiterung %s fehlgeschlagen. Fehler=%i"
++
++#: ../../src/kdc/kdc_authdata.c:292 ../../src/kdc/kdc_authdata.c:328
++#, c-format
++msgid "authdata %s failed to initialize: %s"
++msgstr "Initialisieren von »authdata« %s fehlgeschlagen: %s"
++
++#: ../../src/kdc/kdc_authdata.c:779
++#, c-format
++msgid "authdata (%s) handling failure: %s"
++msgstr "Handhabung von »authdata« %s fehlgeschlagen: %s"
++
++#: ../../src/kdc/kdc_log.c:82
++#, c-format
++msgid "AS_REQ (%s) %s: ISSUE: authtime %d, %s, %s for %s"
++msgstr "AS_REQ (%s) %s: PROBLEM: Authentifizierungszeit %d, %s, %s für %s"
++
++#: ../../src/kdc/kdc_log.c:88
++#, c-format
++msgid "AS_REQ (%s) %s: %s: %s for %s%s%s"
++msgstr "AS_REQ (%s) %s: %s: %s für %s%s%s"
++
++#: ../../src/kdc/kdc_log.c:159
++#, c-format
++msgid "TGS_REQ (%s) %s: %s: authtime %d, %s%s %s for %s%s%s"
++msgstr "TGS_REQ (%s) %s: %s: Authentifizierungszeit %d, %s%s %s für %s%s%s"
++
++#: ../../src/kdc/kdc_log.c:166
++#, c-format
++msgid "... PROTOCOL-TRANSITION s4u-client=%s"
++msgstr "… PROTOKOLLÜBERGANG s4u-client=%s"
++
++#: ../../src/kdc/kdc_log.c:170
++#, c-format
++msgid "... CONSTRAINED-DELEGATION s4u-client=%s"
++msgstr "…  EINHESCHRÄNKTE DELEGIERUNG s4u-client=%s"
++
++#: ../../src/kdc/kdc_log.c:174
++#, c-format
++msgid "TGS_REQ %s: %s: authtime %d, %s for %s, 2nd tkt client %s"
++msgstr "TGS_REQ %s: %s: Authentifizierungszeit %d, %s für %s, 2. TKT-Client %s"
++
++#: ../../src/kdc/kdc_log.c:208
++#, c-format
++msgid "bad realm transit path from '%s' to '%s' via '%.*s%s'"
++msgstr "falscher Realm-Übergangspfad von »%s« zu »%s« über »%.*s%s«"
++
++#: ../../src/kdc/kdc_log.c:214
++#, c-format
++msgid "unexpected error checking transit from '%s' to '%s' via '%.*s%s': %s"
++msgstr ""
++"unerwarteter Fehler bei der Prüfung des Übergangs von »%s« zu »%s« über »%.*s"
++"%s«: %s"
++
++#: ../../src/kdc/kdc_log.c:232
++msgid "TGS_REQ: issuing alternate <un-unparseable> TGT"
++msgstr "TGS_REQ: alternativer <nicht nicht auswertbarer> TGT wird erstellt"
++
++#: ../../src/kdc/kdc_log.c:235
++#, c-format
++msgid "TGS_REQ: issuing TGT %s"
++msgstr "TGS_REQ: TGT %s wird erstellt"
++
++#: ../../src/kdc/kdc_preauth.c:328
++#, c-format
++msgid "preauth %s failed to initialize: %s"
++msgstr "Initialisieren von »preauth« %s fehlgeschlagen: %s"
++
++#: ../../src/kdc/kdc_preauth.c:339
++#, c-format
++msgid "preauth %s failed to setup loop: %s"
++msgstr "Einrichten der Schleife von »preauth« %s fehlgeschlagen: %s"
++
++#: ../../src/kdc/kdc_preauth.c:760
++#, c-format
++msgid "%spreauth required but hint list is empty"
++msgstr "%spreauth benötigt, aber Hinweisliste ist leer"
++
++#: ../../src/kdc/kdc_preauth_ec.c:75
++msgid "Encrypted Challenge used outside of FAST tunnel"
++msgstr "verschlüsselte Aufforderung wurde außerhalb des FAST-Tunnels verwendet"
++
++#: ../../src/kdc/kdc_preauth_ec.c:110
++msgid "Incorrect password in encrypted challenge"
++msgstr "falsches Passwort in verschlüsselter Aufforderung"
++
++#: ../../src/kdc/kdc_util.c:236
++msgid "TGS_REQ: SESSION KEY or MUTUAL"
++msgstr "TGS_REQ: SITZUNGSSCHLÜSSEL oder BEIDERSEITIG"
++
++#: ../../src/kdc/kdc_util.c:314
++msgid "PROCESS_TGS: failed lineage check"
++msgstr "PROCESS_TGS: Abstammungsprüfung fehlgeschlagen"
++
++#: ../../src/kdc/kdc_util.c:468
++#, c-format
++msgid "TGS_REQ: UNKNOWN SERVER: server='%s'"
++msgstr "TGS_REQ: UNBEKANNTER SERVER: Server=»%s«"
++
++#: ../../src/kdc/main.c:231
++#, c-format
++msgid "while getting context for realm %s"
++msgstr "beim Holen des Kontextes für Realm %s"
++
++#: ../../src/kdc/main.c:329
++#, c-format
++msgid "while setting default realm to %s"
++msgstr "beim Setzen des Standard-Realms auf %s"
++
++#: ../../src/kdc/main.c:337
++#, c-format
++msgid "while initializing database for realm %s"
++msgstr "beim Initialisieren der Datenbank für Realm %s"
++
++#: ../../src/kdc/main.c:346
++#, c-format
++msgid "while setting up master key name %s for realm %s"
++msgstr "beim Einrichten des Hauptschlüsselnamens %s für Realm %s"
++
++#: ../../src/kdc/main.c:359
++#, c-format
++msgid "while fetching master key %s for realm %s"
++msgstr "beim Abholen des Hauptschlüssels %s für Realm %s"
++
++#: ../../src/kdc/main.c:367
++#, c-format
++msgid "while fetching master keys list for realm %s"
++msgstr "beim Abholen der Hauptschlüsselliste für Realm %s"
++
++#: ../../src/kdc/main.c:376
++#, c-format
++msgid "while resolving kdb keytab for realm %s"
++msgstr "beim Ermitteln der KDB-Schlüsseltabelle für Realm %s"
++
++#: ../../src/kdc/main.c:385
++#, c-format
++msgid "while building TGS name for realm %s"
++msgstr "beim Bilden des TGS-Namens für Realm %s"
++
++#: ../../src/kdc/main.c:503
++#, c-format
++msgid "creating %d worker processes"
++msgstr "%d Arbeitsprozesse werden erzeugt"
++
++#: ../../src/kdc/main.c:513
++msgid "Unable to reinitialize main loop"
++msgstr "Hauptschleife konnte nicht neu initialisiert werden"
++
++#: ../../src/kdc/main.c:518
++#, c-format
++msgid "Unable to initialize signal handlers in pid %d"
++msgstr ""
++"Signalbehandlungsprogramme in PID %d konnten nicht initialisiert werden"
++
++#: ../../src/kdc/main.c:548
++#, c-format
++msgid "worker %ld exited with status %d"
++msgstr "Arbeitsprozess %ld endete mit Status %d"
++
++#: ../../src/kdc/main.c:572
++#, c-format
++msgid "signal %d received in supervisor"
++msgstr "Überwachungsprogramm empfing Signal %d"
++
++#: ../../src/kdc/main.c:591
++#, c-format
++msgid ""
++"usage: %s [-x db_args]* [-d dbpathname] [-r dbrealmname]\n"
++"\t\t[-R replaycachename] [-m] [-k masterenctype]\n"
++"\t\t[-M masterkeyname] [-p port] [-P pid_file]\n"
++"\t\t[-n] [-w numworkers] [/]\n"
++"\n"
++"where,\n"
++"\t[-x db_args]* - Any number of database specific arguments.\n"
++"\t\t\tLook at each database module documentation for \t\t\tsupported "
++"arguments\n"
++msgstr ""
++"Aufruf: %s [-x Datenbankargumente]* [-d Datenbankpfadname]\n"
++"\t\t[-r Datenbank-Realm-Name] [-m] [-k Hauptverschlüsselungstyp]\n"
++"\t\t[-M Hauptschlüsselname] [-p Port] [-P PID-Datei]\n"
++"\t\t[-n] [-w Arbeitsprozessanzahl] [/]\n"
++"\n"
++"dabei sind\n"
++"\t[-x Datenbankargumente]* - eine beliebige Anzahl datenbankspezifischer "
++"Argumente.\n"
++"\t\t\tWelche Argumente unterstützt werden, finden Sie in der Dokumentation "
++"der jeweiligen Datenbank.\n"
++
++#: ../../src/kdc/main.c:653 ../../src/kdc/main.c:660 ../../src/kdc/main.c:774
++#, c-format
++msgid " KDC cannot initialize. Not enough memory\n"
++msgstr "KDC kann nicht initialisiert werden. Speicher reicht nicht aus\n"
++
++#: ../../src/kdc/main.c:679 ../../src/kdc/main.c:722 ../../src/kdc/main.c:733
++#, c-format
++msgid "%s: KDC cannot initialize. Not enough memory\n"
++msgstr "%s: KDC kann nicht initialisiert werden. Speicher reicht nicht aus\n"
++
++#: ../../src/kdc/main.c:699 ../../src/kdc/main.c:816
++#, c-format
++msgid "%s: cannot initialize realm %s - see log file for details\n"
++msgstr ""
++"%s: Realm %s kann nicht initialisiert werden - Einzelheiten finden Sie in "
++"der Protokolldatei\n"
++
++#: ../../src/kdc/main.c:710
++#, c-format
++msgid "%s: cannot initialize realm %s. Not enough memory\n"
++msgstr ""
++"%s: Realm %s kann nicht initialisiert werden. Speicher reicht nicht aus\n"
++
++#: ../../src/kdc/main.c:761
++#, c-format
++msgid "invalid enctype %s"
++msgstr "ungültiger Verschlüsselungstyp %s"
++
++#: ../../src/kdc/main.c:804
++msgid "while attempting to retrieve default realm"
++msgstr "beim Versuch, den Standard-Realm abzufragen"
++
++#: ../../src/kdc/main.c:806
++#, c-format
++msgid "%s: %s, attempting to retrieve default realm\n"
++msgstr "%s: %s, es wird versucht, den Standard-Realm abzufragen\n"
++
++#: ../../src/kdc/main.c:912
++#, c-format
++msgid "%s: cannot get memory for realm list\n"
++msgstr "%s: Speicher für die Realm-Liste kann nicht erlangt werden\n"
++
++# http://www.oreilly.de/german/freebooks/linuxdrive2ger/getcache.html
++#: ../../src/kdc/main.c:947
++msgid "while initializing lookaside cache"
++msgstr "beim Initialisieren des Lookaside-Zwischenspeichers"
++
++#: ../../src/kdc/main.c:955
++msgid "while creating main loop"
++msgstr "beim Erzeugen der Hauptschleife"
++
++# SAM=Security Accounts Manager
++#: ../../src/kdc/main.c:965
++msgid "while initializing SAM"
++msgstr "beim Initialisieren des SAMs"
++
++#: ../../src/kdc/main.c:1011
++msgid "while initializing routing socket"
++msgstr "beim Initialisieren des Routing-Sockets"
++
++#: ../../src/kdc/main.c:1017
++msgid "while initializing signal handlers"
++msgstr "beim Initialisieren des Signalbehandlungsprogramms"
++
++#: ../../src/kdc/main.c:1024
++msgid "while initializing network"
++msgstr "beim Initialisieren des Netzwerks"
++
++#: ../../src/kdc/main.c:1029
++msgid "while detaching from tty"
++msgstr "beim Lösen vom Terminal"
++
++#: ../../src/kdc/main.c:1036
++msgid "while creating PID file"
++msgstr "beim Erstellen der PID-Datei"
++
++#: ../../src/kdc/main.c:1045
++msgid "creating worker processes"
++msgstr "Arbeitsprozesse werden erzeugt"
++
++#: ../../src/kdc/main.c:1055
++msgid "while loading audit plugin module(s)"
++msgstr "beim Laden des/der Auditerweiterungsmoduls/Auditerweiterungsmodule"
++
++#: ../../src/kdc/main.c:1059
++msgid "commencing operation"
++msgstr "Aktion wird begonnen"
++
++#: ../../src/kdc/main.c:1067
++msgid "shutting down"
++msgstr "wird heruntergefahren"
++
++#: ../../src/lib/apputils/net-server.c:258
++msgid "Got signal to request exit"
++msgstr "Signal zur Anfrage des Beendens empfangen"
++
++#: ../../src/lib/apputils/net-server.c:272
++msgid "Got signal to reset"
++msgstr "Signal zum Zurücksetzen empfangen"
++
++#: ../../src/lib/apputils/net-server.c:429
++#, c-format
++msgid "closing down fd %d"
++msgstr "Dateideskriptor %d wird geschlossen"
++
++#: ../../src/lib/apputils/net-server.c:443
++#, c-format
++msgid "descriptor %d closed but still in svc_fdset"
++msgstr "Deskriptor %d geschlossen, aber immer noch in »svc_fdset«"
++
++#: ../../src/lib/apputils/net-server.c:469
++msgid "cannot create io event"
++msgstr "E/A-Ereignis kann nicht erzeugt werden"
++
++#: ../../src/lib/apputils/net-server.c:475
++msgid "cannot save event"
++msgstr "Ereignis kann nicht gesichert werden"
++
++#: ../../src/lib/apputils/net-server.c:495
++#, c-format
++msgid "file descriptor number %d too high"
++msgstr "Dateideskriptornummer %d zu hoch"
++
++#: ../../src/lib/apputils/net-server.c:503
++msgid "cannot allocate storage for connection info"
++msgstr "Speicher für Verbindungsinformation kann nicht reserviert werden"
++
++#: ../../src/lib/apputils/net-server.c:562
++#, c-format
++msgid "Cannot create TCP server socket on %s"
++msgstr "Auf %s kann kein TCP-Server-Socket erstellt werden."
++
++#: ../../src/lib/apputils/net-server.c:571
++#, c-format
++msgid "TCP socket fd number %d (for %s) too high"
++msgstr "TCP-Socket-Deskriptornummer %d (für %s) zu hoch"
++
++#: ../../src/lib/apputils/net-server.c:579
++#, c-format
++msgid "Cannot enable SO_REUSEADDR on fd %d"
++msgstr "SO_REUSEADDR kann nicht für Dateideskriptor %d aktiviert werden"
++
++#: ../../src/lib/apputils/net-server.c:586
++#, c-format
++msgid "setsockopt(%d,IPV6_V6ONLY,1) failed"
++msgstr "setsockopt(%d,IPV6_V6ONLY,1) fehlgeschlagen"
++
++#: ../../src/lib/apputils/net-server.c:588
++#, c-format
++msgid "setsockopt(%d,IPV6_V6ONLY,1) worked"
++msgstr "setsockopt(%d,IPV6_V6ONLY,1) funktioniert"
++
++#: ../../src/lib/apputils/net-server.c:591
++msgid "no IPV6_V6ONLY socket option support"
++msgstr "keine Socket-Option für IPV6_V6ONLY unterstützt"
++
++#: ../../src/lib/apputils/net-server.c:597
++#, c-format
++msgid "Cannot bind server socket on %s"
++msgstr "Server-Socket kann nicht an %s gebunden werden"
++
++#: ../../src/lib/apputils/net-server.c:624
++#, c-format
++msgid "Cannot create RPC service: %s; continuing"
++msgstr "RPC-Dienst kann nicht erstellt werden: %s; es wird fortgefahren"
++
++#: ../../src/lib/apputils/net-server.c:633
++#, c-format
++msgid "Cannot register RPC service: %s; continuing"
++msgstr "RPC-Dienst kann nicht registriert werden: %s; es wird fortgefahren"
++
++#: ../../src/lib/apputils/net-server.c:682
++#, c-format
++msgid "Cannot listen on TCP server socket on %s"
++msgstr ""
++"Auf dem TCP-Server-Socket kann nicht auf eine Verbindung gewartet werden auf "
++"%s."
++
++#: ../../src/lib/apputils/net-server.c:688
++#, c-format
++msgid "cannot set listening tcp socket on %s non-blocking"
++msgstr ""
++"Das auf eine Verbindung wartende TCP-Socket kann nicht auf nicht-"
++"blockierendes %s gesetzt werden."
++
++#: ../../src/lib/apputils/net-server.c:695
++#, c-format
++msgid "disabling SO_LINGER on TCP socket on %s"
++msgstr "SO_LINGER auf dem TCP-Socket auf %s wird deaktiviert"
++
++#: ../../src/lib/apputils/net-server.c:743
++#: ../../src/lib/apputils/net-server.c:752
++#, c-format
++msgid "listening on fd %d: tcp %s"
++msgstr "auf Dateideskriptor %d wird auf eine Verbindung gewartet: TCP %s"
++
++#: ../../src/lib/apputils/net-server.c:757
++msgid "assuming IPv6 socket accepts IPv4"
++msgstr "es wird davon ausgegangen, dass das IPv6-Socket IPv4 akzeptiert"
++
++#: ../../src/lib/apputils/net-server.c:791
++#: ../../src/lib/apputils/net-server.c:804
++#, c-format
++msgid "listening on fd %d: rpc %s"
++msgstr "auf Dateideskriptor %d wird auf eine Verbindung gewartet: RPC %s"
++
++#: ../../src/lib/apputils/net-server.c:883
++#, c-format
++msgid "Cannot request packet info for udp socket address %s port %d"
++msgstr ""
++"Paketinformation für UDP-Socket-Adresse %s, Port %d, kann nicht abgefragt "
++"werden"
++
++#: ../../src/lib/apputils/net-server.c:889
++#, c-format
++msgid "listening on fd %d: udp %s%s"
++msgstr "auf Dateideskriptor %d wird auf eine Verbindung gewartet: UDP %s%s"
++
++#: ../../src/lib/apputils/net-server.c:918
++msgid "Failed to reconfigure network, exiting"
++msgstr "Neukonfiguration des Netzwerks fehlgeschlagen, wird beendet"
++
++#: ../../src/lib/apputils/net-server.c:979
++#, c-format
++msgid ""
++"unhandled routing message type %d, will reconfigure just for the fun of it"
++msgstr ""
++"nicht behandelter Routing-Meldungstyp %d, es wird es nur zum Spaß neu "
++"konfiguriert"
++
++#: ../../src/lib/apputils/net-server.c:1013
++#, c-format
++msgid "short read (%d/%d) from routing socket"
++msgstr "ungenügende Daten (%d/%d) vom Routing-Socket gelesen"
++
++#: ../../src/lib/apputils/net-server.c:1023
++#, c-format
++msgid "read %d from routing socket but msglen is %d"
++msgstr "%d vom Routing-Socket gelesen, Nachrichtenlänge ist jedoch %d"
++
++#: ../../src/lib/apputils/net-server.c:1055
++#, c-format
++msgid "couldn't set up routing socket: %s"
++msgstr "Routing-Socket konnte nicht eingerichtet werden: %s"
++
++#: ../../src/lib/apputils/net-server.c:1058
++#, c-format
++msgid "routing socket is fd %d"
++msgstr "Das Routing-Socket hat den Dateideskriptor %d."
++
++#: ../../src/lib/apputils/net-server.c:1084
++msgid "setting up network..."
++msgstr "Netzwerk wird eingerichtet …"
++
++#: ../../src/lib/apputils/net-server.c:1101
++#, c-format
++msgid "set up %d sockets"
++msgstr "%d Sockets werden eingerichtet"
++
++#: ../../src/lib/apputils/net-server.c:1103
++msgid "no sockets set up?"
++msgstr "keine Sockets eingerichtet?"
++
++#: ../../src/lib/apputils/net-server.c:1351
++#: ../../src/lib/apputils/net-server.c:1405
++msgid "while dispatching (udp)"
++msgstr "beim Versenden (UDP)"
++
++#: ../../src/lib/apputils/net-server.c:1380
++#, c-format
++msgid "while sending reply to %s/%s from %s"
++msgstr "beim Senden der Antwort zu %s/%s von %s"
++
++#: ../../src/lib/apputils/net-server.c:1385
++#, c-format
++msgid "short reply write %d vs %d\n"
++msgstr "ungenügende Ausgabe der Antwort %d gegenüber %d\n"
++
++#: ../../src/lib/apputils/net-server.c:1430
++msgid "while receiving from network"
++msgstr "beim Empfangen vom Netzwerk"
++
++#: ../../src/lib/apputils/net-server.c:1446
++#, c-format
++msgid "pktinfo says local addr is %s"
++msgstr "Pktinfo sagt, die lokale Adresse sei %s"
++
++#: ../../src/lib/apputils/net-server.c:1479
++msgid "too many connections"
++msgstr "zu viele Verbindungen"
++
++#: ../../src/lib/apputils/net-server.c:1502
++#, c-format
++msgid "dropping %s fd %d from %s"
++msgstr "%s Dateideskriptor %d von %s wird verworfen"
++
++#: ../../src/lib/apputils/net-server.c:1580
++#, c-format
++msgid "allocating buffer for new TCP session from %s"
++msgstr "Puffer für neue TCP-Sitzung von %s wird reserviert"
++
++#: ../../src/lib/apputils/net-server.c:1610
++msgid "while dispatching (tcp)"
++msgstr "beim Versenden (TCP)"
++
++#: ../../src/lib/apputils/net-server.c:1642
++msgid "error allocating tcp dispatch private!"
++msgstr "Fehler beim Reservieren zum nicht öffentlichen TCP-Versand!"
++
++#: ../../src/lib/apputils/net-server.c:1689
++#, c-format
++msgid "TCP client %s wants %lu bytes, cap is %lu"
++msgstr "TCP-Client %s will %lu Byte, Cap ist %lu"
++
++#: ../../src/lib/apputils/net-server.c:1697
++#, c-format
++msgid "error constructing KRB_ERR_FIELD_TOOLONG error! %s"
++msgstr "Fehler beim Erzeugen des KRB_ERR_FIELD_TOOLONG-Fehlers! %s"
++
++#: ../../src/lib/apputils/net-server.c:1876
++#, c-format
++msgid "accepted RPC connection on socket %d from %s"
++msgstr "akzeptierte PRC-Verbindung auf Socket %d von %s"
++
++# pseudo random function
++#: ../../src/lib/crypto/krb/cf2.c:114
++#, c-format
++msgid "Enctype %d has no PRF"
++msgstr "Verschlüsselungstyp %d hat keine PRF"
++
++#: ../../src/lib/crypto/krb/prng_fortuna.c:428
++msgid "Random number generator could not be seeded"
++msgstr "Zufallszahlengenerator konnte kein Startwert zugewiesen werden"
++
++#: ../../src/lib/gssapi/generic/disp_major_status.c:43
++#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:165
++msgid "A required input parameter could not be read"
++msgstr "Ein benötigter Eingabeparameter konnte nicht gelesen werden."
++
++#: ../../src/lib/gssapi/generic/disp_major_status.c:44
++msgid "A required input parameter could not be written"
++msgstr "Ein benötigter Eingabeparameter konnte nicht geschrieben werden."
++
++#: ../../src/lib/gssapi/generic/disp_major_status.c:45
++#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:175
++msgid "A parameter was malformed"
++msgstr "Ein Parameter hatte eine falsche Form"
++
++#: ../../src/lib/gssapi/generic/disp_major_status.c:48
++msgid "calling error"
++msgstr "Aufruffehler"
++
++#: ../../src/lib/gssapi/generic/disp_major_status.c:59
++#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:195
++msgid "An unsupported mechanism was requested"
++msgstr "Ein nicht unterstützter Mechanismus wurde angefordert."
++
++#: ../../src/lib/gssapi/generic/disp_major_status.c:60
++#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:199
++msgid "An invalid name was supplied"
++msgstr "Ein ungültiger Name wurde übergeben."
++
++#: ../../src/lib/gssapi/generic/disp_major_status.c:61
++#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:203
++msgid "A supplied name was of an unsupported type"
++msgstr "Ein übergebener Name hatte einen nicht unterstützten Typ."
++
++#: ../../src/lib/gssapi/generic/disp_major_status.c:62
++#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:208
++msgid "Incorrect channel bindings were supplied"
++msgstr "Falsche Kanalbindungen wurden übergeben."
++
++#: ../../src/lib/gssapi/generic/disp_major_status.c:63
++#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:179
++#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:274
++#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:334
++msgid "An invalid status code was supplied"
++msgstr "Ein ungültiger Statuscode wurde übergeben."
++
++#: ../../src/lib/gssapi/generic/disp_major_status.c:64
++msgid "A token had an invalid signature"
++msgstr "Ein Merkmal hatte eine ungültige Signatur."
++
++#: ../../src/lib/gssapi/generic/disp_major_status.c:65
++msgid "No credentials were supplied"
++msgstr "Es wurden keine Anmeldedaten übergeben."
++
++#: ../../src/lib/gssapi/generic/disp_major_status.c:66
++#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:223
++msgid "No context has been established"
++msgstr "Es wurde keine Kontext etabliert."
++
++#: ../../src/lib/gssapi/generic/disp_major_status.c:67
++msgid "A token was invalid"
++msgstr "Ein Merkmal war ungültig."
++
++#: ../../src/lib/gssapi/generic/disp_major_status.c:68
++msgid "A credential was invalid"
++msgstr "Eine der Anmeldedaten war ungültig."
++
++#: ../../src/lib/gssapi/generic/disp_major_status.c:69
++msgid "The referenced credentials have expired"
++msgstr "Die referenzierten Anmeldedaten sind abgelaufen."
++
++#: ../../src/lib/gssapi/generic/disp_major_status.c:70
++msgid "The context has expired"
++msgstr "Der Kontext ist abgelaufen."
++
++#: ../../src/lib/gssapi/generic/disp_major_status.c:71
++msgid "Miscellaneous failure"
++msgstr "sonstiger Fehlschlag"
++
++#: ../../src/lib/gssapi/generic/disp_major_status.c:72
++msgid "The quality-of-protection requested could not be provided"
++msgstr ""
++"Die angeforderte Qualität des Schutzes konnte nicht bereitgestellt werden."
++
++#: ../../src/lib/gssapi/generic/disp_major_status.c:73
++msgid "The operation is forbidden by the local security policy"
++msgstr "Die Aktion wird durch die lokale Sicherheitsrichtinie verboten."
++
++#: ../../src/lib/gssapi/generic/disp_major_status.c:74
++msgid "The operation or option is not available"
++msgstr "Die Aktion oder Option ist nicht verfügbar."
++
++#: ../../src/lib/gssapi/generic/disp_major_status.c:77
++msgid "routine error"
++msgstr "Fehler in einer Routine"
++
++#: ../../src/lib/gssapi/generic/disp_major_status.c:89
++#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:311
++msgid "The routine must be called again to complete its function"
++msgstr ""
++"Die Routine muss erneut aufgerufen werden, um ihre Funktion zu "
++"vervollständigen."
++
++#: ../../src/lib/gssapi/generic/disp_major_status.c:90
++#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:316
++msgid "The token was a duplicate of an earlier token"
++msgstr "Das Merkmal war ein Zweitexemplar eines früheren Merkmals."
++
++#: ../../src/lib/gssapi/generic/disp_major_status.c:91
++#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:321
++msgid "The token's validity period has expired"
++msgstr "Die Gültigkeitsperiode des Merkmals ist abgelaufen."
++
++#: ../../src/lib/gssapi/generic/disp_major_status.c:92
++#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:325
++msgid "A later token has already been processed"
++msgstr "Es wurde bereits ein neueres Merkmal verarbeitet."
++
++#: ../../src/lib/gssapi/generic/disp_major_status.c:95
++msgid "supplementary info code"
++msgstr "zusätzlicher Informationscode"
++
++#: ../../src/lib/gssapi/generic/disp_major_status.c:106
++#: ../lib/krb5/error_tables/krb5_err.c:23
++msgid "No error"
++msgstr "kein Fehler"
++
++#: ../../src/lib/gssapi/generic/disp_major_status.c:107
++#, c-format
++msgid "Unknown %s (field = %d)"
++msgstr "%s unbekannt (Feld = %d)"
++
++#: ../../src/lib/gssapi/krb5/acquire_cred.c:165
++#, c-format
++msgid "No key table entry found matching %s"
++msgstr "Es wurde kein zu %s passender Schlüsseltabelleneintrag gefunden."
++
++#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:161
++msgid "The routine completed successfully"
++msgstr "Die Routine wurde erfolgreich abgeschlossen"
++
++#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:170
++msgid "A required output parameter could not be written"
++msgstr "Ein erforderlicher Ausgabeparameter konnte nicht geschrieben werden."
++
++#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:212
++msgid "A token had an invalid Message Integrity Check (MIC)"
++msgstr ""
++"Ein Merkmal hatte eine ungültige Meldungsintegritätsprüfung (Message "
++"Integrity Check/MIC)."
++
++#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:217
++msgid ""
++"No credentials were supplied, or the credentials were unavailable or "
++"inaccessible"
++msgstr ""
++"Es wurden keine Anmeldedaten übergeben oder die Anmeldedaten waren nicht "
++"verfügbar bzw. ein Zugriff darauf nicht möglich."
++
++#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:227
++msgid "Invalid token was supplied"
++msgstr "Es wurde ein ungültiges Token übergeben."
++
++#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:231
++msgid "Invalid credential was supplied"
++msgstr "ungültige Anmeldedaten wurden übergeben"
++
++#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:235
++msgid "The referenced credential has expired"
++msgstr "Die referenzierten Anmeldedaten sind abgelaufen."
++
++#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:239
++msgid "The referenced context has expired"
++msgstr "Der referenzierte Kontext ist abgelaufen."
++
++#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:243
++msgid "Unspecified GSS failure.  Minor code may provide more information"
++msgstr ""
++"nicht spezifizierter GSS-Fehlschlag. Möglicherweise stellt der "
++"untergeordnete Code weitere Informationen bereit."
++
++#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:248
++msgid "The quality-of-protection (QOP) requested could not be provided"
++msgstr ""
++"Die Qualität des Schutzes (quality-of-protection/QOP) konnte nicht "
++"bereitgestellt werden."
++
++#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:253
++msgid "The operation is forbidden by local  security policy"
++msgstr "Die Aktion wird durch die lokale Sicherheitsrichtinie verboten."
++
++#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:258
++msgid "The operation or option is not available or unsupported"
++msgstr ""
++"Die Aktion oder Option ist nicht verfügbar oder wird nicht unterstützt."
++
++#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:263
++msgid "The requested credential element already exists"
++msgstr "Das angeforderte Anmeldedatenelement existiert bereits."
++
++#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:268
++msgid "The provided name was not mechanism specific (MN)"
++msgstr "Der bereitgestellte Name war nicht mechanismusspezifisch (MN)."
++
++#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:329
++msgid "An expected per-message token was not received"
++msgstr "Ein erwartetes nachrichtenspezifisches Token wurde nicht empfangen."
++
++#: ../../src/lib/gssapi/spnego/spnego_mech.c:1860
++msgid "SPNEGO cannot find mechanisms to negotiate"
++msgstr "SPNEGO kann keine Mechanismen zum Aushandeln finden."
++
++#: ../../src/lib/gssapi/spnego/spnego_mech.c:1865
++msgid "SPNEGO failed to acquire creds"
++msgstr "SPNEGO ist beim Beschaffen von Anmeldedaten gescheitert"
++
++#: ../../src/lib/gssapi/spnego/spnego_mech.c:1870
++msgid "SPNEGO acceptor did not select a mechanism"
++msgstr "SPNEGO-Abnehmer hat keinen Mechanismus ausgewählt"
++
++#: ../../src/lib/gssapi/spnego/spnego_mech.c:1875
++msgid "SPNEGO failed to negotiate a mechanism"
++msgstr "SPNEGO ist beim Aushandeln eines Mechanismus gescheitert."
++
++#: ../../src/lib/gssapi/spnego/spnego_mech.c:1880
++msgid "SPNEGO acceptor did not return a valid token"
++msgstr "SPNEGO-Abnehmer hat kein gültiges Token zurückgeliefert"
++
++#: ../../src/lib/kadm5/alt_prof.c:854
++#, c-format
++msgid "Cannot resolve address of admin server \"%s\" for realm \"%s\""
++msgstr ""
++"Adresse des Admin-Servers »%s« für Realm »%s« kann nicht ermittelt werden"
++
++#: ../../src/lib/kadm5/logger.c:56
++#, c-format
++msgid "%s: cannot parse <%s>\n"
++msgstr "%s: <%s> kann nicht ausgewertet werden\n"
++
++#: ../../src/lib/kadm5/logger.c:57
++#, c-format
++msgid "%s: warning - logging entry syntax error\n"
++msgstr "%s: Warnung – Syntaxfehler bei Protokolleintrag\n"
++
++#: ../../src/lib/kadm5/logger.c:58
++#, c-format
++msgid "%s: error writing to %s\n"
++msgstr "%s: Fehler beim Schreiben auf %s\n"
++
++#: ../../src/lib/kadm5/logger.c:59
++#, c-format
++msgid "%s: error writing to %s device\n"
++msgstr "%s: Fehler beim Schreiben auf Gerät %s\n"
++
++#: ../../src/lib/kadm5/logger.c:61
++msgid "EMERGENCY"
++msgstr "NOTFALL"
++
++#: ../../src/lib/kadm5/logger.c:62
++msgid "ALERT"
++msgstr "ALARM"
++
++#: ../../src/lib/kadm5/logger.c:63
++msgid "CRITICAL"
++msgstr "KRITISCH"
++
++#: ../../src/lib/kadm5/logger.c:64
++msgid "Error"
++msgstr "Fehler"
++
++#: ../../src/lib/kadm5/logger.c:65
++msgid "Warning"
++msgstr "Warnung"
++
++#: ../../src/lib/kadm5/logger.c:66
++msgid "Notice"
++msgstr "Hinweis"
++
++#: ../../src/lib/kadm5/logger.c:67
++msgid "info"
++msgstr "Information"
++
++#: ../../src/lib/kadm5/logger.c:68
++msgid "debug"
++msgstr "Fehlersuchmeldung"
++
++#: ../../src/lib/kadm5/logger.c:967
++#, c-format
++msgid "Couldn't open log file %s: %s\n"
++msgstr "Protokolldatei %s konnte nicht geöffnet werden: %s\n"
++
++#: ../../src/lib/kadm5/srv/kadm5_hook.c:119
++#, c-format
++msgid "kadm5_hook %s failed postcommit %s: %s"
++msgstr "»kadm5_hook« %s ist beim Nach-Commit %s gescheitert: %s"
++
++#: ../../src/lib/kadm5/srv/pwqual_dict.c:106
++msgid "No dictionary file specified, continuing without one."
++msgstr "keine Wörterbuchdatei angegeben, es wird ohne fortgefahren"
++
++#: ../../src/lib/kadm5/srv/pwqual_dict.c:113
++#, c-format
++msgid "WARNING!  Cannot find dictionary file %s, continuing without one."
++msgstr ""
++"WARNUNG! Wörterbuchdatei %s kann nicht gefunden werden, es wird ohne "
++"fortgefahren"
++
++#: ../../src/lib/kadm5/srv/pwqual_empty.c:42
++msgid "Empty passwords are not allowed"
++msgstr "Leere Passwörter sind nicht erlaubt."
++
++#: ../../src/lib/kadm5/srv/pwqual_hesiod.c:114
++msgid "Password may not match user information."
++msgstr "Das Passwort darf keinen Anwenderdaten entsprechen."
++
++#: ../../src/lib/kadm5/srv/pwqual_princ.c:54
++msgid "Password may not match principal name"
++msgstr "Das Passwort darf nicht mit dem Principal-Namen übereinstimmen."
++
++#: ../../src/lib/kadm5/srv/server_acl.c:89
++#, c-format
++msgid "%s: line %d too long, truncated"
++msgstr "%s: Zeile %d zu lang, wurde gekürzt"
++
++#: ../../src/lib/kadm5/srv/server_acl.c:90
++#, c-format
++msgid "Unrecognized ACL operation '%c' in %s"
++msgstr "unbekannte ACL-Aktion »%c« in %s"
++
++#: ../../src/lib/kadm5/srv/server_acl.c:92
++#, c-format
++msgid "%s: syntax error at line %d <%10s...>"
++msgstr "%s: Syntaxfehler in Zeile %d <%10s …>"
++
++#: ../../src/lib/kadm5/srv/server_acl.c:94
++#, c-format
++msgid "%s while opening ACL file %s"
++msgstr "%s beim Öffnen der ACL-Datei %s"
++
++#: ../../src/lib/kadm5/srv/server_acl.c:353
++#, c-format
++msgid "%s: invalid restrictions: %s"
++msgstr "%s: ungültige Beschränkung: %s"
++
++#: ../../src/lib/kadm5/srv/server_kdb.c:192
++msgid "History entry contains no key data"
++msgstr "Chronikeintrag enthält keine Schlüsseldaten"
++
++#: ../../src/lib/kadm5/srv/server_misc.c:128
++#, c-format
++msgid "password quality module %s rejected password for %s: %s"
++msgstr ""
++"Das Modul %s für Passwortqualität hat das Passwort für %s abgelehnt: %s"
++
++#: ../../src/lib/kadm5/str_conv.c:80
++msgid "Not Postdateable"
++msgstr "nicht vordatierbar"
++
++#: ../../src/lib/kadm5/str_conv.c:81
++msgid "Not Forwardable"
++msgstr "nicht weiterleitbar"
++
++#: ../../src/lib/kadm5/str_conv.c:82
++msgid "No TGT-based requests"
++msgstr "keine TGT-basierten Anfragen"
++
++#: ../../src/lib/kadm5/str_conv.c:83
++msgid "Not renewable"
++msgstr "nicht erneuerbar"
++
++#: ../../src/lib/kadm5/str_conv.c:84
++msgid "Not proxiable"
++msgstr "Proxy nicht nutzbar"
++
++#: ../../src/lib/kadm5/str_conv.c:85
++msgid "No DUP_SKEY requests"
++msgstr "keine DUP_SKEY-Anfragen"
++
++#: ../../src/lib/kadm5/str_conv.c:86
++msgid "All Tickets Disallowed"
++msgstr "keine Tickets erlaubt"
++
++#: ../../src/lib/kadm5/str_conv.c:87
++msgid "Preauthentication required"
++msgstr "Vorauthentifizierung erforderlich"
++
++#: ../../src/lib/kadm5/str_conv.c:88
++msgid "HW authentication required"
++msgstr "HW-Authentifizierung erforderlich"
++
++#: ../../src/lib/kadm5/str_conv.c:89
++msgid "OK as Delegate"
++msgstr "OK als Vertreter"
++
++#: ../../src/lib/kadm5/str_conv.c:90
++msgid "Password Change required"
++msgstr "Passwortänderung erforderlich"
++
++#: ../../src/lib/kadm5/str_conv.c:91
++msgid "Service Disabled"
++msgstr "Dienst deaktiviert"
++
++#: ../../src/lib/kadm5/str_conv.c:92
++msgid "Password Changing Service"
++msgstr "Passwortänderungsdienst"
++
++#: ../../src/lib/kadm5/str_conv.c:93
++msgid "RSA-MD5 supported"
++msgstr "RSA-MD5 unterstützt"
++
++#: ../../src/lib/kadm5/str_conv.c:94
++msgid "Protocol transition with delegation allowed"
++msgstr "Protokollübergang mit Vertretung erlaubt"
++
++#: ../../src/lib/kadm5/str_conv.c:95
++msgid "No authorization data required"
++msgstr "keine Autorisierungsdaten erforderlich"
++
++#: ../../src/lib/kdb/kdb5.c:219
++msgid "No default realm set; cannot initialize KDB"
++msgstr "kein Standard-Realm gesetzt; KDB kann nicht initialisiert werden"
++
++#: ../../src/lib/kdb/kdb5.c:324 ../../src/lib/kdb/kdb5.c:406
++#, c-format
++msgid "Unable to find requested database type: %s"
++msgstr "angeforderter Datenbanktyp kann nicht gefunden werden. %s"
++
++#: ../../src/lib/kdb/kdb5.c:416
++#, c-format
++msgid "plugin symbol 'kdb_function_table' lookup failed: %s"
++msgstr ""
++"Nachschlagen des Erweiterungssymbols »kdb_function_table« fehlgeschlagen: %s"
++
++#: ../../src/lib/kdb/kdb5.c:426
++#, c-format
++msgid ""
++"Unable to load requested database module '%s': plugin symbol "
++"'kdb_function_table' not found"
++msgstr ""
++"angefordertes Datenbankmodul »%s« kann nicht geladen werden: "
++"Erweiterungssymbol »kdb_function_table« nicht gefunden"
++
++#: ../../src/lib/kdb/kdb5.c:1650
++#, c-format
++msgid "Illegal version number for KRB5_TL_MKEY_AUX %d\n"
++msgstr "Ungültige Versionsnummer für KRB5_TL_MKEY_AUX %d\n"
++
++#: ../../src/lib/kdb/kdb5.c:1819
++#, c-format
++msgid "Illegal version number for KRB5_TL_ACTKVNO %d\n"
++msgstr "Ungültige Versionsnummer für KRB5_TL_ACTKVNO %d\n"
++
++#: ../../src/lib/kdb/kdb_default.c:164
++#, c-format
++msgid "keyfile (%s) is not a regular file: %s"
++msgstr "Schlüsseldatei (%s) ist keine normale Datei: %s"
++
++#: ../../src/lib/kdb/kdb_default.c:177
++msgid "Could not create temp keytab file name."
++msgstr "Temporärer Schlüsseltabellendateiname konnte nicht erstellt werden."
++
++#: ../../src/lib/kdb/kdb_default.c:202
++#, c-format
++msgid "Temporary stash file already exists: %s."
++msgstr "Temporäre Ablagedatei existiert bereits: %s."
++
++#: ../../src/lib/kdb/kdb_default.c:230
++#, c-format
++msgid "rename of temporary keyfile (%s) to (%s) failed: %s"
++msgstr ""
++"Umbenennen von temporärer Schlüsseldatei (%s) in (%s) fehlgeschlagen: %s"
++
++#: ../../src/lib/kdb/kdb_default.c:419
++#, c-format
++msgid "Can not fetch master key (error: %s)."
++msgstr "Hauptschlüssel kann nicht abgeholt werden (Fehler: %s)"
++
++#: ../../src/lib/kdb/kdb_default.c:482
++msgid "Unable to decrypt latest master key with the provided master key\n"
++msgstr ""
++"Letzter Hauptschlüssel kann nicht mit dem bereitgestellten Hauptschlüssel "
++"entschlüsselt werden.\n"
++
++#: ../../src/lib/kdb/kdb_log.c:83
++msgid "could not sync ulog header to disk"
++msgstr "Ulog-Kopfzeilen konnten nicht auf die Platte synchronisiert werden"
++
++#: ../../src/lib/krb5/ccache/cc_dir.c:122
++#, c-format
++msgid "Subsidiary cache path %s has no parent directory"
++msgstr ""
++"Ergänzender Zwischenspeicherpfad %s hat kein übergeordnetes Verzeichnis."
++
++#: ../../src/lib/krb5/ccache/cc_dir.c:128
++#, c-format
++msgid "Subsidiary cache path %s filename does not begin with \"tkt\""
++msgstr ""
++"Dateiname des ergänzenden Zwischenspeicherpfads %s beginnt nicht mit »tkt«"
++
++#: ../../src/lib/krb5/ccache/cc_dir.c:169
++#, c-format
++msgid "%s contains invalid filename"
++msgstr "%s enthält einen ungültigen Dateinamen."
++
++#: ../../src/lib/krb5/ccache/cc_dir.c:229
++#, c-format
++msgid "Credential cache directory %s does not exist"
++msgstr "Anmeldedatenzwischenspeicherverzeichnis %s existiert nicht."
++
++#: ../../src/lib/krb5/ccache/cc_dir.c:235
++#, c-format
++msgid "Credential cache directory %s exists but is not a directory"
++msgstr ""
++"Anmeldedatenzwischenspeicherverzeichnis %s existiert, ist jedoch kein "
++"Verzeichnis"
++
++#: ../../src/lib/krb5/ccache/cc_dir.c:400
++msgid ""
++"Can't create new subsidiary cache because default cache is not a directory "
++"collection"
++msgstr ""
++"Der neue ergänzende Zwischenspeicher kann nicht erstellt werden, da der "
++"Standardzwischenspeicher keine Ansammlung von Verzeichnissen ist."
++
++#: ../../src/lib/krb5/ccache/cc_file.c:569
++#, c-format
++msgid "Credentials cache file '%s' not found"
++msgstr "Anmeldedatenzwischenspeicherdatei »%s« nicht gefunden"
++
++#: ../../src/lib/krb5/ccache/cc_file.c:1575
++#, c-format
++msgid "Credentials cache I/O operation failed (%s)"
++msgstr "Anmeldedatenzwischenspeicher-E/A-Aktion fehlgeschlagen (%s)"
++
++#: ../../src/lib/krb5/ccache/cc_keyring.c:1151
++msgid ""
++"Can't create new subsidiary cache because default cache is already a "
++"subsidiary"
++msgstr ""
++"Der neue ergänzende Zwischenspeicher kann nicht erstellt werden, da der "
++"Standardzwischenspeicher bereits eine Ergänzung ist."
++
++#: ../../src/lib/krb5/ccache/cc_keyring.c:1219
++#, c-format
++msgid "Credentials cache keyring '%s' not found"
++msgstr "Schlüsselbund %s des Anmeldedatenzwischenspeichers nicht gefunden"
++
++#: ../../src/lib/krb5/ccache/cccursor.c:212
++#, c-format
++msgid "Can't find client principal %s in cache collection"
++msgstr ""
++"Client-Principal %s kann nicht in der Zwischenspeicheransammlung gefunden "
++"werden"
++
++#: ../../src/lib/krb5/ccache/cccursor.c:253
++msgid "No Kerberos credentials available"
++msgstr "keine Kerberos-Anmeldedaten verfügbar"
++
++#: ../../src/lib/krb5/keytab/kt_file.c:398
++#, c-format
++msgid "No key table entry found for %s"
++msgstr "Für %s wurde kein Schlüsseltabelleneintrag gefunden."
++
++#: ../../src/lib/krb5/keytab/kt_file.c:815
++#: ../../src/lib/krb5/keytab/kt_file.c:848
++msgid "Cannot change keytab with keytab iterators active"
++msgstr ""
++"Schlüsseltabelle mit aktiven Schlüsseltabelleniteratoren kann nicht geändert "
++"werden"
++
++#: ../../src/lib/krb5/keytab/kt_file.c:1047
++#, c-format
++msgid "Key table file '%s' not found"
++msgstr "Schlüsseltabellendatei »%s« nicht gefunden"
++
++#: ../../src/lib/krb5/keytab/ktfns.c:127
++#, c-format
++msgid "Keytab %s is nonexistent or empty"
++msgstr "Schlüsseltabelle %s existiert nicht oder ist leer"
++
++#: ../../src/lib/krb5/krb/chpw.c:251
++msgid "Malformed request error"
++msgstr "Fehler wegen Anfrage in falscher Form"
++
++#: ../../src/lib/krb5/krb/chpw.c:254 ../lib/krb5/error_tables/kdb5_err.c:58
++msgid "Server error"
++msgstr "Serverfehler"
++
++#: ../../src/lib/krb5/krb/chpw.c:257
++msgid "Authentication error"
++msgstr "Authentifizierungsfehler"
++
++#: ../../src/lib/krb5/krb/chpw.c:260
++msgid "Password change rejected"
++msgstr "Passwortänderung abgelehnt"
++
++#: ../../src/lib/krb5/krb/chpw.c:263
++msgid "Access denied"
++msgstr "Zugriff verweigert"
++
++#: ../../src/lib/krb5/krb/chpw.c:266
++msgid "Wrong protocol version"
++msgstr "falsche Protokollversion"
++
++#: ../../src/lib/krb5/krb/chpw.c:269
++msgid "Initial password required"
++msgstr "Erstpasswort erforderlich"
++
++#: ../../src/lib/krb5/krb/chpw.c:272
++msgid "Success"
++msgstr "Erfolg"
++
++#: ../../src/lib/krb5/krb/chpw.c:275 ../lib/krb5/error_tables/krb5_err.c:257
++msgid "Password change failed"
++msgstr "Ändern des Passworts fehlgeschlagen"
++
++#: ../../src/lib/krb5/krb/chpw.c:433
++msgid ""
++"The password must include numbers or symbols.  Don't include any part of "
++"your name in the password."
++msgstr ""
++"Das Passwort muss Zahlen oder Symbole enthalten. Fügen Sie keinen Teil Ihres "
++"Namens in das Passwort ein."
++
++#: ../../src/lib/krb5/krb/chpw.c:439
++#, c-format
++msgid "The password must contain at least %d character."
++msgid_plural "The password must contain at least %d characters."
++msgstr[0] "Das Passwort muss mindestens %d Zeichen enthalten."
++msgstr[1] "Das Passwort muss mindestens %d Zeichen enthalten."
++
++#: ../../src/lib/krb5/krb/chpw.c:448
++#, c-format
++msgid "The password must be different from the previous password."
++msgid_plural "The password must be different from the previous %d passwords."
++msgstr[0] "Das Passwort muss sich vom vorhergehenden Passwort unterscheiden."
++msgstr[1] ""
++"Das Passwort muss sich von den vorhergehenden %d Passwörtern unterscheiden."
++
++#: ../../src/lib/krb5/krb/chpw.c:460
++#, c-format
++msgid "The password can only be changed once a day."
++msgid_plural "The password can only be changed every %d days."
++msgstr[0] "Das Passwort kann nur einmal täglich geändert werden."
++msgstr[1] "Das Passwort kann nur alle %d Tage geändert werden."
++
++#: ../../src/lib/krb5/krb/chpw.c:506
++msgid "Try a more complex password, or contact your administrator."
++msgstr ""
++"Versuchen Sie es mit einem etwas komplexeren Passwort oder wenden Sie sich "
++"an Ihren Administrator."
++
++#: ../../src/lib/krb5/krb/fast.c:217
++#, c-format
++msgid "%s constructing AP-REQ armor"
++msgstr "%s-Konstruktion von AP-REQ-Schutz"
++
++#: ../../src/lib/krb5/krb/fast.c:399
++#, c-format
++msgid "%s while decrypting FAST reply"
++msgstr "%s beim Entschlüsseln der FAST-Antwort"
++
++#: ../../src/lib/krb5/krb/fast.c:408
++msgid "nonce modified in FAST response: KDC response modified"
++msgstr ""
++"Nummer für einmaligen Gebrauch in der FAST-Anwort geändert: KDC-Anwort "
++"geändert"
++
++#: ../../src/lib/krb5/krb/fast.c:474
++msgid "Expecting FX_ERROR pa-data inside FAST container"
++msgstr "Innerhalb des FAST-Containers wird »FX_ERROR pa-data« erwartet."
++
++#: ../../src/lib/krb5/krb/fast.c:545
++msgid "FAST response missing finish message in KDC reply"
++msgstr "Der FAST-Anwort fehlt die Beendigungsnachricht in der KDC-Anwort"
++
++#: ../../src/lib/krb5/krb/fast.c:558
++msgid "Ticket modified in KDC reply"
++msgstr "Ticket in der KDC-Antwort verändert"
++
++#: ../../src/lib/krb5/krb/gc_via_tkt.c:208
++#, c-format
++msgid "KDC returned error string: %.*s"
++msgstr "KDC gab eine Fehlermeldung zurück: %.*s"
++
++#: ../../src/lib/krb5/krb/gc_via_tkt.c:217
++#, c-format
++msgid "Server %s not found in Kerberos database"
++msgstr "Server %s wurde nicht in der Kerberos-Datenbank gefunden"
++
++#: ../../src/lib/krb5/krb/get_in_tkt.c:133
++msgid "Reply has wrong form of session key for anonymous request"
++msgstr ""
++"Antwort hat die falsche Form des Sitzungschlüssels für eine anonyme Anfrage"
++
++#: ../../src/lib/krb5/krb/get_in_tkt.c:1628
++#, c-format
++msgid "%s while storing credentials"
++msgstr "%s beim Speichern der Anmeldedaten"
++
++#: ../../src/lib/krb5/krb/get_in_tkt.c:1715
++#, c-format
++msgid "Client '%s' not found in Kerberos database"
++msgstr "Client »%s« wurde nicht in der Kerberos-Datenbank gefunden"
++
++#: ../../src/lib/krb5/krb/gic_keytab.c:207
++#, c-format
++msgid "Keytab contains no suitable keys for %s"
++msgstr "Schlüsseltabelle enthält keine passenden Schlüssel für %s"
++
++#: ../../src/lib/krb5/krb/gic_pwd.c:75
++#, c-format
++msgid "Password for %s"
++msgstr "Passwort for %s"
++
++#: ../../src/lib/krb5/krb/gic_pwd.c:227
++#, c-format
++msgid "Warning: Your password will expire in less than one hour on %s"
++msgstr ""
++"Warnung: Ihr Passwort auf %s wird in weniger als einer Stunde ablaufen."
++
++# FIXME in German impossible; plural without »s«
++#: ../../src/lib/krb5/krb/gic_pwd.c:231
++#, c-format
++msgid "Warning: Your password will expire in %d hour%s on %s"
++msgstr "Warnung: Ihr Passwort wird in %d Stunden%s auf %s ablaufen."
++
++#: ../../src/lib/krb5/krb/gic_pwd.c:235
++#, c-format
++msgid "Warning: Your password will expire in %d days on %s"
++msgstr "Warnung: Ihr Passwort wird in %d Tagen auf %s ablaufen."
++
++#: ../../src/lib/krb5/krb/gic_pwd.c:409
++msgid "Password expired.  You must change it now."
++msgstr "Passwort abgelaufen. Sie müssen es nun ändern."
++
++#: ../../src/lib/krb5/krb/gic_pwd.c:428 ../../src/lib/krb5/krb/gic_pwd.c:432
++#, c-format
++msgid "%s.  Please try again."
++msgstr "%s. Bitte versuchen Sie es erneut."
++
++#: ../../src/lib/krb5/krb/gic_pwd.c:471
++#, c-format
++msgid "%.*s%s%s.  Please try again.\n"
++msgstr "%.*s%s%s. Bitte versuchen Sie es erneut.\n"
++
++#: ../../src/lib/krb5/krb/parse.c:203
++#, c-format
++msgid "Principal %s is missing required realm"
++msgstr "Principal %s fehlt erforderlicher Realm"
++
++#: ../../src/lib/krb5/krb/parse.c:215
++#, c-format
++msgid "Principal %s has realm present"
++msgstr "Für Principal %s ist Realm vorhanden"
++
++#: ../../src/lib/krb5/krb/plugin.c:165
++#, c-format
++msgid "Invalid module specifier %s"
++msgstr "ungültiger Modulbezeichner %s"
++
++#: ../../src/lib/krb5/krb/plugin.c:402
++#, c-format
++msgid "Could not find %s plugin module named '%s'"
++msgstr "Das Erweiterungsmodul %s namens »%s« konnte nicht gefunden werden."
++
++#: ../../src/lib/krb5/krb/preauth2.c:1018
++msgid "Unable to initialize preauth context"
++msgstr "Vorauthentifizierungskontext konnte nicht initialisiert werden."
++
++#: ../../src/lib/krb5/krb/preauth2.c:1032
++#, c-format
++msgid "Preauth module %s: %s"
++msgstr "Vorauthentifizierungsmodul %s: %s"
++
++#: ../../src/lib/krb5/krb/preauth_otp.c:510
++msgid "Please choose from the following:\n"
++msgstr "Bitte wählen Sie aus dem Folgenden aus:\n"
++
++#: ../../src/lib/krb5/krb/preauth_otp.c:511
++msgid "Vendor:"
++msgstr "Anbieter:"
++
++#: ../../src/lib/krb5/krb/preauth_otp.c:523
++msgid "Enter #"
++msgstr "Geben Sie # ein"
++
++#: ../../src/lib/krb5/krb/preauth_otp.c:559
++msgid "OTP Challenge:"
++msgstr "Anforderung des Einwegpassworts:"
++
++#: ../../src/lib/krb5/krb/preauth_otp.c:588
++msgid "OTP Token PIN"
++msgstr "Einwegpasswort-Token-PIN"
++
++#: ../../src/lib/krb5/krb/preauth_otp.c:702
++msgid "OTP value doesn't match any token formats"
++msgstr "Wert des Einwegpassworts entspricht keinem Token-Format"
++
++#: ../../src/lib/krb5/krb/preauth_otp.c:769
++msgid "Enter OTP Token Value"
++msgstr "Geben Sie den Wert des Einwegpasswort-Tokens an"
++
++#: ../../src/lib/krb5/krb/preauth_otp.c:914
++msgid "No supported tokens"
++msgstr "keine unterstützten Token"
++
++#: ../../src/lib/krb5/krb/preauth_sam2.c:49
++msgid "Challenge for Enigma Logic mechanism"
++msgstr "Anforderung für Enigma-Logic-Mechanismus"
++
++#: ../../src/lib/krb5/krb/preauth_sam2.c:53
++msgid "Challenge for Digital Pathways mechanism"
++msgstr "Anforderung für Digital-Pathway-Mechanismus"
++
++#: ../../src/lib/krb5/krb/preauth_sam2.c:57
++msgid "Challenge for Activcard mechanism"
++msgstr "Anforderung für Activcard-Mechanismus"
++
++#: ../../src/lib/krb5/krb/preauth_sam2.c:60
++msgid "Challenge for Enhanced S/Key mechanism"
++msgstr "Anforderung für erweiterten S/Key-Mechanismus"
++
++#: ../../src/lib/krb5/krb/preauth_sam2.c:63
++msgid "Challenge for Traditional S/Key mechanism"
++msgstr "Anforderung für traditionellen S/Key-Mechanismus"
++
++#: ../../src/lib/krb5/krb/preauth_sam2.c:66
++#: ../../src/lib/krb5/krb/preauth_sam2.c:69
++msgid "Challenge for Security Dynamics mechanism"
++msgstr "Anforderung für Security-Dynamics-Mechanismus"
++
++#: ../../src/lib/krb5/krb/preauth_sam2.c:72
++msgid "Challenge from authentication server"
++msgstr "Anforderung vom Authentifizierungsserver"
++
++#: ../../src/lib/krb5/krb/preauth_sam2.c:166
++msgid "SAM Authentication"
++msgstr "SAM-Authentifizierung"
++
++#: ../../src/lib/krb5/krb/rd_req_dec.c:145
++#, c-format
++msgid "Cannot find key for %s kvno %d in keytab"
++msgstr ""
++"Schlüssel für %s-KNVO %d kann nicht in der Schlüsseltabelle gefunden werden"
++
++#: ../../src/lib/krb5/krb/rd_req_dec.c:150
++#, c-format
++msgid "Cannot find key for %s kvno %d in keytab (request ticket server %s)"
++msgstr ""
++"Schlüssel für %s-KNVO %d kann nicht in der Schlüsseltabelle gefunden werden "
++"(angefragter Ticketserver %s)"
++
++#: ../../src/lib/krb5/krb/rd_req_dec.c:175
++#, c-format
++msgid "Cannot decrypt ticket for %s using keytab key for %s"
++msgstr ""
++"Ticket für %s kann nicht mittels des Schlüsseltabellenschlüssels für %s "
++"entschlüsselt werden"
++
++#: ../../src/lib/krb5/krb/rd_req_dec.c:197
++#, c-format
++msgid "Server principal %s does not match request ticket server %s"
++msgstr "Server-Principal %s passt nicht zum abgefragten Ticketserver %s"
++
++#: ../../src/lib/krb5/krb/rd_req_dec.c:226
++msgid "No keys in keytab"
++msgstr "keine Schlüssel in der Schlüsseltabelle"
++
++#: ../../src/lib/krb5/krb/rd_req_dec.c:229
++#, c-format
++msgid "Server principal %s does not match any keys in keytab"
++msgstr ""
++"Server-Principal %s hat keinen passenden Schlüssel in der Schlüsseltabelle"
++
++#: ../../src/lib/krb5/krb/rd_req_dec.c:236
++#, c-format
++msgid ""
++"Request ticket server %s found in keytab but does not match server principal "
++"%s"
++msgstr ""
++"abgefragter Ticketserver %s wurde in der Schlüsseltabelle gefunden, er passte "
++"jedoch nicht zu Server-Principal %s"
++
++#: ../../src/lib/krb5/krb/rd_req_dec.c:241
++#, c-format
++msgid "Request ticket server %s not found in keytab (ticket kvno %d)"
++msgstr ""
++"Abgefragter Ticketserver %s wurde nicht in der Schlüsseltabelle gefunden "
++"(Ticket KVNO %d)."
++
++#: ../../src/lib/krb5/krb/rd_req_dec.c:247
++#, c-format
++msgid ""
++"Request ticket server %s kvno %d not found in keytab; ticket is likely out "
++"of date"
++msgstr ""
++"Abgefragter Ticketserver %s KVNO %d wurde nicht in der Schlüsseltabelle "
++"gefunden; Ticket ist wahrscheinlich abgelaufen."
++
++#: ../../src/lib/krb5/krb/rd_req_dec.c:252
++#, c-format
++msgid ""
++"Request ticket server %s kvno %d not found in keytab; keytab is likely out "
++"of date"
++msgstr ""
++"Abgefragter Ticketserver %s KVNO %d wurde nicht in der Schlüsseltabelle "
++"gefunden; Schlüsseltabelle ist wahrscheinlich nicht mehr aktuell."
++
++#: ../../src/lib/krb5/krb/rd_req_dec.c:261
++#, c-format
++msgid ""
++"Request ticket server %s kvno %d found in keytab but not with enctype %s"
++msgstr ""
++"Abgefragter Ticketserver %s KVNO %d wurde in der Schlüsseltabelle gefunden, "
++"jedoch nicht mit Verschlüsselungstyp %s."
++
++#: ../../src/lib/krb5/krb/rd_req_dec.c:266
++#, c-format
++msgid ""
++"Request ticket server %s kvno %d enctype %s found in keytab but cannot "
++"decrypt ticket"
++msgstr ""
++"Abgefragter Ticketserver %s KVNO %d mit Verschlüsselungstyp %s in der "
++"Schlüsseltabelle gefunden, Ticket kann jedoch nicht entschlüsselt werden."
++
++#: ../../src/lib/krb5/krb/rd_req_dec.c:897
++#, c-format
++msgid "Encryption type %s not permitted"
++msgstr "Verschlüsselungstyp %s nicht erlaubt"
++
++#: ../../src/lib/krb5/os/expand_path.c:316
++#, c-format
++msgid "Can't find username for uid %lu"
++msgstr "Zu UID %lu kann kein Benutzername gefunden werden."
++
++#: ../../src/lib/krb5/os/expand_path.c:405
++#: ../../src/lib/krb5/os/expand_path.c:421
++msgid "Invalid token"
++msgstr "ungültiges Token"
++
++#: ../../src/lib/krb5/os/expand_path.c:506
++msgid "variable missing }"
++msgstr "Variable fehlt }"
++
++#: ../../src/lib/krb5/os/locate_kdc.c:660
++#, c-format
++msgid "Cannot find KDC for realm \"%.*s\""
++msgstr "KDC für Realm »%.*s« kann nicht gefunden werden"
++
++#: ../../src/lib/krb5/os/sendto_kdc.c:475
++#, c-format
++msgid "Cannot contact any KDC for realm '%.*s'"
++msgstr "für Realm »%.*s« kann nicht KDC kontaktiert werden"
++
++#: ../../src/lib/krb5/rcache/rc_io.c:106
++#, c-format
++msgid "Cannot fstat replay cache file %s: %s"
++msgstr "»fstat« für Antwortzwischenspeicherdatei %s nicht möglich: %s"
++
++#: ../../src/lib/krb5/rcache/rc_io.c:112
++#, c-format
++msgid ""
++"Insecure mkstemp() file mode for replay cache file %s; try running this "
++"program with umask 077"
++msgstr ""
++"unsicherer mkstemp()-Dateimodus für Antwortzwischenspeicherdatei %s; "
++"versuchen Sie, dieses Programm mit der Umask 077 auszuführen"
++
++#: ../../src/lib/krb5/rcache/rc_io.c:144
++#, c-format
++msgid "Cannot %s replay cache file %s: %s"
++msgstr "%s der Wiederholungszwischenspeicherdatei %s nicht möglich: %s"
++
++#: ../../src/lib/krb5/rcache/rc_io.c:149
++#, c-format
++msgid "Cannot %s replay cache: %s"
++msgstr "%s des Wiederholungszwischenspeichers nicht möglich: %s"
++
++#: ../../src/lib/krb5/rcache/rc_io.c:272
++#, c-format
++msgid "Insecure file mode for replay cache file %s"
++msgstr "unsicherer Dateimodus für Wiederholungszwischenspeicherdatei %s"
++
++#: ../../src/lib/krb5/rcache/rc_io.c:278
++#, c-format
++msgid "rcache not owned by %d"
++msgstr "Rcache gehört nicht %d"
++
++#: ../../src/lib/krb5/rcache/rc_io.c:402 ../../src/lib/krb5/rcache/rc_io.c:406
++#: ../../src/lib/krb5/rcache/rc_io.c:411
++#, c-format
++msgid "Can't write to replay cache: %s"
++msgstr ""
++"in Wiederholungszwischenspeicherdatei kann nicht geschrieben werden: %s"
++
++#: ../../src/lib/krb5/rcache/rc_io.c:432
++#, c-format
++msgid "Cannot sync replay cache file: %s"
++msgstr ""
++"Wiederholungszwischenspeicherdatei kann nicht synchronisiert werden: %s"
++
++#: ../../src/lib/krb5/rcache/rc_io.c:451
++#, c-format
++msgid "Can't read from replay cache: %s"
++msgstr "aus dem Wiederholungszwischenspeicher kann nicht gelesen werden: %s"
++
++#: ../../src/lib/krb5/rcache/rc_io.c:482 ../../src/lib/krb5/rcache/rc_io.c:488
++#: ../../src/lib/krb5/rcache/rc_io.c:493
++#, c-format
++msgid "Can't destroy replay cache: %s"
++msgstr "Wiederholungszwischenspeicher kann nicht vernichtet werden: %s"
++
++#: ../../src/plugins/kdb/db2/kdb_db2.c:245
++#: ../../src/plugins/kdb/db2/kdb_db2.c:830
++#, c-format
++msgid "Unsupported argument \"%s\" for db2"
++msgstr "nicht unterstütztes Argument »%s« für DB2"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:69
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:887
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1088
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1507
++msgid "while reading kerberos container information"
++msgstr "beim Lesen der Kerberos-Container-Information"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:129
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:143
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:504
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:518
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:151
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:166
++msgid "while providing time specification"
++msgstr "beim Bereitstellen der Zeitspezifikation"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:268
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:304
++msgid "while creating policy object"
++msgstr "beim Erstellen des Richtlinienobjekts"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:279
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1515
++msgid "while reading realm information"
++msgstr "beim Lesen der Realm-Information"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:348
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:407
++msgid "while destroying policy object"
++msgstr "beim Zerstören des Richtlinienobjekts"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:358
++#, c-format
++msgid "This will delete the policy object '%s', are you sure?\n"
++msgstr "Dies wird das Richtlinienobjekt »%s« löschen, sind Sie sicher?\n"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:473
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:663
++msgid "while modifying policy object"
++msgstr "beim Ändern des Richtlinienobjekts"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:487
++#, c-format
++msgid "while reading information of policy '%s'"
++msgstr "beim Lesen der Information der Richtlinie »%s«"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:692
++msgid "while viewing policy"
++msgstr "beim Betrachten der Richtlinie"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:701
++#, c-format
++msgid "while viewing policy '%s'"
++msgstr "beim Betrachten der Richtlinie »%s«"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:835
++msgid "while listing policy objects"
++msgstr "beim Auflisten der Richtlinienobjekte"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:453
++#, c-format
++msgid "for subtree while creating realm '%s'"
++msgstr "für einen Teilbaum beim Erstellen von Realm »%s«"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:465
++#, c-format
++msgid "for container reference while creating realm '%s'"
++msgstr "für Container-Bezug beim Erstellen von Realm »%s«"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:489
++#, c-format
++msgid "invalid search scope while creating realm '%s'"
++msgstr "ungültiger Suchbereich beim Erstellen von Realm »%s«"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:504
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:823
++#, c-format
++msgid "'%s' is an invalid option\n"
++msgstr "»%s« ist keine gültige Option\n"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:512
++#, c-format
++msgid "Initializing database for realm '%s'\n"
++msgstr "Datenbank für Realm »%s« wird initialisiert\n"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:536
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:696
++#, c-format
++msgid "while creating realm '%s'"
++msgstr "beim Erstellen von Realm »%s«"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:556
++#, c-format
++msgid "Enter DN of Kerberos container: "
++msgstr "Geben Sie die den DN des Kerberos-Containers ein: "
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:591
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:894
++#, c-format
++msgid "while reading information of realm '%s'"
++msgstr "beim Lesen der Information von Realm »%s«"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:733
++msgid "while reading Kerberos container information"
++msgstr "beim Lesen der Kerberos-Container-Information"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:774
++#, c-format
++msgid "for subtree while modifying realm '%s'"
++msgstr "für einen Teilbaum beim Ändern von Realm »%s«"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:785
++#, c-format
++msgid "for container reference while modifying realm '%s'"
++msgstr "für Container-Bezug beim Ändern von Realm »%s«"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:812
++#, c-format
++msgid "specified for search scope while modifying information of realm '%s'"
++msgstr ""
++"angegeben für Suchbereich, während die Information für Realm »%s« geändert "
++"wird"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:851
++#, c-format
++msgid "while modifying information of realm '%s'"
++msgstr "beim Ändern der Information von Realm »%s«"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:940
++msgid "Realm Name"
++msgstr "Realm-Name"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:943
++msgid "Subtree"
++msgstr "Teilbaum"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:946
++msgid "Principal Container Reference"
++msgstr "Principal-Container-Bezug"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:951
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:953
++msgid "SearchScope"
++msgstr "Suchbereich"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:951
++msgid "Invalid !"
++msgstr "ungültig!"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:958
++msgid "KDC Services"
++msgstr "KDC-Dienste"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:973
++msgid "Admin Services"
++msgstr "Administratordienste"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:988
++msgid "Passwd Services"
++msgstr "Passwortdienste"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1004
++msgid "Maximum Ticket Life"
++msgstr "maximale Ticketlebensdauer"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1009
++msgid "Maximum Renewable Life"
++msgstr "maximale verlängerbare Lebensdauer"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1016
++msgid "Ticket flags"
++msgstr "Ticket-Flags"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1095
++msgid "while listing realms"
++msgstr "beim Auflisten der Realms"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1439
++msgid "while adding entries to database"
++msgstr "beim Hinzufügen von Einträgen zur Datenbank"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1480
++#, c-format
++msgid "Deleting KDC database of '%s', are you sure?\n"
++msgstr ""
++"Sind Sie sicher, dass die KDC-Datenbank von »%s« gelöscht werden soll?\n"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1491
++#, c-format
++msgid "OK, deleting database of '%s'...\n"
++msgstr "OK, die Datenbank von »%s« wird gelöscht …\n"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1524
++#, c-format
++msgid "deleting database of '%s'"
++msgstr "Die Datenbank von »%s« wird gelöscht."
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1529
++#, c-format
++msgid "** Database of '%s' destroyed.\n"
++msgstr "** Datenbank von »%s« vernichtet\n"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:81
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:88
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:96
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:104
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:120
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:148
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:227
++msgid "while setting service object password"
++msgstr "beim Setzen des Passworts für das Dienstobjekt"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:140
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:477
++#, c-format
++msgid "Password for \"%s\""
++msgstr "Passwort für »%s«"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:143
++#, c-format
++msgid "Re-enter password for \"%s\""
++msgstr "Geben Sie das Passwort für »%s« erneut ein."
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:154
++#, c-format
++msgid "%s: Invalid password\n"
++msgstr "%s: ungültiges Passwort\n"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:170
++msgid "Failed to convert the password to hexadecimal"
++msgstr "Das Umwandeln des Passworts in Dezimalschreibweise ist fehlgeschlagen."
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:183
++#, c-format
++msgid "Failed to open file %s: %s"
++msgstr "Datei %s konnte nicht geöffnet werden: %s"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:205
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:247
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:256
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:283
++msgid "Failed to write service object password to file"
++msgstr ""
++"Schreiben des Passworts für das Dienstobjekt in eine Datei fehlgeschlagen"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:211
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:268
++msgid "Error reading service object password file"
++msgstr "Fehler beim Lesen der Passwortdatei für das Dienstobjekt"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:236
++#, c-format
++msgid "Error creating file %s"
++msgstr "Fehler beim Erstellen der Datei %s"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:105
++#, c-format
++msgid ""
++"Usage: kdb5_ldap_util [-D user_dn [-w passwd]] [-H ldapuri]\n"
++"\tcmd [cmd_options]\n"
++"create          [-subtrees subtree_dn_list] [-sscope search_scope] [-"
++"containerref container_reference_dn]\n"
++"\t\t[-m|-P password|-sf stashfilename] [-k mkeytype] [-kv mkeyVNO] [-s]\n"
++"\t\t[-maxtktlife max_ticket_life] [-maxrenewlife max_renewable_ticket_life]\n"
++"\t\t[ticket_flags] [-r realm]\n"
++"modify          [-subtrees subtree_dn_list] [-sscope search_scope] [-"
++"containerref container_reference_dn]\n"
++"\t\t[-maxtktlife max_ticket_life] [-maxrenewlife max_renewable_ticket_life]\n"
++"\t\t[ticket_flags] [-r realm]\n"
++"view            [-r realm]\n"
++"destroy                [-f] [-r realm]\n"
++"list\n"
++"stashsrvpw      [-f filename] service_dn\n"
++"create_policy   [-r realm] [-maxtktlife max_ticket_life]\n"
++"\t\t[-maxrenewlife max_renewable_ticket_life] [ticket_flags] policy\n"
++"modify_policy   [-r realm] [-maxtktlife max_ticket_life]\n"
++"\t\t[-maxrenewlife max_renewable_ticket_life] [ticket_flags] policy\n"
++"view_policy     [-r realm] policy\n"
++"destroy_policy  [-r realm] [-force] policy\n"
++"list_policy     [-r realm]\n"
++msgstr ""
++"Aufruf: kdb5_ldap_util [-D Benutzer-DN [-w Passwort]] [-H LDAP-URI]\n"
++"\tcmd [Befehlsoptionen]\n"
++"create          [-subtrees DN-Liste_Teilbäume] [-sscope Suchbereich] [-"
++"containerref Container-Bezug-DN]\n"
++"\t\t[-m|-P Passwort|-sf Ablagedateiname] [-k mkeytype] [-kv mkeyVNO] [-s]\n"
++"\t\t[-maxtktlife maximale_Ticketlebensdauer]\n"
++"\t\t[-maxrenewlife maximale_Dauer_bis_zum_Erneuern_des_Tickets]\n"
++"\t\t[Ticket_Flags] [-r Realm]\n"
++"modify          [-subtrees DN-Liste_Teilbäume] [-sscope Suchbereich] [-"
++"containerref Container-Bezug-DN]\n"
++"\t\t[-maxtktlife maximale_Ticketlebensdauer]\n"
++"\t\t[-maxrenewlife maximale_Dauer_bis_zum_Erneuern_des_Tickets]\n"
++"\t\t[Ticket_Flags] [-r Realm]\n"
++"view            [-r Realm]\n"
++"destroy                [-f] [-r Realm]\n"
++"list\n"
++"stashsrvpw      [-f Dateiname] Dienst-DN\n"
++"create_policy   [-r Realm] [-maxtktlife maximale_Ticketlebensdauer]\n"
++"\t\t[-maxrenewlife maximale_Dauer_bis_zum_Erneuern_des_Tickets]\n"
++"\t\t[Ticket_Flags] Richtlinie\n"
++"modify_policy   [-r Realm] [-maxtktlife maximale_Ticketlebensdauer]\n"
++"\t\t[-maxrenewlife maximale_Dauer_bis_zum_Erneuern_des_Tickets]\n"
++"\t\t[Ticket_Flags] Richtlinie\n"
++"view_policy     [-r Realm] Richtlinie\n"
++"destroy_policy  [-r Realm] [-force] Richtlinie\n"
++"list_policy     [-r Realm]\n"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:325
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:333
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:341
++msgid "while reading ldap parameters"
++msgstr "beim Lesen der LDAP-Parameter"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:439
++msgid "while initializing error handling"
++msgstr "beim Initialisieren der Fehlerbehandlung"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:447
++msgid "while initializing ldap handle"
++msgstr "beim Initialisieren des LDAP-Identifikators"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:461
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:470
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:483
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:525
++msgid "while retrieving ldap configuration"
++msgstr "beim Abfragen der LDAP-Konfiguration"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:500
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:507
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:516
++msgid "while initializing server list"
++msgstr "beim Initialisieren der Serverliste"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:547
++msgid "while setting up lib handle"
++msgstr "ein Einrichten der BibliotheksIdentifikators"
++
++#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:556
++msgid "while reading ldap configuration"
++msgstr "beim Lesen der LDAP-Konfiguration"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c:68
++msgid "Unable to read Kerberos container"
++msgstr "Kerberos-Container kann nicht gelesen werden"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c:74
++msgid "Unable to read Realm"
++msgstr "Realm kann nicht gelesen werden"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c:215
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_create.c:73
++msgid "Error processing LDAP DB params:"
++msgstr "Fehler beim Verarbeiten der LDAP-Datenbankparameter:"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c:222
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_create.c:80
++msgid "Error reading LDAP server params:"
++msgstr "Fehler beim Lesen der LDAP-Server-Parameters:"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c:64
++msgid "LDAP bind dn value missing"
++msgstr "LDAP-Bindungs-DN-Wert fehlt"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c:69
++msgid "LDAP bind password value missing"
++msgstr "LDAP-Bindungs-Passwortwert fehlt"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c:77
++msgid "Error reading password from stash: "
++msgstr "Fehler beim Lesen des Passworts aus der Ablage: "
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c:85
++msgid "Service password length is zero"
++msgstr "Länge des Dienstpassworts ist Null"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c:145
++#, c-format
++msgid "Cannot bind to LDAP server '%s' with SASL mechanism '%s': %s"
++msgstr ""
++"mit LDAP-Server »%s« kann keine Verbindung mit SASL-Mechanismus »%s« "
++"hergestellt werden: %s"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c:158
++#, c-format
++msgid "Cannot bind to LDAP server '%s' as '%s': %s"
++msgstr ""
++"mit LDAP-Server »%s« kann keine Verbindung als »%s« hergestellt werden: %s"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c:183
++#, c-format
++msgid "Cannot create LDAP handle for '%s': %s"
++msgstr "LDAP-Identifikator für »%s« kann nicht erstellt werden: %s"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_create.c:131
++msgid "could not complete roll-back, error deleting Kerberos Container"
++msgstr ""
++"Zurücksetzen kann nicht abgeschlossen werden, Fehler beim Löschen des "
++"Kerberos-Containers"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.c:56
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.c:67
++msgid "Error reading kerberos container location from krb5.conf"
++msgstr ""
++"Fehler beim Lesen des Kerberos-Container-Speicherorts aus der »krb5.conf«."
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.c:75
++msgid "Kerberos container location not specified"
++msgstr "Kerberos-Container-Speicherort nicht angegeben"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c:55
++#, c-format
++msgid "Error reading '%s' attribute: %s"
++msgstr "Fehler beim Lesen des Attributs »%s«: %s"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c:218
++msgid "KDB module requires -update argument"
++msgstr "KDB-Modul benötigt Argument »-update«"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c:224
++#, c-format
++msgid "'%s' value missing"
++msgstr "Wert »%s« fehlt"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c:282
++#, c-format
++msgid "unknown option '%s'"
++msgstr "unbekannte Option »%s«"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c:342
++msgid "Minimum connections required per server is 2"
++msgstr "Die benötigte Mindestanzahl von Verbindungen pro Server ist zwei"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c:159
++msgid "Default realm not set"
++msgstr "Standard-Realm nicht gesetzt"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c:262
++msgid "DN information missing"
++msgstr "DN-Information fehlt"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:108
++msgid "Principal does not belong to realm"
++msgstr "Principal gehört nicht zum Realm"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:278
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:287
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:295
++#, c-format
++msgid "%s option not supported"
++msgstr "Option %s wird nicht unterstützt"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:302
++#, c-format
++msgid "unknown option: %s"
++msgstr "unbekannte Option: %s"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:309
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:316
++#, c-format
++msgid "%s option value missing"
++msgstr "Wert der Option %s fehlt"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:542
++msgid "Principal does not belong to the default realm"
++msgstr "Principal gehört nicht zum Standard-Realm"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:610
++#, c-format
++msgid ""
++"operation can not continue, more than one entry with principal name \"%s\" "
++"found"
++msgstr ""
++"Die Aktion kann nicht fortfahren, da mehr als ein Principal namens »%s« "
++"gefunden wurde."
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:673
++#, c-format
++msgid "'%s' not found: "
++msgstr "»%s« nicht gefunden: "
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:751
++msgid "DN is out of the realm subtree"
++msgstr "DN liegt außerhalb ders Teilbaums des Realms"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:807
++#, c-format
++msgid "ldap object is already kerberized"
++msgstr "LDAP-Objekt ist bereits an Kerberos angepasst"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:827
++#, c-format
++msgid ""
++"link information can not be set/updated as the kerberos principal belongs to "
++"an ldap object"
++msgstr ""
++"Verweisinformation kann nicht eingerichtet/aktualisiert werden, da der "
++"Kerberos-Principal zu einem LDAP-Objekt gehört."
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:842
++#, c-format
++msgid "Failed getting object references"
++msgstr "Holen von Objektbezügen fehlgeschlagen"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:849
++#, c-format
++msgid "kerberos principal is already linked to a ldap object"
++msgstr "Kerberos-Principal ist bereits mit einem LDAP-Objekt verknüpft"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:1167
++msgid "ticket policy object value: "
++msgstr "Wert des Ticket-Richtlinienobjekts: "
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:1215
++#, c-format
++msgid "Principal delete failed (trying to replace entry): %s"
++msgstr ""
++"Löschen des Principals fehlgeschlagen (es wird versucht, den Eintrag zu "
++"ersetzen): %s"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:1225
++#, c-format
++msgid "Principal add failed: %s"
++msgstr "Hinzufügen des Principals fehlgeschlagen: %s"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:1263
++#, c-format
++msgid "User modification failed: %s"
++msgstr "Änderung des Benutzers fehlgeschlagen: %s"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:1336
++msgid "Error reading ticket policy. "
++msgstr "Fehler beim Lesen der Ticket-Richtlinie"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:1402
++#, c-format
++msgid "unable to decode stored principal key data (%s)"
++msgstr ""
++"Die gespeicherten Schlüsseldaten des Principals (%s) konnten nicht "
++"dekodiert werden."
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:223
++msgid "Realm information not available"
++msgstr "Realm-Information nicht verfügbar"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:294
++msgid "Error reading ticket policy: "
++msgstr "Fehler beim Lesen der Ticket-Richtlinie:"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:307
++#, c-format
++msgid "Realm Delete FAILED: %s"
++msgstr "Löschen des Realms FEHLGESCHLAGEN: %s"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:387
++msgid "subtree value: "
++msgstr "Wert des Teilbaums: "
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:404
++msgid "container reference value: "
++msgstr "Wert des Container-Bezugs: "
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:487
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:550
++msgid "Kerberos Container information is missing"
++msgstr "Kerberos-Container-Information fehlt"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:499
++msgid "Invalid Kerberos container DN"
++msgstr "ungültiger Kerberos-Container-DN"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:515
++#, c-format
++msgid "Kerberos Container create FAILED: %s"
++msgstr "Erstellen des Kerberos-Containers FEHLGESCHLAGEN: %s"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:558
++#, c-format
++msgid "Kerberos Container delete FAILED: %s"
++msgstr "Löschen des Kerberos-Containers FEHLGESCHLAGEN: %s"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:634
++msgid "realm object value: "
++msgstr "Wert des Realm-Objekts: "
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c:48
++msgid "Not a hexadecimal password"
++msgstr "kein hexadezimales Passwort"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c:55
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c:66
++msgid "Password corrupt"
++msgstr "Passwort beschädigt"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c:93
++#, c-format
++msgid "Cannot open LDAP password file '%s': %s"
++msgstr "LDAP-Passwortdatei »%s« kann nicht geöffnet werden: %s"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c:123
++#, c-format
++msgid "Bind DN entry '%s' missing in LDAP password file '%s'"
++msgstr "Bind-DN-Eintrag »%s« fehlt in der LDAP-Passwortdatei »%s«"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:56
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:132
++msgid "Ticket Policy Name missing"
++msgstr "Ticket-Richtlinienname fehlt"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:144
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:221
++msgid "ticket policy object: "
++msgstr "Ticket-Richtlinienobjekt: "
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:209
++msgid "Ticket Policy Object information missing"
++msgstr "Ticket-Richtlinienobjekt-Information fehlt"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:300
++msgid "Ticket Policy Object DN missing"
++msgstr "DN des Ticket-Richtlinienobjekts fehlt"
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:327
++msgid "Delete Failed: One or more Principals associated with the Ticket Policy"
++msgstr ""
++"Löschen fehlgeschlagen: Ein oder mehrere Principals gehören zur Ticket-"
++"Richtlinie."
++
++#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:435
++msgid "Error reading container object: "
++msgstr "Fehler beim Lesen des Container-Objekts: "
++
++#: ../../src/plugins/preauth/pkinit/pkinit_crypto_nss.c:667
++#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:652
++#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:4153
++msgid "Pass phrase for"
++msgstr "Passphrase für"
++
++#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:1081
++#, c-format
++msgid "Cannot create cert chain: %s"
++msgstr "Zertifikatskette kann nicht erstellt werden: %s"
++
++#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:1408
++msgid "Invalid pkinit packet: octet string expected"
++msgstr "ungültiges Pkinit-Paket: Achtbit-Zeichenkette erwartet"
++
++#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:1427
++msgid "wrong oid\n"
++msgstr "falsche OID\n"
++
++#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:5994
++#, c-format
++msgid "unknown code 0x%x"
++msgstr "unbekannter Code 0x%x"
++
++#: ../../src/plugins/preauth/pkinit/pkinit_identity.c:424
++#, c-format
++msgid "Unsupported type while processing '%s'\n"
++msgstr "nicht unterstützter Typ bei der Verarbeitung von »%s«\n"
++
++#: ../../src/plugins/preauth/pkinit/pkinit_identity.c:465
++msgid "Internal error parsing X509_user_identity\n"
++msgstr "interner Fehler beim Auswerten von »X509_user_identity«\n"
++
++#: ../../src/plugins/preauth/pkinit/pkinit_identity.c:560
++msgid "No user identity options specified"
++msgstr "keine Optionen der Nutzeridentität angegeben"
++
++#: ../../src/plugins/preauth/pkinit/pkinit_srv.c:414
++msgid "Pkinit request not signed, but client not anonymous."
++msgstr "Pkinit-Anfrage nicht signiert, Client ist jedoch nicht anonym"
++
++# DH = Diffie-Hellman
++#: ../../src/plugins/preauth/pkinit/pkinit_srv.c:447
++msgid "Anonymous pkinit without DH public value not supported."
++msgstr "Anonymes Pkinit wird nicht ohne öffentlichen DH-Wert unterstützt."
++
++#: ../../src/plugins/preauth/pkinit/pkinit_srv.c:1147
++#, c-format
++msgid "No pkinit_identity supplied for realm %s"
++msgstr "Für Realm %s wird keine »pkinit_identity« bereitgestellt."
++
++#: ../../src/plugins/preauth/pkinit/pkinit_srv.c:1158
++#, c-format
++msgid "No pkinit_anchors supplied for realm %s"
++msgstr "Für Realm %s werden keine »pkinit_anchors« bereitgestellt."
++
++#: ../../src/plugins/preauth/pkinit/pkinit_srv.c:1346
++msgid "No realms configured correctly for pkinit support"
++msgstr "Für Pkinit-Unterstützung wurden keine Realms korrekt konfiguriert."
++
++#: ../../src/slave/kprop.c:85
++#, c-format
++msgid ""
++"\n"
++"Usage: %s [-r realm] [-f file] [-d] [-P port] [-s srvtab] slave_host\n"
++"\n"
++msgstr ""
++"\n"
++"Aufruf: %s [-r Realm] [-f Datei] [-d] [-P Port] [-s Dienstschlüsseltabelle] "
++"untergeordneter_Rechner\n"
++"\n"
++
++#: ../../src/slave/kprop.c:114
++#, c-format
++msgid "Database propagation to %s: SUCCEEDED\n"
++msgstr "Datenbankverbreitung auf %s: ERFOLGREICH\n"
++
++#: ../../src/slave/kprop.c:187
++msgid "while setting client principal name"
++msgstr "beim Setzen des Client-Principal-Namens"
++
++#: ../../src/slave/kprop.c:194 ../../src/slave/kprop.c:209
++msgid "while setting client principal realm"
++msgstr "beim Setzen des Client-Principal-Realms"
++
++#: ../../src/slave/kprop.c:217
++#, c-format
++msgid "while opening credential cache %s"
++msgstr "beim Öffnen des Anmeldedatenzwischenspeichers %s"
++
++#: ../../src/slave/kprop.c:233
++msgid "while setting server principal name"
++msgstr "beim Setzen des Server-Principal-Namens"
++
++#: ../../src/slave/kprop.c:255
++msgid "while resolving keytab"
++msgstr "beim Ermitteln der Schlüsseltabelle"
++
++#: ../../src/slave/kprop.c:264
++msgid "while getting initial credentials\n"
++msgstr "beim Holen der Anfangsanmeldedaten\n"
++
++#: ../../src/slave/kprop.c:301
++msgid "while creating socket"
++msgstr "beim Erstellen eines Sockets"
++
++#: ../../src/slave/kprop.c:317
++msgid "while converting server address"
++msgstr "beim Umwandeln der Server-Adresse"
++
++#: ../../src/slave/kprop.c:327
++msgid "while connecting to server"
++msgstr "beim Verbinden mit dem Server"
++
++#: ../../src/slave/kprop.c:334 ../../src/slave/kpropd.c:1215
++msgid "while getting local socket address"
++msgstr "beim Holen der lokalen Socket-Adresse"
++
++#: ../../src/slave/kprop.c:339
++msgid "while converting local address"
++msgstr "beim Umwandeln der lokalen Socket-Adresse"
++
++#: ../../src/slave/kprop.c:362
++msgid "in krb5_auth_con_setaddrs"
++msgstr "in »krb5_auth_con_setaddrs«"
++
++#: ../../src/slave/kprop.c:370
++msgid "while authenticating to server"
++msgstr "beim Authentifizieren am Server"
++
++#: ../../src/slave/kprop.c:374 ../../src/slave/kprop.c:573
++#: ../../src/slave/kpropd.c:1521
++#, c-format
++msgid "Generic remote error: %s\n"
++msgstr "allgemeiner ferner Fehler: %s\n"
++
++#: ../../src/slave/kprop.c:380 ../../src/slave/kprop.c:579
++msgid "signalled from server"
++msgstr "signalisiert vom Server"
++
++#: ../../src/slave/kprop.c:382 ../../src/slave/kprop.c:581
++#, c-format
++msgid "Error text from server: %s\n"
++msgstr "Fehlermeldung vom Server: %s\n"
++
++#: ../../src/slave/kprop.c:410
++#, c-format
++msgid "allocating database file name '%s'"
++msgstr "Datenbankdateiname »%s« wird reserviert"
++
++#: ../../src/slave/kprop.c:416
++#, c-format
++msgid "while trying to open %s"
++msgstr "beim Versuch, %s zu öffnen"
++
++#: ../../src/slave/kprop.c:423
++msgid "database locked"
++msgstr "Datenbank gesperrt"
++
++#: ../../src/slave/kprop.c:426 ../../src/slave/kpropd.c:525
++#, c-format
++msgid "while trying to lock '%s'"
++msgstr "beim Versuch, »%s« zu sperren"
++
++#: ../../src/slave/kprop.c:430 ../../src/slave/kprop.c:438
++#, c-format
++msgid "while trying to stat %s"
++msgstr "beim Versuch, »stat« für %s auszuführen"
++
++#: ../../src/slave/kprop.c:434
++msgid "while trying to malloc data_ok_fn"
++msgstr "beim Versuch, Speicher für »data_ok_fn« zu reservieren"
++
++#: ../../src/slave/kprop.c:443
++#, c-format
++msgid "'%s' more recent than '%s'."
++msgstr "»%s« ist aktueller als »%s«."
++
++#: ../../src/slave/kprop.c:459
++#, c-format
++msgid "while unlocking database '%s'"
++msgstr "beim Entsperren von Datenbank »%s«"
++
++#: ../../src/slave/kprop.c:492 ../../src/slave/kprop.c:493
++msgid "while encoding database size"
++msgstr "beim Aufbereiten der Datenbankgröße"
++
++#: ../../src/slave/kprop.c:501
++msgid "while sending database size"
++msgstr "beim Senden der Datenbankgröße"
++
++#: ../../src/slave/kprop.c:511
++msgid "while allocating i_vector"
++msgstr "beim Reservieren von »i_vector«"
++
++#: ../../src/slave/kprop.c:534
++#, c-format
++msgid "while sending database block starting at %d"
++msgstr "beim Senden des Datenbankblocks, der bei %d beginnt"
++
++#: ../../src/slave/kprop.c:544
++msgid "Premature EOF found for database file!"
++msgstr "vorzeitiges EOF für Datenbankdatei gefunden!"
++
++#: ../../src/slave/kprop.c:557
++msgid "while reading response from server"
++msgstr "beim Lesen der Antwort vom Servers"
++
++#: ../../src/slave/kprop.c:568
++msgid "while decoding error response from server"
++msgstr "beim Aufschlüsseln der Fehlerantwort vom Server"
++
++#: ../../src/slave/kprop.c:599
++#, c-format
++msgid "Kpropd sent database size %d, expecting %d"
++msgstr "Kpropd sendet Datenbankgröße %d, erwartet wurde %d"
++
++#: ../../src/slave/kprop.c:643
++msgid "while allocating filename for update_last_prop_file"
++msgstr "beim Reservieren des Dateinamens für »update_last_prop_file«"
++
++#: ../../src/slave/kprop.c:648
++#, c-format
++msgid "while creating 'last_prop' file, '%s'"
++msgstr "beim Erstellen der Datei »last_prop«, »%s«"
++
++#: ../../src/slave/kpropd.c:170
++#, c-format
++msgid ""
++"\n"
++"Usage: %s [-r realm] [-s srvtab] [-dS] [-f slave_file]\n"
++msgstr ""
++"\n"
++"Aufruf: %s [-r Realm] [-s Dienstschlüsseltabelle] [-dS] [-f "
++"untergeordnete_Datei]\n"
++
++#: ../../src/slave/kpropd.c:172
++#, c-format
++msgid "\t[-F kerberos_db_file ] [-p kdb5_util_pathname]\n"
++msgstr "\t[-F Kerberos-Datenbankdatei ] [-p KDB5-Hilfswerkzeugpfadname]\n"
++
++#: ../../src/slave/kpropd.c:173
++#, c-format
++msgid "\t[-x db_args]* [-P port] [-a acl_file]\n"
++msgstr "\t[-x Datenbankargumente]* [-P Port] [-a ACL-Datei]\n"
++
++#: ../../src/slave/kpropd.c:174
++#, c-format
++msgid "\t[-A admin_server]\n"
++msgstr "\t[-A Serveradministrator]\n"
++
++#: ../../src/slave/kpropd.c:215
++#, c-format
++msgid "Killing fullprop child (%d)\n"
++msgstr "Beenden des Fullprop-Kindprozesses (%d) wird erzwungen\n"
++
++#: ../../src/slave/kpropd.c:244
++msgid "while checking if stdin is a socket"
++msgstr "beim Prüfen, ob die Standardeingabe ein Socket ist"
++
++#: ../../src/slave/kpropd.c:262
++#, c-format
++msgid "ready\n"
++msgstr "bereit\n"
++
++#: ../../src/slave/kpropd.c:272
++#, c-format
++msgid "Could not open /dev/null: %s"
++msgstr "/dev/null konnte nicht geöffnet werden: %s"
++
++#: ../../src/slave/kpropd.c:279
++#, c-format
++msgid "Could not dup the inetd socket: %s"
++msgstr "Das Inetd-Socket konnte nicht dupliziert werden: %s"
++
++#: ../../src/slave/kpropd.c:314 ../../src/slave/kpropd.c:327
++msgid "do_iprop failed.\n"
++msgstr "»do_iprop« fehlgeschlagen\n"
++
++#: ../../src/slave/kpropd.c:366
++#, c-format
++msgid "getaddrinfo: %s\n"
++msgstr "getaddrinfo: %s\n"
++
++#: ../../src/slave/kpropd.c:372
++msgid "while obtaining socket"
++msgstr "beim Erlangen des Sockets"
++
++#: ../../src/slave/kpropd.c:378
++msgid "while setting SO_REUSEADDR option"
++msgstr "beim Setzen der Option SO_REUSEADDR"
++
++#: ../../src/slave/kpropd.c:386
++msgid "while unsetting IPV6_V6ONLY option"
++msgstr "beim Entfernen der Option IPV6_V6ONLY"
++
++#: ../../src/slave/kpropd.c:391
++msgid "while binding listener socket"
++msgstr "beim Anbinden an das auf Verbindung wartende Socket"
++
++#: ../../src/slave/kpropd.c:402
++#, c-format
++msgid "waiting for a kprop connection\n"
++msgstr "warten auf Kprop-Verbindung\n"
++
++#: ../../src/slave/kpropd.c:408
++msgid "while accepting connection"
++msgstr "beim Akzeptieren der Verbindung"
++
++#: ../../src/slave/kpropd.c:414
++msgid "while forking"
++msgstr "beim Erzeugen eines Kindprozesses"
++
++#: ../../src/slave/kpropd.c:429
++#, c-format
++msgid "waitpid() failed to wait for doit() (%d %s)\n"
++msgstr "waitpid() schlug beim Warten auf doit() fehl (%d %s)\n"
++
++#: ../../src/slave/kpropd.c:433
++msgid "while waiting to receive database"
++msgstr "beim Warten auf den Erhalt der Datenbank"
++
++#: ../../src/slave/kpropd.c:437
++#, c-format
++msgid "Database load process for full propagation completed.\n"
++msgstr ""
++"Der Datenbankladeprozess für eine vollständige Verbreitung ist "
++"abgeschlossen.\n"
++
++#: ../../src/slave/kpropd.c:471
++#, c-format
++msgid ""
++"%s: Standard input does not appear to be a network socket.\n"
++"\t(Not run from inetd, and missing the -S option?)\n"
++msgstr ""
++"%s: Bei der Standardeingabe scheint es sich nicht um ein Netzwerk-Socket zu\n"
++"\thandeln (läuft nicht aus Inetd und die Option -S fehlt?).\n"
++
++#: ../../src/slave/kpropd.c:485
++msgid "while attempting setsockopt (SO_KEEPALIVE)"
++msgstr "beim Versuch, »setsockopt« auszuführen (SO_KEEPALIVE)"
++
++#: ../../src/slave/kpropd.c:490
++#, c-format
++msgid "Connection from %s"
++msgstr "Verbindung von %s"
++
++#: ../../src/slave/kpropd.c:510
++#, c-format
++msgid "Rejected connection from unauthorized principal %s\n"
++msgstr "Zurückgewiesene Verbindung von nicht autorisiertem Principal %s\n"
++
++#: ../../src/slave/kpropd.c:514
++#, c-format
++msgid "Rejected connection from unauthorized principal %s"
++msgstr "Zurückgewiesene Verbindung von nicht authorisiertem Principal %s"
++
++#: ../../src/slave/kpropd.c:531
++#, c-format
++msgid "while opening database file, '%s'"
++msgstr "beim Öffnen der Datenbankdatei, »%s«"
++
++#: ../../src/slave/kpropd.c:537
++#, c-format
++msgid "while renaming %s to %s"
++msgstr "beim Umbenennen von %s in %s"
++
++#: ../../src/slave/kpropd.c:543
++#, c-format
++msgid "while downgrading lock on '%s'"
++msgstr "beim Downgrade der Sperre auf »%s«"
++
++#: ../../src/slave/kpropd.c:550
++#, c-format
++msgid "while unlocking '%s'"
++msgstr "beim Aufheben der Sperre »%s«"
++
++#: ../../src/slave/kpropd.c:562
++msgid "while sending # of received bytes"
++msgstr "beim Senden n empfangener Byte"
++
++#: ../../src/slave/kpropd.c:568
++msgid "while trying to close database file"
++msgstr "beim Versuch, die Datenbankdatei zu schließen"
++
++#: ../../src/slave/kpropd.c:624
++#, c-format
++msgid "Incremental propagation enabled\n"
++msgstr "inkrementelle Verbreitung aktiviert\n"
++
++#: ../../src/slave/kpropd.c:634
++msgid "Unable to get default realm"
++msgstr "Standard-Realm kann nicht geholt werden"
++
++#: ../../src/slave/kpropd.c:647
++#, c-format
++msgid "%s: unable to get kiprop host based service name for realm %s\n"
++msgstr ""
++"%s: Kiprop-rechnerbasierter Dienstname für Realm %s kann nicht geholt "
++"werden\n"
++
++#: ../../src/slave/kpropd.c:658
++msgid "while trying to construct host service principal"
++msgstr "beim Versuch, den Rechnerdienst-Principal zu erstellen"
++
++#: ../../src/slave/kpropd.c:672
++msgid "while determining local service principal name"
++msgstr "beim Bestimmen des lokalen Dienst-Principal-Namens"
++
++#: ../../src/slave/kpropd.c:692
++#, c-format
++msgid "Initializing kadm5 as client %s\n"
++msgstr "Kadm5 wird als Client %s initialisiert\n"
++
++#: ../../src/slave/kpropd.c:706
++#, c-format
++msgid "kadm5 initialization failed!\n"
++msgstr "Initialisierung von Kadm5 fehlgeschlagen!\n"
++
++#: ../../src/slave/kpropd.c:715
++msgid "while attempting to connect to master KDC ... retrying"
++msgstr ""
++"beim Versuch, eine Verbindung zum Master-KDC aufzubauen … wird erneut "
++"versucht"
++
++#: ../../src/slave/kpropd.c:719
++#, c-format
++msgid "Sleeping %d seconds to re-initialize kadm5 (RPC ERROR)\n"
++msgstr ""
++"Um Kadm5 neu zu initialisieren, wird %d Sekunden gewartet (RPC-FEHLER).\n"
++
++#: ../../src/slave/kpropd.c:735
++#, c-format
++msgid "while initializing %s interface, retrying"
++msgstr "beim Initialisieren der Schnittstelle %s, wird erneut versucht"
++
++#: ../../src/slave/kpropd.c:739
++#, c-format
++msgid "Sleeping %d seconds to re-initialize kadm5 (krb5kdc not running?)\n"
++msgstr ""
++"Um Kadm5 neu zu initialisieren, wird %d Sekunden gewartet (läuft Krb5kdc "
++"nicht?).\n"
++
++#: ../../src/slave/kpropd.c:749
++#, c-format
++msgid "kadm5 initialization succeeded\n"
++msgstr "Initialisieren von Kadm5 erfolgreich\n"
++
++#: ../../src/slave/kpropd.c:771
++msgid "reading update log header"
++msgstr "Aktualisierungsprotokollkopfzeilen werden gelesen"
++
++#: ../../src/slave/kpropd.c:782
++#, c-format
++msgid "Calling iprop_get_updates_1 (sno=%u sec=%u usec=%u)\n"
++msgstr "»iprop_get_updates_1()« wird aufgerufen (sno=%u sec=%u usec=%u)\n"
++
++#: ../../src/slave/kpropd.c:792
++msgid "iprop_get_updates call failed"
++msgstr "Aufruf von »iprop_get_updates« fehlgeschlagen"
++
++#: ../../src/slave/kpropd.c:798
++#, c-format
++msgid "Reinitializing iprop because get updates failed\n"
++msgstr ""
++"Iprop wird neu initialisiert, da Aktualisierungen fehlgeschlagen sind\n"
++
++#: ../../src/slave/kpropd.c:819
++#, c-format
++msgid "Still waiting for full resync\n"
++msgstr ""
++"Es wird immer noch auf das vollständige erneute Synchronisieren gewartet.\n"
++
++#: ../../src/slave/kpropd.c:824
++#, c-format
++msgid "Full resync needed\n"
++msgstr "erneutes vollständiges Synchronisieren erforderlich\n"
++
++#: ../../src/slave/kpropd.c:825
++msgid "kpropd: Full resync needed."
++msgstr "Kpropd: erneutes vollständiges Synchronisieren erforderlich"
++
++#: ../../src/slave/kpropd.c:830
++msgid "iprop_full_resync call failed"
++msgstr "Aufruf von »iprop_full_resync« fehlgeschlagen"
++
++#: ../../src/slave/kpropd.c:841
++#, c-format
++msgid "Full resync request granted\n"
++msgstr "Anfrage nach vollständigem erneuten Synchronisieren genehmigt\n"
++
++#: ../../src/slave/kpropd.c:842
++msgid "Full resync request granted."
++msgstr "Anfrage nach vollständigem erneuten Synchronisieren genehmigt"
++
++# FIXME s/backoff/back-off/
++#: ../../src/slave/kpropd.c:851
++#, c-format
++msgid "Exponential backoff\n"
++msgstr "exponentieller Wartezyklus\n"
++
++#: ../../src/slave/kpropd.c:857
++#, c-format
++msgid "Full resync permission denied\n"
++msgstr "vollständiges erneutes Synchronisieren nicht gestattet\n"
++
++#: ../../src/slave/kpropd.c:858
++msgid "Full resync, permission denied."
++msgstr "vollständiges erneutes Synchronisieren, nicht gestattet"
++
++#: ../../src/slave/kpropd.c:863
++#, c-format
++msgid "Full resync error from master\n"
++msgstr "Fehler beim vollständigen erneuten Synchronisieren vom Master\n"
++
++#: ../../src/slave/kpropd.c:864
++msgid " Full resync, error returned from master KDC."
++msgstr ""
++"vollständiges erneutes Synchronisieren, das Master-KDC gab einen Fehler "
++"zurück"
++
++#: ../../src/slave/kpropd.c:872
++#, c-format
++msgid "Full resync invalid result from master\n"
++msgstr ""
++"Beim vollständigen erneuten Synchronisieren gab der Master ein ungültiges "
++"Ergebnis zurück.\n"
++
++#: ../../src/slave/kpropd.c:874
++msgid "Full resync, invalid return from master KDC."
++msgstr ""
++"vollständiges erneutes Synchronisieren, ungültiger Rückgabewert vom Master-"
++"KDC"
++
++#: ../../src/slave/kpropd.c:890
++#, c-format
++msgid "Got incremental updates (sno=%u sec=%u usec=%u)\n"
++msgstr ""
++"inkrementelle Aktualisierungen erhalten (sno=%u sec=%u usec=%u)\n"
++
++#: ../../src/slave/kpropd.c:902
++#, c-format
++msgid "ulog_replay failed (%s), updates not registered\n"
++msgstr ""
++"»ulog_replay« fehlgeschlagen (%s), Aktualisierungen nicht registriert\n"
++
++#: ../../src/slave/kpropd.c:905
++#, c-format
++msgid "ulog_replay failed (%s), updates not registered."
++msgstr "»ulog_replay« fehlgeschlagen (%s), Aktualisierungen nicht registriert"
++
++#: ../../src/slave/kpropd.c:914
++#, c-format
++msgid "Incremental updates: %d updates / %lu us"
++msgstr "inkrementelle Aktualisierungen: %d Aktualisierungen / %lu us"
++
++#: ../../src/slave/kpropd.c:917
++#, c-format
++msgid "Incremental updates: %d updates / %lu us\n"
++msgstr "inkrementelle Aktualisierungen: %d Aktualisierungen / %lu us\n"
++
++#: ../../src/slave/kpropd.c:925
++#, c-format
++msgid "get_updates permission denied\n"
++msgstr "Zugriff bei »get_updates« verweigert\n"
++
++#: ../../src/slave/kpropd.c:926
++msgid "get_updates, permission denied."
++msgstr "»get_updates«, Zugriff verweigert"
++
++#: ../../src/slave/kpropd.c:931
++#, c-format
++msgid "get_updates error from master\n"
++msgstr "»get_updates«-Fehler vom Master\n"
++
++#: ../../src/slave/kpropd.c:932
++msgid "get_updates, error returned from master KDC."
++msgstr "Vom Master-KDC wurde ein »get_updates«-Fehler zurückgegeben."
++
++# FIXME s/backoff/back-off/
++#: ../../src/slave/kpropd.c:940
++#, c-format
++msgid "get_updates master busy; backoff\n"
++msgstr "»get_updates«-Master ausgelastet; hält sich zurück\n"
++
++#: ../../src/slave/kpropd.c:949
++#, c-format
++msgid "KDC is synchronized with master.\n"
++msgstr "KDC wurde mit dem Master synchronisiert.\n"
++
++#: ../../src/slave/kpropd.c:957
++#, c-format
++msgid "get_updates invalid result from master\n"
++msgstr "ungültiges »get_updates«-Ergebnis vom Master\n"
++
++#: ../../src/slave/kpropd.c:958
++msgid "get_updates, invalid return from master KDC."
++msgstr "»get_updates«, ungültiger Rückgabewert vom Master-KDC"
++
++# FIXME s/backoff/back-off/
++#: ../../src/slave/kpropd.c:973
++#, c-format
++msgid "Busy signal received from master, backoff for %d secs\n"
++msgstr ""
++"Vom Master wurde ein Signal empfangen, dass er ausgelastet ist, "
++"Zurückhaltung für %d Sekunden\n"
++
++#: ../../src/slave/kpropd.c:980
++#, c-format
++msgid "Waiting for %d seconds before checking for updates again\n"
++msgstr ""
++"vor der erneuten Prufung auf Aktualisierungen wird %d Sekunden gewartet\n"
++
++#: ../../src/slave/kpropd.c:991
++#, c-format
++msgid "ERROR returned by master, bailing\n"
++msgstr "FEHLER vom Master zurückgegeben, Ausstieg\n"
++
++#: ../../src/slave/kpropd.c:992
++msgid "ERROR returned by master KDC, bailing.\n"
++msgstr "FEHLER vom Master-KDC zurückgegeben, Ausstieg\n"
++
++#: ../../src/slave/kpropd.c:1134
++msgid "copying db args"
++msgstr "Datenbankargumente werden kopiert"
++
++#: ../../src/slave/kpropd.c:1161
++msgid "while trying to construct my service name"
++msgstr "beim Versuch, meinen Dienstnamen zu erstellen"
++
++#: ../../src/slave/kpropd.c:1167
++msgid "while constructing my service realm"
++msgstr "beim Erstellen meines Dienst-Realms"
++
++#: ../../src/slave/kpropd.c:1175
++msgid "while allocating filename for temp file"
++msgstr "beim Reservieren des Dateinamens für die temporäre Datei"
++
++#: ../../src/slave/kpropd.c:1181
++msgid "while initializing"
++msgstr "bei der Initialisierung"
++
++#: ../../src/slave/kpropd.c:1189
++msgid "Unable to map log!\n"
++msgstr "Protokoll kann nicht abgebildet werden!\n"
++
++#: ../../src/slave/kpropd.c:1235
++#, c-format
++msgid "Error in krb5_auth_con_ini: %s"
++msgstr "Fehler in »krb5_auth_con_ini«: %s"
++
++#: ../../src/slave/kpropd.c:1243
++#, c-format
++msgid "Error in krb5_auth_con_setflags: %s"
++msgstr "Fehler in »krb5_auth_con_setflags«: %s"
++
++#: ../../src/slave/kpropd.c:1251
++#, c-format
++msgid "Error in krb5_auth_con_setaddrs: %s"
++msgstr "Fehler in »krb5_auth_con_setaddrs«: %s"
++
++#: ../../src/slave/kpropd.c:1259
++#, c-format
++msgid "Error in krb5_kt_resolve: %s"
++msgstr "Fehler in »krb5_kt_resolve«: %s"
++
++#: ../../src/slave/kpropd.c:1268
++#, c-format
++msgid "Error in krb5_recvauth: %s"
++msgstr "Fehler in »krb5_recvauth«: %s"
++
++#: ../../src/slave/kpropd.c:1275
++#, c-format
++msgid "Error in krb5_copy_prinicpal: %s"
++msgstr "Fehler in »krb5_copy_prinicpal«: %s"
++
++#: ../../src/slave/kpropd.c:1291
++msgid "while unparsing ticket etype"
++msgstr "beim Rückgängigmachen der Auswertung des »etype«s des Tickets"
++
++#: ../../src/slave/kpropd.c:1295
++#, c-format
++msgid "authenticated client: %s (etype == %s)\n"
++msgstr "Authentifizierter Client: %s (etype == %s)\n"
++
++#: ../../src/slave/kpropd.c:1374
++msgid "while reading size of database from client"
++msgstr "beim Lesen der Datenbankgröße vom Client"
++
++#: ../../src/slave/kpropd.c:1384
++msgid "while decoding database size from client"
++msgstr "beim Dekodieren der Datenbankgröße vom Client"
++
++#: ../../src/slave/kpropd.c:1397
++msgid "while initializing i_vector"
++msgstr "beim Initialisieren von »i_vector«"
++
++#: ../../src/slave/kpropd.c:1402
++#, c-format
++msgid "Full propagation transfer started.\n"
++msgstr "vollständige Verbreitungsübertragung gestartet\n"
++
++#: ../../src/slave/kpropd.c:1455
++#, c-format
++msgid "Full propagation transfer finished.\n"
++msgstr "vollständige Verbreitungsübertragung beendet\n"
++
++#: ../../src/slave/kpropd.c:1516
++msgid "while decoding error packet from client"
++msgstr "beim Dekodieren des Fehlerpakets vom Client"
++
++#: ../../src/slave/kpropd.c:1525
++msgid "signaled from server"
++msgstr "signalisiert vom Server"
++
++#: ../../src/slave/kpropd.c:1527
++#, c-format
++msgid "Error text from client: %s\n"
++msgstr "Fehlermeldung vom Client: %s\n"
++
++#: ../../src/slave/kpropd.c:1576
++#, c-format
++msgid "while trying to fork %s"
++msgstr "beim Versuch, einen Kindprozess von %s zu erzeugen"
++
++#: ../../src/slave/kpropd.c:1580
++#, c-format
++msgid "while trying to exec %s"
++msgstr "beim Versuch, %s auszuführen"
++
++#: ../../src/slave/kpropd.c:1587
++#, c-format
++msgid "while waiting for %s"
++msgstr "beim Warten auf %s"
++
++#: ../../src/slave/kpropd.c:1593
++#, c-format
++msgid "%s load terminated"
++msgstr "Laden von %s beendet"
++
++#: ../../src/slave/kpropd.c:1599
++#, c-format
++msgid "%s returned a bad exit status (%d)"
++msgstr "%s gab einen falschen Exit-Status (%d) zurück"
++
++#: ../../src/slave/kproplog.c:27
++#, c-format
++msgid ""
++"\n"
++"Usage: %s [-h] [-v] [-v] [-e num]\n"
++"\t%s -R\n"
++"\n"
++msgstr ""
++"\n"
++"Aufruf: %s [-h] [-v] [-v] [-e Zahl]\n"
++"\t%s -R\n"
++"\n"
++
++#: ../../src/slave/kproplog.c:129
++#, c-format
++msgid ""
++"\n"
++"Couldn't allocate memory"
++msgstr ""
++"\n"
++"Speicher konnte nicht reserviert werden"
++
++#: ../../src/slave/kproplog.c:223
++#, c-format
++msgid "\t\tAttribute flags\n"
++msgstr "\t\tAttributschalter\n"
++
++#: ../../src/slave/kproplog.c:228
++#, c-format
++msgid "\t\tMaximum ticket life\n"
++msgstr "\t\tmaximale Ticketlebensdauer\n"
++
++#: ../../src/slave/kproplog.c:233
++#, c-format
++msgid "\t\tMaximum renewable life\n"
++msgstr "\t\tmaximale verlängerbare Lebensdauer\n"
++
++#: ../../src/slave/kproplog.c:238
++#, c-format
++msgid "\t\tPrincipal expiration\n"
++msgstr "\t\tAblauf des Principals\n"
++
++#: ../../src/slave/kproplog.c:243
++#, c-format
++msgid "\t\tPassword expiration\n"
++msgstr "\t\tAblauf des Passworts\n"
++
++#: ../../src/slave/kproplog.c:248
++#, c-format
++msgid "\t\tLast successful auth\n"
++msgstr "\t\tletzte erfolgreiche Authentifizierung\n"
++
++#: ../../src/slave/kproplog.c:253
++#, c-format
++msgid "\t\tLast failed auth\n"
++msgstr "\t\tletzte fehlgeschlagene Authentifizierung\n"
++
++#: ../../src/slave/kproplog.c:258
++#, c-format
++msgid "\t\tFailed passwd attempt\n"
++msgstr "\t\tfehlgeschlagener Passwortversuch\n"
++
++#: ../../src/slave/kproplog.c:263
++#, c-format
++msgid "\t\tPrincipal\n"
++msgstr "\t\tPrincipal\n"
++
++#: ../../src/slave/kproplog.c:268
++#, c-format
++msgid "\t\tKey data\n"
++msgstr "\t\tSchlüsseldaten\n"
++
++#: ../../src/slave/kproplog.c:275
++#, c-format
++msgid "\t\tTL data\n"
++msgstr "\t\tTL-Daten\n"
++
++#: ../../src/slave/kproplog.c:282
++#, c-format
++msgid "\t\tLength\n"
++msgstr "\t\tLänge\n"
++
++#: ../../src/slave/kproplog.c:287
++#, c-format
++msgid "\t\tPassword last changed\n"
++msgstr "\t\tletzte Passwortänderung\n"
++
++#: ../../src/slave/kproplog.c:292
++#, c-format
++msgid "\t\tModifying principal\n"
++msgstr "\t\ttPrincipal wird geändert\n"
++
++#: ../../src/slave/kproplog.c:297
++#, c-format
++msgid "\t\tModification time\n"
++msgstr "\t\tÄnderungszeit\n"
++
++#: ../../src/slave/kproplog.c:302
++#, c-format
++msgid "\t\tModified where\n"
++msgstr "\t\tGeändert wobei\n"
++
++#: ../../src/slave/kproplog.c:307
++#, c-format
++msgid "\t\tPassword policy\n"
++msgstr "\t\tPasswortrichtlinie\n"
++
++#: ../../src/slave/kproplog.c:312
++#, c-format
++msgid "\t\tPassword policy switch\n"
++msgstr "\t\tPasswortrichtlinienumschalter\n"
++
++#: ../../src/slave/kproplog.c:317
++#, c-format
++msgid "\t\tPassword history KVNO\n"
++msgstr "\t\tPasswortchronik KVNO\n"
++
++#: ../../src/slave/kproplog.c:322
++#, c-format
++msgid "\t\tPassword history\n"
++msgstr "\t\tPasswortchronik\n"
++
++#: ../../src/slave/kproplog.c:356
++#, c-format
++msgid ""
++"Corrupt update entry\n"
++"\n"
++msgstr ""
++"beschädigter Aktualisierungseintrag\n"
++"\n"
++
++#: ../../src/slave/kproplog.c:364
++#, c-format
++msgid ""
++"Entry data decode failure\n"
++"\n"
++msgstr ""
++"Dekodieren der eingetragenen Daten fehlgeschlagen\n"
++"\n"
++
++#: ../../src/slave/kproplog.c:369
++#, c-format
++msgid "Update Entry\n"
++msgstr "Aktualisierungseintrag\n"
++
++#: ../../src/slave/kproplog.c:371
++#, c-format
++msgid "\tUpdate serial # : %u\n"
++msgstr "\tAktualisierung der Seriennummer: %u\n"
++
++#: ../../src/slave/kproplog.c:373
++#, c-format
++msgid "\tUpdate operation : "
++msgstr "\tAktualisierungsaktion: "
++
++#: ../../src/slave/kproplog.c:375
++#, c-format
++msgid "Delete\n"
++msgstr "Löschen\n"
++
++#: ../../src/slave/kproplog.c:377
++#, c-format
++msgid "Add\n"
++msgstr "Hinzufügen\n"
++
++#: ../../src/slave/kproplog.c:381
++#, c-format
++msgid ""
++"Could not allocate principal name\n"
++"\n"
++msgstr ""
++"Der Principal-Name konnte nicht reserviert werden.\n"
++"\n"
++
++#: ../../src/slave/kproplog.c:387
++#, c-format
++msgid "\tUpdate principal : %s\n"
++msgstr "\tAktualisierung des Principals: %s\n"
++
++#: ../../src/slave/kproplog.c:389
++#, c-format
++msgid "\tUpdate size : %u\n"
++msgstr "\tGröße der Aktualisierung: %u\n"
++
++#: ../../src/slave/kproplog.c:390
++#, c-format
++msgid "\tUpdate committed : %s\n"
++msgstr "\tAktualisierung übergeben: %s\n"
++
++#: ../../src/slave/kproplog.c:394
++#, c-format
++msgid "\tUpdate time stamp : None\n"
++msgstr "\tZeitstempel der Aktualisierung: keiner\n"
++
++#: ../../src/slave/kproplog.c:396
++#, c-format
++msgid "\tUpdate time stamp : %s"
++msgstr "\tZeitstempel der Aktualisierung: %s"
++
++#: ../../src/slave/kproplog.c:400
++#, c-format
++msgid "\tAttributes changed : %d\n"
++msgstr "\tgeänderte Attribute: %d\n"
++
++#: ../../src/slave/kproplog.c:465
++#, c-format
++msgid ""
++"Unable to initialize Kerberos\n"
++"\n"
++msgstr ""
++"Kerberos kann nicht initialisiert werden\n"
++"\n"
++
++#: ../../src/slave/kproplog.c:472
++#, c-format
++msgid ""
++"Couldn't read database_name\n"
++"\n"
++msgstr ""
++"»database_name« kann nicht gelesen werden\n"
++"\n"
++
++#: ../../src/slave/kproplog.c:476
++#, c-format
++msgid ""
++"\n"
++"Kerberos update log (%s)\n"
++msgstr ""
++"\n"
++"Kerberos-Aktualisierungsprotokoll (%s)\n"
++
++#: ../../src/slave/kproplog.c:480 ../../src/slave/kproplog.c:495
++#, c-format
++msgid ""
++"Unable to map log file %s\n"
++"\n"
++msgstr ""
++"Protokolldatei %s kann nicht abgebildet werden\n"
++"\n"
++
++#: ../../src/slave/kproplog.c:485
++#, c-format
++msgid ""
++"Couldn't reinitialize ulog file %s\n"
++"\n"
++msgstr ""
++"Ulog-Datei %s konnte nicht neu initialisiert werden\n"
++"\n"
++
++#: ../../src/slave/kproplog.c:489
++#, c-format
++msgid "Reinitialized the ulog.\n"
++msgstr "Das Ulog wurde neu initialisiert.\n"
++
++#: ../../src/slave/kproplog.c:501
++#, c-format
++msgid ""
++"Corrupt header log, exiting\n"
++"\n"
++msgstr ""
++"beschädigtes Kopfzeilenprotokoll, wird beendet\n"
++"\n"
++
++#: ../../src/slave/kproplog.c:505
++#, c-format
++msgid "Update log dump :\n"
++msgstr "Aktualisierungsprotokollauszug :\n"
++
++#: ../../src/slave/kproplog.c:506
++#, c-format
++msgid "\tLog version # : %u\n"
++msgstr "\tProtokollversion #:  %u\n"
++
++#: ../../src/slave/kproplog.c:507
++#, c-format
++msgid "\tLog state : "
++msgstr "\tProtokollstatus: "
++
++#: ../../src/slave/kproplog.c:510
++#, c-format
++msgid "Stable\n"
++msgstr "stabil\n"
++
++#: ../../src/slave/kproplog.c:513
++#, c-format
++msgid "Unstable\n"
++msgstr "instabil\n"
++
++#: ../../src/slave/kproplog.c:516
++#, c-format
++msgid "Corrupt\n"
++msgstr "beschädigt\n"
++
++#: ../../src/slave/kproplog.c:519
++#, c-format
++msgid "Unknown state: %d\n"
++msgstr "unbekannter Status: %d\n"
++
++#: ../../src/slave/kproplog.c:522
++#, c-format
++msgid "\tEntry block size : %u\n"
++msgstr "\tBlockgrößeneintrag: %u\n"
++
++#: ../../src/slave/kproplog.c:523
++#, c-format
++msgid "\tNumber of entries : %u\n"
++msgstr "\tAnzahl der Einträge: %u\n"
++
++#: ../../src/slave/kproplog.c:526
++#, c-format
++msgid "\tLast serial # : None\n"
++msgstr "\tletzte Seriennummer: keine\n"
++
++#: ../../src/slave/kproplog.c:529
++#, c-format
++msgid "\tFirst serial # : None\n"
++msgstr "\terste Seriennummer: keine\n"
++
++#: ../../src/slave/kproplog.c:531
++#, c-format
++msgid "\tFirst serial # : "
++msgstr "\terste Seriennummer: "
++
++#: ../../src/slave/kproplog.c:535
++#, c-format
++msgid "\tLast serial # : "
++msgstr "\tletzte Seriennummer: "
++
++#: ../../src/slave/kproplog.c:540
++#, c-format
++msgid "\tLast time stamp : None\n"
++msgstr "\tletzter Zeitstempel: keiner\n"
++
++#: ../../src/slave/kproplog.c:543
++#, c-format
++msgid "\tFirst time stamp : None\n"
++msgstr "\terster Zeitstempel: keiner\n"
++
++#: ../../src/slave/kproplog.c:545
++#, c-format
++msgid "\tFirst time stamp : %s"
++msgstr "\terster Zeitstempel: %s"
++
++#: ../../src/slave/kproplog.c:549
++#, c-format
++msgid "\tLast time stamp : %s\n"
++msgstr "\tletzter Zeitstempel: %s\n"
++
++#: ../../src/util/support/errors.c:77
++msgid "Kerberos library initialization failure"
++msgstr "Initialisieren der Kerberos-Bibliothek fehlgeschlagen"
++
++#: ../../src/util/support/errors.c:93
++#, c-format
++msgid "error %ld"
++msgstr "Fehler %ld"
++
++#: ../../src/util/support/plugins.c:186
++#, c-format
++msgid "unable to find plugin [%s]: %s"
++msgstr "Erweiterung [%s] konnte nicht gefunden werden: %s"
++
++#: ../../src/util/support/plugins.c:274
++msgid "unknown failure"
++msgstr "unbekannter Fehlschlag"
++
++#: ../../src/util/support/plugins.c:277
++#, c-format
++msgid "unable to load plugin [%s]: %s"
++msgstr "Erweiterung [%s] konnte nicht geladen werden: %s"
++
++#: ../../src/util/support/plugins.c:300
++#, c-format
++msgid "unable to load DLL [%s]"
++msgstr "DLL [%s] konnte nicht geladen werden"
++
++#: ../../src/util/support/plugins.c:316
++#, c-format
++msgid "plugin unavailable: %s"
++msgstr "Erweiterung nicht verfügbar: %s"
++
++#: ../lib/gssapi/generic/gssapi_err_generic.c:23
++msgid "No @ in SERVICE-NAME name string"
++msgstr "keine @ in der Namenszeichenkette SERVICE-NAME"
++
++#: ../lib/gssapi/generic/gssapi_err_generic.c:24
++msgid "STRING-UID-NAME contains nondigits"
++msgstr "STRING-UID-NAME enthält etwas anderes als Ziffern"
++
++#: ../lib/gssapi/generic/gssapi_err_generic.c:25
++msgid "UID does not resolve to username"
++msgstr "UID lässt sich nicht zu Benutzernamen ermitteln"
++
++#: ../lib/gssapi/generic/gssapi_err_generic.c:26
++msgid "Validation error"
++msgstr "Überprüfungsfehler"
++
++#: ../lib/gssapi/generic/gssapi_err_generic.c:27
++msgid "Couldn't allocate gss_buffer_t data"
++msgstr "»gss_buffer_t«-Daten konnten reserviert werden"
++
++#: ../lib/gssapi/generic/gssapi_err_generic.c:28
++msgid "Message context invalid"
++msgstr "Nachrichtenkontext ungültig"
++
++#: ../lib/gssapi/generic/gssapi_err_generic.c:29
++msgid "Buffer is the wrong size"
++msgstr "Puffer hat die falsche Größe"
++
++#: ../lib/gssapi/generic/gssapi_err_generic.c:30
++msgid "Credential usage type is unknown"
++msgstr "Typ des Anmeldedatenaufrufs ist unbekannt"
++
++#: ../lib/gssapi/generic/gssapi_err_generic.c:31
++msgid "Unknown quality of protection specified"
++msgstr "unbekannte Schutzqualität angegeben"
++
++#: ../lib/gssapi/generic/gssapi_err_generic.c:32
++msgid "Local host name could not be determined"
++msgstr "lokaler Rechnername konnte nicht bestimmt werden"
++
++#: ../lib/gssapi/generic/gssapi_err_generic.c:33
++msgid "Hostname in SERVICE-NAME string could not be canonicalized"
++msgstr ""
++"Rechnername in der Zeichenkette »SERVICE-NAME« konnte nicht in Normalform "
++"gebracht werden"
++
++#: ../lib/gssapi/generic/gssapi_err_generic.c:34
++msgid "Mechanism is incorrect"
++msgstr "Mechanismus ist nicht korrekt"
++
++#: ../lib/gssapi/generic/gssapi_err_generic.c:35
++msgid "Token header is malformed or corrupt"
++msgstr "Token-Kopfzeilen haben die falsche Form oder sind beschädigt"
++
++#: ../lib/gssapi/generic/gssapi_err_generic.c:36
++msgid "Packet was replayed in wrong direction"
++msgstr "Paket wurde in falscher Richtung erneut abgespielt"
++
++#: ../lib/gssapi/generic/gssapi_err_generic.c:37
++msgid "Token is missing data"
++msgstr "dem Token fehlen Daten"
++
++#: ../lib/gssapi/generic/gssapi_err_generic.c:38
++msgid "Token was reflected"
++msgstr "Token wurde zurückgeworfen"
++
++#: ../lib/gssapi/generic/gssapi_err_generic.c:39
++msgid "Received token ID does not match expected token ID"
++msgstr "Die empfangene Token-Kennung passt nicht zur erwarteten Token-Kennung."
++
++#: ../lib/gssapi/generic/gssapi_err_generic.c:40
++msgid "The given credential's usage does not match the requested usage"
++msgstr ""
++"Die Verwendung der angegebenen Anmeldedaten passt nicht zur angeforderten "
++"Verwendung."
++
++#: ../lib/gssapi/generic/gssapi_err_generic.c:41
++msgid "Storing of acceptor credentials is not supported by the mechanism"
++msgstr ""
++"Das Speichern von Abnehmeranmeldedaten wird nicht durch den Mechanismus "
++"unterstützt."
++
++#: ../lib/gssapi/generic/gssapi_err_generic.c:42
++msgid "Storing of non-default credentials is not supported by the mechanism"
++msgstr ""
++"Das Speichern von Nichtstandardanmeldedaten wird nicht durch den Mechanismus "
++"unterstützt."
++
++#: ../lib/gssapi/krb5/gssapi_err_krb5.c:23
++msgid "Principal in credential cache does not match desired name"
++msgstr ""
++"Principal im Anmeldedatenzwischenspeicher entspricht nicht dem gewünschten "
++"Namen"
++
++#: ../lib/gssapi/krb5/gssapi_err_krb5.c:24
++msgid "No principal in keytab matches desired name"
++msgstr "Kein Principal in der Schlüsseltabelle passt zum gewünschten Namen."
++
++#: ../lib/gssapi/krb5/gssapi_err_krb5.c:25
++msgid "Credential cache has no TGT"
++msgstr "Anmeldedatenzwischenspeicher hat kein TGT"
++
++#: ../lib/gssapi/krb5/gssapi_err_krb5.c:26
++msgid "Authenticator has no subkey"
++msgstr "Schlüsselziffer hat keinen Unterschlüssel"
++
++#: ../lib/gssapi/krb5/gssapi_err_krb5.c:27
++msgid "Context is already fully established"
++msgstr "Kontext wurde bereits vollständig eingerichtet"
++
++#: ../lib/gssapi/krb5/gssapi_err_krb5.c:28
++msgid "Unknown signature type in token"
++msgstr "unbekannter Signaturtyp im Token"
++
++#: ../lib/gssapi/krb5/gssapi_err_krb5.c:29
++msgid "Invalid field length in token"
++msgstr "falsche Feldlänge im Token"
++
++#: ../lib/gssapi/krb5/gssapi_err_krb5.c:30
++msgid "Attempt to use incomplete security context"
++msgstr ""
++"Es wurde versucht, einen unvollständigen Sicherheitskontext zu verwenden."
++
++#: ../lib/gssapi/krb5/gssapi_err_krb5.c:31
++msgid "Bad magic number for krb5_gss_ctx_id_t"
++msgstr "falsche magische Zahl für »krb5_gss_ctx_id_t«"
++
++#: ../lib/gssapi/krb5/gssapi_err_krb5.c:32
++msgid "Bad magic number for krb5_gss_cred_id_t"
++msgstr "falsche magische Zahl für »krb5_gss_cred_id_t«"
++
++#: ../lib/gssapi/krb5/gssapi_err_krb5.c:33
++msgid "Bad magic number for krb5_gss_enc_desc"
++msgstr "falsche magische Zahl für »krb5_gss_enc_desc«"
++
++#: ../lib/gssapi/krb5/gssapi_err_krb5.c:34
++msgid "Sequence number in token is corrupt"
++msgstr "Sequnznummer im Token ist beschädigt"
++
++#: ../lib/gssapi/krb5/gssapi_err_krb5.c:35
++msgid "Credential cache is empty"
++msgstr "Anmeldedatenzwischenspeicher ist leer"
++
++#: ../lib/gssapi/krb5/gssapi_err_krb5.c:36
++msgid "Acceptor and Initiator share no checksum types"
++msgstr "Abnehmer und Initiator haben keinen gemeinsamen Prüfsummentyp"
++
++#: ../lib/gssapi/krb5/gssapi_err_krb5.c:37
++msgid "Requested lucid context version not supported"
++msgstr "angeforderte »lucid«-Kontextversion nicht unterstützt"
++
++# PRF = Pseudo Random Function
++#: ../lib/gssapi/krb5/gssapi_err_krb5.c:38
++msgid "PRF input too long"
++msgstr "PRF-Eingabe zu lang"
++
++#: ../lib/gssapi/krb5/gssapi_err_krb5.c:39
++msgid "Bad magic number for iakerb_ctx_id_t"
++msgstr "falsche magische Zahl für »iakerb_ctx_id_t«"
++
++#: ../lib/kadm5/chpass_util_strings.c:23
++msgid "while getting policy info."
++msgstr "beim Holen der Richtlinieninformation."
++
++#: ../lib/kadm5/chpass_util_strings.c:24
++msgid "while getting principal info."
++msgstr "beim Holen der Principal-Information."
++
++#: ../lib/kadm5/chpass_util_strings.c:25
++msgid "New passwords do not match - password not changed.\n"
++msgstr "neue Passwörter stimmen nicht überein – Passwort nicht geändert\n"
++
++#: ../lib/kadm5/chpass_util_strings.c:26
++msgid "New password"
++msgstr "neues Passwort"
++
++#: ../lib/kadm5/chpass_util_strings.c:27
++msgid "New password (again)"
++msgstr "neues Passwort (erneut)"
++
++#: ../lib/kadm5/chpass_util_strings.c:28
++msgid ""
++"You must type a password. Passwords must be at least one character long.\n"
++msgstr ""
++"Sie müssen ein Passwort eingeben. Passwörter müssen mindestens ein Zeichen "
++"lang sein.\n"
++
++#: ../lib/kadm5/chpass_util_strings.c:29
++msgid "yet no policy set!  Contact your system security administrator."
++msgstr ""
++"noch keine Richtlinie gesetzt! Kontaktieren Sie Ihren "
++"Systemsicherheitsadministrator"
++
++#: ../lib/kadm5/chpass_util_strings.c:31
++msgid ""
++"New password was found in a dictionary of possible passwords and\n"
++"therefore may be easily guessed. Please choose another password.\n"
++"See the kpasswd man page for help in choosing a good password."
++msgstr ""
++"Das neue Passwort wurde in einem Wörterbuch mit möglichen Passwörtern "
++"gefunden\n"
++"und kann daher leicht erraten werden. Bitte wählen Sie ein anderes "
++"Passwort.\n"
++"Hilfe bei der Wahl guter Passwörter finden Sie in der Handbuchseite von\n"
++"»kpasswd«."
++
++#: ../lib/kadm5/chpass_util_strings.c:32
++msgid "Password not changed."
++msgstr "Passwort nicht geändert"
++
++#: ../lib/kadm5/chpass_util_strings.c:33
++#, c-format
++msgid ""
++"New password is too short.\n"
++"Please choose a password which is at least %d characters long."
++msgstr ""
++"Das neue Passwort ist zu kurz.\n"
++"Bitte wählen Sie ein Passwort, das mindestens %d Zeichen lang ist."
++
++#: ../lib/kadm5/chpass_util_strings.c:34
++#, c-format
++msgid ""
++"New password does not have enough character classes.\n"
++"The character classes are:\n"
++"\t- lower-case letters,\n"
++"\t- upper-case letters,\n"
++"\t- digits,\n"
++"\t- punctuation, and\n"
++"\t- all other characters (e.g., control characters).\n"
++"Please choose a password with at least %d character classes."
++msgstr ""
++"Das neue Passwort besteht aus zu wenigen Zeichenklassen.\n"
++"Die Zeichenklassen sind:\n"
++"\t- Kleinbuchstaben,\n"
++"\t- Großbuchstaben,\n"
++"\t- Ziffern,\n"
++"\t- Satzzeichen und\n"
++"\t- alle anderen Zeichen (z.B. Steuerzeichen).\n"
++"Bitte wählen Sie ein Passwort mit mindestens %d Zeichenklassen."
++
++#: ../lib/kadm5/chpass_util_strings.c:35
++#, c-format
++msgid ""
++"Password cannot be changed because it was changed too recently.\n"
++"Please wait until %s before you change it.\n"
++"If you need to change your password before then, contact your system\n"
++"security administrator."
++msgstr ""
++"Das Passwort kann nicht geändert werden, da es erst vor kurzem geändert "
++"wurde.\n"
++"Bitte warten Sie bis %s, ehe Sie es ändern.\n"
++"Falls Sie es vorher ändern müssen, kontaktieren Sie Ihren\n"
++"Systemsicherheitsadministrator."
++
++#: ../lib/kadm5/chpass_util_strings.c:36
++msgid "New password was used previously. Please choose a different password."
++msgstr ""
++"Das neue Passwort wurde zuvor schon benutzt. Bitte wählen Sie ein anderes "
++"Passwort."
++
++#: ../lib/kadm5/chpass_util_strings.c:37
++msgid "while trying to change password."
++msgstr "beim Versuch, das Passwort zu ändern."
++
++#: ../lib/kadm5/chpass_util_strings.c:38
++msgid "while reading new password."
++msgstr "beim Lesen des neuen Passworts."
++
++#: ../lib/kadm5/kadm_err.c:23
++msgid "Operation failed for unspecified reason"
++msgstr "Aktion aus nicht näher beschriebenem Grund fehlgeschlagen"
++
++#: ../lib/kadm5/kadm_err.c:24
++msgid "Operation requires ``get'' privilege"
++msgstr "Aktion erfordert »get«-Recht"
++
++#: ../lib/kadm5/kadm_err.c:25
++msgid "Operation requires ``add'' privilege"
++msgstr "Aktion erfordert »add«-Recht"
++
++#: ../lib/kadm5/kadm_err.c:26
++msgid "Operation requires ``modify'' privilege"
++msgstr "Aktion erfordert »modify«-Recht"
++
++#: ../lib/kadm5/kadm_err.c:27
++msgid "Operation requires ``delete'' privilege"
++msgstr "Aktion erfordert »delete«-Recht"
++
++#: ../lib/kadm5/kadm_err.c:28
++msgid "Insufficient authorization for operation"
++msgstr "unzureichende Berechtigung für diese Aktion"
++
++#: ../lib/kadm5/kadm_err.c:29 ../lib/kdb/adb_err.c:29
++msgid "Database inconsistency detected"
++msgstr "Datenbankinkonsistenz entdeckt"
++
++#: ../lib/kadm5/kadm_err.c:30 ../lib/kdb/adb_err.c:24
++msgid "Principal or policy already exists"
++msgstr "Principal oder Richtlinie existiert bereits"
++
++#: ../lib/kadm5/kadm_err.c:31
++msgid "Communication failure with server"
++msgstr "Kommunikation mit dem Server fehlgeschlagen"
++
++#: ../lib/kadm5/kadm_err.c:32
++msgid "No administration server found for realm"
++msgstr "kein Administrationsserver für den Realm gefunden"
++
++#: ../lib/kadm5/kadm_err.c:33
++msgid "Password history principal key version mismatch"
++msgstr "Die Passwortchronikschlüssel des Principals passen nicht zusammen."
++
++#: ../lib/kadm5/kadm_err.c:34
++msgid "Connection to server not initialized"
++msgstr "Verbindung zum Server nicht initialisiert"
++
++#: ../lib/kadm5/kadm_err.c:35
++msgid "Principal does not exist"
++msgstr "Principal existiert nicht"
++
++#: ../lib/kadm5/kadm_err.c:36
++msgid "Policy does not exist"
++msgstr "Richtlinie existiert nicht"
++
++#: ../lib/kadm5/kadm_err.c:37
++msgid "Invalid field mask for operation"
++msgstr "ungültige Feldmaske für Aktion"
++
++#: ../lib/kadm5/kadm_err.c:38
++msgid "Invalid number of character classes"
++msgstr "ungültige Anzahl von Zeichenklassen"
++
++#: ../lib/kadm5/kadm_err.c:39
++msgid "Invalid password length"
++msgstr "ungültige Passwortlänge"
++
++#: ../lib/kadm5/kadm_err.c:40
++msgid "Illegal policy name"
++msgstr "unzulässiger Richtlinienname"
++
++#: ../lib/kadm5/kadm_err.c:41
++msgid "Illegal principal name"
++msgstr "unzulässiger Principal-Name"
++
++# FIXME s/auxillary/auxilary/
++#: ../lib/kadm5/kadm_err.c:42
++msgid "Invalid auxillary attributes"
++msgstr "ungültige Zusatzattribute"
++
++#: ../lib/kadm5/kadm_err.c:43
++msgid "Invalid password history count"
++msgstr "ungültige Passwortchronikanzahl"
++
++#: ../lib/kadm5/kadm_err.c:44
++msgid "Password minimum life is greater than password maximum life"
++msgstr "Die minimale Lebensdauer des Passworts ist größer als die maximale."
++
++#: ../lib/kadm5/kadm_err.c:45
++msgid "Password is too short"
++msgstr "Das Passwort ist zu kurz."
++
++#: ../lib/kadm5/kadm_err.c:46
++msgid "Password does not contain enough character classes"
++msgstr "Das Passwort enthält nicht genug Zeichenklassen."
++
++#: ../lib/kadm5/kadm_err.c:47
++msgid "Password is in the password dictionary"
++msgstr "Das Passwort steht im Passwortwörterbuch."
++
++#: ../lib/kadm5/kadm_err.c:48
++msgid "Cannot reuse password"
++msgstr "Das Passwort kann nicht erneut verwendet werden."
++
++#: ../lib/kadm5/kadm_err.c:49
++msgid "Current password's minimum life has not expired"
++msgstr "Die aktuell minimale Lebensdauer des Passworts ist nicht abgelaufen."
++
++#: ../lib/kadm5/kadm_err.c:50 ../lib/krb5/error_tables/kdb5_err.c:67
++msgid "Policy is in use"
++msgstr "Richtlinie ist in Benutzung"
++
++#: ../lib/kadm5/kadm_err.c:51
++msgid "Connection to server already initialized"
++msgstr "Verbindung zum Server ist bereits initialisiert"
++
++#: ../lib/kadm5/kadm_err.c:52
++msgid "Incorrect password"
++msgstr "falsches Passwort"
++
++#: ../lib/kadm5/kadm_err.c:53
++msgid "Cannot change protected principal"
++msgstr "geschützter Principal kann nicht geändert werden"
++
++#: ../lib/kadm5/kadm_err.c:54
++msgid "Programmer error! Bad Admin server handle"
++msgstr "Fehler des Programmierers! Falscher Admin-Server-Identifikator"
++
++#: ../lib/kadm5/kadm_err.c:55
++msgid "Programmer error! Bad API structure version"
++msgstr "Fehler des Programmierers! Falsche API-Strukturversion"
++
++#: ../lib/kadm5/kadm_err.c:56
++msgid ""
++"API structure version specified by application is no longer supported (to "
++"fix, recompile application against current KADM5 API header files and "
++"libraries)"
++msgstr ""
++"Die von der Anwendung angegebene Version der API-Struktur wird nicht länger "
++"unterstützt. (Kompilieren Sie die Anwendung mit den aktuellen KADM5-API-"
++"Header-Dateien und -Bibliotheken, um dies zu beheben.)"
++
++#: ../lib/kadm5/kadm_err.c:57
++msgid ""
++"API structure version specified by application is unknown to libraries (to "
++"fix, obtain current KADM5 API header files and libraries and recompile "
++"application)"
++msgstr ""
++"Die von der Anwendung angegebene Version der API-Struktur ist den "
++"Bibliotheken unbekannt. (Besorgen Sie sich die aktuellen KADM5-API-Header-"
++"Dateien und -Bibliotheken und kompilieren Sie die Anwendung neu, um dies zu "
++"beheben.)"
++
++#: ../lib/kadm5/kadm_err.c:58
++msgid "Programmer error! Bad API version"
++msgstr "Fehler des Programmierers! Falsche API-Version"
++
++#: ../lib/kadm5/kadm_err.c:59
++msgid ""
++"API version specified by application is no longer supported by libraries (to "
++"fix, update application to adhere to current API version and recompile)"
++msgstr ""
++"Die von der Anwendung angegebene Version der API-Struktur wird nicht länger "
++"von den Bibliotheken unterstützt. (Aktualisieren Sie die Anwendung, dass sie "
++"zu der aktuellen API-Version passt, und kompilieren Sie sie, um dies zu "
++"beheben.)"
++
++#: ../lib/kadm5/kadm_err.c:60
++msgid ""
++"API version specified by application is no longer supported by server (to "
++"fix, update application to adhere to current API version and recompile)"
++msgstr ""
++"Die von der Anwendung angegebene Version der API-Struktur wird nicht länger "
++"vom Server unterstützt. (Aktualisieren Sie die Anwendung, dass sie zu der "
++"aktuellen API-Version passt, und kompilieren Sie sie, um dies zu beheben.)"
++
++#: ../lib/kadm5/kadm_err.c:61
++msgid ""
++"API version specified by application is unknown to libraries (to fix, obtain "
++"current KADM5 API header files and libraries and recompile application)"
++msgstr ""
++"Die von der Anwendung angegebenene API-Version ist den Bibliotheken "
++"unbekannt. (Besorgen Sie sich die aktuellen KADM5-API-Header-Dateien und -"
++"Bibliotheken und kompilieren Sie die Anwendung neu, um dies zu beheben.)"
++
++#: ../lib/kadm5/kadm_err.c:62
++msgid ""
++"API version specified by application is unknown to server (to fix, obtain "
++"and install newest KADM5 Admin Server)"
++msgstr ""
++"Die von der Anwendung angegebene API-Version ist dem Server unbekannt. "
++"(Besorgen und installieren Sie sich den neuesten KADM5-Admin-Server, um dies "
++"zu beheben.)"
++
++#: ../lib/kadm5/kadm_err.c:63
++msgid "Database error! Required KADM5 principal missing"
++msgstr "Datenbankfehler! Erforderlicher KADM5-Principal fehlt"
++
++#: ../lib/kadm5/kadm_err.c:64
++msgid "The salt type of the specified principal does not support renaming"
++msgstr "Der Salt-Typ des angegebenen Principals unterstützt kein Umbenennen."
++
++#: ../lib/kadm5/kadm_err.c:65
++msgid "Illegal configuration parameter for remote KADM5 client"
++msgstr "widerrechtlicher Konfigurationsparameter für fernen KADM5-Client"
++
++#: ../lib/kadm5/kadm_err.c:66
++msgid "Illegal configuration parameter for local KADM5 client"
++msgstr "widerrechtlicher Konfigurationsparameter für lokalen KADM5-Client"
++
++#: ../lib/kadm5/kadm_err.c:67
++msgid "Operation requires ``list'' privilege"
++msgstr "Aktion erfordert das »list«-Recht"
++
++#: ../lib/kadm5/kadm_err.c:68
++msgid "Operation requires ``change-password'' privilege"
++msgstr "Aktion erfordert das »change-password«-Recht"
++
++#: ../lib/kadm5/kadm_err.c:69
++msgid "GSS-API (or Kerberos) error"
++msgstr "GSS-API- (oder Kerberos-) Fehler"
++
++#: ../lib/kadm5/kadm_err.c:70
++msgid "Programmer error! Illegal tagged data list type"
++msgstr ""
++"Fehler des Programmierers! Widerrechlicher Listentyp für gekennzeichnete "
++"Daten"
++
++#: ../lib/kadm5/kadm_err.c:71
++msgid "Required parameters in kdc.conf missing"
++msgstr "erforderliche Parameter in »kdc.conf« fehlen"
++
++#: ../lib/kadm5/kadm_err.c:72
++msgid "Bad krb5 admin server hostname"
++msgstr "falscher Rechnername des KRB5-Admin-Servers"
++
++#: ../lib/kadm5/kadm_err.c:73
++msgid "Operation requires ``set-key'' privilege"
++msgstr "Aktion erfordert das »set-key«-Recht"
++
++#: ../lib/kadm5/kadm_err.c:74
++msgid "Multiple values for single or folded enctype"
++msgstr ""
++"mehrere Werte für einzelnen Verschlüsselungstyp oder Verschlüsselungstyp mit "
++"Salt"
++
++#: ../lib/kadm5/kadm_err.c:75
++msgid "Invalid enctype for setv4key"
++msgstr "widerrechtlicher Verschlüsselungstyp für Setv4key"
++
++#: ../lib/kadm5/kadm_err.c:76
++msgid "Mismatched enctypes for setkey3"
++msgstr "nicht zusammenpassende Verschlüsselungstypen für Setkey3"
++
++#: ../lib/kadm5/kadm_err.c:77
++msgid "Missing parameters in krb5.conf required for kadmin client"
++msgstr "für Kadmin-Client benötigte Parameter fehlen in »krb5.conf«"
++
++#: ../lib/kadm5/kadm_err.c:78 ../lib/kdb/adb_err.c:30
++msgid "XDR encoding error"
++msgstr "XDR-Verschlüsselungsfehler"
++
++#: ../lib/kadm5/kadm_err.c:79
++msgid "Cannot resolve network address for admin server in requested realm"
++msgstr ""
++"Die Netzwerkadresse für den Admin-Server im angeforderten Realm kann nicht "
++"aufgelöst werden."
++
++#: ../lib/kadm5/kadm_err.c:80
++msgid "Unspecified password quality failure"
++msgstr "nicht näher angegebener Passwortqualitätsfehlschlag"
++
++#: ../lib/kadm5/kadm_err.c:81
++msgid "Invalid key/salt tuples"
++msgstr "ungültige Schlüssel-/Salt-Tupel"
++
++#: ../lib/kdb/adb_err.c:23
++msgid "No Error"
++msgstr "kein Fehler"
++
++#: ../lib/kdb/adb_err.c:25
++msgid "Principal or policy does not exist"
++msgstr "Principal oder Richtlinie existiert nicht"
++
++#: ../lib/kdb/adb_err.c:26
++msgid "Database not initialized"
++msgstr "Datenbank nicht initialisiert"
++
++#: ../lib/kdb/adb_err.c:27
++msgid "Invalid policy name"
++msgstr "ungültiger Richtlinienname"
++
++#: ../lib/kdb/adb_err.c:28
++msgid "Invalid principal name"
++msgstr "ungültiger Principal-Name"
++
++#: ../lib/kdb/adb_err.c:31
++msgid "Failure!"
++msgstr "Fehlschlag!"
++
++#: ../lib/kdb/adb_err.c:32
++msgid "Bad lock mode"
++msgstr "falscher Sperrmodus"
++
++#: ../lib/kdb/adb_err.c:33
++msgid "Cannot lock database"
++msgstr "Datenbank kann nicht gesperrt werden"
++
++#: ../lib/kdb/adb_err.c:34
++msgid "Database not locked"
++msgstr "Datenbank nicht gesperrt"
++
++#: ../lib/kdb/adb_err.c:35
++msgid "KADM5 administration database lock file missing"
++msgstr "Sperrdatei der KADM5-Verwaltungsdatenbank fehlt"
++
++#: ../lib/kdb/adb_err.c:36
++msgid "Insufficient permission to lock file"
++msgstr "keine ausreichenden Rechte zum Sperren der Datei"
++
++#: ../lib/krb5/error_tables/k5e1_err.c:23
++msgid "Plugin does not support interface version"
++msgstr "Erweiterung unterstützt nicht die Schnittstellenversion"
++
++#: ../lib/krb5/error_tables/k5e1_err.c:24
++msgid "Invalid module specifier"
++msgstr "ungültige Modulangabe"
++
++#: ../lib/krb5/error_tables/k5e1_err.c:25
++msgid "Plugin module name not found"
++msgstr "Erweiterungsmodulname nicht gefunden"
++
++#: ../lib/krb5/error_tables/k5e1_err.c:26
++msgid "The KDC should discard this request"
++msgstr "Das KDC sollte diese Anfrage verwerfen"
++
++#: ../lib/krb5/error_tables/k5e1_err.c:27
++msgid "Can't create new subsidiary cache"
++msgstr "Der neue ergänzende Zwischenspeicher kann nicht erzeugt werden"
++
++#: ../lib/krb5/error_tables/k5e1_err.c:28
++msgid "Invalid keyring anchor name"
++msgstr "ungültiger Schlüsselbundverankerungsname"
++
++#: ../lib/krb5/error_tables/k5e1_err.c:29
++msgid "Unknown keyring collection version"
++msgstr "unbekannte Schlüsselbundsammlungsversion"
++
++#: ../lib/krb5/error_tables/k5e1_err.c:30
++msgid "Invalid UID in persistent keyring name"
++msgstr "ungültige UID im beständigen Schlüsselbundnamen"
++
++#: ../lib/krb5/error_tables/k5e1_err.c:31
++msgid "Malformed reply from KCM daemon"
++msgstr "Antwort des KCM-Daemons hat die falsche Form"
++
++#: ../lib/krb5/error_tables/k5e1_err.c:32
++msgid "Mach RPC error communicating with KCM daemon"
++msgstr "Mach-RPC-Fehler beim der Kommunikation mit dem KCM-Daemon"
++
++#: ../lib/krb5/error_tables/k5e1_err.c:33
++msgid "KCM daemon reply too big"
++msgstr "Antwort des KCM-Daemons zu groß"
++
++#: ../lib/krb5/error_tables/k5e1_err.c:34
++msgid "No KCM server found"
++msgstr "Kein KCM-Server gefunden"
++
++#: ../lib/krb5/error_tables/krb5_err.c:24
++msgid "Client's entry in database has expired"
++msgstr "Eintrag des Clients in der Datenbank ist abgelaufen"
++
++#: ../lib/krb5/error_tables/krb5_err.c:25
++msgid "Server's entry in database has expired"
++msgstr "Eintrag des Servers in der Datenbank ist abgelaufen"
++
++#: ../lib/krb5/error_tables/krb5_err.c:26
++msgid "Requested protocol version not supported"
++msgstr "angeforderte Protokollversion nicht unterstützt"
++
++#: ../lib/krb5/error_tables/krb5_err.c:27
++msgid "Client's key is encrypted in an old master key"
++msgstr ""
++"Der Schlüssel des Clients wurde mit einem alten Hauptschlüssel verschlüsselt."
++
++#: ../lib/krb5/error_tables/krb5_err.c:28
++msgid "Server's key is encrypted in an old master key"
++msgstr ""
++"Der Schlüssel des Servers wurde mit einem alten Hauptschlüssel verschlüsselt."
++
++#: ../lib/krb5/error_tables/krb5_err.c:29
++msgid "Client not found in Kerberos database"
++msgstr "Client nicht in der Kerberos-Datenbank gefunden"
++
++#: ../lib/krb5/error_tables/krb5_err.c:30
++msgid "Server not found in Kerberos database"
++msgstr "Server nicht in der Kerberos-Datenbank gefunden"
++
++#: ../lib/krb5/error_tables/krb5_err.c:31
++msgid "Principal has multiple entries in Kerberos database"
++msgstr "Principal hat in der Kerberos-Datenbank mehrere Einträge"
++
++#: ../lib/krb5/error_tables/krb5_err.c:32
++msgid "Client or server has a null key"
++msgstr "Client oder Server hat einen Nullschlüssel"
++
++#: ../lib/krb5/error_tables/krb5_err.c:33
++msgid "Ticket is ineligible for postdating"
++msgstr "Ticket ist zum Vordatieren ungeeignet"
++
++#: ../lib/krb5/error_tables/krb5_err.c:34
++msgid "Requested effective lifetime is negative or too short"
++msgstr "Die angeforderte effektive Lebensdauer ist negativ oder zu kurz."
++
++#: ../lib/krb5/error_tables/krb5_err.c:35
++msgid "KDC policy rejects request"
++msgstr "KDC-Richtlinie weist die Anfrage zurück"
++
++#: ../lib/krb5/error_tables/krb5_err.c:36
++msgid "KDC can't fulfill requested option"
++msgstr "KDC kann erforderliche Option nicht erfüllen"
++
++#: ../lib/krb5/error_tables/krb5_err.c:37
++msgid "KDC has no support for encryption type"
++msgstr "KDC unterstützt diesen Verschlüsselungstyp nicht"
++
++#: ../lib/krb5/error_tables/krb5_err.c:38
++msgid "KDC has no support for checksum type"
++msgstr "KDC unterstützt diesen Prüfsummentyp nicht"
++
++#: ../lib/krb5/error_tables/krb5_err.c:39
++msgid "KDC has no support for padata type"
++msgstr "KDC unterstützt diesen Padata-Typ nicht"
++
++#: ../lib/krb5/error_tables/krb5_err.c:40
++msgid "KDC has no support for transited type"
++msgstr "KDC unterstützt diesen Übergangstyp nicht"
++
++#: ../lib/krb5/error_tables/krb5_err.c:41
++msgid "Clients credentials have been revoked"
++msgstr "Anmeldedaten des Clients wurden widerrufen"
++
++#: ../lib/krb5/error_tables/krb5_err.c:42
++msgid "Credentials for server have been revoked"
++msgstr "Anmeldedaten für den Server wurden widerrufen"
++
++#: ../lib/krb5/error_tables/krb5_err.c:43
++msgid "TGT has been revoked"
++msgstr "TGT wurde widerrufen"
++
++#: ../lib/krb5/error_tables/krb5_err.c:44
++msgid "Client not yet valid - try again later"
++msgstr "Client noch nicht gültig – versuchen Sie es später noch einmal"
++
++#: ../lib/krb5/error_tables/krb5_err.c:45
++msgid "Server not yet valid - try again later"
++msgstr "Server noch nicht gültig – versuchen Sie es später noch einmal"
++
++#: ../lib/krb5/error_tables/krb5_err.c:46
++msgid "Password has expired"
++msgstr "Passwort ist abgelaufen"
++
++#: ../lib/krb5/error_tables/krb5_err.c:47
++msgid "Preauthentication failed"
++msgstr "Vorauthentifizierung fehlgeschlagen"
++
++#: ../lib/krb5/error_tables/krb5_err.c:48
++msgid "Additional pre-authentication required"
++msgstr "zusätzlich Vorauthentifizierung erforderlich"
++
++#: ../lib/krb5/error_tables/krb5_err.c:49
++msgid "Requested server and ticket don't match"
++msgstr "abgefragter Server und Ticket passen nicht zusammen"
++
++#: ../lib/krb5/error_tables/krb5_err.c:50
++msgid "Server principal valid for user2user only"
++msgstr "Der Server-Principal ist nur für »user2user« gültig"
++
++#: ../lib/krb5/error_tables/krb5_err.c:51
++msgid "KDC policy rejects transited path"
++msgstr "KDC-Richtlinie verwirft durchgereichten Pfad"
++
++#: ../lib/krb5/error_tables/krb5_err.c:52
++msgid "A service is not available that is required to process the request"
++msgstr ""
++"Ein Dienst, der zum Verarbeiten der Abfrage erforderlich ist, ist nicht "
++"verfügbar."
++
++#: ../lib/krb5/error_tables/krb5_err.c:53
++msgid "KRB5 error code 30"
++msgstr "KRB5-Fehlercode 30"
++
++#: ../lib/krb5/error_tables/krb5_err.c:54
++msgid "Decrypt integrity check failed"
++msgstr "Entschlüsselungsintegritätsprüfung fehlgeschlagen"
++
++#: ../lib/krb5/error_tables/krb5_err.c:55
++msgid "Ticket expired"
++msgstr "Ticket abgelaufen"
++
++#: ../lib/krb5/error_tables/krb5_err.c:56
++msgid "Ticket not yet valid"
++msgstr "Ticket noch nicht gültig"
++
++#: ../lib/krb5/error_tables/krb5_err.c:57
++msgid "Request is a replay"
++msgstr "Anfrage ist eine Wiederholung"
++
++#: ../lib/krb5/error_tables/krb5_err.c:58
++msgid "The ticket isn't for us"
++msgstr "Das Ticket ist nicht für uns."
++
++#: ../lib/krb5/error_tables/krb5_err.c:59
++msgid "Ticket/authenticator don't match"
++msgstr "Ticket/Schlüsselziffer passen nicht zueinander"
++
++#: ../lib/krb5/error_tables/krb5_err.c:60
++msgid "Clock skew too great"
++msgstr "Uhrzeitabweichung zu groß"
++
++#: ../lib/krb5/error_tables/krb5_err.c:61
++msgid "Incorrect net address"
++msgstr "falsche Netzwerkadresse"
++
++#: ../lib/krb5/error_tables/krb5_err.c:62
++msgid "Protocol version mismatch"
++msgstr "Protokollversion passt nicht"
++
++#: ../lib/krb5/error_tables/krb5_err.c:63
++msgid "Invalid message type"
++msgstr "ungültiger Nachrichtentyp"
++
++#: ../lib/krb5/error_tables/krb5_err.c:64
++msgid "Message stream modified"
++msgstr "Nachrichtendatenstrom geändert"
++
++#: ../lib/krb5/error_tables/krb5_err.c:65
++msgid "Message out of order"
++msgstr "Nachricht nicht in Ordnung"
++
++#: ../lib/krb5/error_tables/krb5_err.c:66
++msgid "Illegal cross-realm ticket"
++msgstr "Widerrechliches Realm-übergreifendes Ticket"
++
++#: ../lib/krb5/error_tables/krb5_err.c:67
++msgid "Key version is not available"
++msgstr "Schlüsselversion ist nicht verfügbar"
++
++#: ../lib/krb5/error_tables/krb5_err.c:68
++msgid "Service key not available"
++msgstr "Dienstschlüssel nicht verfügbar"
++
++#: ../lib/krb5/error_tables/krb5_err.c:69
++#: ../lib/krb5/error_tables/krb5_err.c:181
++msgid "Mutual authentication failed"
++msgstr "gegenseitige Authentifizierung fehlgeschlagen"
++
++#: ../lib/krb5/error_tables/krb5_err.c:70
++msgid "Incorrect message direction"
++msgstr "falsche Nachrichtenrichtung"
++
++#: ../lib/krb5/error_tables/krb5_err.c:71
++msgid "Alternative authentication method required"
++msgstr "alternative Authentifizierungsmethode erforderlich"
++
++#: ../lib/krb5/error_tables/krb5_err.c:72
++msgid "Incorrect sequence number in message"
++msgstr "falsche Sequenznummer in der Nachricht"
++
++#: ../lib/krb5/error_tables/krb5_err.c:73
++msgid "Inappropriate type of checksum in message"
++msgstr "ungeeigneter Prüfsummentyp in der Nachricht"
++
++#: ../lib/krb5/error_tables/krb5_err.c:74
++msgid "Policy rejects transited path"
++msgstr "Richtlinie verwirft durchgereichten Pfad"
++
++#: ../lib/krb5/error_tables/krb5_err.c:75
++msgid "Response too big for UDP, retry with TCP"
++msgstr "Antwort für UDP zu groß, erneuter Versuch mit TCP"
++
++#: ../lib/krb5/error_tables/krb5_err.c:76
++msgid "KRB5 error code 53"
++msgstr "KRB5-Fehlercode 53"
++
++#: ../lib/krb5/error_tables/krb5_err.c:77
++msgid "KRB5 error code 54"
++msgstr "KRB5-Fehlercode 54"
++
++#: ../lib/krb5/error_tables/krb5_err.c:78
++msgid "KRB5 error code 55"
++msgstr "KRB5-Fehlercode 55"
++
++#: ../lib/krb5/error_tables/krb5_err.c:79
++msgid "KRB5 error code 56"
++msgstr "KRB5-Fehlercode 56"
++
++#: ../lib/krb5/error_tables/krb5_err.c:80
++msgid "KRB5 error code 57"
++msgstr "KRB5-Fehlercode 57"
++
++#: ../lib/krb5/error_tables/krb5_err.c:81
++msgid "KRB5 error code 58"
++msgstr "KRB5-Fehlercode 58"
++
++#: ../lib/krb5/error_tables/krb5_err.c:82
++msgid "KRB5 error code 59"
++msgstr "KRB5-Fehlercode 59"
++
++#: ../lib/krb5/error_tables/krb5_err.c:83
++msgid "Generic error (see e-text)"
++msgstr "allgemeiner Fehler (siehe E-Text)"
++
++#: ../lib/krb5/error_tables/krb5_err.c:84
++msgid "Field is too long for this implementation"
++msgstr "Feld ist für diese Implementierung zu lang"
++
++#: ../lib/krb5/error_tables/krb5_err.c:85
++msgid "Client not trusted"
++msgstr "Client nicht vertrauenswürdig"
++
++#: ../lib/krb5/error_tables/krb5_err.c:86
++msgid "KDC not trusted"
++msgstr "KDC nicht vertrauenswürdig"
++
++#: ../lib/krb5/error_tables/krb5_err.c:87
++msgid "Invalid signature"
++msgstr "ungültige Signatur"
++
++#: ../lib/krb5/error_tables/krb5_err.c:88
++msgid "Key parameters not accepted"
++msgstr "Schlüsselparameter nicht akzeptiert"
++
++#: ../lib/krb5/error_tables/krb5_err.c:89
++msgid "Certificate mismatch"
++msgstr "Zertifikat passt nicht"
++
++#: ../lib/krb5/error_tables/krb5_err.c:90
++msgid "No ticket granting ticket"
++msgstr "kein ticketgewährendes Ticket"
++
++#: ../lib/krb5/error_tables/krb5_err.c:91
++msgid "Realm not local to KDC"
++msgstr "Realm für KDC nicht lokal"
++
++#: ../lib/krb5/error_tables/krb5_err.c:92
++msgid "User to user required"
++msgstr "Benutzer-zu-Benutzer erforderlich"
++
++#: ../lib/krb5/error_tables/krb5_err.c:93
++msgid "Can't verify certificate"
++msgstr "Zertifikat kann nicht überprüft werden"
++
++#: ../lib/krb5/error_tables/krb5_err.c:94
++msgid "Invalid certificate"
++msgstr "ungültiges Zertifikat"
++
++#: ../lib/krb5/error_tables/krb5_err.c:95
++msgid "Revoked certificate"
++msgstr "widerrufenes Zertifikat"
++
++#: ../lib/krb5/error_tables/krb5_err.c:96
++msgid "Revocation status unknown"
++msgstr "Widerrufsstatus unbekannt"
++
++#: ../lib/krb5/error_tables/krb5_err.c:97
++msgid "Revocation status unavailable"
++msgstr "Widerrufsstatus nicht verfügbar"
++
++#: ../lib/krb5/error_tables/krb5_err.c:98
++msgid "Client name mismatch"
++msgstr "Client-Name passt nicht"
++
++#: ../lib/krb5/error_tables/krb5_err.c:99
++msgid "KDC name mismatch"
++msgstr "KDC-Name passt nicht"
++
++#: ../lib/krb5/error_tables/krb5_err.c:100
++msgid "Inconsistent key purpose"
++msgstr "inkonstistenter Schlüsselzweck"
++
++#: ../lib/krb5/error_tables/krb5_err.c:101
++msgid "Digest in certificate not accepted"
++msgstr "Kurzfassung im Zertifikat nicht akzeptiert"
++
++#: ../lib/krb5/error_tables/krb5_err.c:102
++msgid "Checksum must be included"
++msgstr "Prüfsumme muss enthalten sein"
++
++#: ../lib/krb5/error_tables/krb5_err.c:103
++msgid "Digest in signed-data not accepted"
++msgstr "Kurzfassung in signierten Daten nicht akzeptiert"
++
++#: ../lib/krb5/error_tables/krb5_err.c:104
++msgid "Public key encryption not supported"
++msgstr "Asymetrische Verschlüsselung nicht unterstützt"
++
++#: ../lib/krb5/error_tables/krb5_err.c:105
++msgid "KRB5 error code 82"
++msgstr "KRB5-Fehlercode 82"
++
++#: ../lib/krb5/error_tables/krb5_err.c:106
++msgid "KRB5 error code 83"
++msgstr "KRB5-Fehlercode 83"
++
++#: ../lib/krb5/error_tables/krb5_err.c:107
++msgid "KRB5 error code 84"
++msgstr "KRB5-Fehlercode 84"
++
++#: ../lib/krb5/error_tables/krb5_err.c:108
++msgid "The IAKERB proxy could not find a KDC"
++msgstr "Der IAKERB-Proxy konnte kein KDC finden."
++
++#: ../lib/krb5/error_tables/krb5_err.c:109
++msgid "The KDC did not respond to the IAKERB proxy"
++msgstr "Das KDC anwortete dem IAKERB-Proxy nicht."
++
++#: ../lib/krb5/error_tables/krb5_err.c:110
++msgid "KRB5 error code 87"
++msgstr "KRB5-Fehlercode 87"
++
++#: ../lib/krb5/error_tables/krb5_err.c:111
++msgid "KRB5 error code 88"
++msgstr "KRB5-Fehlercode 88"
++
++#: ../lib/krb5/error_tables/krb5_err.c:112
++msgid "KRB5 error code 89"
++msgstr "KRB5-Fehlercode 89"
++
++#: ../lib/krb5/error_tables/krb5_err.c:113
++msgid "KRB5 error code 90"
++msgstr "KRB5-Fehlercode 90"
++
++#: ../lib/krb5/error_tables/krb5_err.c:114
++msgid "KRB5 error code 91"
++msgstr "KRB5-Fehlercode 91"
++
++#: ../lib/krb5/error_tables/krb5_err.c:115
++msgid "KRB5 error code 92"
++msgstr "KRB5-Fehlercode 92"
++
++#: ../lib/krb5/error_tables/krb5_err.c:116
++msgid "An unsupported critical FAST option was requested"
++msgstr "Es wurde eine nicht unterstützte kritische FAST-Aktion angefordert."
++
++#: ../lib/krb5/error_tables/krb5_err.c:117
++msgid "KRB5 error code 94"
++msgstr "KRB5-Fehlercode 94"
++
++#: ../lib/krb5/error_tables/krb5_err.c:118
++msgid "KRB5 error code 95"
++msgstr "KRB5-Fehlercode 95"
++
++#: ../lib/krb5/error_tables/krb5_err.c:119
++msgid "KRB5 error code 96"
++msgstr "KRB5-Fehlercode 96"
++
++#: ../lib/krb5/error_tables/krb5_err.c:120
++msgid "KRB5 error code 97"
++msgstr "KRB5-Fehlercode 97"
++
++#: ../lib/krb5/error_tables/krb5_err.c:121
++msgid "KRB5 error code 98"
++msgstr "KRB5-Fehlercode 98"
++
++#: ../lib/krb5/error_tables/krb5_err.c:122
++msgid "KRB5 error code 99"
++msgstr "KRB5-Fehlercode 99"
++
++#: ../lib/krb5/error_tables/krb5_err.c:123
++msgid "No acceptable KDF offered"
++msgstr "kein akzeptables KDF angeboten"
++
++#: ../lib/krb5/error_tables/krb5_err.c:124
++msgid "KRB5 error code 101"
++msgstr "KRB5-Fehlercode 101"
++
++#: ../lib/krb5/error_tables/krb5_err.c:125
++msgid "KRB5 error code 102"
++msgstr "KRB5-Fehlercode 102"
++
++#: ../lib/krb5/error_tables/krb5_err.c:126
++msgid "KRB5 error code 103"
++msgstr "KRB5-Fehlercode 103"
++
++#: ../lib/krb5/error_tables/krb5_err.c:127
++msgid "KRB5 error code 104"
++msgstr "KRB5-Fehlercode 104"
++
++#: ../lib/krb5/error_tables/krb5_err.c:128
++msgid "KRB5 error code 105"
++msgstr "KRB5-Fehlercode 105"
++
++#: ../lib/krb5/error_tables/krb5_err.c:129
++msgid "KRB5 error code 106"
++msgstr "KRB5-Fehlercode 106"
++
++#: ../lib/krb5/error_tables/krb5_err.c:130
++msgid "KRB5 error code 107"
++msgstr "KRB5-Fehlercode 107"
++
++#: ../lib/krb5/error_tables/krb5_err.c:131
++msgid "KRB5 error code 108"
++msgstr "KRB5-Fehlercode 108"
++
++#: ../lib/krb5/error_tables/krb5_err.c:132
++msgid "KRB5 error code 109"
++msgstr "KRB5-Fehlercode 109"
++
++#: ../lib/krb5/error_tables/krb5_err.c:133
++msgid "KRB5 error code 110"
++msgstr "KRB5-Fehlercode 110"
++
++#: ../lib/krb5/error_tables/krb5_err.c:134
++msgid "KRB5 error code 111"
++msgstr "KRB5-Fehlercode 111"
++
++#: ../lib/krb5/error_tables/krb5_err.c:135
++msgid "KRB5 error code 112"
++msgstr "KRB5-Fehlercode 112"
++
++#: ../lib/krb5/error_tables/krb5_err.c:136
++msgid "KRB5 error code 113"
++msgstr "KRB5-Fehlercode 113"
++
++#: ../lib/krb5/error_tables/krb5_err.c:137
++msgid "KRB5 error code 114"
++msgstr "KRB5-Fehlercode 114"
++
++#: ../lib/krb5/error_tables/krb5_err.c:138
++msgid "KRB5 error code 115"
++msgstr "KRB5-Fehlercode 115"
++
++#: ../lib/krb5/error_tables/krb5_err.c:139
++msgid "KRB5 error code 116"
++msgstr "KRB5-Fehlercode 116"
++
++#: ../lib/krb5/error_tables/krb5_err.c:140
++msgid "KRB5 error code 117"
++msgstr "KRB5-Fehlercode 117"
++
++#: ../lib/krb5/error_tables/krb5_err.c:141
++msgid "KRB5 error code 118"
++msgstr "KRB5-Fehlercode 118"
++
++#: ../lib/krb5/error_tables/krb5_err.c:142
++msgid "KRB5 error code 119"
++msgstr "KRB5-Fehlercode 119"
++
++#: ../lib/krb5/error_tables/krb5_err.c:143
++msgid "KRB5 error code 120"
++msgstr "KRB5-Fehlercode 120"
++
++#: ../lib/krb5/error_tables/krb5_err.c:144
++msgid "KRB5 error code 121"
++msgstr "KRB5-Fehlercode 121"
++
++#: ../lib/krb5/error_tables/krb5_err.c:145
++msgid "KRB5 error code 122"
++msgstr "KRB5-Fehlercode 122"
++
++#: ../lib/krb5/error_tables/krb5_err.c:146
++msgid "KRB5 error code 123"
++msgstr "KRB5-Fehlercode 123"
++
++#: ../lib/krb5/error_tables/krb5_err.c:147
++msgid "KRB5 error code 124"
++msgstr "KRB5-Fehlercode 124"
++
++#: ../lib/krb5/error_tables/krb5_err.c:148
++msgid "KRB5 error code 125"
++msgstr "KRB5-Fehlercode 125"
++
++#: ../lib/krb5/error_tables/krb5_err.c:149
++msgid "KRB5 error code 126"
++msgstr "KRB5-Fehlercode 126"
++
++#: ../lib/krb5/error_tables/krb5_err.c:150
++msgid "KRB5 error code 127"
++msgstr "KRB5-Fehlercode 127"
++
++#: ../lib/krb5/error_tables/krb5_err.c:151
++#: ../lib/krb5/error_tables/kdb5_err.c:23
++msgid "$Id$"
++msgstr "$Id$"
++
++#: ../lib/krb5/error_tables/krb5_err.c:152
++msgid "Invalid flag for file lock mode"
++msgstr "ungültiger Schalter für den Datei-Sperrmodus"
++
++#: ../lib/krb5/error_tables/krb5_err.c:153
++msgid "Cannot read password"
++msgstr "Passwort kann nicht gelesen werden"
++
++#: ../lib/krb5/error_tables/krb5_err.c:154
++msgid "Password mismatch"
++msgstr "Passwort stimmt nicht überein"
++
++#: ../lib/krb5/error_tables/krb5_err.c:155
++msgid "Password read interrupted"
++msgstr "Lesen des Passworts unterbrochen"
++
++#: ../lib/krb5/error_tables/krb5_err.c:156
++msgid "Illegal character in component name"
++msgstr "ungültiges Zeichen in Komponentenname"
++
++#: ../lib/krb5/error_tables/krb5_err.c:157
++msgid "Malformed representation of principal"
++msgstr "Darstellung des Principals in falscher Form"
++
++#: ../lib/krb5/error_tables/krb5_err.c:158
++msgid "Can't open/find Kerberos configuration file"
++msgstr "Kerberos-Konfigurationsdatei kann nicht geöffnet/gefunden werden"
++
++#: ../lib/krb5/error_tables/krb5_err.c:159
++msgid "Improper format of Kerberos configuration file"
++msgstr "Format der Kerberos-Konfigurationsdatei ist ungeeignet"
++
++#: ../lib/krb5/error_tables/krb5_err.c:160
++msgid "Insufficient space to return complete information"
++msgstr "Platz reicht nicht zur Rückgabe aller Informationen aus"
++
++#: ../lib/krb5/error_tables/krb5_err.c:161
++msgid "Invalid message type specified for encoding"
++msgstr "der zum Kodieren angegebene Nachrichtentyp ist ungültig"
++
++#: ../lib/krb5/error_tables/krb5_err.c:162
++msgid "Credential cache name malformed"
++msgstr "falsche Form des Anmeldedatenzwischenspeichernamens"
++
++#: ../lib/krb5/error_tables/krb5_err.c:163
++msgid "Unknown credential cache type"
++msgstr "unbekannter Anmeldedatenzwischenspeichertyp"
++
++#: ../lib/krb5/error_tables/krb5_err.c:164
++msgid "Matching credential not found"
++msgstr "keine passenden Anmeldedaten gefunden"
++
++#: ../lib/krb5/error_tables/krb5_err.c:165
++msgid "End of credential cache reached"
++msgstr "Ende des Anmeldedatenzwischenspeichers erreicht"
++
++#: ../lib/krb5/error_tables/krb5_err.c:166
++msgid "Request did not supply a ticket"
++msgstr "Anfrage lieferte kein Ticket"
++
++#: ../lib/krb5/error_tables/krb5_err.c:167
++msgid "Wrong principal in request"
++msgstr "falscher Principal in der Anfrage"
++
++#: ../lib/krb5/error_tables/krb5_err.c:168
++msgid "Ticket has invalid flag set"
++msgstr "Das Ticket hat einen falsch gesetzten Schalter."
++
++#: ../lib/krb5/error_tables/krb5_err.c:169
++msgid "Requested principal and ticket don't match"
++msgstr "angeforderter Principal und Ticket passen nicht zusammen"
++
++#: ../lib/krb5/error_tables/krb5_err.c:170
++msgid "KDC reply did not match expectations"
++msgstr "KDC-Antwort entsprach nicht den Erwartungen"
++
++#: ../lib/krb5/error_tables/krb5_err.c:171
++msgid "Clock skew too great in KDC reply"
++msgstr "Zeitversatz in der KDC-Antwort zu groß"
++
++#: ../lib/krb5/error_tables/krb5_err.c:172
++msgid "Client/server realm mismatch in initial ticket request"
++msgstr ""
++"Client-/Server-Realm passen in der anfänglichen Ticketanfrage nicht zusammen."
++
++#: ../lib/krb5/error_tables/krb5_err.c:173
++msgid "Program lacks support for encryption type"
++msgstr ""
++"Dem Programm fehlt es an der Unterstützung für den Verschlüsselungstyp."
++
++#: ../lib/krb5/error_tables/krb5_err.c:174
++msgid "Program lacks support for key type"
++msgstr "Dem Programm fehlt es an der Unterstützung für den Schlüsseltyp."
++
++#: ../lib/krb5/error_tables/krb5_err.c:175
++msgid "Requested encryption type not used in message"
++msgstr ""
++"Der angeforderte Verschlüsselungstyp wird in der Nachricht nicht verwendet."
++
++#: ../lib/krb5/error_tables/krb5_err.c:176
++msgid "Program lacks support for checksum type"
++msgstr "Dem Programm fehlt es an der Unterstützung für den Prüfsummentyp."
++
++#: ../lib/krb5/error_tables/krb5_err.c:177
++msgid "Cannot find KDC for requested realm"
++msgstr "KDC für angeforderten Realm kann nicht gefunden werden"
++
++#: ../lib/krb5/error_tables/krb5_err.c:178
++msgid "Kerberos service unknown"
++msgstr "Kerberos-Dienst unbekannt"
++
++#: ../lib/krb5/error_tables/krb5_err.c:179
++msgid "Cannot contact any KDC for requested realm"
++msgstr "Für den angeforderten Realm kann kein KDC kontaktiert werden."
++
++#: ../lib/krb5/error_tables/krb5_err.c:180
++msgid "No local name found for principal name"
++msgstr "Für den Principal-Namen wurde kein lokaler Name gefunden."
++
++#: ../lib/krb5/error_tables/krb5_err.c:182
++msgid "Replay cache type is already registered"
++msgstr "Wiederholungszwischenspeichertyp ist bereits registriert"
++
++#: ../lib/krb5/error_tables/krb5_err.c:183
++msgid "No more memory to allocate (in replay cache code)"
++msgstr ""
++"kein Speicher mehr zu reservieren (im Wiederholungszwischenspeichercode)"
++
++#: ../lib/krb5/error_tables/krb5_err.c:184
++msgid "Replay cache type is unknown"
++msgstr "Wiederholungszwischenspeichertyp ist unbekannt"
++
++#: ../lib/krb5/error_tables/krb5_err.c:185
++msgid "Generic unknown RC error"
++msgstr "allgemeiner unbekannter Wiederholungszwischenspeicherfehler"
++
++#: ../lib/krb5/error_tables/krb5_err.c:186
++msgid "Message is a replay"
++msgstr "Nachricht ist eine Wiederholung"
++
++#: ../lib/krb5/error_tables/krb5_err.c:187
++msgid "Replay cache I/O operation failed"
++msgstr "Wiederholungszwischenspeicher-E/A-Aktion fehlgeschlagen"
++
++#: ../lib/krb5/error_tables/krb5_err.c:188
++msgid "Replay cache type does not support non-volatile storage"
++msgstr ""
++"Wiederholungszwischenspeichertyp unterstützt keinen beständigen Speicher"
++
++#: ../lib/krb5/error_tables/krb5_err.c:189
++msgid "Replay cache name parse/format error"
++msgstr "Auswerte-/Formatfehler im Wiederholungszwischenspeichernamens"
++
++#: ../lib/krb5/error_tables/krb5_err.c:190
++msgid "End-of-file on replay cache I/O"
++msgstr "Dateiende bei der E/A des Wiederholungszwischenspeichers"
++
++#: ../lib/krb5/error_tables/krb5_err.c:191
++msgid "No more memory to allocate (in replay cache I/O code)"
++msgstr ""
++"kein weiterer Speicher reservierbar (im Wiederholungszwischenspeicher-E/A-"
++"Code)"
++
++#: ../lib/krb5/error_tables/krb5_err.c:192
++msgid "Permission denied in replay cache code"
++msgstr "Zugriff im Wiederholungszwischenspeichercode verweigert"
++
++#: ../lib/krb5/error_tables/krb5_err.c:193
++msgid "I/O error in replay cache i/o code"
++msgstr "E/A-Fehler im Wiederholungszwischenspeicher-E/A-Code"
++
++#: ../lib/krb5/error_tables/krb5_err.c:194
++msgid "Generic unknown RC/IO error"
++msgstr "allgemeiner unbekannter Wiederholungszwischenspeicher-/E/A-Fehler"
++
++#: ../lib/krb5/error_tables/krb5_err.c:195
++msgid "Insufficient system space to store replay information"
++msgstr ""
++"Platz im System reicht nicht zum Speichern der Wiederholungsinformationen"
++
++#: ../lib/krb5/error_tables/krb5_err.c:196
++msgid "Can't open/find realm translation file"
++msgstr "Realm-Übersetzungsdatei kann nicht geöffnet/gefunden werden"
++
++#: ../lib/krb5/error_tables/krb5_err.c:197
++msgid "Improper format of realm translation file"
++msgstr "Format der Realm-Übersetzungsdatei ist ungeeignet"
++
++#: ../lib/krb5/error_tables/krb5_err.c:198
++msgid "Can't open/find lname translation database"
++msgstr "die Lname-Übersetzungsdatenbank kann nicht geöffnet/gefunden werden"
++
++#: ../lib/krb5/error_tables/krb5_err.c:199
++msgid "No translation available for requested principal"
++msgstr "Für den angeforderten Principal ist keine Übersetzung verfügbar."
++
++#: ../lib/krb5/error_tables/krb5_err.c:200
++msgid "Improper format of translation database entry"
++msgstr "Format des Eintrags der Übersetzungsdatenbank ist ungeeignet"
++
++#: ../lib/krb5/error_tables/krb5_err.c:201
++msgid "Cryptosystem internal error"
++msgstr "interner Fehler des Verschlüsselungssystems"
++
++#: ../lib/krb5/error_tables/krb5_err.c:202
++msgid "Key table name malformed"
++msgstr "falsche Form des Schlüsseltabellennamens"
++
++#: ../lib/krb5/error_tables/krb5_err.c:203
++msgid "Unknown Key table type"
++msgstr "unbekannter Schlüsseltabellentyp"
++
++#: ../lib/krb5/error_tables/krb5_err.c:204
++msgid "Key table entry not found"
++msgstr "Schlüsseltabelleneintrag nicht gefunden"
++
++#: ../lib/krb5/error_tables/krb5_err.c:205
++msgid "End of key table reached"
++msgstr "Ende der Schlüsseltabelle erreicht"
++
++#: ../lib/krb5/error_tables/krb5_err.c:206
++msgid "Cannot write to specified key table"
++msgstr "in angegebene Schlüsseltabelle kann nicht geschrieben werden"
++
++#: ../lib/krb5/error_tables/krb5_err.c:207
++msgid "Error writing to key table"
++msgstr "Fehler beim Schreiben in Schlüsseltabelle"
++
++#: ../lib/krb5/error_tables/krb5_err.c:208
++msgid "Cannot find ticket for requested realm"
++msgstr "Ticket für angeforderten Realm kann nicht gefunden werden"
++
++#: ../lib/krb5/error_tables/krb5_err.c:209
++msgid "DES key has bad parity"
++msgstr "DES-Schlüssel hat falsche Parität"
++
++#: ../lib/krb5/error_tables/krb5_err.c:210
++msgid "DES key is a weak key"
++msgstr "DES-Schlüssel ist schwach"
++
++#: ../lib/krb5/error_tables/krb5_err.c:211
++msgid "Bad encryption type"
++msgstr "falscher Verschlüsselungstyp"
++
++#: ../lib/krb5/error_tables/krb5_err.c:212
++msgid "Key size is incompatible with encryption type"
++msgstr "Schlüssellänge ist nicht mit dem Verschlüsselungstyp kompatibel"
++
++#: ../lib/krb5/error_tables/krb5_err.c:213
++msgid "Message size is incompatible with encryption type"
++msgstr "Nachrichtengröße ist nicht mit Verschlüsselungstyp kompatibel"
++
++#: ../lib/krb5/error_tables/krb5_err.c:214
++msgid "Credentials cache type is already registered."
++msgstr "Anmeldedatenzwischenspeichertyp ist bereits registriert"
++
++#: ../lib/krb5/error_tables/krb5_err.c:215
++msgid "Key table type is already registered."
++msgstr "Schlüsseltabellentyp ist bereits registriert"
++
++#: ../lib/krb5/error_tables/krb5_err.c:216
++msgid "Credentials cache I/O operation failed XXX"
++msgstr "E/A-Aktion für Anmeldedatenzwischenspeicher fehlgeschlagen XXX"
++
++#: ../lib/krb5/error_tables/krb5_err.c:217
++msgid "Credentials cache permissions incorrect"
++msgstr "Anmeldedatenzwischenspeicherrechte nicht korrekt"
++
++#: ../lib/krb5/error_tables/krb5_err.c:218
++msgid "No credentials cache found"
++msgstr "kein Anmeldedatenzwischenspeicher gefunden"
++
++#: ../lib/krb5/error_tables/krb5_err.c:219
++msgid "Internal credentials cache error"
++msgstr "interner Anmeldedatenzwischenspeicherfehler"
++
++#: ../lib/krb5/error_tables/krb5_err.c:220
++msgid "Error writing to credentials cache"
++msgstr "Fehler beim Schreiben in den Anmeldedatenzwischenspeicher"
++
++#: ../lib/krb5/error_tables/krb5_err.c:221
++msgid "No more memory to allocate (in credentials cache code)"
++msgstr ""
++"kein weiterer Speicher zu reservieren (im Anmeldedatenzwischenspeichercode)"
++
++#: ../lib/krb5/error_tables/krb5_err.c:222
++msgid "Bad format in credentials cache"
++msgstr "falsches Format im Anmeldedatenzwischenspeicher"
++
++#: ../lib/krb5/error_tables/krb5_err.c:223
++msgid "No credentials found with supported encryption types"
++msgstr "keine Anmeldedaten mit unterstützten Verschlüsselungstypen gefunden"
++
++#: ../lib/krb5/error_tables/krb5_err.c:224
++msgid "Invalid KDC option combination (library internal error)"
++msgstr "ungültige Kombination von KDC-Optionen (interner Bibliotheksfehler)"
++
++#: ../lib/krb5/error_tables/krb5_err.c:225
++msgid "Request missing second ticket"
++msgstr "Der Anfrage fehlt das zweite Ticket."
++
++#: ../lib/krb5/error_tables/krb5_err.c:226
++msgid "No credentials supplied to library routine"
++msgstr "der Bibliotheks-Routine wurden keine Anmeldedaten geliefert"
++
++#: ../lib/krb5/error_tables/krb5_err.c:227
++msgid "Bad sendauth version was sent"
++msgstr "Es wurde eine falsche Sendauth-Version verschickt"
++
++#: ../lib/krb5/error_tables/krb5_err.c:228
++msgid "Bad application version was sent (via sendauth)"
++msgstr "Es wurde eine falsche Anwendungsversion (über Sendauth) verschickt"
++
++#: ../lib/krb5/error_tables/krb5_err.c:229
++msgid "Bad response (during sendauth exchange)"
++msgstr "falsche Antwort (beim Sendauth-Austausch)"
++
++#: ../lib/krb5/error_tables/krb5_err.c:230
++msgid "Server rejected authentication (during sendauth exchange)"
++msgstr "Server wies Authentifizierung (beim Sendauth-Austausch) zurück"
++
++#: ../lib/krb5/error_tables/krb5_err.c:231
++msgid "Unsupported preauthentication type"
++msgstr "nicht unterstützter Vorauthentifizierungstyp"
++
++#: ../lib/krb5/error_tables/krb5_err.c:232
++msgid "Required preauthentication key not supplied"
++msgstr "erforderlicher Vorauthentifizierungsschlüssel nicht bereitgestellt"
++
++#: ../lib/krb5/error_tables/krb5_err.c:233
++msgid "Generic preauthentication failure"
++msgstr "allgemeiner Fehlschlag der Vorauthentifizierung"
++
++#: ../lib/krb5/error_tables/krb5_err.c:234
++msgid "Unsupported replay cache format version number"
++msgstr ""
++"nicht unterstütztes Versionsnummernformat des Wiederholungszwischenspeichers"
++
++#: ../lib/krb5/error_tables/krb5_err.c:235
++msgid "Unsupported credentials cache format version number"
++msgstr ""
++"nicht unterstütztes Versionsnummernformat des Anmeldedatenzwischenspeichers"
++
++#: ../lib/krb5/error_tables/krb5_err.c:236
++msgid "Unsupported key table format version number"
++msgstr "nicht unterstütztes Versionsnummernformat der Schlüsseltabelle"
++
++#: ../lib/krb5/error_tables/krb5_err.c:237
++msgid "Program lacks support for address type"
++msgstr "Dem Programm fehlt es an der Unterstützung des Adresstyps."
++
++#: ../lib/krb5/error_tables/krb5_err.c:238
++msgid "Message replay detection requires rcache parameter"
++msgstr "Erkennung der Antwortnachricht erfordert den Parameter »rcache«"
++
++#: ../lib/krb5/error_tables/krb5_err.c:239
++msgid "Hostname cannot be canonicalized"
++msgstr "Rechnername kann nicht in Normalform gebracht werden"
++
++#: ../lib/krb5/error_tables/krb5_err.c:240
++msgid "Cannot determine realm for host"
++msgstr "Realm für Rechner kann nicht bestimmt werden"
++
++#: ../lib/krb5/error_tables/krb5_err.c:241
++msgid "Conversion to service principal undefined for name type"
++msgstr "Umwandlung in Dienst-Principal für Namenstyp nicht definiert"
++
++#: ../lib/krb5/error_tables/krb5_err.c:242
++msgid "Initial Ticket response appears to be Version 4 error"
++msgstr "anfängliche Ticket-Antwort scheint ein Fehler der Version 4 zu sein"
++
++#: ../lib/krb5/error_tables/krb5_err.c:243
++msgid "Cannot resolve network address for KDC in requested realm"
++msgstr ""
++"Netzwerkadresse für KDC im angeforderten Realm kann nicht aufgelöst werden"
++
++#: ../lib/krb5/error_tables/krb5_err.c:244
++msgid "Requesting ticket can't get forwardable tickets"
++msgstr "anforderndes Ticket kann keine weiterleitbaren Tickets holen"
++
++#: ../lib/krb5/error_tables/krb5_err.c:245
++msgid "Bad principal name while trying to forward credentials"
++msgstr "falscher Principal beim Versuch, Anmeldedaten weiterzuleiten"
++
++#: ../lib/krb5/error_tables/krb5_err.c:246
++msgid "Looping detected inside krb5_get_in_tkt"
++msgstr "Schleife innerhalb von »krb5_get_in_tkt« entdeckt"
++
++#: ../lib/krb5/error_tables/krb5_err.c:247
++msgid "Configuration file does not specify default realm"
++msgstr "Konfigurationsdatei gibt keinen Standard-Realm an"
++
++#: ../lib/krb5/error_tables/krb5_err.c:248
++msgid "Bad SAM flags in obtain_sam_padata"
++msgstr "falsche SAM-Schalter in »obtain_sam_padata«"
++
++#: ../lib/krb5/error_tables/krb5_err.c:249
++msgid "Invalid encryption type in SAM challenge"
++msgstr "ungültiger Verschlüsselungstyp in der SAM-Aufforderung"
++
++#: ../lib/krb5/error_tables/krb5_err.c:250
++msgid "Missing checksum in SAM challenge"
++msgstr "fehlende Prüfsumme in der SAM-Aufforderung"
++
++#: ../lib/krb5/error_tables/krb5_err.c:251
++msgid "Bad checksum in SAM challenge"
++msgstr "falsche Prüfsumme in der SAM-Aufforderung"
++
++#: ../lib/krb5/error_tables/krb5_err.c:252
++msgid "Keytab name too long"
++msgstr "Schlüsseltabellennamen zu lang"
++
++#: ../lib/krb5/error_tables/krb5_err.c:253
++msgid "Key version number for principal in key table is incorrect"
++msgstr ""
++"Schlüsselversionsnummer des Principals in der Schlüsseltabelle ist nicht "
++"korrekt"
++
++#: ../lib/krb5/error_tables/krb5_err.c:254
++msgid "This application has expired"
++msgstr "Diese Anwendung ist abgelaufen."
++
++#: ../lib/krb5/error_tables/krb5_err.c:255
++msgid "This Krb5 library has expired"
++msgstr "Diese Krb5-Bibliothek ist abgelaufen."
++
++#: ../lib/krb5/error_tables/krb5_err.c:256
++msgid "New password cannot be zero length"
++msgstr "Das neue Passwort kann nicht die Länge Null haben."
++
++#: ../lib/krb5/error_tables/krb5_err.c:258
++msgid "Bad format in keytab"
++msgstr "falsches Format in der Schlüsseltabelle"
++
++#: ../lib/krb5/error_tables/krb5_err.c:259
++msgid "Encryption type not permitted"
++msgstr "Verschlüsselungstyp nicht erlaubt"
++
++#: ../lib/krb5/error_tables/krb5_err.c:260
++msgid "No supported encryption types (config file error?)"
++msgstr ""
++"keine unterstützten Verschlüsselungstypen (Fehler in der "
++"Konfigurationsdatei?)"
++
++#: ../lib/krb5/error_tables/krb5_err.c:261
++msgid "Program called an obsolete, deleted function"
++msgstr "Das Programm rief eine veraltete, gelöschte Funktion auf."
++
++#: ../lib/krb5/error_tables/krb5_err.c:262
++msgid "unknown getaddrinfo failure"
++msgstr "unbekannter Getaddrinfo-Fehlschlag"
++
++#: ../lib/krb5/error_tables/krb5_err.c:263
++msgid "no data available for host/domain name"
++msgstr "keine Daten für Rechner/Domain-Namen verfügbar"
++
++#: ../lib/krb5/error_tables/krb5_err.c:264
++msgid "host/domain name not found"
++msgstr "Rechner/Domain-Name nicht gefunden"
++
++#: ../lib/krb5/error_tables/krb5_err.c:265
++msgid "service name unknown"
++msgstr "Dienstname unbekannt"
++
++#: ../lib/krb5/error_tables/krb5_err.c:266
++msgid "Cannot determine realm for numeric host address"
++msgstr "Realm für numerische Rechneradresse kann nicht bestimmt werden"
++
++#: ../lib/krb5/error_tables/krb5_err.c:267
++msgid "Invalid key generation parameters from KDC"
++msgstr "ungültige Parameter zum Erzeugen von Schlüsseln vom KDC"
++
++#: ../lib/krb5/error_tables/krb5_err.c:268
++msgid "service not available"
++msgstr "Dienst nicht verfügbar"
++
++#: ../lib/krb5/error_tables/krb5_err.c:269
++msgid "Ccache function not supported: read-only ccache type"
++msgstr "Ccache-Funktion nicht unterstützt: Ccache-Typ nur lesbar"
++
++#: ../lib/krb5/error_tables/krb5_err.c:270
++msgid "Ccache function not supported: not implemented"
++msgstr "Ccache-Funktion nicht unterstützt: nicht implementiert"
++
++#: ../lib/krb5/error_tables/krb5_err.c:271
++msgid "Invalid format of Kerberos lifetime or clock skew string"
++msgstr ""
++"ungültiges Format der Kerberos-Lebensdauer oder der Zeitversatzzeichenkette"
++
++#: ../lib/krb5/error_tables/krb5_err.c:272
++msgid "Supplied data not handled by this plugin"
++msgstr ""
++"Die bereitgestellten Daten werden nicht von dieser Erweiterung behandelt."
++
++#: ../lib/krb5/error_tables/krb5_err.c:273
++msgid "Plugin does not support the operation"
++msgstr "Erweiterung unterstützt diese Aktion nicht"
++
++#: ../lib/krb5/error_tables/krb5_err.c:274
++msgid "Invalid UTF-8 string"
++msgstr "ungültige UTF-8-Zeichenkette"
++
++#: ../lib/krb5/error_tables/krb5_err.c:275
++msgid "FAST protected pre-authentication required but not supported by KDC"
++msgstr ""
++"FAST-geschützte Vorauthentifizierung erforderlich, aber nicht vom KDC "
++"unterstützt"
++
++#: ../lib/krb5/error_tables/krb5_err.c:276
++msgid "Auth context must contain local address"
++msgstr "Authentifizierungskontext muss lokale Adresse enthalten"
++
++#: ../lib/krb5/error_tables/krb5_err.c:277
++msgid "Auth context must contain remote address"
++msgstr "Authentifizierungskontext muss ferne Adresse enthalten"
++
++#: ../lib/krb5/error_tables/krb5_err.c:278
++msgid "Tracing unsupported"
++msgstr "Verfolgung nicht unterstützt"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:24
++msgid "Entry already exists in database"
++msgstr "Eintrag existiert bereits in der Datenbank"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:25
++msgid "Database store error"
++msgstr "Datenbank-Speicherfehler"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:26
++msgid "Database read error"
++msgstr "Datenbank-Lesefehler"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:27
++msgid "Insufficient access to perform requested operation"
++msgstr "Zugriffsrechte reichen nicht zur Durchführung der angeforderten Aktion"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:28
++msgid "No such entry in the database"
++msgstr "kein derartiger Eintrag in der Datenbank"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:29
++msgid "Illegal use of wildcard"
++msgstr "ungültige Verwendung eines Platzhalters"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:30
++msgid "Database is locked or in use--try again later"
++msgstr ""
++"Datenbank ist gesperrt oder wird gerade benutzt – versuchen Sie es später "
++"wieder"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:31
++msgid "Database was modified during read"
++msgstr "Datenbank wurde während des Lesens geändert"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:32
++msgid "Database record is incomplete or corrupted"
++msgstr "Datensatz ist unvollständig oder beschädigt"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:33
++msgid "Attempt to lock database twice"
++msgstr "Es wurde zweimal versucht, die Datenbank zu sperren."
++
++#: ../lib/krb5/error_tables/kdb5_err.c:34
++msgid "Attempt to unlock database when not locked"
++msgstr ""
++"Es wurde versucht, die Datenbank zu entsperren, obwohl sie nicht gesperrt "
++"ist."
++
++#: ../lib/krb5/error_tables/kdb5_err.c:35
++msgid "Invalid kdb lock mode"
++msgstr "ungültiger KDB-Sperrmodus"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:36
++msgid "Database has not been initialized"
++msgstr "Datenbank wurde nicht initialisiert"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:37
++msgid "Database has already been initialized"
++msgstr "Datenbank wurde bereits initialisiert"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:38
++msgid "Bad direction for converting keys"
++msgstr "falsche Richtung zum Umwandeln von Schlüsseln"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:39
++msgid "Cannot find master key record in database"
++msgstr "Hauptschlüsseldatensatz kann nicht in der Datenbank gefunden werden"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:40
++msgid "Master key does not match database"
++msgstr "Hauptschlüssel passt nicht zur Datenbank"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:41
++msgid "Key size in database is invalid"
++msgstr "Die Schlüssellänge in der Datenbank ist ungültig,"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:42
++msgid "Cannot find/read stored master key"
++msgstr "Der gespeicherte Hauptschlüssel kann nicht gefunden/gelesen werden."
++
++#: ../lib/krb5/error_tables/kdb5_err.c:43
++msgid "Stored master key is corrupted"
++msgstr "Der gespeicherte Hauptschlüssel ist beschädigt."
++
++#: ../lib/krb5/error_tables/kdb5_err.c:44
++msgid "Cannot find active master key"
++msgstr "Der aktive Hauptschlüssel kann nicht gefunden werden."
++
++#: ../lib/krb5/error_tables/kdb5_err.c:45
++msgid "KVNO of new master key does not match expected value"
++msgstr "KVNO des neuen Hauptschlüssels passt nicht zum erwarteten Wert"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:46
++msgid "Stored master key is not current"
++msgstr "gespeicherter Hauptschlüssel ist nicht aktuell"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:47
++msgid "Insufficient access to lock database"
++msgstr "keine ausreichenden Zugriffsrechte zum Sperren der Datenbank"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:48
++msgid "Database format error"
++msgstr "fehlerhaftes Datenbankformat"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:49
++msgid "Unsupported version in database entry"
++msgstr "nicht unterstützte Version im Datenbankeintrag"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:50
++msgid "Unsupported salt type"
++msgstr "nicht unterstützter Salt-Typ"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:51
++msgid "Unsupported encryption type"
++msgstr "nicht unterstützter Verschlüsselungstyp"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:52
++msgid "Bad database creation flags"
++msgstr "falsche Schalter zum Erstellen der Datenbank"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:53
++msgid "No matching key in entry having a permitted enctype"
++msgstr ""
++"kein passender Schlüssel in einem Eintrag mit erlaubtem Verschlüsselungstyp"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:54
++msgid "No matching key in entry"
++msgstr "kein passender Schlüssel im Eintrag"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:55
++msgid "Unable to find requested database type"
++msgstr "angeforderter Datenbanktyp kann nicht gefunden werden"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:56
++msgid "Database type not supported"
++msgstr "Datenbanktyp nicht unterstützt"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:57
++msgid "Database library failed to initialize"
++msgstr "Initialisieren der Datenbankbibliothek fehlgeschlagen"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:59
++msgid "Unable to access Kerberos database"
++msgstr "auf die Kerberos-Datenbank kann nicht zugegriffen werden"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:60
++msgid "Kerberos database internal error"
++msgstr "interner Kerberos-Datenbankfehler"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:61
++msgid "Kerberos database constraints violated"
++msgstr "Kerberos-Datenbankbeschränkungen verletzt"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:62
++msgid "Update log conversion error"
++msgstr "Fehler beim Umwandeln des Aktualisierungsprotokolls"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:63
++msgid "Update log is unstable"
++msgstr "Aktualisierungsprotokoll ist instabil"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:64
++msgid "Update log is corrupt"
++msgstr "Aktualisierungsprotokoll ist beschädigt"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:65
++msgid "Generic update log error"
++msgstr "allgemeiner Aktualisierungsprotokollfehler"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:66
++msgid "Database module does not match KDC version"
++msgstr "Datenbankmodul passt nicht zur KDC-Version"
++
++#: ../lib/krb5/error_tables/kdb5_err.c:68
++msgid "Too much string mapping data"
++msgstr "zu viele zeichenkettenabbildenden Daten"
++
++#: ../lib/krb5/error_tables/asn1_err.c:23
++msgid "ASN.1 failed call to system time library"
++msgstr "ASN.1 beim Aufruf der Systemzeitbibliothek gescheitert"
++
++#: ../lib/krb5/error_tables/asn1_err.c:24
++msgid "ASN.1 structure is missing a required field"
++msgstr "ein erforderliches Feld fehlt in der ASN.1-Struktur"
++
++#: ../lib/krb5/error_tables/asn1_err.c:25
++msgid "ASN.1 unexpected field number"
++msgstr "ASN.1 unerwartete Feldnummer"
++
++#: ../lib/krb5/error_tables/asn1_err.c:26
++msgid "ASN.1 type numbers are inconsistent"
++msgstr "ASN.1-Typnummern sind inkonsistent"
++
++#: ../lib/krb5/error_tables/asn1_err.c:27
++msgid "ASN.1 value too large"
++msgstr "ASN.1-Wert zu groß"
++
++#: ../lib/krb5/error_tables/asn1_err.c:28
++msgid "ASN.1 encoding ended unexpectedly"
++msgstr "ASN.1-Kodierung endete unerwartet"
++
++#: ../lib/krb5/error_tables/asn1_err.c:29
++msgid "ASN.1 identifier doesn't match expected value"
++msgstr "ASN.1-Bezeichner passt nicht zum erwarteten Wert"
++
++#: ../lib/krb5/error_tables/asn1_err.c:30
++msgid "ASN.1 length doesn't match expected value"
++msgstr "Länge von ASN.1 passt nicht zum erwarteten Wert"
++
++#: ../lib/krb5/error_tables/asn1_err.c:31
++msgid "ASN.1 badly-formatted encoding"
++msgstr "fehlerhaft formatierte ASN.1-Kodierung"
++
++#: ../lib/krb5/error_tables/asn1_err.c:32
++msgid "ASN.1 parse error"
++msgstr "ASN.1-Auswertungsfehler"
++
++#: ../lib/krb5/error_tables/asn1_err.c:33
++msgid "ASN.1 bad return from gmtime"
++msgstr "ASN.1 falscher Rückgabewert von Gmtime"
++
++#: ../lib/krb5/error_tables/asn1_err.c:34
++msgid "ASN.1 non-constructed indefinite encoding"
++msgstr "nicht konstruierte unbestimmte ASN.1-Kodierung"
++
++#: ../lib/krb5/error_tables/asn1_err.c:35
++msgid "ASN.1 missing expected EOC"
++msgstr "ASN.1 fehlt erwartetes EOC"
++
++#: ../lib/krb5/error_tables/asn1_err.c:36
++msgid "ASN.1 object omitted in sequence"
++msgstr "ASN.1-Objekt in Sequenz ausgelassen"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:23
++msgid "Kerberos V5 magic number table"
++msgstr "Tabelle magischer Zahlen von Kerberos V5"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:24
++msgid "Bad magic number for krb5_principal structure"
++msgstr "falsche magische Zahl für Krb5_principal-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:25
++msgid "Bad magic number for krb5_data structure"
++msgstr "falsche magische Zahl für Krb5_data-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:26
++msgid "Bad magic number for krb5_keyblock structure"
++msgstr "falsche magische Zahl für Krb5_krb5_keyblock-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:27
++msgid "Bad magic number for krb5_checksum structure"
++msgstr "falsche magische Zahl für Krb5_krb5_checksum-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:28
++msgid "Bad magic number for krb5_encrypt_block structure"
++msgstr "falsche magische Zahl für Krb5_encrypt_bloc-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:29
++msgid "Bad magic number for krb5_enc_data structure"
++msgstr "falsche magische Zahl für Krb5_enc_data-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:30
++msgid "Bad magic number for krb5_cryptosystem_entry structure"
++msgstr "falsche magische Zahl für Krb5_cryptosystem_entry-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:31
++msgid "Bad magic number for krb5_cs_table_entry structure"
++msgstr "falsche magische Zahl für Krb5_cs_table_entry-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:32
++msgid "Bad magic number for krb5_checksum_entry structure"
++msgstr "falsche magische Zahl für Krb5_checksum_entry-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:33
++msgid "Bad magic number for krb5_authdata structure"
++msgstr "falsche magische Zahl für Krb5_authdata-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:34
++msgid "Bad magic number for krb5_transited structure"
++msgstr "falsche magische Zahl für Krb5_transited-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:35
++msgid "Bad magic number for krb5_enc_tkt_part structure"
++msgstr "falsche magische Zahl für Krb5_enc_tkt_part-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:36
++msgid "Bad magic number for krb5_ticket structure"
++msgstr "falsche magische Zahl für Krb5_ticket-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:37
++msgid "Bad magic number for krb5_authenticator structure"
++msgstr "falsche magische Zahl für Krb5_authenticator-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:38
++msgid "Bad magic number for krb5_tkt_authent structure"
++msgstr "falsche magische Zahl für Krb5_tkt_authent-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:39
++msgid "Bad magic number for krb5_creds structure"
++msgstr "falsche magische Zahl für Krb5_creds-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:40
++msgid "Bad magic number for krb5_last_req_entry structure"
++msgstr "falsche magische Zahl für Krb5_last_req_entry-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:41
++msgid "Bad magic number for krb5_pa_data structure"
++msgstr "falsche magische Zahl für Krb5_pa_data-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:42
++msgid "Bad magic number for krb5_kdc_req structure"
++msgstr "falsche magische Zahl für Krb5_kdc_req-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:43
++msgid "Bad magic number for krb5_enc_kdc_rep_part structure"
++msgstr "falsche magische Zahl für Krb5_enc_kdc_rep_part-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:44
++msgid "Bad magic number for krb5_kdc_rep structure"
++msgstr "falsche magische Zahl für Krb5_kdc_rep-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:45
++msgid "Bad magic number for krb5_error structure"
++msgstr "falsche magische Zahl für Krb5_error-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:46
++msgid "Bad magic number for krb5_ap_req structure"
++msgstr "falsche magische Zahl für Krb5_ap_req-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:47
++msgid "Bad magic number for krb5_ap_rep structure"
++msgstr "falsche magische Zahl für Krb5_ap_rep-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:48
++msgid "Bad magic number for krb5_ap_rep_enc_part structure"
++msgstr "falsche magische Zahl für Krb5_ap_rep_enc_part-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:49
++msgid "Bad magic number for krb5_response structure"
++msgstr "falsche magische Zahl für Krb5_response-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:50
++msgid "Bad magic number for krb5_safe structure"
++msgstr "falsche magische Zahl für Krb5_safe-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:51
++msgid "Bad magic number for krb5_priv structure"
++msgstr "falsche magische Zahl für Krb5_priv-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:52
++msgid "Bad magic number for krb5_priv_enc_part structure"
++msgstr "falsche magische Zahl für Krb5_priv_enc_part-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:53
++msgid "Bad magic number for krb5_cred structure"
++msgstr "falsche magische Zahl für Krb5_cred-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:54
++msgid "Bad magic number for krb5_cred_info structure"
++msgstr "falsche magische Zahl für Krb5_cred_info-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:55
++msgid "Bad magic number for krb5_cred_enc_part structure"
++msgstr "falsche magische Zahl für Krb5_cred_enc_part-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:56
++msgid "Bad magic number for krb5_pwd_data structure"
++msgstr "falsche magische Zahl für Krb5_pwd_data-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:57
++msgid "Bad magic number for krb5_address structure"
++msgstr "falsche magische Zahl für Krb5_address-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:58
++msgid "Bad magic number for krb5_keytab_entry structure"
++msgstr "falsche magische Zahl für Krb5_keytab_entry-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:59
++msgid "Bad magic number for krb5_context structure"
++msgstr "falsche magische Zahl für Krb5_context-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:60
++msgid "Bad magic number for krb5_os_context structure"
++msgstr "falsche magische Zahl für Krb5_os_context-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:61
++msgid "Bad magic number for krb5_alt_method structure"
++msgstr "falsche magische Zahl für Krb5_alt_method-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:62
++msgid "Bad magic number for krb5_etype_info_entry structure"
++msgstr "falsche magische Zahl für Krb5_etype_info_entry-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:63
++msgid "Bad magic number for krb5_db_context structure"
++msgstr "falsche magische Zahl für Krb5_db_context-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:64
++msgid "Bad magic number for krb5_auth_context structure"
++msgstr "falsche magische Zahl für Krb5_auth_context-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:65
++msgid "Bad magic number for krb5_keytab structure"
++msgstr "falsche magische Zahl für Krb5_keytab-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:66
++msgid "Bad magic number for krb5_rcache structure"
++msgstr "falsche magische Zahl für Krb5_rcache-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:67
++msgid "Bad magic number for krb5_ccache structure"
++msgstr "falsche magische Zahl für Krb5_ccache-Struktur"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:68
++msgid "Bad magic number for krb5_preauth_ops"
++msgstr "falsche magische Zahl für Krb5_preauth_ops"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:69
++msgid "Bad magic number for krb5_sam_challenge"
++msgstr "falsche magische Zahl für Krb5_sam_challenge"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:70
++msgid "Bad magic number for krb5_sam_challenge_2"
++msgstr "falsche magische Zahl für Krb5_sam_challenge_2"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:71
++msgid "Bad magic number for krb5_sam_key"
++msgstr "falsche magische Zahl für Krb5_sam_key"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:72
++#: ../lib/krb5/error_tables/kv5m_err.c:73
++msgid "Bad magic number for krb5_enc_sam_response_enc"
++msgstr "falsche magische Zahl für Krb5_enc_sam_response_enc"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:74
++msgid "Bad magic number for krb5_sam_response"
++msgstr "falsche magische Zahl für Krb5_sam_response"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:75
++msgid "Bad magic number for krb5_sam_response 2"
++msgstr "falsche magische Zahl für Krb5_sam_response 2"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:76
++msgid "Bad magic number for krb5_predicted_sam_response"
++msgstr "falsche magische Zahl für Krb5_predicted_sam_response"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:77
++msgid "Bad magic number for passwd_phrase_element"
++msgstr "falsche magische Zahl für Passwd_phrase_element"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:78
++msgid "Bad magic number for GSSAPI OID"
++msgstr "falsche magische Zahl für GSSAPI OID"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:79
++msgid "Bad magic number for GSSAPI QUEUE"
++msgstr "falsche magische Zahl für GSSAPI QUEUE"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:80
++msgid "Bad magic number for fast armored request"
++msgstr "falsche magische Zahl für per FAST geschützte Anfrage"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:81
++msgid "Bad magic number for FAST request"
++msgstr "falsche magische Zahl für FAST-Anfrage"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:82
++msgid "Bad magic number for FAST response"
++msgstr "falsche magische Zahl für FAST-Antwort"
++
++#: ../lib/krb5/error_tables/kv5m_err.c:83
++msgid "Bad magic number for krb5_authdata_context"
++msgstr "falsche magische Zahl für Krb5_authdata_context"
++
++#: ../lib/krb5/error_tables/krb524_err.c:23
++msgid "Cannot convert V5 keyblock"
++msgstr "V5-Schlüsselblock kann nicht umgewandelt werden"
++
++#: ../lib/krb5/error_tables/krb524_err.c:24
++msgid "Cannot convert V5 address information"
++msgstr "V5-Adressinformationen können nicht umgewandelt werden"
++
++#: ../lib/krb5/error_tables/krb524_err.c:25
++msgid "Cannot convert V5 principal"
++msgstr "V5-Principal kann nicht umgewandelt werden"
++
++#: ../lib/krb5/error_tables/krb524_err.c:26
++msgid "V5 realm name longer than V4 maximum"
++msgstr "V5-Realm-Name ist länger als die V4-Maximallänge"
++
++#: ../lib/krb5/error_tables/krb524_err.c:27
++msgid "Kerberos V4 error"
++msgstr "Kerberos-V4-Fehler"
++
++#: ../lib/krb5/error_tables/krb524_err.c:28
++msgid "Encoding too large"
++msgstr "Kodierung zu lang"
++
++#: ../lib/krb5/error_tables/krb524_err.c:29
++msgid "Decoding out of data"
++msgstr "Dekodieren außerhalb der Daten"
++
++#: ../lib/krb5/error_tables/krb524_err.c:30
++msgid "Service not responding"
++msgstr "Dienst antwortet nicht"
++
++#: ../lib/krb5/error_tables/krb524_err.c:31
++msgid "Kerberos version 4 support is disabled"
++msgstr "Kerberos 4 Unterstützung ist deaktiviert"
++
++#~ msgid "while creating server %s principal name"
++#~ msgstr "beim Erstellen des Principal-Namens für Server %s"
++
++# KDC = Key Distribution Center
++#~ msgid "while getting credentials from kdc"
++#~ msgstr "beim Holen der Anmeldedaten vom KDC"
++
++# FIXME s/Retrieving/retrieving/
++#~ msgid "while Retrieving credentials"
++#~ msgstr "beim Abfragen der Anmeldedaten"
++
++#~ msgid "while copying principal"
++#~ msgstr "beim Kopieren des Principals"
++
++#~ msgid "%s does not have correct permissions for %s\n"
++#~ msgstr "%s hat nicht die erforderlichen Zugriffsrechte für %s\n"
++
++#~ msgid "no salt\n"
++#~ msgstr "kein Salt\n"
++
++#~ msgid "%s: Couldn't grab lock\n"
++#~ msgstr "%s: Es konnte keine Sperre erlangt werden.\n"
++
++#~ msgid "%s: Loads disallowed when iprop is enabled and a ulog is present\n"
++#~ msgstr ""
++#~ "%s: Wenn Iprop aktiviert und Ulog vorhanden ist, ist Laden nicht "
++#~ "möglich.\n"
++
++#~ msgid "trying to lock database"
++#~ msgstr "es wird versucht, die Datenbank zu sperren"
++
++#~ msgid "GSS-API error %s: %s\n"
++#~ msgstr "GSS-API-Fehler %s: %s\n"
++
++#~ msgid "Couldn't create KRB5 Name NameType OID\n"
++#~ msgstr "KRB5 Name NameType OID konnte nicht erstellt werden.\n"
++
++#~ msgid "%s: %s while initializing, aborting"
++#~ msgstr "%s: %s beim Initialisieren, wird abgebrochen"
++
++#~ msgid ""
++#~ "%s: Missing required configuration values (%lx) while initializing, "
++#~ "aborting"
++#~ msgstr ""
++#~ "%s: Beim Initialisieren fehlen die erforderlichen Konfigurationswerte "
++#~ "(%lx), wird abgebrochen"
++
++#~ msgid ""
++#~ "%s: Missing required configuration values (%lx) while initializing, "
++#~ "aborting\n"
++#~ msgstr ""
++#~ "%s: Beim Initialisieren fehlen die erforderlichen Konfigurationswerte "
++#~ "(%lx), wird abgebrochen\n"
++
++#~ msgid "%s: could not initialize loop, aborting"
++#~ msgstr "%s: Schleife konnte nicht initialisiert werden, wird abgebrochen"
++
++#~ msgid "%s: could not initialize loop, aborting\n"
++#~ msgstr "%s: Schleife konnte nicht initialisiert werden, wird abgebrochen\n"
++
++#~ msgid "%s: %s while initializing signal handlers, aborting"
++#~ msgstr ""
++#~ "%s: %s beim Initialisieren des Signalbehandlungsprogramms, wird "
++#~ "abgebrochen"
++
++#~ msgid "%s: %s while initializing signal handlers, aborting\n"
++#~ msgstr ""
++#~ "%s: %s beim Initialisieren des Signalbehandlungsprogramms, wird "
++#~ "abgebrochen\n"
++
++#~ msgid "%s: %s while initializing network, aborting"
++#~ msgstr "%s: %s beim Initialisieren des Netzwerks, wird abgebrochen"
++
++#~ msgid "%s: %s while initializing network, aborting\n"
++#~ msgstr "%s: %s beim Initialisieren des Netzwerks, wird abgebrochen\n"
++
++#~ msgid "Cannot build GSS-API authentication names, failing."
++#~ msgstr ""
++#~ "GSS-API-Authentifizierungsnamen können nicht gebildet werden, "
++#~ "fehlgeschlagen"
++
++#~ msgid "Can't set kdb keytab's internal context."
++#~ msgstr ""
++#~ "Der interne Kontext von KDBs Schlüsseltabelle kann nicht gesetzt werden."
++
++#~ msgid "Can't register kdb keytab."
++#~ msgstr "Die KDB-Schlüsseltabelle kann nicht registriert werden."
++
++#~ msgid "Can't register acceptor keytab."
++#~ msgstr "Die Empfängerschlüsseltabelle kann nicht registriert werden."
++
++#~ msgid ""
++#~ "Cannot set GSS-API authentication names (keytab not present?), failing."
++#~ msgstr ""
++#~ "GSS-API-Authentifizierungsnamen können nicht gesetzt werden "
++#~ "(Schlüsseltabelle nicht vorhanden?), fehlgeschlagen"
++
++#~ msgid "Cannot initialize acl file: %s"
++#~ msgstr "ACL-Datei kann nicht initialisiert werden: %s"
++
++#~ msgid "%s: Cannot initialize acl file: %s\n"
++#~ msgstr "%s: ACL-Datei kann nicht initialisiert werden: %s\n"
++
++#~ msgid "Cannot detach from tty: %s"
++#~ msgstr "kann nicht vom Terminal gelöst werden: %s"
++
++#~ msgid "Cannot create PID file %s: %s"
++#~ msgstr "PID-Datei %s kann nicht erstellt werden: %s"
++
++#~ msgid "%s: %s while mapping update log (`%s.ulog')\n"
++#~ msgstr "%s: %s beim Abbilden des Aktualisierungsprotokolls (»%s.ulog«)\n"
++
++#~ msgid "%s while mapping update log (`%s.ulog')"
++#~ msgstr "%s beim Abbilden des Aktualisierungsprotokolls (»%s.ulog«)"
++
++#~ msgid "%s: Cannot create IProp RPC service (PROG=%d, VERS=%d)\n"
++#~ msgstr ""
++#~ "%s: IProp-RPC-Dienst kann nicht erstellt werden (PROG=%d, VERS=%d)\n"
++
++#~ msgid "Cannot create IProp RPC service (PROG=%d, VERS=%d), failing."
++#~ msgstr ""
++#~ "IProp-RPC-Dienst kann nicht erstellt werden (PROG=%d, VERS=%d), "
++#~ "fehlgeschlagen"
++
++#~ msgid "%s while getting IProp svc name, failing"
++#~ msgstr "%s beim Holen des IProp-Dienstnamens, fehlgeschlagen"
++
++#~ msgid "%s: %s while getting IProp svc name, failing\n"
++#~ msgstr "%s: %s beim Holen des IProp-Dienstnamens, fehlgeschlagen\n"
++
++#~ msgid "Unable to set RPCSEC_GSS service name (`%s'), failing."
++#~ msgstr ""
++#~ "der RPCSEC_GSS-Dienstname (»%s«) kann nicht gesetzt werden, fehlgeschlagen"
++
++#~ msgid "%s: Unable to set RPCSEC_GSS service name (`%s'), failing.\n"
++#~ msgstr ""
++#~ "%s: der RPCSEC_GSS-Dienstname (»%s«) kann nicht gesetzt werden, "
++#~ "fehlgeschlagen\n"
++
++#~ msgid "GSS-API authentication error %.*s: recursive failure!"
++#~ msgstr "GSS-API-Authentifizierungsfehler %.*s: rekursiver Fehlschlag!"
++
++#~ msgid "skipping unrecognized local address family %d"
++#~ msgstr "nicht erkannte lokale Adressfamilie %d wird übersprungen"
++
++#~ msgid "got routing msg type %d(%s) v%d"
++#~ msgstr "Routing-Meldungstyp %d(%s) v%d erhalten"
++
++#~ msgid "Could not create temp stash file: %s"
++#~ msgstr "Temporäre Ablagedatei konnte nicht erstellt werden: %s"
++
++#~ msgid "ulog_sync_header: could not sync to disk"
++#~ msgstr "ulog_sync_header: kann nicht auf Platte sychronisiert werden"
++
++#~ msgid "%s: attempt to convert non-extended krb5_get_init_creds_opt"
++#~ msgstr ""
++#~ "%s: Es wird versucht, nicht erweiterte »krb5_get_init_creds_opt« "
++#~ "umzuwandeln"
++
++#~ msgid "krb5_sname_to_principal, while adding entries to the database"
++#~ msgstr ""
++#~ "»krb5_sname_to_principal« beim Hinzufügen von Einträgen zur Datenbank"
++
++#~ msgid "krb5_copy_principal, while adding entries to the database"
++#~ msgstr "»krb5_copy_principal« beim Hinzufügen von Einträgen zur Datenbank"
++
++#~ msgid ""
++#~ "Unable to check if SASL EXTERNAL mechanism is supported by LDAP server. "
++#~ "Proceeding anyway ..."
++#~ msgstr ""
++#~ "Es konnte nicht geprüft werden, ob der Mechanismus SASL EXTERNAL vom LDAP-"
++#~ "Server unterstützt wird. Es wird trotzdem fortgesetzt …"
++
++#~ msgid ""
++#~ "SASL EXTERNAL mechanism not supported by LDAP server. Can't perform "
++#~ "certificate-based bind."
++#~ msgstr ""
++#~ "Der Mechanismus SASL EXTERNAL wird nicht vom LDAP-Server unterstützt. Es "
++#~ "kann keine zertifikatbasierte Verbindung hergestellt werden."
++
++#~ msgid "Error reading 'ldap_servers' attribute"
++#~ msgstr "Fehler beim Lesen des Attributs »ldap_servers«"
++
++#~ msgid "Stash file entry corrupt"
++#~ msgstr "Eintrag in der Ablagedatei beschädigt"
++
++#~ msgid "while setting server principal realm"
++#~ msgstr "beim Setzen des Server-Principal-Realms"
++
++#~ msgid "while getting initial ticket\n"
++#~ msgstr "beim Holen eines Anfangs-Tickets\n"
++
++#~ msgid "while destroying ticket cache"
++#~ msgstr "beim Zerstören des Ticket-Zwischenspeichers"
++
++#~ msgid "while closing default ccache"
++#~ msgstr "beim Schließen des Standard-Ccaches"
diff --git a/SOURCES/Add-KDC-policy-pluggable-interface.patch b/SOURCES/Add-KDC-policy-pluggable-interface.patch
new file mode 100644
index 0000000..58f6db8
--- /dev/null
+++ b/SOURCES/Add-KDC-policy-pluggable-interface.patch
@@ -0,0 +1,994 @@
+From 7ed63b6bdeff7b94775432415682051eca479071 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]
+---
+ 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 ++++++++
+ .../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..74af7bd
--- /dev/null
+++ b/SOURCES/Add-PKINIT-UPN-tests-to-t_pkinit.py.patch
@@ -0,0 +1,101 @@
+From aaa3ceb3c9fa8ff206edcd6d66659c5e69e4811d 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)
+---
+ 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-PKINIT-test-case-for-generic-client-cert.patch b/SOURCES/Add-PKINIT-test-case-for-generic-client-cert.patch
new file mode 100644
index 0000000..7b6928e
--- /dev/null
+++ b/SOURCES/Add-PKINIT-test-case-for-generic-client-cert.patch
@@ -0,0 +1,50 @@
+From 5d072bc7e890e18903a18d22ecda7662db1d603e Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Fri, 25 Aug 2017 12:39:14 -0400
+Subject: [PATCH] Add PKINIT test case for generic client cert
+
+In t_pkinit.py, add a test case where a client cert with no extensions
+is authorized via subject and issuer using a pkinit_cert_match string
+attribute.
+
+ticket: 8562
+(cherry picked from commit 8c5d50888aab554239fd51306e79c5213833c898)
+---
+ src/tests/t_pkinit.py | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/src/tests/t_pkinit.py b/src/tests/t_pkinit.py
+index 5a0624de7..22ab81743 100755
+--- a/src/tests/t_pkinit.py
++++ b/src/tests/t_pkinit.py
+@@ -26,6 +26,7 @@ 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')
++generic_p12 = os.path.join(certs, 'generic.p12')
+ path = os.path.join(os.getcwd(), 'testdir', 'tmp-pkinit-certs')
+ path_enc = os.path.join(os.getcwd(), 'testdir', 'tmp-pkinit-certs-enc')
+ 
+@@ -65,6 +66,7 @@ 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_generic_identity = 'PKCS12:%s' % generic_p12
+ p12_enc_identity = 'PKCS12:%s' % user_enc_p12
+ p11_identity = 'PKCS11:soft-pkcs11.so'
+ p11_token_identity = ('PKCS11:module_name=soft-pkcs11.so:'
+@@ -342,6 +344,14 @@ realm.kinit(realm.user_princ,
+             flags=['-X', 'X509_user_identity=%s' % p12_identity],
+             expected_code=1, expected_msg=msg)
+ 
++# Authorize a client cert with no PKINIT extensions using subject and
++# issuer.  (Relies on EKU checking being turned off.)
++rule = '&&<SUBJECT>CN=user$<ISSUER>O=MIT,'
++realm.run([kadminl, 'setstr', realm.user_princ, 'pkinit_cert_match', rule])
++realm.kinit(realm.user_princ,
++            flags=['-X', 'X509_user_identity=%s' % p12_generic_identity])
++realm.klist(realm.user_princ)
++
+ if not have_soft_pkcs11:
+     skip_rest('PKINIT PKCS11 tests', 'soft-pkcs11.so not found')
+ 
diff --git a/SOURCES/Add-a-hash-table-implementation-to-libkrb5support.patch b/SOURCES/Add-a-hash-table-implementation-to-libkrb5support.patch
new file mode 100644
index 0000000..9e188fd
--- /dev/null
+++ b/SOURCES/Add-a-hash-table-implementation-to-libkrb5support.patch
@@ -0,0 +1,657 @@
+From 4250a33a40c14325fb6076cded8e88b5a717ed13 Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Sat, 4 Aug 2018 20:11:09 -0400
+Subject: [PATCH] Add a hash table implementation to libkrb5support
+
+(cherry picked from commit 09e814fe47f5ceeb35bee15ced6e346db8a5e81d)
+[rharwood@redhat.com: gitignore, no utf16]
+---
+ src/include/k5-hashtab.h                      |  79 ++++++
+ src/util/support/Makefile.in                  |  15 +-
+ src/util/support/deps                         |  11 +
+ src/util/support/hashtab.c                    | 243 ++++++++++++++++++
+ src/util/support/libkrb5support-fixed.exports |   5 +
+ src/util/support/t_hashtab.c                  | 176 +++++++++++++
+ 6 files changed, 526 insertions(+), 3 deletions(-)
+ create mode 100644 src/include/k5-hashtab.h
+ create mode 100644 src/util/support/hashtab.c
+ create mode 100644 src/util/support/t_hashtab.c
+
+diff --git a/src/include/k5-hashtab.h b/src/include/k5-hashtab.h
+new file mode 100644
+index 000000000..dc0ef3613
+--- /dev/null
++++ b/src/include/k5-hashtab.h
+@@ -0,0 +1,79 @@
++/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
++/* include/k5-hash.h - hash table interface definitions */
++/*
++ * Copyright (C) 2018 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.
++ */
++
++/*
++ * This file contains declarations for a simple hash table using siphash.  Some
++ * limitations which might need to be addressed in the future:
++ *
++ * - The table does not manage caller memory.  This limitation could be
++ *   addressed by adding an optional free callback to k5_hashtab_create(), to
++ *   be called by k5_hashtab_free() and k5_hashtab_remove().
++ *
++ * - There is no way to iterate over a hash table.
++ *
++ * - k5_hashtab_add() does not check for duplicate entries.
++ */
++
++#ifndef K5_HASH_H
++#define K5_HASH_H
++
++#define K5_HASH_SEED_LEN 16
++
++struct k5_hashtab;
++
++/*
++ * Create a new hash table in *ht_out.  seed must point to random bytes if keys
++ * might be under the control of an attacker; otherwise it may be NULL.
++ * initial_buckets controls the initial allocation of hash buckets; pass zero
++ * to use a default value.  The number of hash buckets will be doubled as the
++ * number of entries increases.  Return 0 on success, ENOMEM on failure.
++ */
++int k5_hashtab_create(const uint8_t seed[K5_HASH_SEED_LEN],
++                      size_t initial_buckets, struct k5_hashtab **ht_out);
++
++/* Release the memory used by a hash table.  Keys and values are the caller's
++ * responsibility. */
++void k5_hashtab_free(struct k5_hashtab *ht);
++
++/* Add an entry to a hash table.  key and val must remain valid until the entry
++ * is removed or the hash table is freed.  The caller must avoid duplicates. */
++int k5_hashtab_add(struct k5_hashtab *ht, const void *key, size_t klen,
++                   void *val);
++
++/* Remove an entry from a hash table by key.  Does not free key or the
++ * associated value.  Return 1 if the key was found and removed, 0 if not. */
++int k5_hashtab_remove(struct k5_hashtab *ht, const void *key, size_t klen);
++
++/* Retrieve a value from a hash table by key. */
++void *k5_hashtab_get(struct k5_hashtab *ht, const void *key, size_t klen);
++
++#endif /* K5_HASH_H */
+diff --git a/src/util/support/Makefile.in b/src/util/support/Makefile.in
+index b3576f0b7..12797068f 100644
+--- a/src/util/support/Makefile.in
++++ b/src/util/support/Makefile.in
+@@ -83,6 +83,7 @@ STLIBOBJS= \
+ 	base64.o \
+ 	json.o \
+ 	hex.o \
++	hashtab.o \
+ 	bcmp.o \
+ 	strerror_r.o \
+ 	dir_filenames.o \
+@@ -110,6 +111,7 @@ LIBOBJS= \
+ 	$(OUTPRE)base64.$(OBJEXT) \
+ 	$(OUTPRE)json.$(OBJEXT) \
+ 	$(OUTPRE)hex.$(OBJEXT) \
++	$(OUTPRE)hashtab.$(OBJEXT) \
+ 	$(OUTPRE)bcmp.$(OBJEXT) \
+ 	$(OUTPRE)strerror_r.$(OBJEXT) \
+ 	$(OUTPRE)dir_filenames.$(OBJEXT) \
+@@ -142,11 +144,13 @@ SRCS=\
+ 	$(srcdir)/t_path.c \
+ 	$(srcdir)/t_json.c \
+ 	$(srcdir)/t_hex.c \
++	$(srcdir)/t_hashtab.c \
+ 	$(srcdir)/zap.c \
+ 	$(srcdir)/path.c \
+ 	$(srcdir)/base64.c \
+ 	$(srcdir)/json.c \
+ 	$(srcdir)/hex.c \
++	$(srcdir)/hashtab.c \
+ 	$(srcdir)/bcmp.c \
+ 	$(srcdir)/strerror_r.c \
+ 	$(srcdir)/dir_filenames.c \
+@@ -225,13 +229,17 @@ t_json: $(T_JSON_OBJS)
+ t_hex: t_hex.o hex.o
+ 	$(CC_LINK) -o $@ t_hex.o hex.o
+ 
++t_hashtab: t_hashtab.o
++	$(CC_LINK) -o $@ t_hashtab.o
++
+ t_unal: t_unal.o
+ 	$(CC_LINK) -o t_unal t_unal.o
+ 
+ t_utf8: t_utf8.o utf8.o
+ 	$(CC_LINK) -o t_utf8 t_utf8.o utf8.o
+ 
+-TEST_PROGS= t_k5buf t_path t_path_win t_base64 t_json t_hex t_unal t_utf8
++TEST_PROGS= t_k5buf t_path t_path_win t_base64 t_json t_hex t_hashtab t_unal \
++	t_utf8
+ 
+ check-unix: $(TEST_PROGS)
+ 	./t_k5buf
+@@ -240,14 +248,15 @@ check-unix: $(TEST_PROGS)
+ 	./t_base64
+ 	./t_json
+ 	./t_hex
++	./t_hashtab
+ 	./t_unal
+ 	./t_utf8
+ 
+ clean:
+ 	$(RM) t_k5buf.o t_k5buf t_unal.o t_unal path_win.o path_win
+ 	$(RM) t_path_win.o t_path_win t_path.o t_path t_base64.o t_base64
+-	$(RM) t_json.o t_json t_hex.o t_hex libkrb5support.exports
+-	$(RM) t_utf8.o t_utf8
++	$(RM) t_json.o t_json t_hex.o t_hex t_hashtab.o t_hashtab
++	$(RM) t_utf8.o t_utf8 libkrb5support.exports
+ 
+ @lib_frag@
+ @libobj_frag@
+diff --git a/src/util/support/deps b/src/util/support/deps
+index 551843357..d43baea13 100644
+--- a/src/util/support/deps
++++ b/src/util/support/deps
+@@ -65,6 +65,10 @@ t_json.so t_json.po $(OUTPRE)t_json.$(OBJEXT): $(top_srcdir)/include/k5-json.h \
+ t_hex.so t_hex.po $(OUTPRE)t_hex.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+   $(top_srcdir)/include/k5-hex.h $(top_srcdir)/include/k5-platform.h \
+   $(top_srcdir)/include/k5-thread.h t_hex.c
++t_hashtab.so t_hashtab.po $(OUTPRE)t_hashtab.$(OBJEXT): \
++  $(BUILDTOP)/include/autoconf.h $(top_srcdir)/include/k5-hashtab.h \
++  $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-queue.h \
++  $(top_srcdir)/include/k5-thread.h hashtab.c t_hashtab.c
+ zap.so zap.po $(OUTPRE)zap.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+   $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \
+   zap.c
+@@ -81,12 +85,19 @@ json.so json.po $(OUTPRE)json.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ hex.so hex.po $(OUTPRE)hex.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+   $(top_srcdir)/include/k5-hex.h $(top_srcdir)/include/k5-platform.h \
+   $(top_srcdir)/include/k5-thread.h hex.c
++hashtab.so hashtab.po $(OUTPRE)hashtab.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
++  $(top_srcdir)/include/k5-hashtab.h $(top_srcdir)/include/k5-platform.h \
++  $(top_srcdir)/include/k5-queue.h $(top_srcdir)/include/k5-thread.h \
++  hashtab.c
+ bcmp.so bcmp.po $(OUTPRE)bcmp.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+   $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \
+   bcmp.c
+ strerror_r.so strerror_r.po $(OUTPRE)strerror_r.$(OBJEXT): \
+   $(BUILDTOP)/include/autoconf.h $(top_srcdir)/include/k5-platform.h \
+   $(top_srcdir)/include/k5-thread.h strerror_r.c
++dir_filenames.so dir_filenames.po $(OUTPRE)dir_filenames.$(OBJEXT): \
++  $(BUILDTOP)/include/autoconf.h $(top_srcdir)/include/k5-platform.h \
++  $(top_srcdir)/include/k5-thread.h dir_filenames.c
+ t_utf8.so t_utf8.po $(OUTPRE)t_utf8.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+   $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \
+   $(top_srcdir)/include/k5-utf8.h t_utf8.c
+diff --git a/src/util/support/hashtab.c b/src/util/support/hashtab.c
+new file mode 100644
+index 000000000..e04e491b2
+--- /dev/null
++++ b/src/util/support/hashtab.c
+@@ -0,0 +1,243 @@
++/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
++/* util/support/hash.c - hash table implementation */
++/*
++ * Copyright (C) 2018 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-platform.h"
++#include "k5-hashtab.h"
++#include "k5-queue.h"
++
++struct entry {
++    const void *key;
++    size_t klen;
++    void *val;
++    K5_SLIST_ENTRY(entry) next;
++};
++
++struct k5_hashtab {
++    uint64_t k0;
++    uint64_t k1;
++    size_t nbuckets;
++    size_t nentries;
++    K5_SLIST_HEAD(bucket_list, entry) *buckets;
++};
++
++/* Return x rotated to the left by r bits. */
++static inline uint64_t
++rotl64(uint64_t x, int r)
++{
++    return (x << r) | (x >> (64 - r));
++}
++
++static inline void
++sipround(uint64_t *v0, uint64_t *v1, uint64_t *v2, uint64_t *v3)
++{
++    *v0 += *v1;
++    *v2 += *v3;
++    *v1 = rotl64(*v1, 13) ^ *v0;
++    *v3 = rotl64(*v3, 16) ^ *v2;
++    *v0 = rotl64(*v0, 32);
++    *v2 += *v1;
++    *v0 += *v3;
++    *v1 = rotl64(*v1, 17) ^ *v2;
++    *v3 = rotl64(*v3, 21) ^ *v0;
++    *v2 = rotl64(*v2, 32);
++}
++
++/* SipHash-2-4 from https://131002.net/siphash/siphash.pdf (Jean-Philippe
++ * Aumasson and Daniel J. Bernstein) */
++static uint64_t
++siphash24(const uint8_t *data, size_t len, uint64_t k0, uint64_t k1)
++{
++    uint64_t v0 = k0 ^ 0x736F6D6570736575;
++    uint64_t v1 = k1 ^ 0x646F72616E646F6D;
++    uint64_t v2 = k0 ^ 0x6C7967656E657261;
++    uint64_t v3 = k1 ^ 0x7465646279746573;
++    uint64_t mi;
++    const uint8_t *p, *end = data + (len - len % 8);
++    uint8_t last[8] = { 0 };
++
++    /* Process each full 8-byte chunk of data. */
++    for (p = data; p < end; p += 8) {
++        mi = load_64_le(p);
++        v3 ^= mi;
++        sipround(&v0, &v1, &v2, &v3);
++        sipround(&v0, &v1, &v2, &v3);
++        v0 ^= mi;
++    }
++
++    /* Process the last 0-7 bytes followed by the length mod 256. */
++    memcpy(last, end, len % 8);
++    last[7] = len & 0xFF;
++    mi = load_64_le(last);
++    v3 ^= mi;
++    sipround(&v0, &v1, &v2, &v3);
++    sipround(&v0, &v1, &v2, &v3);
++    v0 ^= mi;
++
++    /* Finalize. */
++    v2 ^= 0xFF;
++    sipround(&v0, &v1, &v2, &v3);
++    sipround(&v0, &v1, &v2, &v3);
++    sipround(&v0, &v1, &v2, &v3);
++    sipround(&v0, &v1, &v2, &v3);
++    return v0 ^ v1 ^ v2 ^ v3;
++}
++
++int
++k5_hashtab_create(const uint8_t seed[K5_HASH_SEED_LEN], size_t initial_buckets,
++                  struct k5_hashtab **ht_out)
++{
++    struct k5_hashtab *ht;
++
++    *ht_out = NULL;
++
++    ht = malloc(sizeof(*ht));
++    if (ht == NULL)
++        return ENOMEM;
++
++    if (seed != NULL) {
++        ht->k0 = load_64_le(seed);
++        ht->k1 = load_64_le(seed + 8);
++    } else {
++        ht->k0 = ht->k1 = 0;
++    }
++    ht->nbuckets = (initial_buckets > 0) ? initial_buckets : 64;
++    ht->nentries = 0;
++    ht->buckets = calloc(ht->nbuckets, sizeof(*ht->buckets));
++    if (ht->buckets == NULL) {
++        free(ht);
++        return ENOMEM;
++    }
++
++    *ht_out = ht;
++    return 0;
++}
++
++void
++k5_hashtab_free(struct k5_hashtab *ht)
++{
++    size_t i;
++    struct entry *ent;
++
++    for (i = 0; i < ht->nbuckets; i++) {
++        while (!K5_SLIST_EMPTY(&ht->buckets[i])) {
++            ent = K5_SLIST_FIRST(&ht->buckets[i]);
++            K5_SLIST_REMOVE_HEAD(&ht->buckets[i], next);
++            free(ent);
++        }
++    }
++    free(ht->buckets);
++    free(ht);
++}
++
++static int
++resize_table(struct k5_hashtab *ht)
++{
++    size_t i, j, newsize = ht->nbuckets * 2;
++    struct bucket_list *newbuckets;
++    struct entry *ent;
++
++    newbuckets = calloc(newsize, sizeof(*newbuckets));
++    if (newbuckets == NULL)
++        return ENOMEM;
++
++    /* Rehash all the entries into the new buckets. */
++    for (i = 0; i < ht->nbuckets; i++) {
++        while (!K5_SLIST_EMPTY(&ht->buckets[i])) {
++            ent = K5_SLIST_FIRST(&ht->buckets[i]);
++            j = siphash24(ent->key, ent->klen, ht->k0, ht->k1) % newsize;
++            K5_SLIST_REMOVE_HEAD(&ht->buckets[i], next);
++            K5_SLIST_INSERT_HEAD(&newbuckets[j], ent, next);
++        }
++    }
++
++    free(ht->buckets);
++    ht->buckets = newbuckets;
++    ht->nbuckets = newsize;
++    return 0;
++}
++
++int
++k5_hashtab_add(struct k5_hashtab *ht, const void *key, size_t klen, void *val)
++{
++    size_t i;
++    struct entry *ent;
++
++    if (ht->nentries == ht->nbuckets) {
++        if (resize_table(ht) != 0)
++            return ENOMEM;
++    }
++
++    ent = malloc(sizeof(*ent));
++    if (ent == NULL)
++        return ENOMEM;
++    ent->key = key;
++    ent->klen = klen;
++    ent->val = val;
++
++    i = siphash24(key, klen, ht->k0, ht->k1) % ht->nbuckets;
++    K5_SLIST_INSERT_HEAD(&ht->buckets[i], ent, next);
++
++    ht->nentries++;
++    return 0;
++}
++
++int
++k5_hashtab_remove(struct k5_hashtab *ht, const void *key, size_t klen)
++{
++    size_t i;
++    struct entry *ent;
++
++    i = siphash24(key, klen, ht->k0, ht->k1) % ht->nbuckets;
++    K5_SLIST_FOREACH(ent, &ht->buckets[i], next) {
++        if (ent->klen == klen && memcmp(ent->key, key, klen) == 0) {
++            K5_SLIST_REMOVE(&ht->buckets[i], ent, entry, next);
++            free(ent);
++            ht->nentries--;
++            return 1;
++        }
++    }
++    return 0;
++}
++
++void *
++k5_hashtab_get(struct k5_hashtab *ht, const void *key, size_t klen)
++{
++    size_t i;
++    struct entry *ent;
++
++    i = siphash24(key, klen, ht->k0, ht->k1) % ht->nbuckets;
++    K5_SLIST_FOREACH(ent, &ht->buckets[i], next) {
++        if (ent->klen == klen && memcmp(ent->key, key, klen) == 0)
++            return ent->val;
++    }
++    return NULL;
++}
+diff --git a/src/util/support/libkrb5support-fixed.exports b/src/util/support/libkrb5support-fixed.exports
+index 6193d7331..c63c5fbc3 100644
+--- a/src/util/support/libkrb5support-fixed.exports
++++ b/src/util/support/libkrb5support-fixed.exports
+@@ -16,6 +16,11 @@ k5_get_error
+ k5_free_error
+ k5_clear_error
+ k5_set_error_info_callout_fn
++k5_hashtab_add
++k5_hashtab_create
++k5_hashtab_free
++k5_hashtab_get
++k5_hashtab_remove
+ k5_hex_decode
+ k5_hex_encode
+ k5_json_array_add
+diff --git a/src/util/support/t_hashtab.c b/src/util/support/t_hashtab.c
+new file mode 100644
+index 000000000..f51abc4f1
+--- /dev/null
++++ b/src/util/support/t_hashtab.c
+@@ -0,0 +1,176 @@
++/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
++/* util/support/t_hash.c - tests for hash table code */
++/*
++ * Copyright (C) 2018 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.
++ */
++
++/* hash.c has no linker dependencies, so we can simply include its source code
++ * to test its static functions and look inside its structures. */
++#include "hashtab.c"
++
++/* These match the sip64 test vectors in the reference C implementation of
++ * siphash at https://github.com/veorq/SipHash */
++const uint64_t vectors[64] = {
++    0x726FDB47DD0E0E31,
++    0x74F839C593DC67FD,
++    0x0D6C8009D9A94F5A,
++    0x85676696D7FB7E2D,
++    0xCF2794E0277187B7,
++    0x18765564CD99A68D,
++    0xCBC9466E58FEE3CE,
++    0xAB0200F58B01D137,
++    0x93F5F5799A932462,
++    0x9E0082DF0BA9E4B0,
++    0x7A5DBBC594DDB9F3,
++    0xF4B32F46226BADA7,
++    0x751E8FBC860EE5FB,
++    0x14EA5627C0843D90,
++    0xF723CA908E7AF2EE,
++    0xA129CA6149BE45E5,
++    0x3F2ACC7F57C29BDB,
++    0x699AE9F52CBE4794,
++    0x4BC1B3F0968DD39C,
++    0xBB6DC91DA77961BD,
++    0xBED65CF21AA2EE98,
++    0xD0F2CBB02E3B67C7,
++    0x93536795E3A33E88,
++    0xA80C038CCD5CCEC8,
++    0xB8AD50C6F649AF94,
++    0xBCE192DE8A85B8EA,
++    0x17D835B85BBB15F3,
++    0x2F2E6163076BCFAD,
++    0xDE4DAAACA71DC9A5,
++    0xA6A2506687956571,
++    0xAD87A3535C49EF28,
++    0x32D892FAD841C342,
++    0x7127512F72F27CCE,
++    0xA7F32346F95978E3,
++    0x12E0B01ABB051238,
++    0x15E034D40FA197AE,
++    0x314DFFBE0815A3B4,
++    0x027990F029623981,
++    0xCADCD4E59EF40C4D,
++    0x9ABFD8766A33735C,
++    0x0E3EA96B5304A7D0,
++    0xAD0C42D6FC585992,
++    0x187306C89BC215A9,
++    0xD4A60ABCF3792B95,
++    0xF935451DE4F21DF2,
++    0xA9538F0419755787,
++    0xDB9ACDDFF56CA510,
++    0xD06C98CD5C0975EB,
++    0xE612A3CB9ECBA951,
++    0xC766E62CFCADAF96,
++    0xEE64435A9752FE72,
++    0xA192D576B245165A,
++    0x0A8787BF8ECB74B2,
++    0x81B3E73D20B49B6F,
++    0x7FA8220BA3B2ECEA,
++    0x245731C13CA42499,
++    0xB78DBFAF3A8D83BD,
++    0xEA1AD565322A1A0B,
++    0x60E61C23A3795013,
++    0x6606D7E446282B93,
++    0x6CA4ECB15C5F91E1,
++    0x9F626DA15C9625F3,
++    0xE51B38608EF25F57,
++    0x958A324CEB064572
++};
++
++static void
++test_siphash()
++{
++    uint8_t seq[64];
++    uint64_t k0, k1, hval;
++    size_t i;
++
++    for (i = 0; i < sizeof(seq); i++)
++        seq[i] = i;
++    k0 = load_64_le(seq);
++    k1 = load_64_le(seq + 8);
++
++    for (i = 0; i < sizeof(seq); i++) {
++        hval = siphash24(seq, i, k0, k1);
++        assert(hval == vectors[i]);
++    }
++}
++
++static void
++test_hashtab()
++{
++    int st;
++    struct k5_hashtab *ht;
++    size_t i;
++    char zeros[100] = { 0 };
++
++    st = k5_hashtab_create(NULL, 4, &ht);
++    assert(st == 0 && ht != NULL && ht->nentries == 0);
++
++    st = k5_hashtab_add(ht, "abc", 3, &st);
++    assert(st == 0 && ht->nentries == 1);
++    assert(k5_hashtab_get(ht, "abc", 3) == &st);
++    assert(k5_hashtab_get(ht, "bcde", 4) == NULL);
++
++    st = k5_hashtab_add(ht, "bcde", 4, &ht);
++    assert(st == 0 && ht->nentries == 2);
++    assert(k5_hashtab_get(ht, "abc", 3) == &st);
++    assert(k5_hashtab_get(ht, "bcde", 4) == &ht);
++
++    k5_hashtab_remove(ht, "abc", 3);
++    assert(ht->nentries == 1);
++    assert(k5_hashtab_get(ht, "abc", 3) == NULL);
++    assert(k5_hashtab_get(ht, "bcde", 4) == &ht);
++
++    k5_hashtab_remove(ht, "bcde", 4);
++    assert(ht->nentries == 0);
++    assert(k5_hashtab_get(ht, "abc", 3) == NULL);
++    assert(k5_hashtab_get(ht, "bcde", 4) == NULL);
++
++    for (i = 0; i < sizeof(zeros); i++) {
++        st = k5_hashtab_add(ht, zeros, i, zeros + i);
++        assert(st == 0 && ht->nentries == i + 1 && ht->nbuckets >= i + 1);
++    }
++    for (i = 0; i < sizeof(zeros); i++) {
++        assert(k5_hashtab_get(ht, zeros, i) == zeros + i);
++        k5_hashtab_remove(ht, zeros, i);
++        assert(ht->nentries == sizeof(zeros) - i - 1);
++        if (i > 0)
++            assert(k5_hashtab_get(ht, zeros, i - 1) == NULL);
++    }
++
++    k5_hashtab_free(ht);
++}
++
++int
++main()
++{
++    test_siphash();
++    test_hashtab();
++    return 0;
++}
diff --git a/SOURCES/Add-certauth-pluggable-interface.patch b/SOURCES/Add-certauth-pluggable-interface.patch
new file mode 100644
index 0000000..a6f2525
--- /dev/null
+++ b/SOURCES/Add-certauth-pluggable-interface.patch
@@ -0,0 +1,1146 @@
+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)
+---
+ 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 ++
+ .../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 +
+ .../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-k5_dir_filenames-to-libkrb5support.patch b/SOURCES/Add-k5_dir_filenames-to-libkrb5support.patch
new file mode 100644
index 0000000..a6c9a83
--- /dev/null
+++ b/SOURCES/Add-k5_dir_filenames-to-libkrb5support.patch
@@ -0,0 +1,224 @@
+From a3f548a88d0bbf16ccc60843fb72e02e32a765f3 Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Tue, 5 Jun 2018 14:01:05 -0400
+Subject: [PATCH] Add k5_dir_filenames() to libkrb5support
+
+Add a support function to get a list of filenames from a directory in
+sorted order.
+
+(cherry picked from commit 27534121eb39089ff4335d8b465027e9ba783682)
+(cherry picked from commit 9010a0dbf59771cb0a9c1e6fd5a18a92a1200ca7)
+[rharwood@redhat.com: exports file context doesn't match]
+---
+ src/include/k5-platform.h                     |   7 +
+ src/util/support/Makefile.in                  |   3 +
+ src/util/support/dir_filenames.c              | 135 ++++++++++++++++++
+ src/util/support/libkrb5support-fixed.exports |   2 +
+ 4 files changed, 147 insertions(+)
+ create mode 100644 src/util/support/dir_filenames.c
+
+diff --git a/src/include/k5-platform.h b/src/include/k5-platform.h
+index 994f46323..5a58ccba2 100644
+--- a/src/include/k5-platform.h
++++ b/src/include/k5-platform.h
+@@ -44,6 +44,8 @@
+  * + constant time memory comparison
+  * + path manipulation
+  * + _, N_, dgettext, bindtextdomain (for localization)
++ * + getopt_long
++ * + fetching filenames from a directory
+  */
+ 
+ #ifndef K5_PLATFORM_H
+@@ -1099,4 +1101,9 @@ extern int k5_getopt_long(int nargc, char **nargv, char *options,
+ #define getopt_long k5_getopt_long
+ #endif /* HAVE_GETOPT_LONG */
+ 
++/* Set *fnames_out to a null-terminated list of filenames within dirname,
++ * sorted according to strcmp().  Return 0 on success, or ENOENT/ENOMEM. */
++int k5_dir_filenames(const char *dirname, char ***fnames_out);
++void k5_free_filenames(char **fnames);
++
+ #endif /* K5_PLATFORM_H */
+diff --git a/src/util/support/Makefile.in b/src/util/support/Makefile.in
+index 17bcd2a67..9326742d7 100644
+--- a/src/util/support/Makefile.in
++++ b/src/util/support/Makefile.in
+@@ -84,6 +84,7 @@ STLIBOBJS= \
+ 	json.o \
+ 	bcmp.o \
+ 	strerror_r.o \
++	dir_filenames.o \
+ 	$(GETTIMEOFDAY_ST_OBJ) \
+ 	$(IPC_ST_OBJ) \
+ 	$(STRLCPY_ST_OBJ) \
+@@ -109,6 +110,7 @@ LIBOBJS= \
+ 	$(OUTPRE)json.$(OBJEXT) \
+ 	$(OUTPRE)bcmp.$(OBJEXT) \
+ 	$(OUTPRE)strerror_r.$(OBJEXT) \
++	$(OUTPRE)dir_filenames.$(OBJEXT) \
+ 	$(GETTIMEOFDAY_OBJ) \
+ 	$(IPC_OBJ) \
+ 	$(STRLCPY_OBJ) \
+@@ -143,6 +145,7 @@ SRCS=\
+ 	$(srcdir)/json.c \
+ 	$(srcdir)/bcmp.c \
+ 	$(srcdir)/strerror_r.c \
++	$(srcdir)/dir_filenames.c \
+ 	$(srcdir)/t_utf8.c \
+ 	$(srcdir)/getopt.c \
+ 	$(srcdir)/getopt_long.c
+diff --git a/src/util/support/dir_filenames.c b/src/util/support/dir_filenames.c
+new file mode 100644
+index 000000000..9312b0238
+--- /dev/null
++++ b/src/util/support/dir_filenames.c
+@@ -0,0 +1,135 @@
++/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
++/* util/support/dir_filenames.c - fetch filenames in a directory */
++/*
++ * Copyright (C) 2018 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-platform.h"
++
++void
++k5_free_filenames(char **fnames)
++{
++    char **fn;
++
++    for (fn = fnames; fn != NULL && *fn != NULL; fn++)
++        free(*fn);
++    free(fnames);
++}
++
++/* Resize the filename list and add a name. */
++static int
++add_filename(char ***fnames, int *n_fnames, const char *name)
++{
++    char **newlist;
++
++    newlist = realloc(*fnames, (*n_fnames + 2) * sizeof(*newlist));
++    if (newlist == NULL)
++        return ENOMEM;
++    *fnames = newlist;
++    newlist[*n_fnames] = strdup(name);
++    if (newlist[*n_fnames] == NULL)
++        return ENOMEM;
++    (*n_fnames)++;
++    newlist[*n_fnames] = NULL;
++    return 0;
++}
++
++static int
++compare_with_strcmp(const void *a, const void *b)
++{
++    return strcmp(*(char **)a, *(char **)b);
++}
++
++#ifdef _WIN32
++
++int
++k5_dir_filenames(const char *dirname, char ***fnames_out)
++{
++    char *wildcard;
++    WIN32_FIND_DATA ffd;
++    HANDLE handle;
++    char **fnames = NULL;
++    int n_fnames = 0;
++
++    *fnames_out = NULL;
++
++    if (asprintf(&wildcard, "%s\\*", dirname) < 0)
++        return ENOMEM;
++    handle = FindFirstFile(wildcard, &ffd);
++    free(wildcard);
++    if (handle == INVALID_HANDLE_VALUE)
++        return ENOENT;
++
++    do {
++        if (add_filename(&fnames, &n_fnames, &ffd.cFileName) != 0) {
++            k5_free_filenames(fnames);
++            FindClose(handle);
++            return ENOMEM;
++        }
++    } while (FindNextFile(handle, &ffd) != 0);
++
++    FindClose(handle);
++    qsort(fnames, n_fnames, sizeof(*fnames), compare_with_strcmp);
++    *fnames_out = fnames;
++    return 0;
++}
++
++#else /* _WIN32 */
++
++#include <dirent.h>
++
++int
++k5_dir_filenames(const char *dirname, char ***fnames_out)
++{
++    DIR *dir;
++    struct dirent *ent;
++    char **fnames = NULL;
++    int n_fnames = 0;
++
++    *fnames_out = NULL;
++
++    dir = opendir(dirname);
++    if (dir == NULL)
++        return ENOENT;
++
++    while ((ent = readdir(dir)) != NULL) {
++        if (add_filename(&fnames, &n_fnames, ent->d_name) != 0) {
++            k5_free_filenames(fnames);
++            closedir(dir);
++            return ENOMEM;
++        }
++    }
++
++    closedir(dir);
++    qsort(fnames, n_fnames, sizeof(*fnames), compare_with_strcmp);
++    *fnames_out = fnames;
++    return 0;
++}
++
++#endif /* not _WIN32 */
+diff --git a/src/util/support/libkrb5support-fixed.exports b/src/util/support/libkrb5support-fixed.exports
+index d5d4177b7..2cdcddfe0 100644
+--- a/src/util/support/libkrb5support-fixed.exports
++++ b/src/util/support/libkrb5support-fixed.exports
+@@ -52,6 +52,8 @@ k5_path_isabs
+ k5_path_join
+ k5_path_split
+ k5_strerror_r
++k5_dir_filenames
++k5_free_filenames
+ krb5int_key_register
+ krb5int_key_delete
+ krb5int_getspecific
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..0ac868b
--- /dev/null
+++ b/SOURCES/Add-k5test-expected_msg-expected_trace.patch
@@ -0,0 +1,96 @@
+From 6ad27ff3bde8911a6f873269a61924937d45cd8c 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]
+---
+ 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-libkrb5support-hex-functions-and-tests.patch b/SOURCES/Add-libkrb5support-hex-functions-and-tests.patch
new file mode 100644
index 0000000..0ab3952
--- /dev/null
+++ b/SOURCES/Add-libkrb5support-hex-functions-and-tests.patch
@@ -0,0 +1,480 @@
+From 795c3972220e97bf7bb6557a424c9d246132ac84 Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Mon, 19 Feb 2018 00:51:44 -0500
+Subject: [PATCH] Add libkrb5support hex functions and tests
+
+(cherry picked from commit 720dea558da0062d3cea4385327161e62cf09a5e)
+[rharwood@redhat.com: gitignore, backport around no utf16]
+---
+ src/include/k5-hex.h                          |  53 ++++++
+ src/util/support/Makefile.in                  |  13 +-
+ src/util/support/deps                         |   6 +
+ src/util/support/hex.c                        | 116 ++++++++++++
+ src/util/support/libkrb5support-fixed.exports |   2 +
+ src/util/support/t_hex.c                      | 169 ++++++++++++++++++
+ 6 files changed, 357 insertions(+), 2 deletions(-)
+ create mode 100644 src/include/k5-hex.h
+ create mode 100644 src/util/support/hex.c
+ create mode 100644 src/util/support/t_hex.c
+
+diff --git a/src/include/k5-hex.h b/src/include/k5-hex.h
+new file mode 100644
+index 000000000..75bd2cb19
+--- /dev/null
++++ b/src/include/k5-hex.h
+@@ -0,0 +1,53 @@
++/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
++/* include/k5-hex.h - libkrb5support hex encoding/decoding declarations */
++/*
++ * Copyright (C) 2018 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.
++ */
++
++#ifndef K5_HEX_H
++#define K5_HEX_H
++
++#include "k5-platform.h"
++
++/*
++ * Encode len bytes in hex, placing the result in allocated storage in
++ * *hex_out.  Use uppercase hex digits if uppercase is non-zero.  Return 0 on
++ * success, ENOMEM on error.
++ */
++int k5_hex_encode(const void *bytes, size_t len, int uppercase,
++                  char **hex_out);
++
++/*
++ * Decode hex bytes, placing the result in allocated storage in *bytes_out and
++ * *len_out.  Null-terminate the result (primarily for decoding passwords in
++ * libkdb_ldap).  Return 0 on success, ENOMEM or EINVAL on error.
++ */
++int k5_hex_decode(const char *hex, uint8_t **bytes_out, size_t *len_out);
++
++#endif /* K5_HEX_H */
+diff --git a/src/util/support/Makefile.in b/src/util/support/Makefile.in
+index 9326742d7..b3576f0b7 100644
+--- a/src/util/support/Makefile.in
++++ b/src/util/support/Makefile.in
+@@ -82,6 +82,7 @@ STLIBOBJS= \
+ 	path.o \
+ 	base64.o \
+ 	json.o \
++	hex.o \
+ 	bcmp.o \
+ 	strerror_r.o \
+ 	dir_filenames.o \
+@@ -108,6 +109,7 @@ LIBOBJS= \
+ 	$(OUTPRE)path.$(OBJEXT) \
+ 	$(OUTPRE)base64.$(OBJEXT) \
+ 	$(OUTPRE)json.$(OBJEXT) \
++	$(OUTPRE)hex.$(OBJEXT) \
+ 	$(OUTPRE)bcmp.$(OBJEXT) \
+ 	$(OUTPRE)strerror_r.$(OBJEXT) \
+ 	$(OUTPRE)dir_filenames.$(OBJEXT) \
+@@ -139,10 +141,12 @@ SRCS=\
+ 	$(srcdir)/t_unal.c \
+ 	$(srcdir)/t_path.c \
+ 	$(srcdir)/t_json.c \
++	$(srcdir)/t_hex.c \
+ 	$(srcdir)/zap.c \
+ 	$(srcdir)/path.c \
+ 	$(srcdir)/base64.c \
+ 	$(srcdir)/json.c \
++	$(srcdir)/hex.c \
+ 	$(srcdir)/bcmp.c \
+ 	$(srcdir)/strerror_r.c \
+ 	$(srcdir)/dir_filenames.c \
+@@ -218,13 +222,16 @@ T_JSON_OBJS= t_json.o json.o base64.o k5buf.o $(PRINTF_ST_OBJ)
+ t_json: $(T_JSON_OBJS)
+ 	$(CC_LINK) -o $@ $(T_JSON_OBJS)
+ 
++t_hex: t_hex.o hex.o
++	$(CC_LINK) -o $@ t_hex.o hex.o
++
+ t_unal: t_unal.o
+ 	$(CC_LINK) -o t_unal t_unal.o
+ 
+ t_utf8: t_utf8.o utf8.o
+ 	$(CC_LINK) -o t_utf8 t_utf8.o utf8.o
+ 
+-TEST_PROGS= t_k5buf t_path t_path_win t_base64 t_json t_unal t_utf8
++TEST_PROGS= t_k5buf t_path t_path_win t_base64 t_json t_hex t_unal t_utf8
+ 
+ check-unix: $(TEST_PROGS)
+ 	./t_k5buf
+@@ -232,13 +239,15 @@ check-unix: $(TEST_PROGS)
+ 	./t_path_win
+ 	./t_base64
+ 	./t_json
++	./t_hex
+ 	./t_unal
+ 	./t_utf8
+ 
+ clean:
+ 	$(RM) t_k5buf.o t_k5buf t_unal.o t_unal path_win.o path_win
+ 	$(RM) t_path_win.o t_path_win t_path.o t_path t_base64.o t_base64
+-	$(RM) t_json.o t_json libkrb5support.exports t_utf8.o t_utf8
++	$(RM) t_json.o t_json t_hex.o t_hex libkrb5support.exports
++	$(RM) t_utf8.o t_utf8
+ 
+ @lib_frag@
+ @libobj_frag@
+diff --git a/src/util/support/deps b/src/util/support/deps
+index 4dff014f4..551843357 100644
+--- a/src/util/support/deps
++++ b/src/util/support/deps
+@@ -62,6 +62,9 @@ t_path.so t_path.po $(OUTPRE)t_path.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+   t_path.c
+ t_json.so t_json.po $(OUTPRE)t_json.$(OBJEXT): $(top_srcdir)/include/k5-json.h \
+   t_json.c
++t_hex.so t_hex.po $(OUTPRE)t_hex.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
++  $(top_srcdir)/include/k5-hex.h $(top_srcdir)/include/k5-platform.h \
++  $(top_srcdir)/include/k5-thread.h t_hex.c
+ zap.so zap.po $(OUTPRE)zap.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+   $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \
+   zap.c
+@@ -75,6 +78,9 @@ json.so json.po $(OUTPRE)json.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+   $(top_srcdir)/include/k5-base64.h $(top_srcdir)/include/k5-buf.h \
+   $(top_srcdir)/include/k5-json.h $(top_srcdir)/include/k5-platform.h \
+   $(top_srcdir)/include/k5-thread.h json.c
++hex.so hex.po $(OUTPRE)hex.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
++  $(top_srcdir)/include/k5-hex.h $(top_srcdir)/include/k5-platform.h \
++  $(top_srcdir)/include/k5-thread.h hex.c
+ bcmp.so bcmp.po $(OUTPRE)bcmp.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+   $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \
+   bcmp.c
+diff --git a/src/util/support/hex.c b/src/util/support/hex.c
+new file mode 100644
+index 000000000..4407ff9ff
+--- /dev/null
++++ b/src/util/support/hex.c
+@@ -0,0 +1,116 @@
++/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
++/* util/support/hex.c - hex encoding/decoding implementation */
++/*
++ * Copyright (C) 2018 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-platform.h>
++#include <k5-hex.h>
++#include <ctype.h>
++
++static inline char
++hex_digit(uint8_t bval, int uppercase)
++{
++    assert(bval >= 0 && bval <= 0xF);
++    if (bval < 10)
++        return '0' + bval;
++    else if (uppercase)
++        return 'A' + (bval - 10);
++    else
++        return 'a' + (bval - 10);
++}
++
++int
++k5_hex_encode(const void *bytes, size_t len, int uppercase, char **hex_out)
++{
++    size_t i;
++    const uint8_t *p = bytes;
++    char *hex;
++
++    *hex_out = NULL;
++
++    hex = malloc(len * 2 + 1);
++    if (hex == NULL)
++        return ENOMEM;
++
++    for (i = 0; i < len; i++) {
++        hex[i * 2] = hex_digit(p[i] >> 4, uppercase);
++        hex[i * 2 + 1] = hex_digit(p[i] & 0xF, uppercase);
++    }
++    hex[len * 2] = '\0';
++
++    *hex_out = hex;
++    return 0;
++}
++
++/* Decode a hex digit.  Return 0-15 on success, -1 on invalid input. */
++static inline int
++decode_hexchar(unsigned char c)
++{
++    if (isdigit(c))
++        return c - '0';
++    if (c >= 'A' && c <= 'F')
++        return c - 'A' + 10;
++    if (c >= 'a' && c <= 'f')
++        return c - 'a' + 10;
++    return -1;
++}
++
++int
++k5_hex_decode(const char *hex, uint8_t **bytes_out, size_t *len_out)
++{
++    size_t hexlen, i;
++    int h1, h2;
++    uint8_t *bytes;
++
++    *bytes_out = NULL;
++    *len_out = 0;
++
++    hexlen = strlen(hex);
++    if (hexlen % 2 != 0)
++        return EINVAL;
++    bytes = malloc(hexlen / 2 + 1);
++    if (bytes == NULL)
++        return ENOMEM;
++
++    for (i = 0; i < hexlen / 2; i++) {
++        h1 = decode_hexchar(hex[i * 2]);
++        h2 = decode_hexchar(hex[i * 2 + 1]);
++        if (h1 == -1 || h2 == -1) {
++            free(bytes);
++            return EINVAL;
++        }
++        bytes[i] = h1 * 16 + h2;
++    }
++    bytes[i] = 0;
++
++    *bytes_out = bytes;
++    *len_out = hexlen / 2;
++    return 0;
++}
+diff --git a/src/util/support/libkrb5support-fixed.exports b/src/util/support/libkrb5support-fixed.exports
+index 2cdcddfe0..6193d7331 100644
+--- a/src/util/support/libkrb5support-fixed.exports
++++ b/src/util/support/libkrb5support-fixed.exports
+@@ -16,6 +16,8 @@ k5_get_error
+ k5_free_error
+ k5_clear_error
+ k5_set_error_info_callout_fn
++k5_hex_decode
++k5_hex_encode
+ k5_json_array_add
+ k5_json_array_create
+ k5_json_array_fmt
+diff --git a/src/util/support/t_hex.c b/src/util/support/t_hex.c
+new file mode 100644
+index 000000000..a586a1bc8
+--- /dev/null
++++ b/src/util/support/t_hex.c
+@@ -0,0 +1,169 @@
++/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
++/* util/support/t_hex.c - Test hex encoding and decoding */
++/*
++ * Copyright (C) 2018 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-platform.h>
++#include <k5-hex.h>
++
++struct {
++    const char *hex;
++    const char *binary;
++    size_t binary_len;
++    int uppercase;
++} tests[] = {
++    /* Invalid hex strings */
++    { "1" },
++    { "123" },
++    { "0/" },
++    { "/0" },
++    { "0:" },
++    { ":0" },
++    { "0@" },
++    { "@0" },
++    { "0G" },
++    { "G0" },
++    { "0`" },
++    { "`0" },
++    { "0g" },
++    { "g0" },
++    { " 00 " },
++    { "0\x01" },
++
++    { "", "", 0 },
++    { "00", "\x00", 1 },
++    { "01", "\x01", 1 },
++    { "10", "\x10", 1 },
++    { "01ff", "\x01\xFF", 2 },
++    { "A0B0C0", "\xA0\xB0\xC0", 3, 1 },
++    { "1a2b3c4d5e6f", "\x1A\x2B\x3C\x4D\x5E\x6F", 6 },
++    { "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
++      "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
++      "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 32 },
++
++    /* All byte values, lowercase */
++    { "0001020304050607", "\x00\x01\x02\x03\x04\x05\x06\x07", 8 },
++    { "08090a0b0c0d0e0f", "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 8 },
++    { "1011121314151617", "\x10\x11\x12\x13\x14\x15\x16\x17", 8 },
++    { "18191a1b1c1d1e1f", "\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F", 8 },
++    { "2021222324252627", "\x20\x21\x22\x23\x24\x25\x26\x27", 8 },
++    { "28292a2b2c2d2e2f", "\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F", 8 },
++    { "3031323334353637", "\x30\x31\x32\x33\x34\x35\x36\x37", 8 },
++    { "38393a3b3c3d3e3f", "\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F", 8 },
++    { "4041424344454647", "\x40\x41\x42\x43\x44\x45\x46\x47", 8 },
++    { "48494a4b4c4d4e4f", "\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F", 8 },
++    { "5051525354555657", "\x50\x51\x52\x53\x54\x55\x56\x57", 8 },
++    { "58595a5b5c5d5e5f", "\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F", 8 },
++    { "6061626364656667", "\x60\x61\x62\x63\x64\x65\x66\x67", 8 },
++    { "68696a6b6c6d6e6f", "\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F", 8 },
++    { "7071727374757677", "\x70\x71\x72\x73\x74\x75\x76\x77", 8 },
++    { "78797a7b7c7d7e7f", "\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F", 8 },
++    { "8081828384858687", "\x80\x81\x82\x83\x84\x85\x86\x87", 8 },
++    { "88898a8b8c8d8e8f", "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F", 8 },
++    { "9091929394959697", "\x90\x91\x92\x93\x94\x95\x96\x97", 8 },
++    { "98999a9b9c9d9e9f", "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F", 8 },
++    { "a0a1a2a3a4a5a6a7", "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7", 8 },
++    { "a8a9aaabacadaeaf", "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF", 8 },
++    { "b0b1b2b3b4b5b6b7", "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7", 8 },
++    { "b8b9babbbcbdbebf", "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF", 8 },
++    { "c0c1c2c3c4c5c6c7", "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7", 8 },
++    { "c8c9cacbcccdcecf", "\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF", 8 },
++    { "d0d1d2d3d4d5d6d7", "\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7", 8 },
++    { "d8d9dadbdcdddedf", "\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF", 8 },
++    { "e0e1e2e3e4e5e6e7", "\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7", 8 },
++    { "e8e9eaebecedeeef", "\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF", 8 },
++    { "f0f1f2f3f4f5f6f7", "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7", 8 },
++    { "f8f9fafbfcfdfeff", "\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF", 8 },
++
++    /* All byte values, uppercase */
++    { "0001020304050607", "\x00\x01\x02\x03\x04\x05\x06\x07", 8, 1 },
++    { "08090A0B0C0D0E0F", "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 8, 1 },
++    { "1011121314151617", "\x10\x11\x12\x13\x14\x15\x16\x17", 8, 1 },
++    { "18191A1B1C1D1E1F", "\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F", 8, 1 },
++    { "2021222324252627", "\x20\x21\x22\x23\x24\x25\x26\x27", 8, 1 },
++    { "28292A2B2C2D2E2F", "\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F", 8, 1 },
++    { "3031323334353637", "\x30\x31\x32\x33\x34\x35\x36\x37", 8, 1 },
++    { "38393A3B3C3D3E3F", "\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F", 8, 1 },
++    { "4041424344454647", "\x40\x41\x42\x43\x44\x45\x46\x47", 8, 1 },
++    { "48494A4B4C4D4E4F", "\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F", 8, 1 },
++    { "5051525354555657", "\x50\x51\x52\x53\x54\x55\x56\x57", 8, 1 },
++    { "58595A5B5C5D5E5F", "\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F", 8, 1 },
++    { "6061626364656667", "\x60\x61\x62\x63\x64\x65\x66\x67", 8, 1 },
++    { "68696A6B6C6D6E6F", "\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F", 8, 1 },
++    { "7071727374757677", "\x70\x71\x72\x73\x74\x75\x76\x77", 8, 1 },
++    { "78797A7B7C7D7E7F", "\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F", 8, 1 },
++    { "8081828384858687", "\x80\x81\x82\x83\x84\x85\x86\x87", 8, 1 },
++    { "88898A8B8C8D8E8F", "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F", 8, 1 },
++    { "9091929394959697", "\x90\x91\x92\x93\x94\x95\x96\x97", 8, 1 },
++    { "98999A9B9C9D9E9F", "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F", 8, 1 },
++    { "A0A1A2A3A4A5A6A7", "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7", 8, 1 },
++    { "A8A9AAABACADAEAF", "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF", 8, 1 },
++    { "B0B1B2B3B4B5B6B7", "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7", 8, 1 },
++    { "B8B9BABBBCBDBEBF", "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF", 8, 1 },
++    { "C0C1C2C3C4C5C6C7", "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7", 8, 1 },
++    { "C8C9CACBCCCDCECF", "\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF", 8, 1 },
++    { "D0D1D2D3D4D5D6D7", "\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7", 8, 1 },
++    { "D8D9DADBDCDDDEDF", "\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF", 8, 1 },
++    { "E0E1E2E3E4E5E6E7", "\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7", 8, 1 },
++    { "E8E9EAEBECEDEEEF", "\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF", 8, 1 },
++    { "F0F1F2F3F4F5F6F7", "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7", 8, 1 },
++    { "F8F9FAFBFCFDFEFF", "\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF", 8, 1 },
++};
++
++int main()
++{
++    size_t i;
++    char *hex;
++    int ret;
++    uint8_t *bytes;
++    size_t len;
++
++    for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) {
++        if (tests[i].binary == NULL) {
++            ret = k5_hex_decode(tests[i].hex, &bytes, &len);
++            assert(ret == EINVAL && bytes == NULL && len == 0);
++            continue;
++        }
++
++        ret = k5_hex_decode(tests[i].hex, &bytes, &len);
++        assert(ret == 0);
++        assert(len == tests[i].binary_len);
++        assert(memcmp(bytes, tests[i].binary, len) == 0);
++        assert(bytes[len] == 0);
++        free(bytes);
++
++        ret = k5_hex_encode((uint8_t *)tests[i].binary, tests[i].binary_len,
++                            tests[i].uppercase, &hex);
++        assert(ret == 0);
++        assert(strcmp(tests[i].hex, hex) == 0);
++        free(hex);
++    }
++    return 0;
++}
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..28d8a50
--- /dev/null
+++ b/SOURCES/Add-support-to-query-the-SSF-of-a-GSS-context.patch
@@ -0,0 +1,419 @@
+From 0bcadcebe22566a3bebd95974603b6b6593a4119 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]
+---
+ 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-case-for-PKINIT-DH-renegotiation.patch b/SOURCES/Add-test-case-for-PKINIT-DH-renegotiation.patch
new file mode 100644
index 0000000..51d5ee1
--- /dev/null
+++ b/SOURCES/Add-test-case-for-PKINIT-DH-renegotiation.patch
@@ -0,0 +1,45 @@
+From d65bcba04f0051ac3ad74be7415da85b1c80a0ad Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Wed, 11 Jan 2017 10:49:30 -0500
+Subject: [PATCH] Add test case for PKINIT DH renegotiation
+
+In t_pkinit.py, add a PKINIT test case where the KDC sends
+KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED and the client retries with the
+KDC's TD_DH_PARAMETERS value, using the clpreauth tryagain method.
+Use the trace log to verify that the renegotiation actually takes
+place.
+
+(cherry picked from commit 7ad7eb7fd591e6c789ea24b94eccbf74ee4d79f8)
+---
+ src/tests/t_pkinit.py | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+diff --git a/src/tests/t_pkinit.py b/src/tests/t_pkinit.py
+index ac4d326b6..183977750 100755
+--- a/src/tests/t_pkinit.py
++++ b/src/tests/t_pkinit.py
+@@ -174,6 +174,24 @@ realm.kinit(realm.user_princ,
+                    '-X', 'flag_RSA_PROTOCOL=yes'])
+ realm.klist(realm.user_princ)
+ 
++# Test a DH parameter renegotiation by temporarily setting a 4096-bit
++# minimum on the KDC.
++tracefile = os.path.join(realm.testdir, 'trace')
++minbits_kdc_conf = {'realms': {'$realm': {'pkinit_dh_min_bits': '4096'}}}
++minbits_env = realm.special_env('restrict', True, kdc_conf=minbits_kdc_conf)
++realm.stop_kdc()
++realm.start_kdc(env=minbits_env)
++realm.run(['env', 'KRB5_TRACE=' + tracefile, kinit, '-X',
++           'X509_user_identity=' + file_identity, realm.user_princ])
++with open(tracefile, 'r') as f:
++    trace = f.read()
++if ('Key parameters not accepted' not in trace or
++    'Preauth tryagain input types' not in trace or
++    'trying again with KDC-provided parameters' not in trace):
++    fail('DH renegotiation steps not found in kinit trace log')
++realm.stop_kdc()
++realm.start_kdc()
++
+ # Run the basic test - PKINIT with FILE: identity, with a password on the key,
+ # supplied by the prompter.
+ # Expect failure if the responder does nothing, and we have no prompter.
diff --git a/SOURCES/Add-test-cases-for-preauth-fallback-behavior.patch b/SOURCES/Add-test-cases-for-preauth-fallback-behavior.patch
new file mode 100644
index 0000000..8002723
--- /dev/null
+++ b/SOURCES/Add-test-cases-for-preauth-fallback-behavior.patch
@@ -0,0 +1,826 @@
+From e1448b09ac4e94ff8e66a7cf0315841c38c48c37 Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Fri, 20 Jan 2017 12:44:12 -0500
+Subject: [PATCH] Add test cases for preauth fallback behavior
+
+Add options to icred for performing optimistic preauth and setting
+preauth options, and for choosing between the normal and stepwise
+interfaces.  Add options to the test preauth module to allow induced
+failures at several points in processing, factoring out some padata
+manipulation functions into a new file to avoid repeating too much
+code.  Add test cases to t_preauth.py using the new facilities to
+exercise and verify several preauth fallback scenarios.  Amend the
+tryagain test case in t_pkinit.py to look for more trace log messages.
+
+ticket: 8537
+(cherry picked from commit 748beda1e36d76bed8b06b272ecb72988eede94b)
+[rharwood@redhat.com: more expected_trace]
+---
+ src/plugins/preauth/test/Makefile.in |   4 +-
+ src/plugins/preauth/test/cltest.c    |  86 ++++++++++-----
+ src/plugins/preauth/test/common.c    |  61 +++++++++++
+ src/plugins/preauth/test/common.h    |  41 +++++++
+ src/plugins/preauth/test/deps        |  14 ++-
+ src/plugins/preauth/test/kdctest.c   |  96 ++++++++++------
+ src/tests/icred.c                    |  69 +++++++++---
+ src/tests/t_general.py               |   1 +
+ src/tests/t_pkinit.py                |  12 +-
+ src/tests/t_preauth.py               | 158 ++++++++++++++++++++++++++-
+ 10 files changed, 452 insertions(+), 90 deletions(-)
+ create mode 100644 src/plugins/preauth/test/common.c
+ create mode 100644 src/plugins/preauth/test/common.h
+
+diff --git a/src/plugins/preauth/test/Makefile.in b/src/plugins/preauth/test/Makefile.in
+index ac3cb8155..77321b60f 100644
+--- a/src/plugins/preauth/test/Makefile.in
++++ b/src/plugins/preauth/test/Makefile.in
+@@ -9,9 +9,9 @@ RELDIR=../plugins/preauth/test
+ SHLIB_EXPDEPS=$(KRB5_BASE_DEPLIBS)
+ SHLIB_EXPLIBS=$(KRB5_BASE_LIBS)
+ 
+-STLIBOBJS=cltest.o kdctest.o
++STLIBOBJS=cltest.o kdctest.o common.o
+ 
+-SRCS= $(srcdir)/cltest.c $(srcdir)/kdctest.c
++SRCS= $(srcdir)/cltest.c $(srcdir)/kdctest.c $(srcdir)/common.c
+ 
+ all-unix: all-liblinks
+ install-unix: install-libs
+diff --git a/src/plugins/preauth/test/cltest.c b/src/plugins/preauth/test/cltest.c
+index 4c31e1c0f..f5f7c5aba 100644
+--- a/src/plugins/preauth/test/cltest.c
++++ b/src/plugins/preauth/test/cltest.c
+@@ -1,7 +1,7 @@
+ /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+ /* plugins/preauth/test/cltest.c - Test clpreauth module */
+ /*
+- * Copyright (C) 2015 by the Massachusetts Institute of Technology.
++ * Copyright (C) 2015, 2017 by the Massachusetts Institute of Technology.
+  * All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+@@ -32,7 +32,7 @@
+ 
+ /*
+  * This module is used to test preauth interface features.  At this time, the
+- * clpreauth module does two things:
++ * clpreauth module does the following:
+  *
+  * - It decrypts a message from the initial KDC pa-data using the reply key and
+  *   prints it to stdout.  (The unencrypted message "no key" can also be
+@@ -45,17 +45,27 @@
+  *   it to the server, instructing the kdcpreauth module to assert one or more
+  *   space-separated authentication indicators.  (This string is sent on both
+  *   round trips if a second round trip is requested.)
++ *
++ * - If a KDC_ERR_ENCTYPE_NOSUPP error with e-data is received, it prints the
++ *   accompanying error padata and sends a follow-up request containing
++ *   "tryagain".
++ *
++ * - If the "fail_optimistic", "fail_2rt", or "fail_tryagain" gic options are
++ *   set, it fails with a recognizable error string at the requested point in
++ *   processing.
+  */
+ 
+ #include "k5-int.h"
+ #include <krb5/clpreauth_plugin.h>
+-
+-#define TEST_PA_TYPE -123
++#include "common.h"
+ 
+ static krb5_preauthtype pa_types[] = { TEST_PA_TYPE, 0 };
+ 
+ struct client_state {
+     char *indicators;
++    krb5_boolean fail_optimistic;
++    krb5_boolean fail_2rt;
++    krb5_boolean fail_tryagain;
+ };
+ 
+ struct client_request_state {
+@@ -70,6 +80,7 @@ test_init(krb5_context context, krb5_clpreauth_moddata *moddata_out)
+     st = malloc(sizeof(*st));
+     assert(st != NULL);
+     st->indicators = NULL;
++    st->fail_optimistic = st->fail_2rt = st->fail_tryagain = FALSE;
+     *moddata_out = (krb5_clpreauth_moddata)st;
+     return 0;
+ }
+@@ -114,7 +125,6 @@ test_process(krb5_context context, krb5_clpreauth_moddata moddata,
+     struct client_state *st = (struct client_state *)moddata;
+     struct client_request_state *reqst = (struct client_request_state *)modreq;
+     krb5_error_code ret;
+-    krb5_pa_data **list, *pa;
+     krb5_keyblock *k;
+     krb5_enc_data enc;
+     krb5_data plain;
+@@ -123,20 +133,18 @@ test_process(krb5_context context, krb5_clpreauth_moddata moddata,
+     if (pa_data->length == 0) {
+         /* This is an optimistic preauth test.  Send a recognizable padata
+          * value so the KDC knows not to expect a cookie. */
+-        list = k5calloc(2, sizeof(*list), &ret);
+-        assert(!ret);
+-        pa = k5alloc(sizeof(*pa), &ret);
+-        assert(!ret);
+-        pa->pa_type = TEST_PA_TYPE;
+-        pa->contents = (uint8_t *)strdup("optimistic");
+-        assert(pa->contents != NULL);
+-        pa->length = 10;
+-        list[0] = pa;
+-        list[1] = NULL;
+-        *out_pa_data = list;
++        if (st->fail_optimistic) {
++            k5_setmsg(context, KRB5_PREAUTH_FAILED, "induced optimistic fail");
++            return KRB5_PREAUTH_FAILED;
++        }
++        *out_pa_data = make_pa_list("optimistic", 10);
+         return 0;
+     } else if (reqst->second_round_trip) {
+         printf("2rt: %.*s\n", pa_data->length, pa_data->contents);
++        if (st->fail_2rt) {
++            k5_setmsg(context, KRB5_PREAUTH_FAILED, "induced 2rt fail");
++            return KRB5_PREAUTH_FAILED;
++        }
+     } else if (pa_data->length == 6 &&
+                memcmp(pa_data->contents, "no key", 6) == 0) {
+         printf("no key\n");
+@@ -157,17 +165,34 @@ test_process(krb5_context context, krb5_clpreauth_moddata moddata,
+     reqst->second_round_trip = TRUE;
+ 
+     indstr = (st->indicators != NULL) ? st->indicators : "";
+-    list = k5calloc(2, sizeof(*list), &ret);
+-    assert(!ret);
+-    pa = k5alloc(sizeof(*pa), &ret);
+-    assert(!ret);
+-    pa->pa_type = TEST_PA_TYPE;
+-    pa->contents = (uint8_t *)strdup(indstr);
+-    assert(pa->contents != NULL);
+-    pa->length = strlen(indstr);
+-    list[0] = pa;
+-    list[1] = NULL;
+-    *out_pa_data = list;
++    *out_pa_data = make_pa_list(indstr, strlen(indstr));
++    return 0;
++}
++
++static krb5_error_code
++test_tryagain(krb5_context context, krb5_clpreauth_moddata moddata,
++              krb5_clpreauth_modreq modreq, krb5_get_init_creds_opt *opt,
++              krb5_clpreauth_callbacks cb, krb5_clpreauth_rock rock,
++              krb5_kdc_req *request, krb5_data *enc_req, krb5_data *enc_prev,
++              krb5_preauthtype pa_type, krb5_error *error,
++              krb5_pa_data **padata, krb5_prompter_fct prompter,
++              void *prompter_data, krb5_pa_data ***padata_out)
++{
++    struct client_state *st = (struct client_state *)moddata;
++    int i;
++
++    *padata_out = NULL;
++    if (st->fail_tryagain) {
++        k5_setmsg(context, KRB5_PREAUTH_FAILED, "induced tryagain fail");
++        return KRB5_PREAUTH_FAILED;
++    }
++    if (error->error != KDC_ERR_ENCTYPE_NOSUPP)
++        return KRB5_PREAUTH_FAILED;
++    for (i = 0; padata[i] != NULL; i++) {
++        if (padata[i]->pa_type == TEST_PA_TYPE)
++            printf("tryagain: %.*s\n", padata[i]->length, padata[i]->contents);
++    }
++    *padata_out = make_pa_list("tryagain", 8);
+     return 0;
+ }
+ 
+@@ -181,6 +206,12 @@ test_gic_opt(krb5_context kcontext, krb5_clpreauth_moddata moddata,
+         free(st->indicators);
+         st->indicators = strdup(value);
+         assert(st->indicators != NULL);
++    } else if (strcmp(attr, "fail_optimistic") == 0) {
++        st->fail_optimistic = TRUE;
++    } else if (strcmp(attr, "fail_2rt") == 0) {
++        st->fail_2rt = TRUE;
++    } else if (strcmp(attr, "fail_tryagain") == 0) {
++        st->fail_tryagain = TRUE;
+     }
+     return 0;
+ }
+@@ -205,6 +236,7 @@ clpreauth_test_initvt(krb5_context context, int maj_ver,
+     vt->request_init = test_request_init;
+     vt->request_fini = test_request_fini;
+     vt->process = test_process;
++    vt->tryagain = test_tryagain;
+     vt->gic_opts = test_gic_opt;
+     return 0;
+ }
+diff --git a/src/plugins/preauth/test/common.c b/src/plugins/preauth/test/common.c
+new file mode 100644
+index 000000000..4d1f49dfa
+--- /dev/null
++++ b/src/plugins/preauth/test/common.c
+@@ -0,0 +1,61 @@
++/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
++/* plugins/preauth/test/common.c - common functions for test preauth module */
++/*
++ * 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 "common.h"
++
++krb5_pa_data *
++make_pa(const char *contents, size_t len)
++{
++    krb5_error_code ret;
++    krb5_pa_data *pa;
++
++    pa = calloc(1, sizeof(*pa));
++    assert(pa != NULL);
++    pa->pa_type = TEST_PA_TYPE;
++    pa->contents = k5memdup(contents, len, &ret);
++    assert(!ret);
++    pa->length = len;
++    return pa;
++}
++
++/* Make a one-element padata list of type TEST_PA_TYPE. */
++krb5_pa_data **
++make_pa_list(const char *contents, size_t len)
++{
++    krb5_pa_data **list;
++
++    list = calloc(2, sizeof(*list));
++    assert(list != NULL);
++    list[0] = make_pa(contents, len);
++    return list;
++}
+diff --git a/src/plugins/preauth/test/common.h b/src/plugins/preauth/test/common.h
+new file mode 100644
+index 000000000..b748e0874
+--- /dev/null
++++ b/src/plugins/preauth/test/common.h
+@@ -0,0 +1,41 @@
++/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
++/* plugins/preauth/test/common.h - Declarations for test preauth module */
++/*
++ * 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.
++ */
++
++#ifndef COMMON_H
++#define COMMON_H
++
++#define TEST_PA_TYPE -123
++
++krb5_pa_data *make_pa(const char *contents, size_t len);
++krb5_pa_data **make_pa_list(const char *contents, size_t len);
++
++#endif /* COMMON_H */
+diff --git a/src/plugins/preauth/test/deps b/src/plugins/preauth/test/deps
+index b48f00032..b1429e9e1 100644
+--- a/src/plugins/preauth/test/deps
++++ b/src/plugins/preauth/test/deps
+@@ -11,7 +11,7 @@ cltest.so cltest.po $(OUTPRE)cltest.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+   $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+   $(top_srcdir)/include/krb5/clpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+   $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+-  cltest.c
++  cltest.c common.h
+ kdctest.so kdctest.po $(OUTPRE)kdctest.$(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 \
+@@ -22,4 +22,14 @@ kdctest.so kdctest.po $(OUTPRE)kdctest.$(OBJEXT): $(BUILDTOP)/include/autoconf.h
+   $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+   $(top_srcdir)/include/krb5/kdcpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+   $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+-  kdctest.c
++  common.h kdctest.c
++common.so common.po $(OUTPRE)common.$(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/plugin.h $(top_srcdir)/include/port-sockets.h \
++  $(top_srcdir)/include/socket-utils.h common.c common.h
+diff --git a/src/plugins/preauth/test/kdctest.c b/src/plugins/preauth/test/kdctest.c
+index 026dc680d..66b77969a 100644
+--- a/src/plugins/preauth/test/kdctest.c
++++ b/src/plugins/preauth/test/kdctest.c
+@@ -1,7 +1,7 @@
+ /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+ /* plugins/preauth/test/kdctest.c - Test kdcpreauth module */
+ /*
+- * Copyright (C) 2015 by the Massachusetts Institute of Technology.
++ * Copyright (C) 2015, 2017 by the Massachusetts Institute of Technology.
+  * All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+@@ -40,10 +40,20 @@
+  *   key; the encrypted message "no attr" is sent if there is no string
+  *   attribute.)  It also sets a cookie containing "method-data".
+  *
+- * - It retrieves the "2rt" attribute from the client principal.  If set, the
+- *   verify method sends the client a KDC_ERR_MORE_PREAUTH_DATA_REQUIRED error
+- *   with the contents of the 2rt attribute as pa-data, and sets a cookie
+- *   containing "more".
++ * - If the "err" attribute is set on the client principal, the verify method
++ *   returns an KDC_ERR_ETYPE_NOSUPP error on the first try, with the contents
++ *   of the err attribute as pa-data.  If the client tries again with the
++ *   padata value "tryagain", the verify method preuthenticates successfully
++ *   with no additional processing.
++ *
++ * - If the "failopt" attribute is set on the client principal, the verify
++ *   method returns KDC_ERR_PREAUTH_FAILED on optimistic preauth attempts.
++ *
++ * - If the "2rt" attribute is set on client principal, the verify method sends
++ *   the client a KDC_ERR_MORE_PREAUTH_DATA_REQUIRED error with the contents of
++ *   the 2rt attribute as pa-data, and sets a cookie containing "more".  If the
++ *   "fail2rt" attribute is set on the client principal, the client's second
++ *   try results in a KDC_ERR_PREAUTH_FAILED error.
+  *
+  * - It receives a space-separated list from the clpreauth module and asserts
+  *   each string as an authentication indicator.  It always succeeds in
+@@ -52,6 +62,7 @@
+ 
+ #include "k5-int.h"
+ #include <krb5/kdcpreauth_plugin.h>
++#include "common.h"
+ 
+ #define TEST_PA_TYPE -123
+ 
+@@ -73,11 +84,6 @@ test_edata(krb5_context context, krb5_kdc_req *req,
+ 
+     ret = cb->get_string(context, rock, "teststring", &attr);
+     assert(!ret);
+-    pa = k5alloc(sizeof(*pa), &ret);
+-    assert(!ret);
+-    if (pa == NULL)
+-        abort();
+-    pa->pa_type = TEST_PA_TYPE;
+     if (k != NULL) {
+         d = string2data((attr != NULL) ? attr : "no attr");
+         ret = krb5_c_encrypt_length(context, k->enctype, d.length, &enclen);
+@@ -86,12 +92,10 @@ test_edata(krb5_context context, krb5_kdc_req *req,
+         assert(!ret);
+         ret = krb5_c_encrypt(context, k, 1024, NULL, &d, &enc);
+         assert(!ret);
+-        pa->contents = (uint8_t *)enc.ciphertext.data;
+-        pa->length = enc.ciphertext.length;
++        pa = make_pa(enc.ciphertext.data, enc.ciphertext.length);
++        free(enc.ciphertext.data);
+     } else {
+-        pa->contents = (uint8_t *)strdup("no key");
+-        assert(pa->contents != NULL);
+-        pa->length = 6;
++        pa = make_pa("no key", 6);
+     }
+ 
+     /* Exercise setting a cookie information from the edata method. */
+@@ -111,12 +115,19 @@ test_verify(krb5_context context, krb5_data *req_pkt, krb5_kdc_req *request,
+             krb5_kdcpreauth_verify_respond_fn respond, void *arg)
+ {
+     krb5_error_code ret;
+-    krb5_boolean second_round_trip = FALSE;
+-    krb5_pa_data **list;
++    krb5_boolean second_round_trip = FALSE, optimistic = FALSE;
++    krb5_pa_data **list = NULL;
+     krb5_data cookie_data, d;
+-    char *str, *ind, *attr, *toksave = NULL;
++    char *str, *ind, *toksave = NULL;
++    char *attr_err, *attr_2rt, *attr_fail2rt, *attr_failopt;
+ 
+-    ret = cb->get_string(context, rock, "2rt", &attr);
++    ret = cb->get_string(context, rock, "err", &attr_err);
++    assert(!ret);
++    ret = cb->get_string(context, rock, "2rt", &attr_2rt);
++    assert(!ret);
++    ret = cb->get_string(context, rock, "fail2rt", &attr_fail2rt);
++    assert(!ret);
++    ret = cb->get_string(context, rock, "failopt", &attr_failopt);
+     assert(!ret);
+ 
+     /* Check the incoming cookie value. */
+@@ -124,13 +135,36 @@ test_verify(krb5_context context, krb5_data *req_pkt, krb5_kdc_req *request,
+         /* Make sure we are seeing optimistic preauth and not a lost cookie. */
+         d = make_data(data->contents, data->length);
+         assert(data_eq_string(d, "optimistic"));
++        optimistic = TRUE;
+     } else if (data_eq_string(cookie_data, "more")) {
+         second_round_trip = TRUE;
+     } else {
+-        assert(data_eq_string(cookie_data, "method-data"));
++        assert(data_eq_string(cookie_data, "method-data") ||
++               data_eq_string(cookie_data, "err"));
+     }
+ 
+-    if (attr == NULL || second_round_trip) {
++    if (attr_err != NULL) {
++        d = make_data(data->contents, data->length);
++        if (data_eq_string(d, "tryagain")) {
++            /* Authenticate successfully. */
++            enc_tkt_reply->flags |= TKT_FLG_PRE_AUTH;
++        } else {
++            d = string2data("err");
++            ret = cb->set_cookie(context, rock, TEST_PA_TYPE, &d);
++            assert(!ret);
++            ret = KRB5KDC_ERR_ETYPE_NOSUPP;
++            list = make_pa_list(attr_err, strlen(attr_err));
++        }
++    } else if (attr_2rt != NULL && !second_round_trip) {
++        d = string2data("more");
++        ret = cb->set_cookie(context, rock, TEST_PA_TYPE, &d);
++        assert(!ret);
++        ret = KRB5KDC_ERR_MORE_PREAUTH_DATA_REQUIRED;
++        list = make_pa_list(attr_2rt, strlen(attr_2rt));
++    } else if ((attr_fail2rt != NULL && second_round_trip) ||
++               (attr_failopt != NULL && optimistic)) {
++        ret = KRB5KDC_ERR_PREAUTH_FAILED;
++    } else {
+         /* Parse and assert the indicators. */
+         str = k5memdup0(data->contents, data->length, &ret);
+         if (ret)
+@@ -142,21 +176,13 @@ test_verify(krb5_context context, krb5_data *req_pkt, krb5_kdc_req *request,
+         }
+         free(str);
+         enc_tkt_reply->flags |= TKT_FLG_PRE_AUTH;
+-        cb->free_string(context, rock, attr);
+-        (*respond)(arg, 0, NULL, NULL, NULL);
+-    } else {
+-        d = string2data("more");
+-        ret = cb->set_cookie(context, rock, TEST_PA_TYPE, &d);
+-        list = k5calloc(2, sizeof(*list), &ret);
+-        assert(!ret);
+-        list[0] = k5alloc(sizeof(*list[0]), &ret);
+-        assert(!ret);
+-        list[0]->pa_type = TEST_PA_TYPE;
+-        list[0]->contents = (uint8_t *)attr;
+-        list[0]->length = strlen(attr);
+-        (*respond)(arg, KRB5KDC_ERR_MORE_PREAUTH_DATA_REQUIRED, NULL, list,
+-                   NULL);
+     }
++
++    cb->free_string(context, rock, attr_err);
++    cb->free_string(context, rock, attr_2rt);
++    cb->free_string(context, rock, attr_fail2rt);
++    cb->free_string(context, rock, attr_failopt);
++    (*respond)(arg, ret, NULL, list, NULL);
+ }
+ 
+ static krb5_error_code
+diff --git a/src/tests/icred.c b/src/tests/icred.c
+index 071f91c80..55f929cd7 100644
+--- a/src/tests/icred.c
++++ b/src/tests/icred.c
+@@ -35,8 +35,8 @@
+  * it is very simplistic, but it can be extended as needed.
+  */
+ 
++#include "k5-platform.h"
+ #include <krb5.h>
+-#include <stdio.h>
+ 
+ static krb5_context ctx;
+ 
+@@ -59,29 +59,64 @@ main(int argc, char **argv)
+     const char *princstr, *password;
+     krb5_principal client;
+     krb5_init_creds_context icc;
++    krb5_get_init_creds_opt *opt;
+     krb5_creds creds;
+-
+-    if (argc != 3) {
+-        fprintf(stderr, "Usage: icred princname password\n");
+-        exit(1);
+-    }
+-    princstr = argv[1];
+-    password = argv[2];
++    krb5_boolean stepwise = FALSE;
++    krb5_preauthtype ptypes[64];
++    int c, nptypes = 0;
++    char *val;
+ 
+     check(krb5_init_context(&ctx));
++    check(krb5_get_init_creds_opt_alloc(ctx, &opt));
++
++    while ((c = getopt(argc, argv, "so:X:")) != -1) {
++        switch (c) {
++        case 's':
++            stepwise = TRUE;
++            break;
++        case 'o':
++            assert(nptypes < 64);
++            ptypes[nptypes++] = atoi(optarg);
++            break;
++        case 'X':
++            val = strchr(optarg, '=');
++            if (val != NULL)
++                *val++ = '\0';
++            else
++                val = "yes";
++            check(krb5_get_init_creds_opt_set_pa(ctx, opt, optarg, val));
++            break;
++        default:
++            abort();
++        }
++    }
++
++    argc -= optind;
++    argv += optind;
++    if (argc != 2)
++        abort();
++    princstr = argv[0];
++    password = argv[1];
++
+     check(krb5_parse_name(ctx, princstr, &client));
+ 
+-    /* Try once with the traditional interface. */
+-    check(krb5_get_init_creds_password(ctx, &creds, client, password, NULL,
+-                                       NULL, 0, NULL, NULL));
+-    krb5_free_cred_contents(ctx, &creds);
++    if (nptypes > 0)
++        krb5_get_init_creds_opt_set_preauth_list(opt, ptypes, nptypes);
+ 
+-    /* Try again with the step interface. */
+-    check(krb5_init_creds_init(ctx, client, NULL, NULL, 0, NULL, &icc));
+-    check(krb5_init_creds_set_password(ctx, icc, password));
+-    check(krb5_init_creds_get(ctx, icc));
+-    krb5_init_creds_free(ctx, icc);
++    if (stepwise) {
++        /* Use the stepwise interface. */
++        check(krb5_init_creds_init(ctx, client, NULL, NULL, 0, NULL, &icc));
++        check(krb5_init_creds_set_password(ctx, icc, password));
++        check(krb5_init_creds_get(ctx, icc));
++        krb5_init_creds_free(ctx, icc);
++    } else {
++        /* Use the traditional one-shot interface. */
++        check(krb5_get_init_creds_password(ctx, &creds, client, password, NULL,
++                                           NULL, 0, NULL, opt));
++        krb5_free_cred_contents(ctx, &creds);
++    }
+ 
++    krb5_get_init_creds_opt_free(ctx, opt);
+     krb5_free_principal(ctx, client);
+     krb5_free_context(ctx);
+     return 0;
+diff --git a/src/tests/t_general.py b/src/tests/t_general.py
+index 6d523fe45..b16cffa37 100755
+--- a/src/tests/t_general.py
++++ b/src/tests/t_general.py
+@@ -30,6 +30,7 @@ conf={'plugins': {'pwqual': {'disable': 'empty'}}}
+ realm = K5Realm(create_user=False, create_host=False, krb5_conf=conf)
+ realm.run([kadminl, 'addprinc', '-pw', '', 'user'])
+ realm.run(['./icred', 'user', ''])
++realm.run(['./icred', '-s', 'user', ''])
+ realm.stop()
+ 
+ realm = K5Realm(create_host=False)
+diff --git a/src/tests/t_pkinit.py b/src/tests/t_pkinit.py
+index 38424932b..c25475096 100755
+--- a/src/tests/t_pkinit.py
++++ b/src/tests/t_pkinit.py
+@@ -176,14 +176,20 @@ realm.klist(realm.user_princ)
+ 
+ # Test a DH parameter renegotiation by temporarily setting a 4096-bit
+ # minimum on the KDC.  (Preauth type 16 is PKINIT PA_PK_AS_REQ;
+-# 133 is FAST PA-FX-COOKIE.)
++# 109 is PKINIT TD_DH_PARAMETERS; 133 is FAST PA-FX-COOKIE.)
+ minbits_kdc_conf = {'realms': {'$realm': {'pkinit_dh_min_bits': '4096'}}}
+ minbits_env = realm.special_env('restrict', True, kdc_conf=minbits_kdc_conf)
+ realm.stop_kdc()
+ realm.start_kdc(env=minbits_env)
+-expected_trace = ('Key parameters not accepted',
+-                  'Preauth tryagain input types',
++expected_trace = ('Sending unauthenticated request',
++                  '/Additional pre-authentication required',
++                  'Preauthenticating using KDC method data',
++                  'Preauth module pkinit (16) (real) returned: 0/Success',
++                  'Produced preauth for next request: 133, 16',
++                  '/Key parameters not accepted',
++                  'Preauth tryagain input types (16): 109, 133',
+                   'trying again with KDC-provided parameters',
++                  'Preauth module pkinit (16) tryagain returned: 0/Success',
+                   'Followup preauth for next request: 16, 133')
+ realm.kinit(realm.user_princ,
+             flags=['-X', 'X509_user_identity=%s' % file_identity],
+diff --git a/src/tests/t_preauth.py b/src/tests/t_preauth.py
+index 9b6da5a96..7d4d299dc 100644
+--- a/src/tests/t_preauth.py
++++ b/src/tests/t_preauth.py
+@@ -18,11 +18,161 @@ out = realm.run([kinit, 'nokeyuser'], input=password('user')+'\n',
+ if 'no key' not in out:
+     fail('Expected "no key" message not in kinit output')
+ 
+-# Exercise KDC_ERR_MORE_PREAUTH_DATA_REQUIRED and secure cookies.
++# Preauth type -123 is the test preauth module type; 133 is FAST
++# PA-FX-COOKIE; 2 is encrypted timestamp.
++
++# Test normal preauth flow.
++expected_trace = ('Sending unauthenticated request',
++                  '/Additional pre-authentication required',
++                  'Preauthenticating using KDC method data',
++                  'Processing preauth types:',
++                  'Preauth module test (-123) (real) returned: 0/Success',
++                  'Produced preauth for next request: 133, -123',
++                  'Decrypted AS reply')
++realm.run(['./icred', realm.user_princ, password('user')],
++          expected_msg='testval', expected_trace=expected_trace)
++
++# Test successful optimistic preauth.
++expected_trace = ('Attempting optimistic preauth',
++                  'Processing preauth types: -123',
++                  'Preauth module test (-123) (real) returned: 0/Success',
++                  'Produced preauth for next request: -123',
++                  'Decrypted AS reply')
++realm.run(['./icred', '-o', '-123', realm.user_princ, password('user')],
++          expected_trace=expected_trace)
++
++# Test optimistic preauth failing on client, followed by successful
++# preauth using the same module.
++expected_trace = ('Attempting optimistic preauth',
++                  'Processing preauth types: -123',
++                  '/induced optimistic fail',
++                  'Sending unauthenticated request',
++                  '/Additional pre-authentication required',
++                  'Preauthenticating using KDC method data',
++                  'Processing preauth types:',
++                  'Preauth module test (-123) (real) returned: 0/Success',
++                  'Produced preauth for next request: 133, -123',
++                  'Decrypted AS reply')
++realm.run(['./icred', '-o', '-123', '-X', 'fail_optimistic', realm.user_princ,
++           password('user')], expected_msg='testval',
++          expected_trace=expected_trace)
++
++# Test optimistic preauth failing on KDC, followed by successful preauth
++# using the same module.
++realm.run([kadminl, 'setstr', realm.user_princ, 'failopt', 'yes'])
++expected_trace = ('Attempting optimistic preauth',
++                  'Processing preauth types: -123',
++                  'Preauth module test (-123) (real) returned: 0/Success',
++                  'Produced preauth for next request: -123',
++                  '/Preauthentication failed',
++                  'Preauthenticating using KDC method data',
++                  'Processing preauth types:',
++                  'Preauth module test (-123) (real) returned: 0/Success',
++                  'Produced preauth for next request: 133, -123',
++                  'Decrypted AS reply')
++realm.run(['./icred', '-o', '-123', realm.user_princ, password('user')],
++          expected_msg='testval', expected_trace=expected_trace)
++realm.run([kadminl, 'delstr', realm.user_princ, 'failopt'])
++
++# Test KDC_ERR_MORE_PREAUTH_DATA_REQUIRED and secure cookies.
+ realm.run([kadminl, 'setstr', realm.user_princ, '2rt', 'secondtrip'])
+-out = realm.run([kinit, realm.user_princ], input=password('user')+'\n')
+-if '2rt: secondtrip' not in out:
+-    fail('multi round-trip cookie test')
++expected_trace = ('Sending unauthenticated request',
++                  '/Additional pre-authentication required',
++                  'Preauthenticating using KDC method data',
++                  'Processing preauth types:',
++                  'Preauth module test (-123) (real) returned: 0/Success',
++                  'Produced preauth for next request: 133, -123',
++                  '/More preauthentication data is required',
++                  'Continuing preauth mech -123',
++                  'Processing preauth types: -123, 133',
++                  'Produced preauth for next request: 133, -123',
++                  'Decrypted AS reply')
++realm.run(['./icred', realm.user_princ, password('user')],
++          expected_msg='2rt: secondtrip', expected_trace=expected_trace)
++
++# Test client-side failure after KDC_ERR_MORE_PREAUTH_DATA_REQUIRED,
++# falling back to encrypted timestamp.
++expected_trace = ('Sending unauthenticated request',
++                  '/Additional pre-authentication required',
++                  'Preauthenticating using KDC method data',
++                  'Processing preauth types:',
++                  'Preauth module test (-123) (real) returned: 0/Success',
++                  'Produced preauth for next request: 133, -123',
++                  '/More preauthentication data is required',
++                  'Continuing preauth mech -123',
++                  'Processing preauth types: -123, 133',
++                  '/induced 2rt fail',
++                  'Preauthenticating using KDC method data',
++                  'Processing preauth types:',
++                  'Encrypted timestamp (for ',
++                  'module encrypted_timestamp (2) (real) returned: 0/Success',
++                  'Produced preauth for next request: 133, 2',
++                  'Decrypted AS reply')
++realm.run(['./icred', '-X', 'fail_2rt', realm.user_princ, password('user')],
++          expected_msg='2rt: secondtrip', expected_trace=expected_trace)
++
++# Test KDC-side failure after KDC_ERR_MORE_PREAUTH_DATA_REQUIRED,
++# falling back to encrypted timestamp.
++realm.run([kadminl, 'setstr', realm.user_princ, 'fail2rt', 'yes'])
++expected_trace = ('Sending unauthenticated request',
++                  '/Additional pre-authentication required',
++                  'Preauthenticating using KDC method data',
++                  'Processing preauth types:',
++                  'Preauth module test (-123) (real) returned: 0/Success',
++                  'Produced preauth for next request: 133, -123',
++                  '/More preauthentication data is required',
++                  'Continuing preauth mech -123',
++                  'Processing preauth types: -123, 133',
++                  'Preauth module test (-123) (real) returned: 0/Success',
++                  'Produced preauth for next request: 133, -123',
++                  '/Preauthentication failed',
++                  'Preauthenticating using KDC method data',
++                  'Processing preauth types:',
++                  'Encrypted timestamp (for ',
++                  'module encrypted_timestamp (2) (real) returned: 0/Success',
++                  'Produced preauth for next request: 133, 2',
++                  'Decrypted AS reply')
++realm.run(['./icred', realm.user_princ, password('user')],
++          expected_msg='2rt: secondtrip', expected_trace=expected_trace)
++realm.run([kadminl, 'delstr', realm.user_princ, 'fail2rt'])
++
++# Test tryagain flow by inducing a KDC_ERR_ENCTYPE_NOSUPP error on the KDC.
++realm.run([kadminl, 'setstr', realm.user_princ, 'err', 'testagain'])
++expected_trace = ('Sending unauthenticated request',
++                  '/Additional pre-authentication required',
++                  'Preauthenticating using KDC method data',
++                  'Processing preauth types:',
++                  'Preauth module test (-123) (real) returned: 0/Success',
++                  'Produced preauth for next request: 133, -123',
++                  '/KDC has no support for encryption type',
++                  'Recovering from KDC error 14 using preauth mech -123',
++                  'Preauth tryagain input types (-123): -123, 133',
++                  'Preauth module test (-123) tryagain returned: 0/Success',
++                  'Followup preauth for next request: -123, 133',
++                  'Decrypted AS reply')
++realm.run(['./icred', realm.user_princ, password('user')],
++          expected_msg='tryagain: testagain', expected_trace=expected_trace)
++
++# Test a client-side tryagain failure, falling back to encrypted
++# timestamp.
++expected_trace = ('Sending unauthenticated request',
++                  '/Additional pre-authentication required',
++                  'Preauthenticating using KDC method data',
++                  'Processing preauth types:',
++                  'Preauth module test (-123) (real) returned: 0/Success',
++                  'Produced preauth for next request: 133, -123',
++                  '/KDC has no support for encryption type',
++                  'Recovering from KDC error 14 using preauth mech -123',
++                  'Preauth tryagain input types (-123): -123, 133',
++                  '/induced tryagain fail',
++                  'Preauthenticating using KDC method data',
++                  'Processing preauth types:',
++                  'Encrypted timestamp (for ',
++                  'module encrypted_timestamp (2) (real) returned: 0/Success',
++                  'Produced preauth for next request: 133, 2',
++                  'Decrypted AS reply')
++realm.run(['./icred', '-X', 'fail_tryagain', realm.user_princ,
++           password('user')], expected_trace=expected_trace)
+ 
+ # Test that multiple stepwise initial creds operations can be
+ # performed with the same krb5_context, with proper tracking of
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..c44a755
--- /dev/null
+++ b/SOURCES/Add-test-cert-generation-to-make-certs.sh.patch
@@ -0,0 +1,90 @@
+From c1bda7ba15f8dcf04b6ca24d9f1c7bcf842e4feb 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.
+---
+ 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..5c5e361
--- /dev/null
+++ b/SOURCES/Add-test-cert-with-no-extensions.patch
@@ -0,0 +1,34 @@
+From 728d567d1c7445e89edad046d8aac5344143d51d 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]
+---
+ 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-tests-for-per-request-preauth-data-scoping.patch b/SOURCES/Add-tests-for-per-request-preauth-data-scoping.patch
new file mode 100644
index 0000000..dc9ca95
--- /dev/null
+++ b/SOURCES/Add-tests-for-per-request-preauth-data-scoping.patch
@@ -0,0 +1,228 @@
+From 2d8f53212aec704a60e0a96327d8cfd999306ceb Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Wed, 4 Jan 2017 18:31:15 -0500
+Subject: [PATCH] Add tests for per-request preauth data scoping
+
+Add a test harness which interleaves calls for multiple initial creds
+contexts using the same library context.  Add a test case to
+t_preauth.py using the new harness and the test preauth module to
+verify that modreq pointers are correctly tracked.
+
+ticket: 7877
+(cherry picked from commit c0b25fe282355d4f329418956b9c6295780af633)
+[rharwood@redhat.com: drop .gitignore]
+---
+ src/tests/Makefile.in    |  23 +++++---
+ src/tests/icinterleave.c | 124 +++++++++++++++++++++++++++++++++++++++
+ src/tests/t_preauth.py   |  13 ++++
+ 3 files changed, 151 insertions(+), 9 deletions(-)
+ create mode 100644 src/tests/icinterleave.c
+
+diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in
+index a2093108b..bd1b21346 100644
+--- a/src/tests/Makefile.in
++++ b/src/tests/Makefile.in
+@@ -6,12 +6,12 @@ SUBDIRS = resolve asn.1 create hammer verify gssapi dejagnu shlib \
+ RUN_DB_TEST = $(RUN_SETUP) KRB5_KDC_PROFILE=kdc.conf KRB5_CONFIG=krb5.conf \
+ 	LC_ALL=C $(VALGRIND)
+ 
+-OBJS= adata.o etinfo.o forward.o gcred.o hist.o hooks.o hrealm.o icred.o \
+-	kdbtest.o localauth.o plugorder.o rdreq.o responder.o s2p.o \
+-	s4u2proxy.o unlockiter.o
++OBJS= adata.o etinfo.o forward.o gcred.o hist.o hooks.o hrealm.o \
++	icinterleave.o icred.o kdbtest.o localauth.o plugorder.o rdreq.o \
++	responder.o s2p.o s4u2proxy.o unlockiter.o
+ EXTRADEPSRCS= adata.c etinfo.c forward.c gcred.c hist.c hooks.c hrealm.c \
+-	icred.c kdbtest.c localauth.c plugorder.c rdreq.o responder.c s2p.c \
+-	s4u2proxy.c unlockiter.c
++	icinterleave.c icred.c kdbtest.c localauth.c plugorder.c rdreq.o \
++	responder.c s2p.c s4u2proxy.c unlockiter.c
+ 
+ TEST_DB = ./testdb
+ TEST_REALM = FOO.TEST.REALM
+@@ -44,6 +44,9 @@ hooks: hooks.o $(KRB5_BASE_DEPLIBS)
+ hrealm: hrealm.o $(KRB5_BASE_DEPLIBS)
+ 	$(CC_LINK) -o $@ hrealm.o $(KRB5_BASE_LIBS)
+ 
++icinterleave: icinterleave.o $(KRB5_BASE_DEPLIBS)
++	$(CC_LINK) -o $@ icinterleave.o $(KRB5_BASE_LIBS)
++
+ icred: icred.o $(KRB5_BASE_DEPLIBS)
+ 	$(CC_LINK) -o $@ icred.o $(KRB5_BASE_LIBS)
+ 
+@@ -115,8 +118,9 @@ kdb_check: kdc.conf krb5.conf
+ 	$(RUN_DB_TEST) ../kadmin/dbutil/kdb5_util $(KADMIN_OPTS) destroy -f
+ 	$(RM) $(TEST_DB)* stash_file
+ 
+-check-pytests: adata etinfo forward gcred hist hooks hrealm icred kdbtest
+-check-pytests: localauth plugorder rdreq responder s2p s4u2proxy unlockiter
++check-pytests: adata etinfo forward gcred hist hooks hrealm icinterleave icred
++check-pytests: kdbtest localauth plugorder rdreq responder s2p s4u2proxy
++check-pytests: unlockiter
+ 	$(RUNPYTEST) $(srcdir)/t_general.py $(PYTESTFLAGS)
+ 	$(RUNPYTEST) $(srcdir)/t_hooks.py $(PYTESTFLAGS)
+ 	$(RUNPYTEST) $(srcdir)/t_dump.py $(PYTESTFLAGS)
+@@ -172,8 +176,9 @@ check-pytests: localauth plugorder rdreq responder s2p s4u2proxy unlockiter
+ 	$(RUNPYTEST) $(srcdir)/t_kdcpolicy.py $(PYTESTFLAGS)
+ 
+ clean:
+-	$(RM) adata etinfo forward gcred hist hooks hrealm icred kdbtest
+-	$(RM) localauth plugorder rdreq responder s2p s4u2proxy unlockiter
++	$(RM) adata etinfo forward gcred hist hooks hrealm icinterleave icred
++	$(RM) kdbtest localauth plugorder rdreq responder s2p s4u2proxy
++	$(RM) unlockiter
+ 	$(RM) krb5.conf kdc.conf
+ 	$(RM) -rf kdc_realm/sandbox ldap
+ 	$(RM) au.log
+diff --git a/src/tests/icinterleave.c b/src/tests/icinterleave.c
+new file mode 100644
+index 000000000..d76ecf361
+--- /dev/null
++++ b/src/tests/icinterleave.c
+@@ -0,0 +1,124 @@
++/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
++/* tests/icinterleave.c - interleaved init_creds_step test harness */
++/*
++ * 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.
++ */
++
++/*
++ * This test harness performs multiple initial creds operations using
++ * krb5_init_creds_step(), interleaving the operations to test the scoping of
++ * the preauth state.  All principals must have the same password (or not
++ * require a password).
++ */
++
++#include "k5-int.h"
++
++static krb5_context ctx;
++
++static void
++check(krb5_error_code code)
++{
++    const char *errmsg;
++
++    if (code) {
++        errmsg = krb5_get_error_message(ctx, code);
++        fprintf(stderr, "%s\n", errmsg);
++        krb5_free_error_message(ctx, errmsg);
++        exit(1);
++    }
++}
++
++int
++main(int argc, char **argv)
++{
++    const char *password;
++    char **princstrs;
++    krb5_principal client;
++    krb5_init_creds_context *iccs;
++    krb5_data req, *reps, realm;
++    krb5_boolean any_left;
++    int i, nclients, master;
++    unsigned int flags;
++
++    if (argc < 3) {
++        fprintf(stderr, "Usage: icinterleave password princ1 princ2 ...\n");
++        exit(1);
++    }
++    password = argv[1];
++    princstrs = argv + 2;
++    nclients = argc - 2;
++
++    check(krb5_init_context(&ctx));
++
++    /* Create an initial creds context for each client principal. */
++    iccs = calloc(nclients, sizeof(*iccs));
++    assert(iccs != NULL);
++    for (i = 0; i < nclients; i++) {
++        check(krb5_parse_name(ctx, princstrs[i], &client));
++        check(krb5_init_creds_init(ctx, client, NULL, NULL, 0, NULL,
++                                   &iccs[i]));
++        check(krb5_init_creds_set_password(ctx, iccs[i], password));
++        krb5_free_principal(ctx, client);
++    }
++
++    reps = calloc(nclients, sizeof(*reps));
++    assert(reps != NULL);
++
++    any_left = TRUE;
++    while (any_left) {
++        any_left = FALSE;
++        for (i = 0; i < nclients; i++)  {
++            if (iccs[i] == NULL)
++                continue;
++            any_left = TRUE;
++
++            printf("step %d\n", i + 1);
++
++            req = empty_data();
++            realm = empty_data();
++            check(krb5_init_creds_step(ctx, iccs[i], &reps[i], &req, &realm,
++                                       &flags));
++            if (!(flags & KRB5_INIT_CREDS_STEP_FLAG_CONTINUE)) {
++                printf("finish %d\n", i + 1);
++                krb5_init_creds_free(ctx, iccs[i]);
++                iccs[i] = NULL;
++                continue;
++            }
++
++            master = 0;
++            krb5_free_data_contents(ctx, &reps[i]);
++            check(krb5_sendto_kdc(ctx, &req, &realm, &reps[i], &master, 0));
++            krb5_free_data_contents(ctx, &req);
++            krb5_free_data_contents(ctx, &realm);
++        }
++    }
++
++    krb5_free_context(ctx);
++    return 0;
++}
+diff --git a/src/tests/t_preauth.py b/src/tests/t_preauth.py
+index 0ef8bbca4..9b6da5a96 100644
+--- a/src/tests/t_preauth.py
++++ b/src/tests/t_preauth.py
+@@ -24,4 +24,17 @@ out = realm.run([kinit, realm.user_princ], input=password('user')+'\n')
+ if '2rt: secondtrip' not in out:
+     fail('multi round-trip cookie test')
+ 
++# Test that multiple stepwise initial creds operations can be
++# performed with the same krb5_context, with proper tracking of
++# clpreauth module request handles.
++realm.run([kadminl, 'addprinc', '-pw', 'pw', 'u1'])
++realm.run([kadminl, 'addprinc', '+requires_preauth', '-pw', 'pw', 'u2'])
++realm.run([kadminl, 'addprinc', '+requires_preauth', '-pw', 'pw', 'u3'])
++realm.run([kadminl, 'setstr', 'u2', '2rt', 'extra'])
++out = realm.run(['./icinterleave', 'pw', 'u1', 'u2', 'u3'])
++if out != ('step 1\nstep 2\nstep 3\nstep 1\nfinish 1\nstep 2\nno attr\n'
++           'step 3\nno attr\nstep 2\n2rt: extra\nstep 3\nfinish 3\nstep 2\n'
++           'finish 2\n'):
++    fail('unexpected output from icinterleave')
++
+ success('Pre-authentication framework tests')
diff --git a/SOURCES/Add-the-certauth-dbmatch-module.patch b/SOURCES/Add-the-certauth-dbmatch-module.patch
new file mode 100644
index 0000000..e14b029
--- /dev/null
+++ b/SOURCES/Add-the-certauth-dbmatch-module.patch
@@ -0,0 +1,316 @@
+From fab1e4f8553dcf8a573c41bb8ea93912a622aae0 Mon Sep 17 00:00:00 2001
+From: Matt Rogers <mrogers@redhat.com>
+Date: Wed, 15 Mar 2017 19:57:15 -0400
+Subject: [PATCH] Add the certauth dbmatch module
+
+Add and enable the "dbmatch" builtin module.  Add the
+pkinit_client_cert_match() and crypto_req_cert_matching_data() helper
+functions.  Add dbmatch tests to t_pkinit.py.  Add documentation to
+krb5_conf.rst, pkinit.rst, and kadmin_local.rst.
+
+[ghudson@mit.edu: simplified code, edited docs]
+
+ticket: 8562 (new)
+(cherry picked from commit 89634ca049e698d7dd2554f5c49bfc499be96188)
+---
+ doc/admin/admin_commands/kadmin_local.rst     |  7 +++
+ doc/admin/conf_files/krb5_conf.rst            |  5 ++
+ doc/admin/pkinit.rst                          | 20 +++++++
+ src/plugins/preauth/pkinit/pkinit.h           |  7 +++
+ src/plugins/preauth/pkinit/pkinit_crypto.h    |  6 ++
+ .../preauth/pkinit/pkinit_crypto_openssl.c    | 18 ++++++
+ src/plugins/preauth/pkinit/pkinit_matching.c  | 37 +++++++++++++
+ src/plugins/preauth/pkinit/pkinit_srv.c       | 55 +++++++++++++++++++
+ src/tests/t_pkinit.py                         | 37 +++++++++++++
+ 9 files changed, 192 insertions(+)
+
+diff --git a/doc/admin/admin_commands/kadmin_local.rst b/doc/admin/admin_commands/kadmin_local.rst
+index 0e955faf2..cefe6054b 100644
+--- a/doc/admin/admin_commands/kadmin_local.rst
++++ b/doc/admin/admin_commands/kadmin_local.rst
+@@ -661,6 +661,13 @@ KDC:
+     *principal*.  The *value* is a JSON string representing an array
+     of objects, each having optional ``type`` and ``username`` fields.
+ 
++**pkinit_cert_match**
++    Specifies a matching expression that defines the certificate
++    attributes required for the client certificate used by the
++    principal during PKINIT authentication.  The matching expression
++    is in the same format as those used by the **pkinit_cert_match**
++    option in :ref:`krb5.conf(5)`.  (New in release 1.16.)
++
+ This command requires the **modify** privilege.
+ 
+ Alias: **setstr**
+diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
+index cc996f11a..d428124c9 100644
+--- a/doc/admin/conf_files/krb5_conf.rst
++++ b/doc/admin/conf_files/krb5_conf.rst
+@@ -883,6 +883,11 @@ following built-in modules exist for this interface:
+     Extended Key Usage attribute consistent with the
+     **pkinit_eku_checking** value for the realm.
+ 
++**dbmatch**
++    This module authorizes or rejects the certificate according to
++    whether it matches the **pkinit_cert_match** string attribute on
++    the client principal, if that attribute is present.
++
+ 
+ PKINIT options
+ --------------
+diff --git a/doc/admin/pkinit.rst b/doc/admin/pkinit.rst
+index 460d75d1e..c601c5c9e 100644
+--- a/doc/admin/pkinit.rst
++++ b/doc/admin/pkinit.rst
+@@ -223,6 +223,26 @@ time as follows::
+ 
+     kadmin -q 'add_principal +requires_preauth -nokey YOUR_PRINCNAME'
+ 
++By default, the KDC requires PKINIT client certificates to have the
++standard Extended Key Usage and Subject Alternative Name attributes
++for PKINIT.  Starting in release 1.16, it is possible to authorize
++client certificates based on the subject or other criteria instead of
++the standard PKINIT Subject Alternative Name, by setting the
++**pkinit_cert_match** string attribute on each client principal entry.
++For example::
++
++    kadmin set_string user@REALM pkinit_cert_match "<SUBJECT>CN=user@REALM$"
++
++The **pkinit_cert_match** string attribute follows the syntax used by
++the :ref:`krb5.conf(5)` **pkinit_cert_match** relation.  To allow the
++use of non-PKINIT client certificates, it will also be necessary to
++disable key usage checking using the **pkinit_eku_checking** relation;
++for example::
++
++    [kdcdefaults]
++        pkinit_eku_checking = none
++
++
+ 
+ Configuring the clients
+ -----------------------
+diff --git a/src/plugins/preauth/pkinit/pkinit.h b/src/plugins/preauth/pkinit/pkinit.h
+index a49f3078e..430b3f334 100644
+--- a/src/plugins/preauth/pkinit/pkinit.h
++++ b/src/plugins/preauth/pkinit/pkinit.h
+@@ -292,6 +292,13 @@ krb5_error_code pkinit_cert_matching
+ 	pkinit_identity_crypto_context id_cryptoctx,
+ 	krb5_principal princ);
+ 
++krb5_error_code pkinit_client_cert_match
++	(krb5_context context,
++	pkinit_plg_crypto_context plgctx,
++	pkinit_req_crypto_context reqctx,
++	const char *match_rule,
++	krb5_boolean *matched);
++
+ /*
+  * Client's list of identities for which it needs PINs or passwords
+  */
+diff --git a/src/plugins/preauth/pkinit/pkinit_crypto.h b/src/plugins/preauth/pkinit/pkinit_crypto.h
+index b6e4e0ac3..149923b1d 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto.h
++++ b/src/plugins/preauth/pkinit/pkinit_crypto.h
+@@ -637,4 +637,10 @@ krb5_error_code
+ crypto_encode_der_cert(krb5_context context, pkinit_req_crypto_context reqctx,
+ 		       uint8_t **der_out, size_t *der_len);
+ 
++krb5_error_code
++crypto_req_cert_matching_data(krb5_context context,
++			      pkinit_plg_crypto_context plgctx,
++			      pkinit_req_crypto_context reqctx,
++			      pkinit_cert_matching_data **md_out);
++
+ #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 3949eb9c2..534161b19 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+@@ -6099,3 +6099,21 @@ crypto_encode_der_cert(krb5_context context, pkinit_req_crypto_context reqctx,
+     *der_len = len;
+     return 0;
+ }
++
++/*
++ * Get the certificate matching data from the request certificate.
++ */
++krb5_error_code
++crypto_req_cert_matching_data(krb5_context context,
++                              pkinit_plg_crypto_context plgctx,
++                              pkinit_req_crypto_context reqctx,
++                              pkinit_cert_matching_data **md_out)
++{
++    *md_out = NULL;
++
++    if (reqctx == NULL || reqctx->received_cert == NULL)
++        return ENOENT;
++
++    return get_matching_data(context, plgctx, reqctx, reqctx->received_cert,
++                             md_out);
++}
+diff --git a/src/plugins/preauth/pkinit/pkinit_matching.c b/src/plugins/preauth/pkinit/pkinit_matching.c
+index d929fb3c0..c2a4c084d 100644
+--- a/src/plugins/preauth/pkinit/pkinit_matching.c
++++ b/src/plugins/preauth/pkinit/pkinit_matching.c
+@@ -724,3 +724,40 @@ cleanup:
+     crypto_cert_free_matching_data_list(context, matchdata);
+     return retval;
+ }
++
++krb5_error_code
++pkinit_client_cert_match(krb5_context context,
++                         pkinit_plg_crypto_context plgctx,
++                         pkinit_req_crypto_context reqctx,
++                         const char *match_rule,
++                         krb5_boolean *matched)
++{
++    krb5_error_code ret;
++    pkinit_cert_matching_data *md = NULL;
++    rule_component *rc = NULL;
++    int comp_match = 0;
++    rule_set *rs = NULL;
++
++    *matched = FALSE;
++    ret = parse_rule_set(context, match_rule, &rs);
++    if (ret)
++        goto cleanup;
++
++    ret = crypto_req_cert_matching_data(context, plgctx, reqctx, &md);
++    if (ret)
++        goto cleanup;
++
++    for (rc = rs->crs; rc != NULL; rc = rc->next) {
++        comp_match = component_match(context, rc, md);
++        if ((comp_match && rs->relation == relation_or) ||
++            (!comp_match && rs->relation == relation_and)) {
++            break;
++        }
++    }
++    *matched = comp_match;
++
++cleanup:
++    free_rule_set(context, rs);
++    crypto_cert_free_matching_data(context, md);
++    return ret;
++}
+diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c
+index 42ad45fe4..7d86e597e 100644
+--- a/src/plugins/preauth/pkinit/pkinit_srv.c
++++ b/src/plugins/preauth/pkinit/pkinit_srv.c
+@@ -1537,6 +1537,56 @@ certauth_pkinit_eku_initvt(krb5_context context, int maj_ver, int min_ver,
+     return 0;
+ }
+ 
++/*
++ * Do certificate auth based on a match expression in the pkinit_cert_match
++ * attribute string.  An expression should be in the same form as those used
++ * for the pkinit_cert_match configuration option.
++ */
++static krb5_error_code
++dbmatch_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;
++    const struct certauth_req_opts *req_opts = opts;
++    char *pattern;
++    krb5_boolean matched;
++
++    *authinds_out = NULL;
++
++    /* Fetch the matching pattern.  Pass if it isn't specified. */
++    ret = req_opts->cb->get_string(context, req_opts->rock,
++                                   "pkinit_cert_match", &pattern);
++    if (ret)
++        return ret;
++    if (pattern == NULL)
++        return KRB5_PLUGIN_NO_HANDLE;
++
++    /* Check the certificate against the match expression. */
++    ret = pkinit_client_cert_match(context, req_opts->plgctx->cryptoctx,
++                                   req_opts->reqctx->cryptoctx, pattern,
++                                   &matched);
++    req_opts->cb->free_string(context, req_opts->rock, pattern);
++    if (ret)
++        return ret;
++    return matched ? 0 : KRB5KDC_ERR_CERTIFICATE_MISMATCH;
++}
++
++static krb5_error_code
++certauth_dbmatch_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 = "dbmatch";
++    vt->authorize = dbmatch_authorize;
++    return 0;
++}
++
+ static krb5_error_code
+ load_certauth_plugins(krb5_context context, certauth_handle **handle_out)
+ {
+@@ -1556,6 +1606,11 @@ load_certauth_plugins(krb5_context context, certauth_handle **handle_out)
+     if (ret)
+         goto cleanup;
+ 
++    ret = k5_plugin_register(context, PLUGIN_INTERFACE_CERTAUTH, "dbmatch",
++                             certauth_dbmatch_initvt);
++    if (ret)
++        goto cleanup;
++
+     ret = k5_plugin_load_all(context, PLUGIN_INTERFACE_CERTAUTH, &modules);
+     if (ret)
+         goto cleanup;
+diff --git a/src/tests/t_pkinit.py b/src/tests/t_pkinit.py
+index 64ff2393a..5a0624de7 100755
+--- a/src/tests/t_pkinit.py
++++ b/src/tests/t_pkinit.py
+@@ -305,6 +305,43 @@ realm.run(['./responder', '-X', 'X509_user_identity=%s' % p12_enc_identity,
+ realm.klist(realm.user_princ)
+ realm.run([kvno, realm.host_princ])
+ 
++# Match a single rule.
++rule = '<SAN>^user@KRBTEST.COM$'
++realm.run([kadminl, 'setstr', realm.user_princ, 'pkinit_cert_match', rule])
++realm.kinit(realm.user_princ,
++            flags=['-X', 'X509_user_identity=%s' % p12_identity])
++realm.klist(realm.user_princ)
++
++# Match a combined rule (default prefix is &&).
++rule = '<SUBJECT>CN=user$<KU>digitalSignature,keyEncipherment'
++realm.run([kadminl, 'setstr', realm.user_princ, 'pkinit_cert_match', rule])
++realm.kinit(realm.user_princ,
++            flags=['-X', 'X509_user_identity=%s' % p12_identity])
++realm.klist(realm.user_princ)
++
++# Fail an && rule.
++rule = '&&<SUBJECT>O=OTHER.COM<SAN>^user@KRBTEST.COM$'
++realm.run([kadminl, 'setstr', realm.user_princ, 'pkinit_cert_match', rule])
++msg = 'kinit: Certificate mismatch while getting initial credentials'
++realm.kinit(realm.user_princ,
++            flags=['-X', 'X509_user_identity=%s' % p12_identity],
++            expected_code=1, expected_msg=msg)
++
++# Pass an || rule.
++rule = '||<SUBJECT>O=KRBTEST.COM<SAN>^otheruser@KRBTEST.COM$'
++realm.run([kadminl, 'setstr', realm.user_princ, 'pkinit_cert_match', rule])
++realm.kinit(realm.user_princ,
++            flags=['-X', 'X509_user_identity=%s' % p12_identity])
++realm.klist(realm.user_princ)
++
++# Fail an || rule.
++rule = '||<SUBJECT>O=OTHER.COM<SAN>^otheruser@KRBTEST.COM$'
++realm.run([kadminl, 'setstr', realm.user_princ, 'pkinit_cert_match', rule])
++msg = 'kinit: Certificate mismatch while getting initial credentials'
++realm.kinit(realm.user_princ,
++            flags=['-X', 'X509_user_identity=%s' % p12_identity],
++            expected_code=1, expected_msg=msg)
++
+ if not have_soft_pkcs11:
+     skip_rest('PKINIT PKCS11 tests', 'soft-pkcs11.so not found')
+ 
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..d9f3412
--- /dev/null
+++ b/SOURCES/Add-the-client_name-kdcpreauth-callback.patch
@@ -0,0 +1,58 @@
+From 810e831592eeed8422197d9c8de237552645412f 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)
+---
+ 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..6cf4fa8
--- /dev/null
+++ b/SOURCES/Add-timestamp-helper-functions.patch
@@ -0,0 +1,80 @@
+From 7beabe5cf16644dd0857a5e65fc43470e8b5d852 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)
+---
+ 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..704fed1
--- /dev/null
+++ b/SOURCES/Add-timestamp-tests.patch
@@ -0,0 +1,599 @@
+From 88c93d33d66abe9811e478fd678ff2e5f38a29aa 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]
+---
+ 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-vector-support-to-k5_sha256.patch b/SOURCES/Add-vector-support-to-k5_sha256.patch
new file mode 100644
index 0000000..63438d3
--- /dev/null
+++ b/SOURCES/Add-vector-support-to-k5_sha256.patch
@@ -0,0 +1,106 @@
+From d8620f016248a9ee1fbb93aa773eb3952b99fd3d Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Sat, 3 Feb 2018 20:53:42 -0500
+Subject: [PATCH] Add vector support to k5_sha256()
+
+Add a length argument so that multiple krb5_data values can be passed
+to k5_sha256(), for efficient computation of SHA-256 hashes over
+concatenations of data values.
+
+(cherry picked from commit 4f3373e8c55b3e9bdfb5b065e07214c5816c85fa)
+---
+ src/include/k5-int.h                 | 4 ++--
+ src/lib/crypto/builtin/sha2/sha256.c | 6 ++++--
+ src/lib/crypto/crypto_tests/t_sha2.c | 2 +-
+ src/lib/crypto/openssl/sha256.c      | 6 ++++--
+ src/lib/krb5/rcache/rc_conv.c        | 2 +-
+ 5 files changed, 12 insertions(+), 8 deletions(-)
+
+diff --git a/src/include/k5-int.h b/src/include/k5-int.h
+index 10b034037..7c549bce2 100644
+--- a/src/include/k5-int.h
++++ b/src/include/k5-int.h
+@@ -634,9 +634,9 @@ krb5int_arcfour_gsscrypt(const krb5_keyblock *keyblock, krb5_keyusage usage,
+ 
+ #define K5_SHA256_HASHLEN (256 / 8)
+ 
+-/* Write the SHA-256 hash of in to out. */
++/* Write the SHA-256 hash of in (containing n elements) to out. */
+ krb5_error_code
+-k5_sha256(const krb5_data *in, uint8_t out[K5_SHA256_HASHLEN]);
++k5_sha256(const krb5_data *in, size_t n, uint8_t out[K5_SHA256_HASHLEN]);
+ 
+ /*
+  * Attempt to zero memory in a way that compilers won't optimize out.
+diff --git a/src/lib/crypto/builtin/sha2/sha256.c b/src/lib/crypto/builtin/sha2/sha256.c
+index e34bed575..4b5fe10a3 100644
+--- a/src/lib/crypto/builtin/sha2/sha256.c
++++ b/src/lib/crypto/builtin/sha2/sha256.c
+@@ -257,12 +257,14 @@ k5_sha256_final(void *res, SHA256_CTX *m)
+ }
+ 
+ krb5_error_code
+-k5_sha256(const krb5_data *in, uint8_t out[K5_SHA256_HASHLEN])
++k5_sha256(const krb5_data *in, size_t n, uint8_t out[K5_SHA256_HASHLEN])
+ {
+     SHA256_CTX ctx;
++    size_t i;
+ 
+     k5_sha256_init(&ctx);
+-    k5_sha256_update(&ctx, in->data, in->length);
++    for (i = 0; i < n; i++)
++        k5_sha256_update(&ctx, in[i].data, in[i].length);
+     k5_sha256_final(out, &ctx);
+     return 0;
+ }
+diff --git a/src/lib/crypto/crypto_tests/t_sha2.c b/src/lib/crypto/crypto_tests/t_sha2.c
+index 12f32869b..e6fa58498 100644
+--- a/src/lib/crypto/crypto_tests/t_sha2.c
++++ b/src/lib/crypto/crypto_tests/t_sha2.c
+@@ -125,7 +125,7 @@ hash_test(const struct krb5_hash_provider *hash, struct test *tests)
+ 
+ 	    if (hash == &krb5int_hash_sha256) {
+ 		/* Try again using k5_sha256(). */
+-		if (k5_sha256(&iov.data, (uint8_t *)hval.data) != 0)
++		if (k5_sha256(&iov.data, 1, (uint8_t *)hval.data) != 0)
+ 		    abort();
+ 		if (memcmp(hval.data, t->hash, hval.length) != 0)
+ 		    abort();
+diff --git a/src/lib/crypto/openssl/sha256.c b/src/lib/crypto/openssl/sha256.c
+index fa095d472..0edd8b7ba 100644
+--- a/src/lib/crypto/openssl/sha256.c
++++ b/src/lib/crypto/openssl/sha256.c
+@@ -34,16 +34,18 @@
+ #include <openssl/evp.h>
+ 
+ krb5_error_code
+-k5_sha256(const krb5_data *in, uint8_t out[K5_SHA256_HASHLEN])
++k5_sha256(const krb5_data *in, size_t n, uint8_t out[K5_SHA256_HASHLEN])
+ {
+     EVP_MD_CTX *ctx;
++    size_t i;
+     int ok;
+ 
+     ctx = EVP_MD_CTX_new();
+     if (ctx == NULL)
+         return ENOMEM;
+     ok = EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
+-    ok = ok && EVP_DigestUpdate(ctx, in->data, in->length);
++    for (i = 0; i < n; i++)
++        ok = ok && EVP_DigestUpdate(ctx, in[i].data, in[i].length);
+     ok = ok && EVP_DigestFinal_ex(ctx, out, NULL);
+     EVP_MD_CTX_free(ctx);
+     return ok ? 0 : ENOMEM;
+diff --git a/src/lib/krb5/rcache/rc_conv.c b/src/lib/krb5/rcache/rc_conv.c
+index 0e021f5d8..f2fe528ac 100644
+--- a/src/lib/krb5/rcache/rc_conv.c
++++ b/src/lib/krb5/rcache/rc_conv.c
+@@ -58,7 +58,7 @@ krb5_rc_hash_message(krb5_context context, const krb5_data *message,
+     *out = NULL;
+ 
+     /* Calculate the binary checksum. */
+-    retval = k5_sha256(message, cksum);
++    retval = k5_sha256(message, 1, cksum);
+     if (retval)
+         return retval;
+ 
diff --git a/SOURCES/Add-y2038-documentation.patch b/SOURCES/Add-y2038-documentation.patch
new file mode 100644
index 0000000..a7fcce8
--- /dev/null
+++ b/SOURCES/Add-y2038-documentation.patch
@@ -0,0 +1,59 @@
+From 087bd1bdff17025af6e5189898209035ec8d75da 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)
+---
+ 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/Address-some-optimized-out-memset-calls.patch b/SOURCES/Address-some-optimized-out-memset-calls.patch
new file mode 100644
index 0000000..2c5ddd6
--- /dev/null
+++ b/SOURCES/Address-some-optimized-out-memset-calls.patch
@@ -0,0 +1,96 @@
+From 05dc6552ea0e8f0002d21ca36d7ff47d4c088bd7 Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Sun, 30 Dec 2018 16:40:28 -0500
+Subject: [PATCH] Address some optimized-out memset() calls
+
+Ilja Van Sprundel reported a list of memset() calls which gcc
+optimizes out.  In krb_auth_su.c, use zap() to clear the password, and
+remove two memset() calls when there is no password to clear.  In
+iakerb.c, remove an unnecessary memset() before setting the only two
+fields of the IAKERB header structure.  In svr_principal.c, use
+krb5_free_key_keyblock_contents() instead of hand-freeing key data.
+In asn1_k_encode.c, remove an unnecessary memset() of the kdc_req_hack
+shell before returning.
+
+(cherry picked from commit 1057b0befec1f1c0e9d4da5521a58496e2dc0997)
+(cherry picked from commit 1dfff7202448a950c9133cdfe43d650092d930fd)
+(cherry picked from commit 54348bbfaec50bb72d1625c015f8e5c4cfa59e0d)
+---
+ src/clients/ksu/krb_auth_su.c      |  4 +---
+ src/lib/gssapi/krb5/iakerb.c       |  1 -
+ src/lib/kadm5/srv/svr_principal.c  | 10 ++--------
+ src/lib/krb5/asn.1/asn1_k_encode.c |  1 -
+ 4 files changed, 3 insertions(+), 13 deletions(-)
+
+diff --git a/src/clients/ksu/krb_auth_su.c b/src/clients/ksu/krb_auth_su.c
+index 7af48195c..e39685fff 100644
+--- a/src/clients/ksu/krb_auth_su.c
++++ b/src/clients/ksu/krb_auth_su.c
+@@ -183,21 +183,19 @@ krb5_boolean ksu_get_tgt_via_passwd(context, client, options, zero_password,
+     if (code ) {
+         com_err(prog_name, code, _("while reading password for '%s'\n"),
+                 client_name);
+-        memset(password, 0, sizeof(password));
+         return (FALSE);
+     }
+ 
+     if ( pwsize == 0) {
+         fprintf(stderr, _("No password given\n"));
+         *zero_password = TRUE;
+-        memset(password, 0, sizeof(password));
+         return (FALSE);
+     }
+ 
+     code = krb5_get_init_creds_password(context, &creds, client, password,
+                                         krb5_prompter_posix, NULL, 0, NULL,
+                                         options);
+-    memset(password, 0, sizeof(password));
++    zap(password, sizeof(password));
+ 
+ 
+     if (code) {
+diff --git a/src/lib/gssapi/krb5/iakerb.c b/src/lib/gssapi/krb5/iakerb.c
+index bb1072fe4..47c161ec9 100644
+--- a/src/lib/gssapi/krb5/iakerb.c
++++ b/src/lib/gssapi/krb5/iakerb.c
+@@ -262,7 +262,6 @@ iakerb_make_token(iakerb_ctx_id_t ctx,
+     /*
+      * Assemble the IAKERB-HEADER from the realm and cookie
+      */
+-    memset(&iah, 0, sizeof(iah));
+     iah.target_realm = *realm;
+     iah.cookie = cookie;
+ 
+diff --git a/src/lib/kadm5/srv/svr_principal.c b/src/lib/kadm5/srv/svr_principal.c
+index 64a4a2e97..73733d371 100644
+--- a/src/lib/kadm5/srv/svr_principal.c
++++ b/src/lib/kadm5/srv/svr_principal.c
+@@ -2141,14 +2141,8 @@ static int decrypt_key_data(krb5_context context,
+         ret = krb5_dbe_decrypt_key_data(context, NULL, &key_data[i], &keys[i],
+                                         NULL);
+         if (ret) {
+-            for (; i >= 0; i--) {
+-                if (keys[i].contents) {
+-                    memset (keys[i].contents, 0, keys[i].length);
+-                    free( keys[i].contents );
+-                }
+-            }
+-
+-            memset(keys, 0, n_key_data*sizeof(krb5_keyblock));
++            for (; i >= 0; i--)
++                krb5_free_keyblock_contents(context, &keys[i]);
+             free(keys);
+             return ret;
+         }
+diff --git a/src/lib/krb5/asn.1/asn1_k_encode.c b/src/lib/krb5/asn.1/asn1_k_encode.c
+index 889460989..c4f9aacdf 100644
+--- a/src/lib/krb5/asn.1/asn1_k_encode.c
++++ b/src/lib/krb5/asn.1/asn1_k_encode.c
+@@ -532,7 +532,6 @@ decode_kdc_req_body(const taginfo *t, const unsigned char *asn1, size_t len,
+         if (ret) {
+             free_kdc_req_body(b);
+             free(h.server_realm.data);
+-            memset(&h, 0, sizeof(h));
+             return ret;
+         }
+         b->server->realm = h.server_realm;
diff --git a/SOURCES/Adjust-processing-of-pa_type-ccache-config.patch b/SOURCES/Adjust-processing-of-pa_type-ccache-config.patch
new file mode 100644
index 0000000..4b787e1
--- /dev/null
+++ b/SOURCES/Adjust-processing-of-pa_type-ccache-config.patch
@@ -0,0 +1,121 @@
+From bfeb18163ba1364d37c9179bcf5e9c042c268a8b Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Fri, 13 Jan 2017 10:14:36 -0500
+Subject: [PATCH] Adjust processing of pa_type ccache config
+
+Read the allowed preauth type from the input ccache in
+restart_init_creds_loop(); there is no need to reread it each time we
+produce a request.  Move read_allowed_preauth_type() earlier in the
+file to allow it to be called from restart_init_creds_loop() without a
+prototype.
+
+Clear the selected preauth type in restart_init_creds_loop(), not in
+init_creds_step_request().  We want to make sure that it doesn't
+survive a restart due to a realm referral or expiry, but we don't want
+to forget about it when retrying after an error.
+
+(cherry picked from commit 468c6eb7bb860f7ec0381086a22859f822b41c43)
+---
+ src/lib/krb5/krb/get_in_tkt.c | 61 ++++++++++++++++++-----------------
+ 1 file changed, 31 insertions(+), 30 deletions(-)
+
+diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
+index 52e07bb67..da12204ac 100644
+--- a/src/lib/krb5/krb/get_in_tkt.c
++++ b/src/lib/krb5/krb/get_in_tkt.c
+@@ -791,6 +791,31 @@ set_request_times(krb5_context context, krb5_init_creds_context ctx)
+     return 0;
+ }
+ 
++static void
++read_allowed_preauth_type(krb5_context context, krb5_init_creds_context ctx)
++{
++    krb5_error_code ret;
++    krb5_data config;
++    char *tmp, *p;
++    krb5_ccache in_ccache = k5_gic_opt_get_in_ccache(ctx->opt);
++
++    ctx->allowed_preauth_type = KRB5_PADATA_NONE;
++    if (in_ccache == NULL)
++        return;
++    memset(&config, 0, sizeof(config));
++    if (krb5_cc_get_config(context, in_ccache, ctx->request->server,
++                           KRB5_CC_CONF_PA_TYPE, &config) != 0)
++        return;
++    tmp = k5memdup0(config.data, config.length, &ret);
++    krb5_free_data_contents(context, &config);
++    if (tmp == NULL)
++        return;
++    ctx->allowed_preauth_type = strtol(tmp, &p, 10);
++    if (p == NULL || *p != '\0')
++        ctx->allowed_preauth_type = KRB5_PADATA_NONE;
++    free(tmp);
++}
++
+ /**
+  * Throw away any pre-authentication realm state and begin with a
+  * unauthenticated or optimistically authenticated request.  If fast_upgrade is
+@@ -807,6 +832,7 @@ restart_init_creds_loop(krb5_context context, krb5_init_creds_context ctx,
+     krb5_free_error(context, ctx->err_reply);
+     ctx->preauth_to_use = ctx->err_padata = NULL;
+     ctx->err_reply = NULL;
++    ctx->selected_preauth_type = KRB5_PADATA_NONE;
+ 
+     krb5int_fast_free_state(context, ctx->fast_state);
+     ctx->fast_state = NULL;
+@@ -849,6 +875,11 @@ restart_init_creds_loop(krb5_context context, krb5_init_creds_context ctx,
+                                       &ctx->outer_request_body);
+     if (code != 0)
+         goto cleanup;
++
++    /* Read the allowed preauth type for this server principal from the input
++     * ccache, if the application supplied one. */
++    read_allowed_preauth_type(context, ctx);
++
+ cleanup:
+     return code;
+ }
+@@ -1154,31 +1185,6 @@ init_creds_validate_reply(krb5_context context,
+     return 0;
+ }
+ 
+-static void
+-read_allowed_preauth_type(krb5_context context, krb5_init_creds_context ctx)
+-{
+-    krb5_error_code ret;
+-    krb5_data config;
+-    char *tmp, *p;
+-    krb5_ccache in_ccache = k5_gic_opt_get_in_ccache(ctx->opt);
+-
+-    ctx->allowed_preauth_type = KRB5_PADATA_NONE;
+-    if (in_ccache == NULL)
+-        return;
+-    memset(&config, 0, sizeof(config));
+-    if (krb5_cc_get_config(context, in_ccache, ctx->request->server,
+-                           KRB5_CC_CONF_PA_TYPE, &config) != 0)
+-        return;
+-    tmp = k5memdup0(config.data, config.length, &ret);
+-    krb5_free_data_contents(context, &config);
+-    if (tmp == NULL)
+-        return;
+-    ctx->allowed_preauth_type = strtol(tmp, &p, 10);
+-    if (p == NULL || *p != '\0')
+-        ctx->allowed_preauth_type = KRB5_PADATA_NONE;
+-    free(tmp);
+-}
+-
+ static krb5_error_code
+ save_selected_preauth_type(krb5_context context, krb5_ccache ccache,
+                            krb5_init_creds_context ctx)
+@@ -1317,11 +1323,6 @@ init_creds_step_request(krb5_context context,
+     if (code)
+         goto cleanup;
+ 
+-    /* Read the allowed patype for this server principal from the in_ccache,
+-     * if the application supplied one. */
+-    read_allowed_preauth_type(context, ctx);
+-    ctx->selected_preauth_type = KRB5_PADATA_NONE;
+-
+     /*
+      * Read cached preauth configuration data for this server principal from
+      * the in_ccache, if the application supplied one, and delete any that was
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..d9e5c5f
--- /dev/null
+++ b/SOURCES/Allow-clock-skew-in-krb5-gss_context_time.patch
@@ -0,0 +1,36 @@
+From 527fafc0e0abf90c1bb3d66c31ea92a96e095f08 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)
+---
+ 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/Bring-back-general-kerberos-man-page.patch b/SOURCES/Bring-back-general-kerberos-man-page.patch
new file mode 100644
index 0000000..dcfe5e9
--- /dev/null
+++ b/SOURCES/Bring-back-general-kerberos-man-page.patch
@@ -0,0 +1,468 @@
+From df8c8cc7cd18fa94c920c4763545b6fd93a21fcd Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Tue, 9 Oct 2018 17:05:10 -0400
+Subject: [PATCH] Bring back general kerberos man page
+
+Restore the content of kerberos(1) as it stood in
+0f81e372a2830c9170f6e08dfa956841d0ebdfb1.  Convert to ReST to match
+the other man pages, and install it as the more appropriate
+kerberos(7).
+
+Build kerberos(7) and check it in to avoid breaking the build.
+
+ticket: 8755 (new)
+tags: pullup
+target_version: 1.16-next
+
+(cherry picked from commit c38197ee9808503f86ccffd4a2bd94389e17df0b)
+---
+ doc/conf.py                       |   1 +
+ doc/user/user_config/index.rst    |   1 +
+ doc/user/user_config/kerberos.rst | 148 ++++++++++++++++++++++++
+ src/Makefile.in                   |   4 +-
+ src/config/pre.in                 |   2 +
+ src/man/Makefile.in               |  14 ++-
+ src/man/kerberos.man              | 180 ++++++++++++++++++++++++++++++
+ 7 files changed, 345 insertions(+), 5 deletions(-)
+ create mode 100644 doc/user/user_config/kerberos.rst
+ create mode 100644 src/man/kerberos.man
+
+diff --git a/doc/conf.py b/doc/conf.py
+index 3ee2df630..68dad781f 100644
+--- a/doc/conf.py
++++ b/doc/conf.py
+@@ -292,6 +292,7 @@ man_pages = [
+     ('user/user_commands/krb5-config', 'krb5-config', u'tool for linking against MIT Kerberos libraries', [u'MIT'], 1),
+     ('user/user_config/k5login', 'k5login', u'Kerberos V5 acl file for host access', [u'MIT'], 5),
+     ('user/user_config/k5identity', 'k5identity', u'Kerberos V5 client principal selection rules', [u'MIT'], 5),
++    ('user/user_config/kerberos', 'kerberos', u'Overview of using Kerberos', [u'MIT'], 7),
+     ('admin/admin_commands/krb5kdc', 'krb5kdc', u'Kerberos V5 KDC', [u'MIT'], 8),
+     ('admin/admin_commands/kadmin_local', 'kadmin', u'Kerberos V5 database administration program', [u'MIT'], 1),
+     ('admin/admin_commands/kprop', 'kprop', u'propagate a Kerberos V5 principal database to a slave server', [u'MIT'], 8),
+diff --git a/doc/user/user_config/index.rst b/doc/user/user_config/index.rst
+index 6b3d4393b..ad0dc1a72 100644
+--- a/doc/user/user_config/index.rst
++++ b/doc/user/user_config/index.rst
+@@ -8,5 +8,6 @@ been disabled by your host's configuration):
+ .. toctree::
+    :maxdepth: 1
+ 
++   kerberos.rst
+    k5login.rst
+    k5identity.rst
+diff --git a/doc/user/user_config/kerberos.rst b/doc/user/user_config/kerberos.rst
+new file mode 100644
+index 000000000..6c4453b3b
+--- /dev/null
++++ b/doc/user/user_config/kerberos.rst
+@@ -0,0 +1,148 @@
++.. _kerberos(7):
++
++kerberos
++========
++
++DESCRIPTION
++-----------
++
++The Kerberos system authenticates individual users in a network
++environment.  After authenticating yourself to Kerberos, you can use
++Kerberos-enabled programs without having to present passwords.
++
++If you enter your username and :ref:`kinit(1)` responds with this
++message:
++
++kinit(v5): Client not found in Kerberos database while getting initial
++credentials
++
++you haven't been registered as a Kerberos user.  See your system
++administrator.
++
++A Kerberos name usually contains three parts.  The first is the
++**primary**, which is usually a user's or service's name.  The second
++is the **instance**, which in the case of a user is usually null.
++Some users may have privileged instances, however, such as ``root`` or
++``admin``.  In the case of a service, the instance is the fully
++qualified name of the machine on which it runs; i.e. there can be an
++rlogin service running on the machine ABC, which is different from the
++rlogin service running on the machine XYZ.  The third part of a
++Kerberos name is the **realm**.  The realm corresponds to the Kerberos
++service providing authentication for the principal.
++
++When writing a Kerberos name, the principal name is separated from the
++instance (if not null) by a slash, and the realm (if not the local
++realm) follows, preceded by an "@" sign.  The following are examples
++of valid Kerberos names::
++
++    david
++    jennifer/admin
++    joeuser@BLEEP.COM
++    cbrown/root@FUBAR.ORG
++
++When you authenticate yourself with Kerberos you get an initial
++Kerberos **ticket**.  (A Kerberos ticket is an encrypted protocol
++message that provides authentication.)  Kerberos uses this ticket for
++network utilities such as rlogin and rcp.  The ticket transactions are
++done transparently, so you don't have to worry about their management.
++
++Note, however, that tickets expire.  Privileged tickets, such as those
++with the instance ``root``, expire in a few minutes, while tickets
++that carry more ordinary privileges may be good for several hours or a
++day, depending on the installation's policy.  If your login session
++extends beyond the time limit, you will have to re-authenticate
++yourself to Kerberos to get new tickets.  Use the :ref:`kinit(1)`
++command to re-authenticate yourself.
++
++If you use the kinit command to get your tickets, make sure you use
++the kdestroy command to destroy your tickets before you end your login
++session.  You should put the kdestroy command in your ``.logout`` file
++so that your tickets will be destroyed automatically when you logout.
++For more information about the kinit and kdestroy commands, see the
++:ref:`kinit(1)` and :ref:`kdestroy(1)` manual pages.
++
++Kerberos tickets can be forwarded.  In order to forward tickets, you
++must request **forwardable** tickets when you kinit.  Once you have
++forwardable tickets, most Kerberos programs have a command line option
++to forward them to the remote host.
++
++ENVIRONMENT VARIABLES
++---------------------
++
++Several environment variables affect the operation of Kerberos-enabled
++programs.  These inclide:
++
++**KRB5CCNAME**
++    Specifies the location of the credential cache, in the form
++    *TYPE*:*residual*.  If no *type* prefix is present, the **FILE**
++    type is assumed and *residual* is the pathname of the cache file.
++    A collection of multiple caches may be used by specifying the
++    **dir** type and the pathname of a private directory (which must
++    already exist).  The default cache file is /tmp/krb5cc_*uid*,
++    where *uid* is the decimal user ID of the user.
++
++**KRB5_KTNAME**
++    Specifies the location of the keytab file, in the form
++    *TYPE*:*residual*.  If no *type* is present, the **FILE** type is
++    assumed and *residual* is the pathname of the keytab file.  The
++    default keytab file is ``/etc/krb5.keytab``.
++
++**KRB5_CONFIG**
++    Specifies the location of the Kerberos configuration file.  The
++    default is ``/etc/krb5.conf``.
++
++**KRB5_KDC_PROFILE**
++    Specifies the location of the KDC configuration file, which
++    contains additional configuration directives for the Key
++    Distribution Center daemon and associated programs.  The default
++    is ``/usr/local/var/krb5kdc/kdc.conf``.
++
++**KRB5RCACHETYPE**
++    Specifies the default type of replay cache to use for servers.
++    Valid types include **dfl** for the normal file type and **none**
++    for no replay cache.
++
++**KRB5RCACHEDIR**
++    Specifies the default directory for replay caches used by servers.
++    The default is the value of the **TMPDIR** environment variable,
++    or ``/var/tmp`` if **TMPDIR** is not set.
++
++**KRB5_TRACE**
++    Specifies a filename to write trace log output to.  Trace logs can
++    help illuminate decisions made internally by the Kerberos
++    libraries.  The default is not to write trace log output anywhere.
++
++Most environment variables are disabled for certain programs, such as
++login system programs and setuid programs, which are designed to be
++secure when run within an untrusted process environment.
++
++SEE ALSO
++--------
++
++:ref:`kdestroy(1)`, :ref:`kinit(1)`, :ref:`klist(1)`,
++:ref:`kswitch(1)`, :ref:`kpasswd(1)`, :ref:`ksu(1)`,
++:ref:`krb5.conf(5)`, :ref:`kdc.conf(5)`, :ref:`kadmin(1)`,
++:ref:`kadmind(8)`, :ref:`kdb5_util(8)`, :ref:`krb5kdc(8)`
++
++BUGS
++----
++
++AUTHORS
++-------
++
++| Steve Miller, MIT Project Athena/Digital Equipment Corporation
++| Clifford Neuman, MIT Project Athena
++| Greg Hudson, MIT Kerberos Consortium
++
++HISTORY
++-------
++
++The MIT Kerberos 5 implementation was developed at MIT, with
++contributions from many outside parties.  It is currently maintained
++by the MIT Kerberos Consortium.
++
++RESTRICTIONS
++------------
++
++Copyright 1985, 1986, 1989-1996, 2002, 2011 Masachusetts Institute of
++Technology
+diff --git a/src/Makefile.in b/src/Makefile.in
+index e47bddcb1..91032361f 100644
+--- a/src/Makefile.in
++++ b/src/Makefile.in
+@@ -60,9 +60,9 @@ world:
+ INSTALLMKDIRS = $(KRB5ROOT) $(KRB5MANROOT) $(KRB5OTHERMKDIRS) \
+ 		$(ADMIN_BINDIR) $(SERVER_BINDIR) $(CLIENT_BINDIR) \
+ 		$(ADMIN_MANDIR) $(SERVER_MANDIR) $(CLIENT_MANDIR) \
+-		$(FILE_MANDIR) \
++		$(FILE_MANDIR) $(OVERVIEW_MANDIR) \
+ 		$(ADMIN_CATDIR) $(SERVER_CATDIR) $(CLIENT_CATDIR) \
+-		$(FILE_CATDIR) \
++		$(FILE_CATDIR) $(OVERVIEW_CATDIR) \
+ 		$(KRB5_LIBDIR) $(KRB5_INCDIR) \
+ 		$(KRB5_DB_MODULE_DIR) $(KRB5_PA_MODULE_DIR) \
+ 		$(KRB5_AD_MODULE_DIR) \
+diff --git a/src/config/pre.in b/src/config/pre.in
+index f23c07d9d..a851c56c7 100644
+--- a/src/config/pre.in
++++ b/src/config/pre.in
+@@ -210,6 +210,8 @@ ADMIN_CATDIR = $(KRB5MANROOT)/cat8
+ SERVER_CATDIR = $(KRB5MANROOT)/cat8
+ CLIENT_CATDIR = $(KRB5MANROOT)/cat1
+ FILE_CATDIR = $(KRB5MANROOT)/cat5
++OVERVIEW_MANDIR = $(KRB5MANROOT)/man7
++OVERVIEW_CATDIR = $(KRB5MANROOT)/cat7
+ KRB5_LIBDIR = @libdir@
+ KRB5_INCDIR = @includedir@
+ MODULE_DIR = @libdir@/krb5/plugins
+diff --git a/src/man/Makefile.in b/src/man/Makefile.in
+index 4bc670bad..e3722b1cd 100644
+--- a/src/man/Makefile.in
++++ b/src/man/Makefile.in
+@@ -15,7 +15,7 @@ MANSUBS=k5identity.sub k5login.sub k5srvutil.sub kadm5.acl.sub kadmin.sub \
+ 	kadmind.sub kdb5_ldap_util.sub kdb5_util.sub kdc.conf.sub \
+ 	kdestroy.sub kinit.sub klist.sub kpasswd.sub kprop.sub kpropd.sub \
+ 	kproplog.sub krb5.conf.sub krb5-config.sub krb5kdc.sub ksu.sub \
+-	kswitch.sub ktutil.sub kvno.sub sclient.sub sserver.sub
++	kswitch.sub ktutil.sub kvno.sub sclient.sub sserver.sub kerberos.sub
+ 
+ docsrc=$(top_srcdir)/../doc
+ 
+@@ -56,9 +56,11 @@ all: $(MANSUBS)
+ clean:
+ 	rm -rf $(MANSUBS) rst_man
+ 
+-install: install-clientman install-fileman install-adminman install-serverman
++install: install-clientman install-fileman install-adminman \
++	install-overviewman install-serverman
+ 
+-install-catman: install-clientcat install-filecat install-admincat install-servercat
++install-catman: install-clientcat install-filecat install-admincat \
++	install-overviewcat install-servercat
+ 
+ install-clientman:
+ 	$(INSTALL_DATA) k5srvutil.sub $(DESTDIR)$(CLIENT_MANDIR)/k5srvutil.1
+@@ -85,6 +87,9 @@ install-fileman:
+ 	$(INSTALL_DATA) kdc.conf.sub $(DESTDIR)$(FILE_MANDIR)/kdc.conf.5
+ 	$(INSTALL_DATA) krb5.conf.sub $(DESTDIR)$(FILE_MANDIR)/krb5.conf.5
+ 
++install-overviewman:
++	$(INSTALL_DATA) kerberos.sub $(DESTDIR)$(OVERVIEW_MANDIR)/kerberos.7
++
+ install-adminman:
+ 	$(INSTALL_DATA) $(srcdir)/kadmin.local.8 \
+ 		$(DESTDIR)$(ADMIN_MANDIR)/kadmin.local.8
+@@ -127,6 +132,9 @@ install-filecat:
+ 	$(GROFF_MAN) kdc.conf.sub > $(DESTDIR)$(FILE_CATDIR)/kdc.conf.5
+ 	$(GROFF_MAN) krb5.conf.sub > $(DESTDIR)$(FILE_CATDIR)/krb5.conf.5
+ 
++install-overviewcat:
++	$(GROFF_MAN) kerberos.sub > $(DESTDIR)$(OVERVIEW_CATDIR)/kerberos.7
++
+ install-admincat:
+ 	($(RM) $(DESTDIR)$(ADMIN_CATDIR)/kadmin.local.8; \
+ 		$(LN_S) $(CLIENT_CATDIR)/kadmin.1 \
+diff --git a/src/man/kerberos.man b/src/man/kerberos.man
+new file mode 100644
+index 000000000..7b2b5d932
+--- /dev/null
++++ b/src/man/kerberos.man
+@@ -0,0 +1,180 @@
++.\" Man page generated from reStructuredText.
++.
++.TH "KERBEROS" "7" " " "1.17" "MIT Kerberos"
++.SH NAME
++kerberos \- Overview of using Kerberos
++.
++.nr rst2man-indent-level 0
++.
++.de1 rstReportMargin
++\\$1 \\n[an-margin]
++level \\n[rst2man-indent-level]
++level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
++-
++\\n[rst2man-indent0]
++\\n[rst2man-indent1]
++\\n[rst2man-indent2]
++..
++.de1 INDENT
++.\" .rstReportMargin pre:
++. RS \\$1
++. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
++. nr rst2man-indent-level +1
++.\" .rstReportMargin post:
++..
++.de UNINDENT
++. RE
++.\" indent \\n[an-margin]
++.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
++.nr rst2man-indent-level -1
++.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
++.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
++..
++.SH DESCRIPTION
++.sp
++The Kerberos system authenticates individual users in a network
++environment.  After authenticating yourself to Kerberos, you can use
++Kerberos\-enabled programs without having to present passwords.
++.sp
++If you enter your username and kinit(1) responds with this
++message:
++.sp
++kinit(v5): Client not found in Kerberos database while getting initial
++credentials
++.sp
++you haven\(aqt been registered as a Kerberos user.  See your system
++administrator.
++.sp
++A Kerberos name usually contains three parts.  The first is the
++\fBprimary\fP, which is usually a user\(aqs or service\(aqs name.  The second
++is the \fBinstance\fP, which in the case of a user is usually null.
++Some users may have privileged instances, however, such as \fBroot\fP or
++\fBadmin\fP\&.  In the case of a service, the instance is the fully
++qualified name of the machine on which it runs; i.e. there can be an
++rlogin service running on the machine ABC, which is different from the
++rlogin service running on the machine XYZ.  The third part of a
++Kerberos name is the \fBrealm\fP\&.  The realm corresponds to the Kerberos
++service providing authentication for the principal.
++.sp
++When writing a Kerberos name, the principal name is separated from the
++instance (if not null) by a slash, and the realm (if not the local
++realm) follows, preceded by an "@" sign.  The following are examples
++of valid Kerberos names:
++.INDENT 0.0
++.INDENT 3.5
++.sp
++.nf
++.ft C
++david
++jennifer/admin
++joeuser@BLEEP.COM
++cbrown/root@FUBAR.ORG
++.ft P
++.fi
++.UNINDENT
++.UNINDENT
++.sp
++When you authenticate yourself with Kerberos you get an initial
++Kerberos \fBticket\fP\&.  (A Kerberos ticket is an encrypted protocol
++message that provides authentication.)  Kerberos uses this ticket for
++network utilities such as rlogin and rcp.  The ticket transactions are
++done transparently, so you don\(aqt have to worry about their management.
++.sp
++Note, however, that tickets expire.  Privileged tickets, such as those
++with the instance \fBroot\fP, expire in a few minutes, while tickets
++that carry more ordinary privileges may be good for several hours or a
++day, depending on the installation\(aqs policy.  If your login session
++extends beyond the time limit, you will have to re\-authenticate
++yourself to Kerberos to get new tickets.  Use the kinit(1)
++command to re\-authenticate yourself.
++.sp
++If you use the kinit command to get your tickets, make sure you use
++the kdestroy command to destroy your tickets before you end your login
++session.  You should put the kdestroy command in your \fB\&.logout\fP file
++so that your tickets will be destroyed automatically when you logout.
++For more information about the kinit and kdestroy commands, see the
++kinit(1) and kdestroy(1) manual pages.
++.sp
++Kerberos tickets can be forwarded.  In order to forward tickets, you
++must request \fBforwardable\fP tickets when you kinit.  Once you have
++forwardable tickets, most Kerberos programs have a command line option
++to forward them to the remote host.
++.SH ENVIRONMENT VARIABLES
++.sp
++Several environment variables affect the operation of Kerberos\-enabled
++programs.  These inclide:
++.INDENT 0.0
++.TP
++\fBKRB5CCNAME\fP
++Specifies the location of the credential cache, in the form
++\fITYPE\fP:\fIresidual\fP\&.  If no \fItype\fP prefix is present, the \fBFILE\fP
++type is assumed and \fIresidual\fP is the pathname of the cache file.
++A collection of multiple caches may be used by specifying the
++\fBdir\fP type and the pathname of a private directory (which must
++already exist).  The default cache file is /tmp/krb5cc_*uid*,
++where \fIuid\fP is the decimal user ID of the user.
++.TP
++\fBKRB5_KTNAME\fP
++Specifies the location of the keytab file, in the form
++\fITYPE\fP:\fIresidual\fP\&.  If no \fItype\fP is present, the \fBFILE\fP type is
++assumed and \fIresidual\fP is the pathname of the keytab file.  The
++default keytab file is \fB/etc/krb5.keytab\fP\&.
++.TP
++\fBKRB5_CONFIG\fP
++Specifies the location of the Kerberos configuration file.  The
++default is \fB/etc/krb5.conf\fP\&.
++.TP
++\fBKRB5_KDC_PROFILE\fP
++Specifies the location of the KDC configuration file, which
++contains additional configuration directives for the Key
++Distribution Center daemon and associated programs.  The default
++is \fB/usr/local/var/krb5kdc/kdc.conf\fP\&.
++.TP
++\fBKRB5RCACHETYPE\fP
++Specifies the default type of replay cache to use for servers.
++Valid types include \fBdfl\fP for the normal file type and \fBnone\fP
++for no replay cache.
++.TP
++\fBKRB5RCACHEDIR\fP
++Specifies the default directory for replay caches used by servers.
++The default is the value of the \fBTMPDIR\fP environment variable,
++or \fB/var/tmp\fP if \fBTMPDIR\fP is not set.
++.TP
++\fBKRB5_TRACE\fP
++Specifies a filename to write trace log output to.  Trace logs can
++help illuminate decisions made internally by the Kerberos
++libraries.  The default is not to write trace log output anywhere.
++.UNINDENT
++.sp
++Most environment variables are disabled for certain programs, such as
++login system programs and setuid programs, which are designed to be
++secure when run within an untrusted process environment.
++.SH SEE ALSO
++.sp
++kdestroy(1), kinit(1), klist(1),
++kswitch(1), kpasswd(1), ksu(1),
++krb5.conf(5), kdc.conf(5), kadmin(1),
++kadmind(8), kdb5_util(8), krb5kdc(8)
++.SH BUGS
++.SH AUTHORS
++.nf
++Steve Miller, MIT Project Athena/Digital Equipment Corporation
++Clifford Neuman, MIT Project Athena
++Greg Hudson, MIT Kerberos Consortium
++.fi
++.sp
++.SH HISTORY
++.sp
++The MIT Kerberos 5 implementation was developed at MIT, with
++contributions from many outside parties.  It is currently maintained
++by the MIT Kerberos Consortium.
++.SH RESTRICTIONS
++.sp
++Copyright 1985, 1986, 1989\-1996, 2002, 2011 Masachusetts Institute of
++Technology
++.SH AUTHOR
++MIT
++.SH COPYRIGHT
++1985-2018, MIT
++.\" Generated by docutils manpage writer.
++.
diff --git a/SOURCES/Continue-after-KDC_ERR_PREAUTH_FAILED.patch b/SOURCES/Continue-after-KDC_ERR_PREAUTH_FAILED.patch
new file mode 100644
index 0000000..7da3368
--- /dev/null
+++ b/SOURCES/Continue-after-KDC_ERR_PREAUTH_FAILED.patch
@@ -0,0 +1,100 @@
+From 75b375abcec69421c430a0241e5c72cafd96cb7f Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Mon, 16 Jan 2017 15:09:32 -0500
+Subject: [PATCH] Continue after KDC_ERR_PREAUTH_FAILED
+
+If the KDC sends KDC_ERR_PREAUTH_FAILED, try another mechanism, or
+send an unauthenticated request if optimistic preauth failed.
+
+ticket: 8537
+(cherry picked from commit 52d2de31bc4728dbc2f59c6033dcdab86da919e9)
+---
+ src/lib/krb5/krb/get_in_tkt.c | 45 ++++++++++++++++++++++++++++-------
+ 1 file changed, 36 insertions(+), 9 deletions(-)
+
+diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
+index 8d0f964f9..c7d7bfe74 100644
+--- a/src/lib/krb5/krb/get_in_tkt.c
++++ b/src/lib/krb5/krb/get_in_tkt.c
+@@ -1308,6 +1308,7 @@ init_creds_step_request(krb5_context context,
+     krb5_error_code code;
+     krb5_preauthtype pa_type;
+     struct errinfo save = EMPTY_ERRINFO;
++    uint32_t rcode = (ctx->err_reply == NULL) ? 0 : ctx->err_reply->error;
+ 
+     if (ctx->loopcount >= MAX_IN_TKT_LOOPS) {
+         code = KRB5_GET_IN_TKT_LOOP;
+@@ -1358,8 +1359,10 @@ init_creds_step_request(krb5_context context,
+         TRACE_INIT_CREDS_PREAUTH_MORE(context, ctx->selected_preauth_type);
+         code = k5_preauth(context, ctx, ctx->more_padata, TRUE,
+                           &ctx->request->padata, &pa_type);
+-    } else if (ctx->err_reply != NULL &&
+-               ctx->err_reply->error != KDC_ERR_PREAUTH_REQUIRED) {
++    } else if (rcode == KDC_ERR_PREAUTH_FAILED) {
++        /* Report the KDC-side failure code if we can't try another mech. */
++        code = KRB5KDC_ERR_PREAUTH_FAILED;
++    } else if (rcode && rcode != KDC_ERR_PREAUTH_REQUIRED) {
+         /* Retrying after an error (possibly mechanism-specific), using error
+          * padata to figure out what to change. */
+         TRACE_INIT_CREDS_PREAUTH_TRYAGAIN(context, ctx->err_reply->error,
+@@ -1380,7 +1383,7 @@ init_creds_step_request(krb5_context context,
+ 
+     if (ctx->request->padata == NULL && ctx->method_padata != NULL) {
+         /* Retrying after KDC_ERR_PREAUTH_REQUIRED, or trying again with a
+-         * different mechanism after a client-side failure. */
++         * different mechanism after a failure. */
+         TRACE_INIT_CREDS_PREAUTH(context);
+         code = k5_preauth(context, ctx, ctx->method_padata, TRUE,
+                           &ctx->request->padata, &ctx->selected_preauth_type);
+@@ -1480,6 +1483,18 @@ is_referral(krb5_context context, krb5_error *err, krb5_principal client)
+     return !krb5_realm_compare(context, err->client, client);
+ }
+ 
++/* Transfer error padata to method data in ctx and sort it according to
++ * configuration. */
++static krb5_error_code
++accept_method_data(krb5_context context, krb5_init_creds_context ctx)
++{
++    krb5_free_pa_data(context, ctx->method_padata);
++    ctx->method_padata = ctx->err_padata;
++    ctx->err_padata = NULL;
++    return sort_krb5_padata_sequence(context, &ctx->request->client->realm,
++                                     ctx->method_padata);
++}
++
+ static krb5_error_code
+ init_creds_step_reply(krb5_context context,
+                       krb5_init_creds_context ctx,
+@@ -1538,14 +1553,26 @@ init_creds_step_reply(krb5_context context,
+             ctx->restarted = FALSE;
+             code = restart_init_creds_loop(context, ctx, FALSE);
+         } else if (reply_code == KDC_ERR_PREAUTH_REQUIRED && retry) {
+-            krb5_free_pa_data(context, ctx->method_padata);
+-            ctx->method_padata = ctx->err_padata;
+-            ctx->err_padata = NULL;
+             note_req_timestamp(context, ctx, ctx->err_reply->stime,
+                                ctx->err_reply->susec);
+-            code = sort_krb5_padata_sequence(context,
+-                                             &ctx->request->client->realm,
+-                                             ctx->method_padata);
++            code = accept_method_data(context, ctx);
++        } else if (reply_code == KDC_ERR_PREAUTH_FAILED && retry) {
++            note_req_timestamp(context, ctx, ctx->err_reply->stime,
++                               ctx->err_reply->susec);
++            if (ctx->method_padata == NULL) {
++                /* Optimistic preauth failed on the KDC.  Allow all mechanisms
++                 * to be tried again using method data. */
++                k5_reset_preauth_types_tried(ctx);
++            } else {
++                /* Don't try again with the mechanism that failed. */
++                code = k5_preauth_note_failed(ctx, ctx->selected_preauth_type);
++                if (code)
++                    goto cleanup;
++            }
++            ctx->selected_preauth_type = KRB5_PADATA_NONE;
++            /* Accept or update method data if the KDC sent it. */
++            if (ctx->err_padata != NULL)
++                code = accept_method_data(context, ctx);
+         } else if (reply_code == KDC_ERR_MORE_PREAUTH_DATA_REQUIRED && retry) {
+             ctx->more_padata = ctx->err_padata;
+             ctx->err_padata = NULL;
diff --git a/SOURCES/Continue-after-KRB5_CC_END-in-KCM-cache-iteration.patch b/SOURCES/Continue-after-KRB5_CC_END-in-KCM-cache-iteration.patch
new file mode 100644
index 0000000..08ba8cc
--- /dev/null
+++ b/SOURCES/Continue-after-KRB5_CC_END-in-KCM-cache-iteration.patch
@@ -0,0 +1,42 @@
+From c66f120e6eba811ba1417ce67b49a01958b1c9d1 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <fidencio@redhat.com>
+Date: Wed, 28 Mar 2018 18:27:06 +0200
+Subject: [PATCH] Continue after KRB5_CC_END in KCM cache iteration
+
+The KCM server returns KRB5_CC_END in response to a GET_CACHE_BY_UUID
+request to indicate that the specified ccache uuid no longer exists.
+In krb5_ptcursor_next(), ignore this error and continue the iteration,
+as the Heimdal KCM client code does.
+
+In addition to addressing the case where a third party deletes a cache
+between the GET_CACHE_UUID_LIST request and when we reach that uuid in
+the iteration, this change also fixes a bug in kdestroy -A where the
+caller deletes the primary cache and we later request it by uuid when
+iterating over the list.
+
+[ghudson@mit.edu: rewrote commit message; edited comment]
+
+(cherry picked from commit 49087f5e6309f298f8898c35af6f4ade418ced60)
+
+ticket: 8658
+version_fixed: 1.16.1
+
+(cherry picked from commit 576d4294ea789c3d25c50a43fe9246cfe499585f)
+---
+ src/lib/krb5/ccache/cc_kcm.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/src/lib/krb5/ccache/cc_kcm.c b/src/lib/krb5/ccache/cc_kcm.c
+index a889e67b4..a3afd7056 100644
+--- a/src/lib/krb5/ccache/cc_kcm.c
++++ b/src/lib/krb5/ccache/cc_kcm.c
+@@ -966,6 +966,9 @@ kcm_ptcursor_next(krb5_context context, krb5_cc_ptcursor cursor,
+         kcmreq_init(&req, KCM_OP_GET_CACHE_BY_UUID, NULL);
+         k5_buf_add_len(&req.reqbuf, id, KCM_UUID_LEN);
+         ret = kcmio_call(context, data->io, &req);
++        /* Continue if the cache has been deleted. */
++        if (ret == KRB5_CC_END)
++            continue;
+         if (ret)
+             goto cleanup;
+         ret = kcmreq_get_name(&req, &name);
diff --git a/SOURCES/Continue-preauth-after-client-side-failures.patch b/SOURCES/Continue-preauth-after-client-side-failures.patch
new file mode 100644
index 0000000..c03b071
--- /dev/null
+++ b/SOURCES/Continue-preauth-after-client-side-failures.patch
@@ -0,0 +1,109 @@
+From d45e1ea83a6ed9eef0e7e6bfe86c8d4995a7402d Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Sat, 14 Jan 2017 13:55:22 -0500
+Subject: [PATCH] Continue preauth after client-side failures
+
+If the module for the selected preauth mechanism fails when processing
+a KDC_ERR_MORE_PREAUTH_DATA_REQUIRED error, or fails a tryagain
+operation, try again with a different preauth mech using the cached
+method data.
+
+If optimistic preauth fails on the client side, send an
+unauthenticated request, allowing the mechanisms we tried
+optimistically to be tried again.
+
+ticket: 8537
+(cherry picked from commit 644840a207917661a6ccf706e7830bec273e23b3)
+---
+ src/lib/krb5/krb/get_in_tkt.c | 49 +++++++++++++++++++++++------------
+ 1 file changed, 32 insertions(+), 17 deletions(-)
+
+diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
+index 8c7919e65..8d0f964f9 100644
+--- a/src/lib/krb5/krb/get_in_tkt.c
++++ b/src/lib/krb5/krb/get_in_tkt.c
+@@ -1307,6 +1307,7 @@ init_creds_step_request(krb5_context context,
+ {
+     krb5_error_code code;
+     krb5_preauthtype pa_type;
++    struct errinfo save = EMPTY_ERRINFO;
+ 
+     if (ctx->loopcount >= MAX_IN_TKT_LOOPS) {
+         code = KRB5_GET_IN_TKT_LOOP;
+@@ -1341,38 +1342,51 @@ init_creds_step_request(krb5_context context,
+     if (ctx->optimistic_padata != NULL) {
+         /* Our first attempt, using an optimistic padata list. */
+         TRACE_INIT_CREDS_PREAUTH_OPTIMISTIC(context);
+-        code = k5_preauth(context, ctx, ctx->optimistic_padata, FALSE,
++        code = k5_preauth(context, ctx, ctx->optimistic_padata, TRUE,
+                           &ctx->request->padata, &ctx->selected_preauth_type);
+         krb5_free_pa_data(context, ctx->optimistic_padata);
+         ctx->optimistic_padata = NULL;
+-        if (code != 0)
+-            goto cleanup;
++        if (code) {
++            /* Make an unauthenticated request, and possibly try again using
++             * the same mechanisms as we tried optimistically. */
++            k5_reset_preauth_types_tried(ctx);
++            krb5_clear_error_message(context);
++            code = 0;
++        }
+     } if (ctx->more_padata != NULL) {
+         /* Continuing after KDC_ERR_MORE_PREAUTH_DATA_REQUIRED. */
+         TRACE_INIT_CREDS_PREAUTH_MORE(context, ctx->selected_preauth_type);
+         code = k5_preauth(context, ctx, ctx->more_padata, TRUE,
+                           &ctx->request->padata, &pa_type);
+-        if (code != 0)
+-            goto cleanup;
+     } else if (ctx->err_reply != NULL &&
+-               ctx->err_reply->error == KDC_ERR_PREAUTH_REQUIRED) {
+-        /* Continuing after KDC_ERR_PREAUTH_REQUIRED, using method data. */
+-        TRACE_INIT_CREDS_PREAUTH(context);
+-        code = k5_preauth(context, ctx, ctx->method_padata, TRUE,
+-                          &ctx->request->padata, &ctx->selected_preauth_type);
+-        if (code != 0)
+-            goto cleanup;
+-    } else if (ctx->err_reply != NULL) {
+-        /* Retry after an error other than PREAUTH_REQUIRED, using error padata
+-         * to figure out what to change. */
++               ctx->err_reply->error != KDC_ERR_PREAUTH_REQUIRED) {
++        /* Retrying after an error (possibly mechanism-specific), using error
++         * padata to figure out what to change. */
+         TRACE_INIT_CREDS_PREAUTH_TRYAGAIN(context, ctx->err_reply->error,
+                                           ctx->selected_preauth_type);
+         code = k5_preauth_tryagain(context, ctx, ctx->selected_preauth_type,
+                                    ctx->err_reply, ctx->err_padata,
+                                    &ctx->request->padata);
+-        if (code != 0) {
+-            /* couldn't come up with anything better */
++        if (code) {
++            krb5_clear_error_message(context);
+             code = ctx->err_reply->error + ERROR_TABLE_BASE_krb5;
++        }
++    }
++    if (code) {
++        /* See if we can try a different preauth mech before giving up. */
++        k5_save_ctx_error(context, code, &save);
++        ctx->selected_preauth_type = KRB5_PADATA_NONE;
++    }
++
++    if (ctx->request->padata == NULL && ctx->method_padata != NULL) {
++        /* Retrying after KDC_ERR_PREAUTH_REQUIRED, or trying again with a
++         * different mechanism after a client-side failure. */
++        TRACE_INIT_CREDS_PREAUTH(context);
++        code = k5_preauth(context, ctx, ctx->method_padata, TRUE,
++                          &ctx->request->padata, &ctx->selected_preauth_type);
++        if (code) {
++            if (save.code != 0)
++                code = k5_restore_ctx_error(context, &save);
+             goto cleanup;
+         }
+     }
+@@ -1413,6 +1427,7 @@ init_creds_step_request(krb5_context context,
+ cleanup:
+     krb5_free_pa_data(context, ctx->request->padata);
+     ctx->request->padata = NULL;
++    k5_clear_error(&save);
+     return code;
+ }
+ 
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..5d28f23
--- /dev/null
+++ b/SOURCES/Convert-some-pkiDebug-messages-to-TRACE-macros.patch
@@ -0,0 +1,423 @@
+From 7564be02d140b5caa225679c8f728ee49d9a9e0a 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)
+---
+ .../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 a5b010b26..792a2f771 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..4ae2ec9
--- /dev/null
+++ b/SOURCES/Correct-error-handling-bug-in-prior-commit.patch
@@ -0,0 +1,32 @@
+From ce220f7a4c0a6bda0004626d702a2a60dd51e181 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)
+---
+ 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 534161b19..25bcef292 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+@@ -6089,10 +6089,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/Correct-kpasswd_server-description-in-krb5.conf-5.patch b/SOURCES/Correct-kpasswd_server-description-in-krb5.conf-5.patch
new file mode 100644
index 0000000..2406545
--- /dev/null
+++ b/SOURCES/Correct-kpasswd_server-description-in-krb5.conf-5.patch
@@ -0,0 +1,28 @@
+From fce9cdd8b264343a30b37bea8442da03b258ce45 Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Tue, 16 Oct 2018 17:32:29 -0400
+Subject: [PATCH] Correct kpasswd_server description in krb5.conf(5)
+
+ticket: 8754 (new)
+tags: pullup
+target_version: 1.16-next
+
+(cherry picked from commit 762d804701f78fc76f728ec05a205eea6a2b2dd7)
+---
+ doc/admin/conf_files/krb5_conf.rst | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
+index a959e0e60..cc996f11a 100644
+--- a/doc/admin/conf_files/krb5_conf.rst
++++ b/doc/admin/conf_files/krb5_conf.rst
+@@ -496,7 +496,8 @@ following tags may be specified in the realm's subsection:
+ 
+ **kpasswd_server**
+     Points to the server where all the password changes are performed.
+-    If there is no such entry, the port 464 on the **admin_server**
++    If there is no such entry, DNS will be queried (unless forbidden
++    by **dns_lookup_kdc**).  Finally, port 464 on the **admin_server**
+     host will be tried.
+ 
+ **master_kdc**
diff --git a/SOURCES/Deindent-crypto_retrieve_X509_sans.patch b/SOURCES/Deindent-crypto_retrieve_X509_sans.patch
new file mode 100644
index 0000000..d9878d7
--- /dev/null
+++ b/SOURCES/Deindent-crypto_retrieve_X509_sans.patch
@@ -0,0 +1,264 @@
+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)
+---
+ .../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/Document-and-check-init_creds-context-requirement.patch b/SOURCES/Document-and-check-init_creds-context-requirement.patch
new file mode 100644
index 0000000..53b2b9c
--- /dev/null
+++ b/SOURCES/Document-and-check-init_creds-context-requirement.patch
@@ -0,0 +1,127 @@
+From 86fd6a4e1a768eff55aa3df6bc5794dfa63b801f Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Mon, 9 Jan 2017 11:44:29 -0500
+Subject: [PATCH] Document and check init_creds context requirement
+
+To ensure that the same clpreauth plugin modules and moddata pointers
+are used for each step of an initial creds operation, the caller must
+use the same library context for krb5_init_creds_init(),
+krb5_init_creds_step(), and krb5_init_creds_free().  Document and
+enforce this requirement.
+
+ticket: 7877
+(cherry picked from commit c4beb35c9ac0711ef650abc4f1e44a4c82d5f3d0)
+---
+ src/include/krb5/krb5.hin     | 13 +++++++++++++
+ src/lib/krb5/krb/get_in_tkt.c |  6 +++++-
+ src/lib/krb5/krb/int-proto.h  |  3 +++
+ src/lib/krb5/krb/preauth2.c   | 13 +++++++++++++
+ 4 files changed, 34 insertions(+), 1 deletion(-)
+
+diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
+index 53ad85384..28557659e 100644
+--- a/src/include/krb5/krb5.hin
++++ b/src/include/krb5/krb5.hin
+@@ -7321,6 +7321,9 @@ typedef struct _krb5_init_creds_context *krb5_init_creds_context;
+  *
+  * @param [in] context          Library context
+  * @param [in] ctx              Initial credentials context
++ *
++ * @a context must be the same as the one passed to krb5_init_creds_init() for
++ * this initial credentials context.
+  */
+ void KRB5_CALLCONV
+ krb5_init_creds_free(krb5_context context, krb5_init_creds_context ctx);
+@@ -7335,6 +7338,9 @@ krb5_init_creds_free(krb5_context context, krb5_init_creds_context ctx);
+  * krb5_init_creds_init().  On successful return, the credentials can be
+  * retrieved with krb5_init_creds_get_creds().
+  *
++ * @a context must be the same as the one passed to krb5_init_creds_init() for
++ * this initial credentials context.
++ *
+  * @retval 0 Success; otherwise - Kerberos error codes
+  */
+ krb5_error_code KRB5_CALLCONV
+@@ -7385,6 +7391,10 @@ krb5_init_creds_get_error(krb5_context context, krb5_init_creds_context ctx,
+  * This function creates a new context for acquiring initial credentials.  Use
+  * krb5_init_creds_free() to free @a ctx when it is no longer needed.
+  *
++ * Any subsequent calls to krb5_init_creds_step(), krb5_init_creds_get(), or
++ * krb5_init_creds_free() for this initial credentials context must use the
++ * same @a context argument as the one passed to this function.
++ *
+  * @retval 0 Success; otherwise - Kerberos error codes
+  */
+ krb5_error_code KRB5_CALLCONV
+@@ -7434,6 +7444,9 @@ krb5_init_creds_set_keytab(krb5_context context, krb5_init_creds_context ctx,
+  * transmit the next request using TCP rather than UDP.  If this function
+  * returns any other error, the initial credential exchange has failed.
+  *
++ * @a context must be the same as the one passed to krb5_init_creds_init() for
++ * this initial credentials context.
++ *
+  * @retval 0 Success; otherwise - Kerberos error codes
+  */
+ krb5_error_code KRB5_CALLCONV
+diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
+index 80f5e1870..52e07bb67 100644
+--- a/src/lib/krb5/krb/get_in_tkt.c
++++ b/src/lib/krb5/krb/get_in_tkt.c
+@@ -1667,7 +1667,7 @@ krb5_init_creds_step(krb5_context context,
+                      krb5_data *realm,
+                      unsigned int *flags)
+ {
+-    krb5_error_code code = 0, code2;
++    krb5_error_code code, code2;
+ 
+     *flags = 0;
+ 
+@@ -1680,6 +1680,10 @@ krb5_init_creds_step(krb5_context context,
+     if (ctx->complete)
+         return EINVAL;
+ 
++    code = k5_preauth_check_context(context, ctx);
++    if (code)
++        return code;
++
+     if (in->length != 0) {
+         code = init_creds_step_reply(context, ctx, in);
+         if (code == KRB5KRB_ERR_RESPONSE_TOO_BIG) {
+diff --git a/src/lib/krb5/krb/int-proto.h b/src/lib/krb5/krb/int-proto.h
+index f1667c238..628f0baa8 100644
+--- a/src/lib/krb5/krb/int-proto.h
++++ b/src/lib/krb5/krb/int-proto.h
+@@ -208,6 +208,9 @@ void
+ k5_preauth_request_context_fini(krb5_context context,
+                                 krb5_init_creds_context ctx);
+ 
++krb5_error_code
++k5_preauth_check_context(krb5_context context, krb5_init_creds_context ctx);
++
+ krb5_error_code
+ k5_response_items_new(k5_response_items **ri_out);
+ 
+diff --git a/src/lib/krb5/krb/preauth2.c b/src/lib/krb5/krb/preauth2.c
+index 9a178f4e3..9c5d6eaa9 100644
+--- a/src/lib/krb5/krb/preauth2.c
++++ b/src/lib/krb5/krb/preauth2.c
+@@ -296,6 +296,19 @@ k5_preauth_request_context_fini(krb5_context context,
+     ctx->preauth_reqctx = NULL;
+ }
+ 
++krb5_error_code
++k5_preauth_check_context(krb5_context context, krb5_init_creds_context ctx)
++{
++    krb5_preauth_req_context reqctx = ctx->preauth_reqctx;
++
++    if (reqctx != NULL && reqctx->orig_context != context) {
++        k5_setmsg(context, EINVAL,
++                  _("krb5_init_creds calls must use same library context"));
++        return EINVAL;
++    }
++    return 0;
++}
++
+ /* Return 1 if pa_type is a real preauthentication mechanism according to the
+  * module h.  Return 0 if it is not. */
+ static int
diff --git a/SOURCES/Don-t-include-all-MEMORY-ccaches-in-collection.patch b/SOURCES/Don-t-include-all-MEMORY-ccaches-in-collection.patch
new file mode 100644
index 0000000..284c911
--- /dev/null
+++ b/SOURCES/Don-t-include-all-MEMORY-ccaches-in-collection.patch
@@ -0,0 +1,91 @@
+From 7c50ae9787c2fbfb479fbc513a2aeb2aff039d43 Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Wed, 1 Aug 2018 15:53:12 -0400
+Subject: [PATCH] Don't include all MEMORY ccaches in collection
+
+In the MEMORY ccache implementation, only yield a cache in the
+per-type cursor if it is the context default cache, matching the
+behavior of FILE after commit 45360c9688ca963f75a2480f2cf818424fc3dc7b
+(ticket 6955).
+
+ticket: 8720 (new)
+(cherry picked from commit 49bb627fed70c5258c151c5135ac3d95ed1ee55d)
+---
+ src/lib/krb5/ccache/cc_memory.c | 25 ++++++++++---------------
+ src/lib/krb5/ccache/t_cccol.py  |  7 ++++---
+ 2 files changed, 14 insertions(+), 18 deletions(-)
+
+diff --git a/src/lib/krb5/ccache/cc_memory.c b/src/lib/krb5/ccache/cc_memory.c
+index 8cdaff7fb..cfd5c6389 100644
+--- a/src/lib/krb5/ccache/cc_memory.c
++++ b/src/lib/krb5/ccache/cc_memory.c
+@@ -132,7 +132,7 @@ struct mcc_cursor {
+ 
+ /* Iterator over memory caches.  */
+ struct krb5_mcc_ptcursor_data {
+-    struct krb5_mcc_list_node *cur;
++    krb5_boolean first;
+ };
+ 
+ k5_cc_mutex krb5int_mcc_mutex = K5_CC_MUTEX_PARTIAL_INITIALIZER;
+@@ -693,9 +693,7 @@ krb5_mcc_ptcursor_new(
+         return ENOMEM;
+     }
+     n->data = cdata;
+-    k5_cc_mutex_lock(context, &krb5int_mcc_mutex);
+-    cdata->cur = mcc_head;
+-    k5_cc_mutex_unlock(context, &krb5int_mcc_mutex);
++    cdata->first = TRUE;
+     *cursor = n;
+     return 0;
+ }
+@@ -707,22 +705,19 @@ krb5_mcc_ptcursor_next(
+     krb5_ccache *ccache)
+ {
+     struct krb5_mcc_ptcursor_data *cdata = NULL;
++    const char *defname;
+ 
+     *ccache = NULL;
+     cdata = cursor->data;
+-    if (cdata->cur == NULL)
++    if (!cdata->first)
++        return 0;
++    cdata->first = FALSE;
++
++    defname = krb5_cc_default_name(context);
++    if (defname == NULL || strncmp(defname, "MEMORY:", 7) != 0)
+         return 0;
+ 
+-    *ccache = malloc(sizeof(**ccache));
+-    if (*ccache == NULL)
+-        return ENOMEM;
+-
+-    (*ccache)->ops = &krb5_mcc_ops;
+-    (*ccache)->data = cdata->cur->cache;
+-    k5_cc_mutex_lock(context, &krb5int_mcc_mutex);
+-    cdata->cur = cdata->cur->next;
+-    k5_cc_mutex_unlock(context, &krb5int_mcc_mutex);
+-    return 0;
++    return krb5_cc_resolve(context, defname, ccache);
+ }
+ 
+ static krb5_error_code KRB5_CALLCONV
+diff --git a/src/lib/krb5/ccache/t_cccol.py b/src/lib/krb5/ccache/t_cccol.py
+index f7f178564..c6d5f514d 100755
+--- a/src/lib/krb5/ccache/t_cccol.py
++++ b/src/lib/krb5/ccache/t_cccol.py
+@@ -97,10 +97,11 @@ if test_keyring:
+ 
+ mfoo = 'MEMORY:foo'
+ mbar = 'MEMORY:bar'
+-cursor_test('filemem', [fccname, mfoo, mbar], [fccname, mfoo, mbar])
+-cursor_test('dirmem', [dccname, mfoo], [duser, dalice, dbob, mfoo])
++cursor_test('filemem', [fccname, mfoo], [fccname])
++cursor_test('dirmem', [dccname, mfoo], [duser, dalice, dbob])
++cursor_test('mem', [mfoo, mbar], [mfoo])
+ if test_keyring:
+-    cursor_test('keyringmem', [krccname, mfoo], [kruser, kralice, krbob, mfoo])
++    cursor_test('keyringmem', [krccname, mfoo], [kruser, kralice, krbob])
+ 
+ # Test krb5_cccol_have_content.
+ realm.run(['./t_cccursor', dccname, 'CONTENT'])
diff --git a/SOURCES/Echo-KDC-cookies-in-preauth-tryagain.patch b/SOURCES/Echo-KDC-cookies-in-preauth-tryagain.patch
new file mode 100644
index 0000000..19fa3e8
--- /dev/null
+++ b/SOURCES/Echo-KDC-cookies-in-preauth-tryagain.patch
@@ -0,0 +1,76 @@
+From 7439bb967c7c7d860bc69b6b4eaa290a7fe7f530 Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Sat, 21 Jan 2017 13:20:38 -0500
+Subject: [PATCH] Echo KDC cookies in preauth tryagain
+
+When trying again after a mechanism-specific error, we should send the
+KDC cookie for conformance with RFC 6113.
+
+ticket: 8539
+(cherry picked from commit 25f12e90d98b677d0a72893b3c6eb859377aee68)
+[rharwood@redhat.com: backport around expected_trace]
+---
+ src/lib/krb5/krb/preauth2.c |  8 +++++++-
+ src/tests/t_pkinit.py       | 19 +++++++++----------
+ 2 files changed, 16 insertions(+), 11 deletions(-)
+
+diff --git a/src/lib/krb5/krb/preauth2.c b/src/lib/krb5/krb/preauth2.c
+index 9c5d6eaa9..cfe3dd5b0 100644
+--- a/src/lib/krb5/krb/preauth2.c
++++ b/src/lib/krb5/krb/preauth2.c
+@@ -923,7 +923,7 @@ k5_preauth_tryagain(krb5_context context, krb5_init_creds_context ctx,
+     krb5_pa_data **mod_pa;
+     krb5_clpreauth_modreq modreq;
+     clpreauth_handle h;
+-    int i;
++    int i, count;
+ 
+     *padata_out = NULL;
+ 
+@@ -942,6 +942,12 @@ k5_preauth_tryagain(krb5_context context, krb5_init_creds_context ctx,
+                                  ctx->err_reply, ctx->err_padata,
+                                  ctx->prompter, ctx->prompter_data, &mod_pa);
+         if (ret == 0 && mod_pa != NULL) {
++            for (count = 0; mod_pa[count] != NULL; count++);
++            ret = copy_cookie(context, ctx->err_padata, &mod_pa, &count);
++            if (ret) {
++                krb5_free_pa_data(context, mod_pa);
++                return ret;
++            }
+             TRACE_PREAUTH_TRYAGAIN_OUTPUT(context, mod_pa);
+             *padata_out = mod_pa;
+             return 0;
+diff --git a/src/tests/t_pkinit.py b/src/tests/t_pkinit.py
+index 183977750..38424932b 100755
+--- a/src/tests/t_pkinit.py
++++ b/src/tests/t_pkinit.py
+@@ -175,20 +175,19 @@ realm.kinit(realm.user_princ,
+ realm.klist(realm.user_princ)
+ 
+ # Test a DH parameter renegotiation by temporarily setting a 4096-bit
+-# minimum on the KDC.
+-tracefile = os.path.join(realm.testdir, 'trace')
++# minimum on the KDC.  (Preauth type 16 is PKINIT PA_PK_AS_REQ;
++# 133 is FAST PA-FX-COOKIE.)
+ minbits_kdc_conf = {'realms': {'$realm': {'pkinit_dh_min_bits': '4096'}}}
+ minbits_env = realm.special_env('restrict', True, kdc_conf=minbits_kdc_conf)
+ realm.stop_kdc()
+ realm.start_kdc(env=minbits_env)
+-realm.run(['env', 'KRB5_TRACE=' + tracefile, kinit, '-X',
+-           'X509_user_identity=' + file_identity, realm.user_princ])
+-with open(tracefile, 'r') as f:
+-    trace = f.read()
+-if ('Key parameters not accepted' not in trace or
+-    'Preauth tryagain input types' not in trace or
+-    'trying again with KDC-provided parameters' not in trace):
+-    fail('DH renegotiation steps not found in kinit trace log')
++expected_trace = ('Key parameters not accepted',
++                  'Preauth tryagain input types',
++                  'trying again with KDC-provided parameters',
++                  'Followup preauth for next request: 16, 133')
++realm.kinit(realm.user_princ,
++            flags=['-X', 'X509_user_identity=%s' % file_identity],
++            expected_trace=expected_trace)
+ realm.stop_kdc()
+ realm.start_kdc()
+ 
diff --git a/SOURCES/Exit-with-status-0-from-kadmind.patch b/SOURCES/Exit-with-status-0-from-kadmind.patch
new file mode 100644
index 0000000..b2a7317
--- /dev/null
+++ b/SOURCES/Exit-with-status-0-from-kadmind.patch
@@ -0,0 +1,32 @@
+From 987d80aba6a59dae5242cb544864e23785098106 Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Wed, 14 Mar 2018 14:31:22 -0400
+Subject: [PATCH] Exit with status 0 from kadmind
+
+Typically, 0 denotes successful exit.  In particular, init systems
+will complain if another different value is returned.  This presents a
+problem for automated installation jobs which want to restart kadmind.
+
+`service kadmin stop` typically sends SIGTERM, which is caught by
+verto and passed to our handler.  Besides cleanup, we then call
+verto_break(), which causes the verto_run() event loop to return.  The
+weird return code has been present since the addition of the kadmin
+code, which used a similar event model for signals.
+
+(cherry picked from commit f970ad412aca36f8a7d3addb1cd4026ed22e5592)
+(cherry picked from commit 3bfe632c7011c335362d78356232507d9ee26f73)
+---
+ src/kadmin/server/ovsec_kadmd.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/kadmin/server/ovsec_kadmd.c b/src/kadmin/server/ovsec_kadmd.c
+index a3edd3b00..9fc49f1e6 100644
+--- a/src/kadmin/server/ovsec_kadmd.c
++++ b/src/kadmin/server/ovsec_kadmd.c
+@@ -558,5 +558,5 @@ main(int argc, char *argv[])
+ 
+     krb5_klog_close(context);
+     krb5_free_context(context);
+-    exit(2);
++    exit(0);
+ }
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..05b880c
--- /dev/null
+++ b/SOURCES/Expose-context-errors-in-pkinit_server_plugin_init.patch
@@ -0,0 +1,73 @@
+From 97a39c0048344c43af4006a4b9e7da609095510d 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)
+---
+ 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-PKINIT-cert-matching-data-construction.patch b/SOURCES/Fix-PKINIT-cert-matching-data-construction.patch
new file mode 100644
index 0000000..da24ba8
--- /dev/null
+++ b/SOURCES/Fix-PKINIT-cert-matching-data-construction.patch
@@ -0,0 +1,115 @@
+From 62eb62a3db7d40a44f26c3e563cfa22b1f05d93d Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Tue, 17 Oct 2017 18:50:15 -0400
+Subject: [PATCH] Fix PKINIT cert matching data construction
+
+Rewrite X509_NAME_oneline_ex() and its call sites to use dynamic
+allocation and to perform proper error checking.
+
+ticket: 8617
+target_version: 1.16
+target_version: 1.15-next
+target_version: 1.14-next
+tags: pullup
+
+(cherry picked from commit fbb687db1088ddd894d975996e5f6a4252b9a2b4)
+---
+ .../preauth/pkinit/pkinit_crypto_openssl.c    | 67 +++++++------------
+ 1 file changed, 25 insertions(+), 42 deletions(-)
+
+diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+index f70aab5b3..34ed7afaf 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+@@ -5052,33 +5052,29 @@ out:
+     return retval;
+ }
+ 
+-/*
+- * Return a string format of an X509_NAME in buf where
+- * size is an in/out parameter.  On input it is the size
+- * of the buffer, and on output it is the actual length
+- * of the name.
+- * If buf is NULL, returns the length req'd to hold name
+- */
+-static char *
+-X509_NAME_oneline_ex(X509_NAME * a,
+-                     char *buf,
+-                     unsigned int *size,
+-                     unsigned long flag)
++static krb5_error_code
++rfc2253_name(X509_NAME *name, char **str_out)
+ {
+-    BIO *out = NULL;
++    BIO *b = NULL;
++    char *str;
+ 
+-    out = BIO_new(BIO_s_mem ());
+-    if (X509_NAME_print_ex(out, a, 0, flag) > 0) {
+-        if (buf != NULL && (*size) >  (unsigned int) BIO_number_written(out)) {
+-            memset(buf, 0, *size);
+-            BIO_read(out, buf, (int) BIO_number_written(out));
+-        }
+-        else {
+-            *size = BIO_number_written(out);
+-        }
+-    }
+-    BIO_free(out);
+-    return (buf);
++    *str_out = NULL;
++    b = BIO_new(BIO_s_mem());
++    if (b == NULL)
++        return ENOMEM;
++    if (X509_NAME_print_ex(b, name, 0, XN_FLAG_SEP_COMMA_PLUS) < 0)
++        goto error;
++    str = calloc(BIO_number_written(b) + 1, 1);
++    if (str == NULL)
++        goto error;
++    BIO_read(b, str, BIO_number_written(b));
++    BIO_free(b);
++    *str_out = str;
++    return 0;
++
++error:
++    BIO_free(b);
++    return ENOMEM;
+ }
+ 
+ /*
+@@ -5144,8 +5140,6 @@ get_matching_data(krb5_context context,
+     pkinit_cert_matching_data *md = NULL;
+     krb5_principal *pkinit_sans = NULL, *upn_sans = NULL;
+     size_t i, j;
+-    char buf[DN_BUF_LEN];
+-    unsigned int bufsize = sizeof(buf);
+ 
+     *md_out = NULL;
+ 
+@@ -5153,23 +5147,12 @@ get_matching_data(krb5_context context,
+     if (md == NULL)
+         goto cleanup;
+ 
+-    /* Get the subject name (in rfc2253 format). */
+-    X509_NAME_oneline_ex(X509_get_subject_name(cert), buf, &bufsize,
+-                         XN_FLAG_SEP_COMMA_PLUS);
+-    md->subject_dn = strdup(buf);
+-    if (md->subject_dn == NULL) {
+-        ret = ENOMEM;
++    ret = rfc2253_name(X509_get_subject_name(cert), &md->subject_dn);
++    if (ret)
+         goto cleanup;
+-    }
+-
+-    /* Get the issuer name (in rfc2253 format). */
+-    X509_NAME_oneline_ex(X509_get_issuer_name(cert), buf, &bufsize,
+-                         XN_FLAG_SEP_COMMA_PLUS);
+-    md->issuer_dn = strdup(buf);
+-    if (md->issuer_dn == NULL) {
+-        ret = ENOMEM;
++    ret = rfc2253_name(X509_get_issuer_name(cert), &md->issuer_dn);
++    if (ret)
+         goto cleanup;
+-    }
+ 
+     /* Get the SAN data. */
+     ret = crypto_retrieve_X509_sans(context, plg_cryptoctx, req_cryptoctx,
diff --git a/SOURCES/Fix-bugs-in-kdcpolicy-commit.patch b/SOURCES/Fix-bugs-in-kdcpolicy-commit.patch
new file mode 100644
index 0000000..1d87c25
--- /dev/null
+++ b/SOURCES/Fix-bugs-in-kdcpolicy-commit.patch
@@ -0,0 +1,130 @@
+From ffd715b98da026a6a9b3aac48de42e4f19860ce4 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)
+---
+ 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-bugs-with-concurrent-use-of-MEMORY-ccaches.patch b/SOURCES/Fix-bugs-with-concurrent-use-of-MEMORY-ccaches.patch
new file mode 100644
index 0000000..99e0f7b
--- /dev/null
+++ b/SOURCES/Fix-bugs-with-concurrent-use-of-MEMORY-ccaches.patch
@@ -0,0 +1,396 @@
+From 8cb69a3657064ff6bb90a208cfad5fb91e30c307 Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Sun, 1 Jul 2018 00:12:25 -0400
+Subject: [PATCH] Fix bugs with concurrent use of MEMORY ccaches
+
+A memory ccache iterator stores an alias into the cache object's
+linked list of credentials.  If the cache is reinitialized while the
+iterator is active, the alias becomes invalid.  Also, multiple handles
+referencing the same memory ccache all use aliases to the same data
+object; if one of the handles is destroyed, the other contains a
+dangling pointer.
+
+Fix the first issue by adding a generation counter to the cache and to
+cursors, incremented each time the cache is initialized or destroyed.
+Check the generation on each cursor step and end the iteration if the
+list was invalidated.  Fix the second issue by adding a reference
+count to the cache object, counting one reference for the table slot
+and one for each open handle.  Empty the cache object on each destroy
+operation, but only release the object when the last handle to it is
+destroyed or closed.
+
+Add regression tests for the two issues to t_cc.c.
+
+The first issue was reported by Sorin Manolache.
+
+ticket: 8202
+tags: pullup
+target_version: 1.16-next
+target_version: 1.15-next
+
+(cherry picked from commit 146dadec8fe7ccc4149eb2e3f577cc320aee6efb)
+---
+ src/lib/krb5/ccache/cc_memory.c | 164 ++++++++++++++++++++------------
+ src/lib/krb5/ccache/t_cc.c      |  51 ++++++++++
+ 2 files changed, 154 insertions(+), 61 deletions(-)
+
+diff --git a/src/lib/krb5/ccache/cc_memory.c b/src/lib/krb5/ccache/cc_memory.c
+index c5425eb3a..8cdaff7fb 100644
+--- a/src/lib/krb5/ccache/cc_memory.c
++++ b/src/lib/krb5/ccache/cc_memory.c
+@@ -102,18 +102,20 @@ extern krb5_error_code krb5_change_cache (void);
+ typedef struct _krb5_mcc_link {
+     struct _krb5_mcc_link *next;
+     krb5_creds *creds;
+-} krb5_mcc_link, *krb5_mcc_cursor;
++} krb5_mcc_link;
+ 
+ /* Per-cache data header.  */
+ typedef struct _krb5_mcc_data {
+     char *name;
+     k5_cc_mutex lock;
+     krb5_principal prin;
+-    krb5_mcc_cursor link;
++    krb5_mcc_link *link;
+     krb5_timestamp changetime;
+     /* Time offsets for clock-skewed clients.  */
+     krb5_int32 time_offset;
+     krb5_int32 usec_offset;
++    int refcount;               /* One for the table slot, one per handle */
++    int generation;             /* Incremented at each initialize */
+ } krb5_mcc_data;
+ 
+ /* List of memory caches.  */
+@@ -122,6 +124,12 @@ typedef struct krb5_mcc_list_node {
+     krb5_mcc_data *cache;
+ } krb5_mcc_list_node;
+ 
++/* Iterator over credentials in a memory cache. */
++struct mcc_cursor {
++    int generation;
++    krb5_mcc_link *next_link;
++};
++
+ /* Iterator over memory caches.  */
+ struct krb5_mcc_ptcursor_data {
+     struct krb5_mcc_list_node *cur;
+@@ -132,7 +140,23 @@ static krb5_mcc_list_node *mcc_head = 0;
+ 
+ static void update_mcc_change_time(krb5_mcc_data *);
+ 
+-static void krb5_mcc_free (krb5_context context, krb5_ccache id);
++/* Remove creds from d, invalidate any existing cursors, and unset the client
++ * principal.  The caller is responsible for locking. */
++static void
++empty_mcc_cache(krb5_context context, krb5_mcc_data *d)
++{
++    krb5_mcc_link *curr, *next;
++
++    for (curr = d->link; curr != NULL; curr = next) {
++        next = curr->next;
++        krb5_free_creds(context, curr->creds);
++        free(curr);
++    }
++    d->link = NULL;
++    d->generation++;
++    krb5_free_principal(context, d->prin);
++    d->prin = NULL;
++}
+ 
+ /*
+  * Modifies:
+@@ -150,16 +174,12 @@ krb5_mcc_initialize(krb5_context context, krb5_ccache id, krb5_principal princ)
+ {
+     krb5_os_context os_ctx = &context->os_context;
+     krb5_error_code ret;
+-    krb5_mcc_data *d;
++    krb5_mcc_data *d = id->data;
+ 
+-    d = (krb5_mcc_data *)id->data;
+     k5_cc_mutex_lock(context, &d->lock);
++    empty_mcc_cache(context, d);
+ 
+-    krb5_mcc_free(context, id);
+-
+-    d = (krb5_mcc_data *)id->data;
+-    ret = krb5_copy_principal(context, princ,
+-                              &d->prin);
++    ret = krb5_copy_principal(context, princ, &d->prin);
+     update_mcc_change_time(d);
+ 
+     if (os_ctx->os_flags & KRB5_OS_TOFFSET_VALID) {
+@@ -185,61 +205,59 @@ krb5_mcc_initialize(krb5_context context, krb5_ccache id, krb5_principal princ)
+ krb5_error_code KRB5_CALLCONV
+ krb5_mcc_close(krb5_context context, krb5_ccache id)
+ {
++    krb5_mcc_data *d = id->data;
++    int count;
++
+     free(id);
+-    return KRB5_OK;
+-}
+-
+-static void
+-krb5_mcc_free(krb5_context context, krb5_ccache id)
+-{
+-    krb5_mcc_cursor curr,next;
+-    krb5_mcc_data *d;
+-
+-    d = (krb5_mcc_data *) id->data;
+-    for (curr = d->link; curr;) {
+-        krb5_free_creds(context, curr->creds);
+-        next = curr->next;
+-        free(curr);
+-        curr = next;
++    k5_cc_mutex_lock(context, &d->lock);
++    count = --d->refcount;
++    k5_cc_mutex_unlock(context, &d->lock);
++    if (count == 0) {
++        /* This is the last active handle referencing d and d has been removed
++         * from the table, so we can release it. */
++        empty_mcc_cache(context, d);
++        free(d->name);
++        k5_cc_mutex_destroy(&d->lock);
++        free(d);
+     }
+-    d->link = NULL;
+-    krb5_free_principal(context, d->prin);
++    return KRB5_OK;
+ }
+ 
+ /*
+  * Effects:
+  * Destroys the contents of id. id is invalid after call.
+- *
+- * Errors:
+- * system errors (locks related)
+  */
+ krb5_error_code KRB5_CALLCONV
+ krb5_mcc_destroy(krb5_context context, krb5_ccache id)
+ {
+     krb5_mcc_list_node **curr, *node;
+-    krb5_mcc_data *d;
++    krb5_mcc_data *d = id->data;
++    krb5_boolean removed_from_table = FALSE;
+ 
+     k5_cc_mutex_lock(context, &krb5int_mcc_mutex);
+ 
+-    d = (krb5_mcc_data *)id->data;
+     for (curr = &mcc_head; *curr; curr = &(*curr)->next) {
+         if ((*curr)->cache == d) {
+             node = *curr;
+             *curr = node->next;
+             free(node);
++            removed_from_table = TRUE;
+             break;
+         }
+     }
+     k5_cc_mutex_unlock(context, &krb5int_mcc_mutex);
+ 
++    /* Empty the cache and remove the reference for the table slot.  There will
++     * always be at least one reference left for the handle being destroyed. */
+     k5_cc_mutex_lock(context, &d->lock);
+-
+-    krb5_mcc_free(context, id);
+-    free(d->name);
++    empty_mcc_cache(context, d);
++    if (removed_from_table)
++        d->refcount--;
+     k5_cc_mutex_unlock(context, &d->lock);
+-    k5_cc_mutex_destroy(&d->lock);
+-    free(d);
+-    free(id);
++
++    /* Invalidate the handle, possibly removing the last reference to d and
++     * freeing it. */
++    krb5_mcc_close(context, id);
+ 
+     krb5_change_cache ();
+     return KRB5_OK;
+@@ -279,9 +297,12 @@ krb5_mcc_resolve (krb5_context context, krb5_ccache *id, const char *residual)
+     for (ptr = mcc_head; ptr; ptr=ptr->next)
+         if (!strcmp(ptr->cache->name, residual))
+             break;
+-    if (ptr)
++    if (ptr != NULL) {
+         d = ptr->cache;
+-    else {
++        k5_cc_mutex_lock(context, &d->lock);
++        d->refcount++;
++        k5_cc_mutex_unlock(context, &d->lock);
++    } else {
+         err = new_mcc_data(residual, &d);
+         if (err) {
+             k5_cc_mutex_unlock(context, &krb5int_mcc_mutex);
+@@ -326,14 +347,18 @@ krb5_error_code KRB5_CALLCONV
+ krb5_mcc_start_seq_get(krb5_context context, krb5_ccache id,
+                        krb5_cc_cursor *cursor)
+ {
+-    krb5_mcc_cursor mcursor;
++    struct mcc_cursor *mcursor;
+     krb5_mcc_data *d;
+ 
++    mcursor = malloc(sizeof(*mcursor));
++    if (mcursor == NULL)
++        return KRB5_CC_NOMEM;
+     d = id->data;
+     k5_cc_mutex_lock(context, &d->lock);
+-    mcursor = d->link;
++    mcursor->generation = d->generation;
++    mcursor->next_link = d->link;
+     k5_cc_mutex_unlock(context, &d->lock);
+-    *cursor = (krb5_cc_cursor) mcursor;
++    *cursor = mcursor;
+     return KRB5_OK;
+ }
+ 
+@@ -361,23 +386,34 @@ krb5_error_code KRB5_CALLCONV
+ krb5_mcc_next_cred(krb5_context context, krb5_ccache id,
+                    krb5_cc_cursor *cursor, krb5_creds *creds)
+ {
+-    krb5_mcc_cursor mcursor;
++    struct mcc_cursor *mcursor;
+     krb5_error_code retval;
++    krb5_mcc_data *d = id->data;
+ 
+-    /* Once the node in the linked list is created, it's never
+-       modified, so we don't need to worry about locking here.  (Note
+-       that we don't support _remove_cred.)  */
+-    mcursor = (krb5_mcc_cursor) *cursor;
+-    if (mcursor == NULL)
+-        return KRB5_CC_END;
+     memset(creds, 0, sizeof(krb5_creds));
+-    if (mcursor->creds) {
+-        retval = k5_copy_creds_contents(context, mcursor->creds, creds);
+-        if (retval)
+-            return retval;
++    mcursor = *cursor;
++    if (mcursor->next_link == NULL)
++        return KRB5_CC_END;
++
++    /*
++     * Check the cursor generation against the cache generation in case the
++     * cache has been reinitialized or destroyed, freeing the pointer in the
++     * cursor.  Keep the cache locked while we copy the creds and advance the
++     * pointer, in case another thread reinitializes the cache after we check
++     * the generation.
++     */
++    k5_cc_mutex_lock(context, &d->lock);
++    if (mcursor->generation != d->generation) {
++        k5_cc_mutex_unlock(context, &d->lock);
++        return KRB5_CC_END;
+     }
+-    *cursor = (krb5_cc_cursor)mcursor->next;
+-    return KRB5_OK;
++
++    retval = k5_copy_creds_contents(context, mcursor->next_link->creds, creds);
++    if (retval == 0)
++        mcursor->next_link = mcursor->next_link->next;
++
++    k5_cc_mutex_unlock(context, &d->lock);
++    return retval;
+ }
+ 
+ /*
+@@ -396,14 +432,18 @@ krb5_mcc_next_cred(krb5_context context, krb5_ccache id,
+ krb5_error_code KRB5_CALLCONV
+ krb5_mcc_end_seq_get(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor)
+ {
+-    *cursor = 0L;
++    free(*cursor);
++    *cursor = NULL;
+     return KRB5_OK;
+ }
+ 
+-/* Utility routine: Creates the back-end data for a memory cache, and
+-   threads it into the global linked list.
+-
+-   Call with the global list lock held.  */
++/*
++ * Utility routine: Creates the back-end data for a memory cache, and threads
++ * it into the global linked list.  Give the new object two references, one for
++ * the table slot and one for the caller's handle.
++ *
++ * Call with the global list lock held.
++ */
+ static krb5_error_code
+ new_mcc_data (const char *name, krb5_mcc_data **dataptr)
+ {
+@@ -432,6 +472,8 @@ new_mcc_data (const char *name, krb5_mcc_data **dataptr)
+     d->changetime = 0;
+     d->time_offset = 0;
+     d->usec_offset = 0;
++    d->refcount = 2;
++    d->generation = 0;
+     update_mcc_change_time(d);
+ 
+     n = malloc(sizeof(krb5_mcc_list_node));
+diff --git a/src/lib/krb5/ccache/t_cc.c b/src/lib/krb5/ccache/t_cc.c
+index 6069cabd3..cd4569c4c 100644
+--- a/src/lib/krb5/ccache/t_cc.c
++++ b/src/lib/krb5/ccache/t_cc.c
+@@ -386,6 +386,55 @@ test_misc(krb5_context context)
+     krb5_cc_dfl_ops = ops_save;
+ 
+ }
++
++/*
++ * Regression tests for #8202.  Because memory ccaches share objects between
++ * different handles to the same cache and between iterators and caches,
++ * historically there have been some bugs when those objects are released.
++ */
++static void
++test_memory_concurrent(krb5_context context)
++{
++    krb5_error_code kret;
++    krb5_ccache id1, id2;
++    krb5_cc_cursor cursor;
++    krb5_creds creds;
++
++    /* Create two handles to the same memory ccache and destroy them. */
++    kret = krb5_cc_resolve(context, "MEMORY:x", &id1);
++    CHECK(kret, "resolve 1");
++    kret = krb5_cc_resolve(context, "MEMORY:x", &id2);
++    CHECK(kret, "resolve 2");
++    kret = krb5_cc_destroy(context, id1);
++    CHECK(kret, "destroy 1");
++    kret = krb5_cc_destroy(context, id2);
++    CHECK(kret, "destroy 2");
++
++    kret = init_test_cred(context);
++    CHECK(kret, "init_creds");
++
++    /* Reinitialize the cache after creating an iterator for it, and verify
++     * that the iterator ends gracefully. */
++    kret = krb5_cc_resolve(context, "MEMORY:x", &id1);
++    CHECK(kret, "resolve");
++    kret = krb5_cc_initialize(context, id1, test_creds.client);
++    CHECK(kret, "initialize");
++    kret = krb5_cc_store_cred(context, id1, &test_creds);
++    CHECK(kret, "store");
++    kret = krb5_cc_start_seq_get(context, id1, &cursor);
++    CHECK(kret, "start_seq_get");
++    kret = krb5_cc_initialize(context, id1, test_creds.client);
++    CHECK(kret, "initialize again");
++    kret = krb5_cc_next_cred(context, id1, &cursor, &creds);
++    CHECK_BOOL(kret != KRB5_CC_END, "iterator should end", "next_cred");
++    kret = krb5_cc_end_seq_get(context, id1, &cursor);
++    CHECK(kret, "end_seq_get");
++    kret = krb5_cc_destroy(context, id1);
++    CHECK(kret, "destroy");
++
++    free_test_cred(context);
++}
++
+ extern const krb5_cc_ops krb5_mcc_ops;
+ extern const krb5_cc_ops krb5_fcc_ops;
+ 
+@@ -434,6 +483,8 @@ main(void)
+     do_test(context, "MEMORY:");
+     do_test(context, "FILE:");
+ 
++    test_memory_concurrent(context);
++
+     krb5_free_context(context);
+     return 0;
+ }
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..6b3adbb
--- /dev/null
+++ b/SOURCES/Fix-certauth-built-in-module-returns.patch
@@ -0,0 +1,124 @@
+From 5fbdf62de3883be137ed9a1a2eff3985e4ca05ae 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)
+---
+ .../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 792a2f771..85ca8885d 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-flaws-in-LDAP-DN-checking.patch b/SOURCES/Fix-flaws-in-LDAP-DN-checking.patch
new file mode 100644
index 0000000..d823a0b
--- /dev/null
+++ b/SOURCES/Fix-flaws-in-LDAP-DN-checking.patch
@@ -0,0 +1,350 @@
+From bc1ff677dcb45c59107c39465b032f555e3d99f6 Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Fri, 12 Jan 2018 11:43:01 -0500
+Subject: [PATCH] Fix flaws in LDAP DN checking
+
+KDB_TL_USER_INFO tl-data is intended to be internal to the LDAP KDB
+module, and not used in disk or wire principal entries.  Prevent
+kadmin clients from sending KDB_TL_USER_INFO tl-data by giving it a
+type number less than 256 and filtering out type numbers less than 256
+in kadm5_create_principal_3().  (We already filter out low type
+numbers in kadm5_modify_principal()).
+
+In the LDAP KDB module, if containerdn and linkdn are both specified
+in a put_principal operation, check both linkdn and the computed
+standalone_principal_dn for container membership.  To that end, factor
+out the checks into helper functions and call them on all applicable
+client-influenced DNs.
+
+CVE-2018-5729:
+
+In MIT krb5 1.6 or later, an authenticated kadmin user with permission
+to add principals to an LDAP Kerberos database can cause a null
+dereference in kadmind, or circumvent a DN container check, by
+supplying tagged data intended to be internal to the database module.
+Thanks to Sharwan Ram and Pooja Anil for discovering the potential
+null dereference.
+
+CVE-2018-5730:
+
+In MIT krb5 1.6 or later, an authenticated kadmin user with permission
+to add principals to an LDAP Kerberos database can circumvent a DN
+containership check by supplying both a "linkdn" and "containerdn"
+database argument, or by supplying a DN string which is a left
+extension of a container DN string but is not hierarchically within
+the container DN.
+
+ticket: 8643 (new)
+tags: pullup
+target_version: 1.16-next
+target_version: 1.15-next
+
+(cherry picked from commit e1caf6fb74981da62039846931ebdffed71309d1)
+[rharwood@redhat.com fuzz - didn't port tests to expected_msg]
+---
+ src/lib/kadm5/srv/svr_principal.c             |   7 +
+ src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h   |   2 +-
+ .../kdb/ldap/libkdb_ldap/ldap_principal2.c    | 200 ++++++++++--------
+ src/tests/t_kdb.py                            |  14 ++
+ 4 files changed, 128 insertions(+), 95 deletions(-)
+
+diff --git a/src/lib/kadm5/srv/svr_principal.c b/src/lib/kadm5/srv/svr_principal.c
+index 0d4f0a632..64a4a2e97 100644
+--- a/src/lib/kadm5/srv/svr_principal.c
++++ b/src/lib/kadm5/srv/svr_principal.c
+@@ -330,6 +330,13 @@ kadm5_create_principal_3(void *server_handle,
+         return KADM5_BAD_MASK;
+     if((mask & ~ALL_PRINC_MASK))
+         return KADM5_BAD_MASK;
++    if (mask & KADM5_TL_DATA) {
++        for (tl_data_tail = entry->tl_data; tl_data_tail != NULL;
++             tl_data_tail = tl_data_tail->tl_data_next) {
++            if (tl_data_tail->tl_data_type < 256)
++                return KADM5_BAD_TL_TYPE;
++        }
++    }
+ 
+     /*
+      * Check to see if the principal exists
+diff --git a/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h b/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h
+index 06b477537..0c19804ad 100644
+--- a/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h
++++ b/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h
+@@ -141,7 +141,7 @@ extern int set_ldap_error (krb5_context ctx, int st, int op);
+ #define UNSTORE16_INT(ptr, val) (val = load_16_be(ptr))
+ #define UNSTORE32_INT(ptr, val) (val = load_32_be(ptr))
+ 
+-#define  KDB_TL_USER_INFO      0x7ffe
++#define  KDB_TL_USER_INFO      0xff
+ 
+ #define KDB_TL_PRINCTYPE          0x01
+ #define KDB_TL_PRINCCOUNT         0x02
+diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c
+index 88a170495..b7c9212cb 100644
+--- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c
++++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c
+@@ -651,6 +651,107 @@ cleanup:
+     return ret;
+ }
+ 
++static krb5_error_code
++check_dn_in_container(krb5_context context, const char *dn,
++                      char *const *subtrees, unsigned int ntrees)
++{
++    unsigned int i;
++    size_t dnlen = strlen(dn), stlen;
++
++    for (i = 0; i < ntrees; i++) {
++        if (subtrees[i] == NULL || *subtrees[i] == '\0')
++            return 0;
++        stlen = strlen(subtrees[i]);
++        if (dnlen >= stlen &&
++            strcasecmp(dn + dnlen - stlen, subtrees[i]) == 0 &&
++            (dnlen == stlen || dn[dnlen - stlen - 1] == ','))
++            return 0;
++    }
++
++    k5_setmsg(context, EINVAL, _("DN is out of the realm subtree"));
++    return EINVAL;
++}
++
++static krb5_error_code
++check_dn_exists(krb5_context context,
++                krb5_ldap_server_handle *ldap_server_handle,
++                const char *dn, krb5_boolean nonkrb_only)
++{
++    krb5_error_code st = 0, tempst;
++    krb5_ldap_context *ldap_context = context->dal_handle->db_context;
++    LDAP *ld = ldap_server_handle->ldap_handle;
++    LDAPMessage *result = NULL, *ent;
++    char *attrs[] = { "krbticketpolicyreference", "krbprincipalname", NULL };
++    char **values;
++
++    LDAP_SEARCH_1(dn, LDAP_SCOPE_BASE, 0, attrs, IGNORE_STATUS);
++    if (st != LDAP_SUCCESS)
++        return set_ldap_error(context, st, OP_SEARCH);
++
++    ent = ldap_first_entry(ld, result);
++    CHECK_NULL(ent);
++
++    values = ldap_get_values(ld, ent, "krbticketpolicyreference");
++    if (values != NULL)
++        ldap_value_free(values);
++
++    values = ldap_get_values(ld, ent, "krbprincipalname");
++    if (values != NULL) {
++        ldap_value_free(values);
++        if (nonkrb_only) {
++            st = EINVAL;
++            k5_setmsg(context, st, _("ldap object is already kerberized"));
++            goto cleanup;
++        }
++    }
++
++cleanup:
++    ldap_msgfree(result);
++    return st;
++}
++
++static krb5_error_code
++validate_xargs(krb5_context context,
++               krb5_ldap_server_handle *ldap_server_handle,
++               const xargs_t *xargs, const char *standalone_dn,
++               char *const *subtrees, unsigned int ntrees)
++{
++    krb5_error_code st;
++
++    if (xargs->dn != NULL) {
++        /* The supplied dn must be within a realm container. */
++        st = check_dn_in_container(context, xargs->dn, subtrees, ntrees);
++        if (st)
++            return st;
++        /* The supplied dn must exist without Kerberos attributes. */
++        st = check_dn_exists(context, ldap_server_handle, xargs->dn, TRUE);
++        if (st)
++            return st;
++    }
++
++    if (xargs->linkdn != NULL) {
++        /* The supplied linkdn must be within a realm container. */
++        st = check_dn_in_container(context, xargs->linkdn, subtrees, ntrees);
++        if (st)
++            return st;
++        /* The supplied linkdn must exist. */
++        st = check_dn_exists(context, ldap_server_handle, xargs->linkdn,
++                             FALSE);
++        if (st)
++            return st;
++    }
++
++    if (xargs->containerdn != NULL && standalone_dn != NULL) {
++        /* standalone_dn (likely composed using containerdn) must be within a
++         * container. */
++        st = check_dn_in_container(context, standalone_dn, subtrees, ntrees);
++        if (st)
++            return st;
++    }
++
++    return 0;
++}
++
+ krb5_error_code
+ krb5_ldap_put_principal(krb5_context context, krb5_db_entry *entry,
+                         char **db_args)
+@@ -662,12 +763,12 @@ krb5_ldap_put_principal(krb5_context context, krb5_db_entry *entry,
+     LDAPMessage                 *result=NULL, *ent=NULL;
+     char                        **subtreelist = NULL;
+     char                        *user=NULL, *subtree=NULL, *principal_dn=NULL;
+-    char                        **values=NULL, *strval[10]={NULL}, errbuf[1024];
++    char                        *strval[10]={NULL}, errbuf[1024];
+     char                        *filtuser=NULL;
+     struct berval               **bersecretkey=NULL;
+     LDAPMod                     **mods=NULL;
+     krb5_boolean                create_standalone=FALSE;
+-    krb5_boolean                krb_identity_exists=FALSE, establish_links=FALSE;
++    krb5_boolean                establish_links=FALSE;
+     char                        *standalone_principal_dn=NULL;
+     krb5_tl_data                *tl_data=NULL;
+     krb5_key_data               **keys=NULL;
+@@ -860,24 +961,6 @@ krb5_ldap_put_principal(krb5_context context, krb5_db_entry *entry,
+      * any of the subtrees
+      */
+     if (xargs.dn_from_kbd == TRUE) {
+-        /* make sure the DN falls in the subtree */
+-        int              dnlen=0, subtreelen=0;
+-        char             *dn=NULL;
+-        krb5_boolean     outofsubtree=TRUE;
+-
+-        if (xargs.dn != NULL) {
+-            dn = xargs.dn;
+-        } else if (xargs.linkdn != NULL) {
+-            dn = xargs.linkdn;
+-        } else if (standalone_principal_dn != NULL) {
+-            /*
+-             * Even though the standalone_principal_dn is constructed
+-             * within this function, there is the containerdn input
+-             * from the user that can become part of the it.
+-             */
+-            dn = standalone_principal_dn;
+-        }
+-
+         /* Get the current subtree list if we haven't already done so. */
+         if (subtreelist == NULL) {
+             st = krb5_get_subtree_info(ldap_context, &subtreelist, &ntrees);
+@@ -885,81 +968,10 @@ krb5_ldap_put_principal(krb5_context context, krb5_db_entry *entry,
+                 goto cleanup;
+         }
+ 
+-        for (tre=0; tre<ntrees; ++tre) {
+-            if (subtreelist[tre] == NULL || strlen(subtreelist[tre]) == 0) {
+-                outofsubtree = FALSE;
+-                break;
+-            } else {
+-                dnlen = strlen (dn);
+-                subtreelen = strlen(subtreelist[tre]);
+-                if ((dnlen >= subtreelen) && (strcasecmp((dn + dnlen - subtreelen), subtreelist[tre]) == 0)) {
+-                    outofsubtree = FALSE;
+-                    break;
+-                }
+-            }
+-        }
+-
+-        if (outofsubtree == TRUE) {
+-            st = EINVAL;
+-            k5_setmsg(context, st, _("DN is out of the realm subtree"));
++        st = validate_xargs(context, ldap_server_handle, &xargs,
++                            standalone_principal_dn, subtreelist, ntrees);
++        if (st)
+             goto cleanup;
+-        }
+-
+-        /*
+-         * dn value will be set either by dn, linkdn or the standalone_principal_dn
+-         * In the first 2 cases, the dn should be existing and in the last case we
+-         * are supposed to create the ldap object. so the below should not be
+-         * executed for the last case.
+-         */
+-
+-        if (standalone_principal_dn == NULL) {
+-            /*
+-             * If the ldap object is missing, this results in an error.
+-             */
+-
+-            /*
+-             * Search for krbprincipalname attribute here.
+-             * This is to find if a kerberos identity is already present
+-             * on the ldap object, in which case adding a kerberos identity
+-             * on the ldap object should result in an error.
+-             */
+-            char  *attributes[]={"krbticketpolicyreference", "krbprincipalname", NULL};
+-
+-            ldap_msgfree(result);
+-            result = NULL;
+-            LDAP_SEARCH_1(dn, LDAP_SCOPE_BASE, 0, attributes, IGNORE_STATUS);
+-            if (st == LDAP_SUCCESS) {
+-                ent = ldap_first_entry(ld, result);
+-                if (ent != NULL) {
+-                    if ((values=ldap_get_values(ld, ent, "krbticketpolicyreference")) != NULL) {
+-                        ldap_value_free(values);
+-                    }
+-
+-                    if ((values=ldap_get_values(ld, ent, "krbprincipalname")) != NULL) {
+-                        krb_identity_exists = TRUE;
+-                        ldap_value_free(values);
+-                    }
+-                }
+-            } else {
+-                st = set_ldap_error(context, st, OP_SEARCH);
+-                goto cleanup;
+-            }
+-        }
+-    }
+-
+-    /*
+-     * If xargs.dn is set then the request is to add a
+-     * kerberos principal on a ldap object, but if
+-     * there is one already on the ldap object this
+-     * should result in an error.
+-     */
+-
+-    if (xargs.dn != NULL && krb_identity_exists == TRUE) {
+-        st = EINVAL;
+-        snprintf(errbuf, sizeof(errbuf),
+-                 _("ldap object is already kerberized"));
+-        k5_setmsg(context, st, "%s", errbuf);
+-        goto cleanup;
+     }
+ 
+     if (xargs.linkdn != NULL) {
+diff --git a/src/tests/t_kdb.py b/src/tests/t_kdb.py
+index c0eeb0118..319687ff3 100755
+--- a/src/tests/t_kdb.py
++++ b/src/tests/t_kdb.py
+@@ -171,6 +171,14 @@ out = realm.run([kadminl, 'ank', '-randkey', '-x', 'dn=cn=krb5', 'princ1'],
+                 expected_code=1)
+ if 'DN is out of the realm subtree' not in out:
+     fail('Unexpected kadmin.local output for out-of-realm dn')
++
++# Check that the DN container check is a hierarchy test, not a simple
++# suffix match (CVE-2018-5730).  We expect this operation to fail
++# either way (because "xcn" isn't a valid DN tag) but the container
++# check should happen before the DN is parsed.
++realm.run([kadminl, 'ank', '-randkey', '-x', 'dn=xcn=t1,cn=krb5', 'princ1'],
++          expected_code=1, expected_msg='DN is out of the realm subtree')
++
+ realm.run([kadminl, 'ank', '-randkey', '-x', 'dn=cn=t2,cn=krb5', 'princ1'])
+ out = realm.run([kadminl, 'getprinc', 'princ1'])
+ if 'Principal: princ1' not in out:
+@@ -209,6 +217,12 @@ out = realm.run([kadminl, 'modprinc', '-x', 'containerdn=cn=t2,cn=krb5',
+ if 'containerdn option not supported' not in out:
+     fail('Unexpected kadmin.local output trying to reset containerdn')
+ 
++# Verify that containerdn is checked when linkdn is also supplied
++# (CVE-2018-5730).
++realm.run([kadminl, 'ank', '-randkey', '-x', 'containerdn=cn=krb5',
++           '-x', 'linkdn=cn=t2,cn=krb5', 'princ4'], expected_code=1,
++          expected_msg='DN is out of the realm subtree')
++
+ # Create and modify a ticket policy.
+ kldaputil(['create_policy', '-maxtktlife', '3hour', '-maxrenewlife', '6hour',
+            '-allow_forwardable', 'tktpol'])
diff --git a/SOURCES/Fix-hex-conversion-of-PKINIT-certid-strings.patch b/SOURCES/Fix-hex-conversion-of-PKINIT-certid-strings.patch
new file mode 100644
index 0000000..792219e
--- /dev/null
+++ b/SOURCES/Fix-hex-conversion-of-PKINIT-certid-strings.patch
@@ -0,0 +1,92 @@
+From 73c156f998e848c5e383ddd715193d84d95e5c39 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Fri, 26 Jan 2018 11:47:50 -0500
+Subject: [PATCH] Fix hex conversion of PKINIT certid strings
+
+When parsing a PKCS11 token specification, correctly convert from hex
+to binary instead of using OpenSSL bignum functions (which would strip
+leading zeros).
+
+[ghudson@mit.edu: made hex_string_to_bin() a bit less verbose; wrote
+commit message]
+
+ticket: 8636
+(cherry picked from commit 63e8b8142fd7b3931a7bf2d6448978ca536bafc0)
+---
+ .../preauth/pkinit/pkinit_crypto_openssl.c    | 55 +++++++++++++++----
+ 1 file changed, 44 insertions(+), 11 deletions(-)
+
+diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+index 85ca8885d..6098acc6a 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+@@ -4640,6 +4640,43 @@ reassemble_pkcs11_name(pkinit_identity_opts *idopts)
+     return ret;
+ }
+ 
++static int
++hex_string_to_bin(const char *str, int *bin_len_out, CK_BYTE **bin_out)
++{
++    size_t str_len, i;
++    CK_BYTE *bin;
++    char *endptr, tmp[3] = { '\0', '\0', '\0' };
++    long val;
++
++    *bin_len_out = 0;
++    *bin_out = NULL;
++
++    str_len = strlen(str);
++    if (str_len % 2 != 0)
++        return EINVAL;
++    bin = malloc(str_len / 2);
++    if (bin == NULL)
++        return ENOMEM;
++
++    errno = 0;
++    for (i = 0; i < str_len / 2; i++) {
++        tmp[0] = str[i * 2];
++        tmp[1] = str[i * 2 + 1];
++
++        val = strtol(tmp, &endptr, 16);
++        if (val < 0 || val > 255 || errno != 0 || endptr != &tmp[2]) {
++            free(bin);
++            return EINVAL;
++        }
++
++        bin[i] = (CK_BYTE)val;
++    }
++
++    *bin_len_out = str_len / 2;
++    *bin_out = bin;
++    return 0;
++}
++
+ static krb5_error_code
+ pkinit_get_certs_pkcs11(krb5_context context,
+                         pkinit_plg_crypto_context plg_cryptoctx,
+@@ -4682,18 +4719,14 @@ pkinit_get_certs_pkcs11(krb5_context context,
+     }
+     /* Convert the ascii cert_id string into a binary blob */
+     if (idopts->cert_id_string != NULL) {
+-        BIGNUM *bn = NULL;
+-        BN_hex2bn(&bn, idopts->cert_id_string);
+-        if (bn == NULL)
+-            return ENOMEM;
+-        id_cryptoctx->cert_id_len = BN_num_bytes(bn);
+-        id_cryptoctx->cert_id = malloc((size_t) id_cryptoctx->cert_id_len);
+-        if (id_cryptoctx->cert_id == NULL) {
+-            BN_free(bn);
+-            return ENOMEM;
++        r = hex_string_to_bin(idopts->cert_id_string,
++                              &id_cryptoctx->cert_id_len,
++                              &id_cryptoctx->cert_id);
++        if (r != 0) {
++            pkiDebug("Failed to convert certid string [%s]\n",
++                     idopts->cert_id_string);
++            return r;
+         }
+-        BN_bn2bin(bn, id_cryptoctx->cert_id);
+-        BN_free(bn);
+     }
+     id_cryptoctx->slotid = idopts->slotid;
+     id_cryptoctx->pkcs11_method = 1;
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..e11a490
--- /dev/null
+++ b/SOURCES/Fix-in_clock_skew-and-use-it-in-AS-client-code.patch
@@ -0,0 +1,58 @@
+From 4d42f950965f16a9eb77444a99abe76a8b4ac12c 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)
+---
+ 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..26ab1d5
--- /dev/null
+++ b/SOURCES/Fix-make-certs.sh-for-OpenSSL-1.1.patch
@@ -0,0 +1,70 @@
+From 7113cdfa8b06d1f2a9512a1a69c5313a79509298 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]
+---
+ 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..e796c92
--- /dev/null
+++ b/SOURCES/Fix-more-time-manipulations-for-y2038.patch
@@ -0,0 +1,83 @@
+From 5fd12bd6e550bc178923b25abc30d8f7c250837a 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)
+---
+ 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/Fix-segfault-in-finish_dispatch.patch b/SOURCES/Fix-segfault-in-finish_dispatch.patch
new file mode 100644
index 0000000..dc6a7f0
--- /dev/null
+++ b/SOURCES/Fix-segfault-in-finish_dispatch.patch
@@ -0,0 +1,135 @@
+From 9680ab4bd9f38c67ffeb249cf1572d30a1475d28 Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Wed, 18 Apr 2018 14:13:28 -0400
+Subject: [PATCH] Fix segfault in finish_dispatch()
+
+dispatch() doesn't necessarily initialize state->active_realm which
+led to an explicit NULL dereference in finish_dispatch().
+
+Additionally, fix make_too_big_error() so that it won't subsequently
+dereference state->active_realm.
+
+tags: pullup
+target_version: 1.16-next
+target_version: 1.15-next
+
+(cherry picked from commit c822bacc1b33970a2a20d9eae80f43307e783516)
+---
+ src/kdc/dispatch.c | 79 ++++++++++++++++++++++++----------------------
+ 1 file changed, 42 insertions(+), 37 deletions(-)
+
+diff --git a/src/kdc/dispatch.c b/src/kdc/dispatch.c
+index 4ecc23481..1f4b70874 100644
+--- a/src/kdc/dispatch.c
++++ b/src/kdc/dispatch.c
+@@ -35,9 +35,6 @@
+ 
+ static krb5_int32 last_usec = 0, last_os_random = 0;
+ 
+-static krb5_error_code make_too_big_error(kdc_realm_t *kdc_active_realm,
+-                                          krb5_data **out);
+-
+ struct dispatch_state {
+     loop_respond_fn respond;
+     void *arg;
+@@ -47,6 +44,41 @@ struct dispatch_state {
+     krb5_context kdc_err_context;
+ };
+ 
++
++static krb5_error_code
++make_too_big_error(krb5_context context, krb5_principal tgsprinc,
++                   krb5_data **out)
++{
++    krb5_error errpkt;
++    krb5_error_code retval;
++    krb5_data *scratch;
++
++    *out = NULL;
++    memset(&errpkt, 0, sizeof(errpkt));
++
++    retval = krb5_us_timeofday(context, &errpkt.stime, &errpkt.susec);
++    if (retval)
++        return retval;
++    errpkt.error = KRB_ERR_RESPONSE_TOO_BIG;
++    errpkt.server = tgsprinc;
++    errpkt.client = NULL;
++    errpkt.text.length = 0;
++    errpkt.text.data = 0;
++    errpkt.e_data.length = 0;
++    errpkt.e_data.data = 0;
++    scratch = malloc(sizeof(*scratch));
++    if (scratch == NULL)
++        return ENOMEM;
++    retval = krb5_mk_error(context, &errpkt, scratch);
++    if (retval) {
++        free(scratch);
++        return retval;
++    }
++
++    *out = scratch;
++    return 0;
++}
++
+ static void
+ finish_dispatch(struct dispatch_state *state, krb5_error_code code,
+                 krb5_data *response)
+@@ -54,12 +86,17 @@ finish_dispatch(struct dispatch_state *state, krb5_error_code code,
+     loop_respond_fn oldrespond = state->respond;
+     void *oldarg = state->arg;
+     kdc_realm_t *kdc_active_realm = state->active_realm;
++    krb5_principal tgsprinc = NULL;
++
++    if (kdc_active_realm != NULL)
++        tgsprinc = kdc_active_realm->realm_tgsprinc;
+ 
+     if (state->is_tcp == 0 && response &&
+         response->length > (unsigned int)max_dgram_reply_size) {
+-        krb5_free_data(kdc_context, response);
++        krb5_free_data(state->kdc_err_context, response);
+         response = NULL;
+-        code = make_too_big_error(kdc_active_realm, &response);
++        code = make_too_big_error(state->kdc_err_context, tgsprinc,
++                                  &response);
+         if (code)
+             krb5_klog_syslog(LOG_ERR, "error constructing "
+                              "KRB_ERR_RESPONSE_TOO_BIG error: %s",
+@@ -201,38 +238,6 @@ dispatch(void *cb, struct sockaddr *local_saddr,
+     finish_dispatch_cache(state, retval, response);
+ }
+ 
+-static krb5_error_code
+-make_too_big_error(kdc_realm_t *kdc_active_realm, krb5_data **out)
+-{
+-    krb5_error errpkt;
+-    krb5_error_code retval;
+-    krb5_data *scratch;
+-
+-    *out = NULL;
+-    memset(&errpkt, 0, sizeof(errpkt));
+-
+-    retval = krb5_us_timeofday(kdc_context, &errpkt.stime, &errpkt.susec);
+-    if (retval)
+-        return retval;
+-    errpkt.error = KRB_ERR_RESPONSE_TOO_BIG;
+-    errpkt.server = tgs_server;
+-    errpkt.client = NULL;
+-    errpkt.text.length = 0;
+-    errpkt.text.data = 0;
+-    errpkt.e_data.length = 0;
+-    errpkt.e_data.data = 0;
+-    scratch = malloc(sizeof(*scratch));
+-    if (scratch == NULL)
+-        return ENOMEM;
+-    retval = krb5_mk_error(kdc_context, &errpkt, scratch);
+-    if (retval) {
+-        free(scratch);
+-        return retval;
+-    }
+-
+-    *out = scratch;
+-    return 0;
+-}
+ 
+ krb5_context get_context(void *handle)
+ {
diff --git a/SOURCES/Ignore-dotfiles-in-profile-includedir.patch b/SOURCES/Ignore-dotfiles-in-profile-includedir.patch
new file mode 100644
index 0000000..1237061
--- /dev/null
+++ b/SOURCES/Ignore-dotfiles-in-profile-includedir.patch
@@ -0,0 +1,61 @@
+From df09bfffaf5a8e5a3c646838f7d87b16a2680cfe Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Fri, 24 Mar 2017 11:07:21 -0400
+Subject: [PATCH] Ignore dotfiles in profile includedir
+
+Editors and filesystems may create artifacts related to .conf files
+which don't change the file suffix; these artifacts generally begin
+with "." so that they don't appear in normal directory listings
+(e.g. ".#filename" for emacs interlock files).  Make sure to ignore
+any such artifacts when processing a profile includedir directive.
+
+ticket: 8563 (new)
+target_version: 1.15-next
+tags: pullup
+
+(cherry picked from commit e8e1d841f8e43e4f441b451d91333a01e43c1b6f)
+---
+ doc/admin/conf_files/krb5_conf.rst | 7 ++++---
+ src/util/profile/prof_parse.c      | 6 +++++-
+ 2 files changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
+index c0e4349c0..1d9bc9e34 100644
+--- a/doc/admin/conf_files/krb5_conf.rst
++++ b/doc/admin/conf_files/krb5_conf.rst
+@@ -55,9 +55,10 @@ following directives at the beginning of a line::
+ directory must exist and be readable.  Including a directory includes
+ all files within the directory whose names consist solely of
+ alphanumeric characters, dashes, or underscores.  Starting in release
+-1.15, files with names ending in ".conf" are also included.  Included
+-profile files are syntactically independent of their parents, so each
+-included file must begin with a section header.
++1.15, files with names ending in ".conf" are also included, unless the
++name begins with ".".  Included profile files are syntactically
++independent of their parents, so each included file must begin with a
++section header.
+ 
+ The krb5.conf file can specify that configuration should be obtained
+ from a loadable module, rather than the file itself, using the
+diff --git a/src/util/profile/prof_parse.c b/src/util/profile/prof_parse.c
+index e7c1f65aa..1baceea9e 100644
+--- a/src/util/profile/prof_parse.c
++++ b/src/util/profile/prof_parse.c
+@@ -222,12 +222,16 @@ static errcode_t parse_include_file(const char *filename,
+ }
+ 
+ /* Return non-zero if filename contains only alphanumeric characters, dashes,
+- * and underscores, or if the filename ends in ".conf". */
++ * and underscores, or if the filename ends in ".conf" and is not a dotfile. */
+ static int valid_name(const char *filename)
+ {
+     const char *p;
+     size_t len = strlen(filename);
+ 
++    /* Ignore dotfiles, which might be editor or filesystem artifacts. */
++    if (*filename == '.')
++        return 0;
++
+     if (len >= 5 && !strcmp(filename + len - 5, ".conf"))
+         return 1;
+ 
diff --git a/SOURCES/Improve-PKINIT-UPN-SAN-matching.patch b/SOURCES/Improve-PKINIT-UPN-SAN-matching.patch
new file mode 100644
index 0000000..73c9740
--- /dev/null
+++ b/SOURCES/Improve-PKINIT-UPN-SAN-matching.patch
@@ -0,0 +1,151 @@
+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)
+---
+ src/include/krb5/kdcpreauth_plugin.h          | 13 +++++++++
+ src/kdc/kdc_preauth.c                         | 28 +++++++++++++++++--
+ .../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/In-FIPS-mode-add-plaintext-fallback-for-RC4-usages-a.patch b/SOURCES/In-FIPS-mode-add-plaintext-fallback-for-RC4-usages-a.patch
new file mode 100644
index 0000000..98c2bcc
--- /dev/null
+++ b/SOURCES/In-FIPS-mode-add-plaintext-fallback-for-RC4-usages-a.patch
@@ -0,0 +1,327 @@
+From c1f14d371be42cbe851c573d26e425ebecc2ea35 Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Tue, 31 Jul 2018 13:47:26 -0400
+Subject: [PATCH] In FIPS mode, add plaintext fallback for RC4 usages and taint
+
+---
+ src/lib/krad/attr.c      | 38 ++++++++++++++++++++++++++++----------
+ src/lib/krad/attrset.c   |  5 +++--
+ src/lib/krad/internal.h  | 13 +++++++++++--
+ src/lib/krad/packet.c    | 18 +++++++++---------
+ src/lib/krad/remote.c    | 10 ++++++++--
+ src/lib/krad/t_attr.c    |  3 ++-
+ src/lib/krad/t_attrset.c |  4 +++-
+ 7 files changed, 64 insertions(+), 27 deletions(-)
+
+diff --git a/src/lib/krad/attr.c b/src/lib/krad/attr.c
+index 9c13d9d75..f96153e2e 100644
+--- a/src/lib/krad/attr.c
++++ b/src/lib/krad/attr.c
+@@ -38,7 +38,8 @@
+ typedef krb5_error_code
+ (*attribute_transform_fn)(krb5_context ctx, const char *secret,
+                           const unsigned char *auth, const krb5_data *in,
+-                          unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen);
++                          unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
++                          krb5_boolean *is_fips);
+ 
+ typedef struct {
+     const char *name;
+@@ -51,12 +52,14 @@ typedef struct {
+ static krb5_error_code
+ user_password_encode(krb5_context ctx, const char *secret,
+                      const unsigned char *auth, const krb5_data *in,
+-                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen);
++                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
++                     krb5_boolean *is_fips);
+ 
+ static krb5_error_code
+ user_password_decode(krb5_context ctx, const char *secret,
+                      const unsigned char *auth, const krb5_data *in,
+-                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen);
++                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
++                     krb5_boolean *ignored);
+ 
+ static const attribute_record attributes[UCHAR_MAX] = {
+     {"User-Name", 1, MAX_ATTRSIZE, NULL, NULL},
+@@ -128,7 +131,8 @@ static const attribute_record attributes[UCHAR_MAX] = {
+ static krb5_error_code
+ user_password_encode(krb5_context ctx, const char *secret,
+                      const unsigned char *auth, const krb5_data *in,
+-                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen)
++                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
++                     krb5_boolean *is_fips)
+ {
+     const unsigned char *indx;
+     krb5_error_code retval;
+@@ -156,7 +160,12 @@ user_password_encode(krb5_context ctx, const char *secret,
+ 
+         retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &tmp,
+                                       &sum);
+-        if (retval != 0) {
++        if (retval == ENOMEM) {
++            /* I'm Linux, so we know this is a FIPS failure.  RSA_MD5 doesn't
++             * provide security so let's move on. */
++            *is_fips = TRUE;
++            sum.contents = calloc(1, BLOCKSIZE);
++        } else if (retval != 0) {
+             zap(tmp.data, tmp.length);
+             zap(outbuf, len);
+             krb5_free_data_contents(ctx, &tmp);
+@@ -180,7 +189,8 @@ user_password_encode(krb5_context ctx, const char *secret,
+ static krb5_error_code
+ user_password_decode(krb5_context ctx, const char *secret,
+                      const unsigned char *auth, const krb5_data *in,
+-                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen)
++                     unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
++                     krb5_boolean *is_fips)
+ {
+     const unsigned char *indx;
+     krb5_error_code retval;
+@@ -206,7 +216,12 @@ user_password_decode(krb5_context ctx, const char *secret,
+ 
+         retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0,
+                                       &tmp, &sum);
+-        if (retval != 0) {
++        if (retval == ENOMEM) {
++            /* I'm Linux, so we know this is a FIPS failure.  Assume the
++             * other side is running locally and move on. */
++            *is_fips = TRUE;
++            sum.contents = calloc(1, BLOCKSIZE);
++        } else if (retval != 0) {
+             zap(tmp.data, tmp.length);
+             zap(outbuf, in->length);
+             krb5_free_data_contents(ctx, &tmp);
+@@ -248,7 +263,7 @@ krb5_error_code
+ kr_attr_encode(krb5_context ctx, const char *secret,
+                const unsigned char *auth, krad_attr type,
+                const krb5_data *in, unsigned char outbuf[MAX_ATTRSIZE],
+-               size_t *outlen)
++               size_t *outlen, krb5_boolean *is_fips)
+ {
+     krb5_error_code retval;
+ 
+@@ -265,7 +280,8 @@ kr_attr_encode(krb5_context ctx, const char *secret,
+         return 0;
+     }
+ 
+-    return attributes[type - 1].encode(ctx, secret, auth, in, outbuf, outlen);
++    return attributes[type - 1].encode(ctx, secret, auth, in, outbuf, outlen,
++                                       is_fips);
+ }
+ 
+ krb5_error_code
+@@ -274,6 +290,7 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth,
+                unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen)
+ {
+     krb5_error_code retval;
++    krb5_boolean ignored;
+ 
+     retval = kr_attr_valid(type, in);
+     if (retval != 0)
+@@ -288,7 +305,8 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth,
+         return 0;
+     }
+ 
+-    return attributes[type - 1].decode(ctx, secret, auth, in, outbuf, outlen);
++    return attributes[type - 1].decode(ctx, secret, auth, in, outbuf, outlen,
++                                       &ignored);
+ }
+ 
+ krad_attr
+diff --git a/src/lib/krad/attrset.c b/src/lib/krad/attrset.c
+index 03c613716..d89982a13 100644
+--- a/src/lib/krad/attrset.c
++++ b/src/lib/krad/attrset.c
+@@ -167,7 +167,8 @@ krad_attrset_copy(const krad_attrset *set, krad_attrset **copy)
+ krb5_error_code
+ kr_attrset_encode(const krad_attrset *set, const char *secret,
+                   const unsigned char *auth,
+-                  unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen)
++                  unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen,
++                  krb5_boolean *is_fips)
+ {
+     unsigned char buffer[MAX_ATTRSIZE];
+     krb5_error_code retval;
+@@ -181,7 +182,7 @@ kr_attrset_encode(const krad_attrset *set, const char *secret,
+ 
+     K5_TAILQ_FOREACH(a, &set->list, list) {
+         retval = kr_attr_encode(set->ctx, secret, auth, a->type, &a->attr,
+-                                buffer, &attrlen);
++                                buffer, &attrlen, is_fips);
+         if (retval != 0)
+             return retval;
+ 
+diff --git a/src/lib/krad/internal.h b/src/lib/krad/internal.h
+index 996a89372..a53ce31ce 100644
+--- a/src/lib/krad/internal.h
++++ b/src/lib/krad/internal.h
+@@ -49,6 +49,13 @@
+ 
+ typedef struct krad_remote_st krad_remote;
+ 
++struct krad_packet_st {
++    char buffer[KRAD_PACKET_SIZE_MAX];
++    krad_attrset *attrset;
++    krb5_data pkt;
++    krb5_boolean is_fips;
++};
++
+ /* Validate constraints of an attribute. */
+ krb5_error_code
+ kr_attr_valid(krad_attr type, const krb5_data *data);
+@@ -57,7 +64,8 @@ kr_attr_valid(krad_attr type, const krb5_data *data);
+ krb5_error_code
+ kr_attr_encode(krb5_context ctx, const char *secret, const unsigned char *auth,
+                krad_attr type, const krb5_data *in,
+-               unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen);
++               unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
++               krb5_boolean *is_fips);
+ 
+ /* Decode an attribute. */
+ krb5_error_code
+@@ -69,7 +77,8 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth,
+ krb5_error_code
+ kr_attrset_encode(const krad_attrset *set, const char *secret,
+                   const unsigned char *auth,
+-                  unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen);
++                  unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen,
++                  krb5_boolean *is_fips);
+ 
+ /* Decode attributes from a buffer. */
+ krb5_error_code
+diff --git a/src/lib/krad/packet.c b/src/lib/krad/packet.c
+index c597174b6..2fbf0ee1e 100644
+--- a/src/lib/krad/packet.c
++++ b/src/lib/krad/packet.c
+@@ -53,12 +53,6 @@ typedef unsigned char uchar;
+ #define pkt_auth(p) ((uchar *)offset(&(p)->pkt, OFFSET_AUTH))
+ #define pkt_attr(p) ((unsigned char *)offset(&(p)->pkt, OFFSET_ATTR))
+ 
+-struct krad_packet_st {
+-    char buffer[KRAD_PACKET_SIZE_MAX];
+-    krad_attrset *attrset;
+-    krb5_data pkt;
+-};
+-
+ typedef struct {
+     uchar x[(UCHAR_MAX + 1) / 8];
+ } idmap;
+@@ -190,7 +184,11 @@ auth_generate_response(krb5_context ctx, const char *secret,
+     retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &data,
+                                   &hash);
+     free(data.data);
+-    if (retval != 0)
++    if (retval == ENOMEM) {
++        /* We're on Linux, so this is a FIPS failure, and this checksum
++         * does very little security-wise anyway, so don't taint. */
++        hash.contents = calloc(1, AUTH_FIELD_SIZE);
++    } else if (retval != 0)
+         return retval;
+ 
+     memcpy(rauth, hash.contents, AUTH_FIELD_SIZE);
+@@ -276,7 +274,7 @@ krad_packet_new_request(krb5_context ctx, const char *secret, krad_code code,
+ 
+     /* Encode the attributes. */
+     retval = kr_attrset_encode(set, secret, pkt_auth(pkt), pkt_attr(pkt),
+-                               &attrset_len);
++                               &attrset_len, &pkt->is_fips);
+     if (retval != 0)
+         goto error;
+ 
+@@ -314,7 +312,7 @@ krad_packet_new_response(krb5_context ctx, const char *secret, krad_code code,
+ 
+     /* Encode the attributes. */
+     retval = kr_attrset_encode(set, secret, pkt_auth(request), pkt_attr(pkt),
+-                               &attrset_len);
++                               &attrset_len, &pkt->is_fips);
+     if (retval != 0)
+         goto error;
+ 
+@@ -451,6 +449,8 @@ krad_packet_decode_response(krb5_context ctx, const char *secret,
+ const krb5_data *
+ krad_packet_encode(const krad_packet *pkt)
+ {
++    if (pkt->is_fips)
++        return NULL;
+     return &pkt->pkt;
+ }
+ 
+diff --git a/src/lib/krad/remote.c b/src/lib/krad/remote.c
+index 437f7e91a..0f90443ce 100644
+--- a/src/lib/krad/remote.c
++++ b/src/lib/krad/remote.c
+@@ -263,7 +263,7 @@ on_io_write(krad_remote *rr)
+     request *r;
+ 
+     K5_TAILQ_FOREACH(r, &rr->list, list) {
+-        tmp = krad_packet_encode(r->request);
++        tmp = &r->request->pkt;
+ 
+         /* If the packet has already been sent, do nothing. */
+         if (r->sent == tmp->length)
+@@ -359,7 +359,7 @@ on_io_read(krad_remote *rr)
+     if (req != NULL) {
+         K5_TAILQ_FOREACH(r, &rr->list, list) {
+             if (r->request == req &&
+-                r->sent == krad_packet_encode(req)->length) {
++                r->sent == req->pkt.length) {
+                 request_finish(r, 0, rsp);
+                 break;
+             }
+@@ -455,6 +455,12 @@ kr_remote_send(krad_remote *rr, krad_code code, krad_attrset *attrs,
+                                      (krad_packet_iter_cb)iterator, &r, &tmp);
+     if (retval != 0)
+         goto error;
++    else if (tmp->is_fips && rr->info->ai_family != AF_LOCAL &&
++        rr->info->ai_family != AF_UNIX) {
++        /* This would expose cleartext passwords, so abort. */
++        retval = ESOCKTNOSUPPORT;
++        goto error;
++    }
+ 
+     K5_TAILQ_FOREACH(r, &rr->list, list) {
+         if (r->request == tmp) {
+diff --git a/src/lib/krad/t_attr.c b/src/lib/krad/t_attr.c
+index eb2a780c8..4d285ad9d 100644
+--- a/src/lib/krad/t_attr.c
++++ b/src/lib/krad/t_attr.c
+@@ -50,6 +50,7 @@ main()
+     const char *tmp;
+     krb5_data in;
+     size_t len;
++    krb5_boolean is_fips = FALSE;
+ 
+     noerror(krb5_init_context(&ctx));
+ 
+@@ -73,7 +74,7 @@ main()
+     in = string2data((char *)decoded);
+     retval = kr_attr_encode(ctx, secret, auth,
+                             krad_attr_name2num("User-Password"),
+-                            &in, outbuf, &len);
++                            &in, outbuf, &len, &is_fips);
+     insist(retval == 0);
+     insist(len == sizeof(encoded));
+     insist(memcmp(outbuf, encoded, len) == 0);
+diff --git a/src/lib/krad/t_attrset.c b/src/lib/krad/t_attrset.c
+index 7928335ca..0f9576253 100644
+--- a/src/lib/krad/t_attrset.c
++++ b/src/lib/krad/t_attrset.c
+@@ -49,6 +49,7 @@ main()
+     krb5_context ctx;
+     size_t len = 0, encode_len;
+     krb5_data tmp;
++    krb5_boolean is_fips = FALSE;
+ 
+     noerror(krb5_init_context(&ctx));
+     noerror(krad_attrset_new(ctx, &set));
+@@ -62,7 +63,8 @@ main()
+     noerror(krad_attrset_add(set, krad_attr_name2num("User-Password"), &tmp));
+ 
+     /* Encode attrset. */
+-    noerror(kr_attrset_encode(set, "foo", auth, buffer, &encode_len));
++    noerror(kr_attrset_encode(set, "foo", auth, buffer, &encode_len,
++                              &is_fips));
+     krad_attrset_free(set);
+ 
+     /* Manually encode User-Name. */
diff --git a/SOURCES/Include-preauth-name-in-trace-output-if-possible.patch b/SOURCES/Include-preauth-name-in-trace-output-if-possible.patch
new file mode 100644
index 0000000..a78f166
--- /dev/null
+++ b/SOURCES/Include-preauth-name-in-trace-output-if-possible.patch
@@ -0,0 +1,506 @@
+From c9b74036064b7f3aebbd3c482703ce97ff868bb6 Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Thu, 15 Mar 2018 14:37:28 -0400
+Subject: [PATCH] Include preauth name in trace output if possible
+
+Add a {patype} trace format specifier for a single pa-type value.  Add
+a krb5_preauthtype to string conversion function to trace machinery
+and use it when formatting {patype} or {patypes}.
+
+[ghudson@mit.edu: wrote conversion function; edited commit message]
+
+ticket: 8653 (new)
+(cherry picked from commit 9c68fe39b018666eabe033b639c1f35d03ba51c7)
+[rharwood@redhat.com: freshness, expected_msg]
+---
+ src/include/k5-trace.h      |  17 +--
+ src/lib/krb5/os/t_trace.ref |   2 +-
+ src/lib/krb5/os/trace.c     |  60 +++++++++-
+ src/tests/t_pkinit.py       |  36 +++---
+ src/tests/t_preauth.py      | 216 ++++++++++++++++++------------------
+ 5 files changed, 199 insertions(+), 132 deletions(-)
+
+diff --git a/src/include/k5-trace.h b/src/include/k5-trace.h
+index e60ee0b75..49b1b6756 100644
+--- a/src/include/k5-trace.h
++++ b/src/include/k5-trace.h
+@@ -75,6 +75,7 @@
+  *   {cksum}       const krb5_checksum *, display cksumtype and hex checksum
+  *   {princ}       krb5_principal, unparse and display
+  *   {ptype}       krb5_int32, krb5_principal type, display name
++ *   {patype}      krb5_preauthtype, a single padata type number
+  *   {patypes}     krb5_pa_data **, display list of padata type numbers
+  *   {etype}       krb5_enctype, display shortest name of enctype
+  *   {etypes}      krb5_enctype *, display list of enctypes
+@@ -218,14 +219,14 @@ void krb5int_trace(krb5_context context, const char *fmt, ...);
+ #define TRACE_INIT_CREDS_PREAUTH_DECRYPT_FAIL(c, code)                  \
+     TRACE(c, "Decrypt with preauth AS key failed: {kerr}", code)
+ #define TRACE_INIT_CREDS_PREAUTH_MORE(c, patype)                \
+-    TRACE(c, "Continuing preauth mech {int}", (int)patype)
++    TRACE(c, "Continuing preauth mech {patype}", patype)
+ #define TRACE_INIT_CREDS_PREAUTH_NONE(c)        \
+     TRACE(c, "Sending unauthenticated request")
+ #define TRACE_INIT_CREDS_PREAUTH_OPTIMISTIC(c)  \
+     TRACE(c, "Attempting optimistic preauth")
+ #define TRACE_INIT_CREDS_PREAUTH_TRYAGAIN(c, patype, code)              \
+-    TRACE(c, "Recovering from KDC error {int} using preauth mech {int}", \
+-          (int)patype, (int)code)
++    TRACE(c, "Recovering from KDC error {int} using preauth mech {patype}", \
++          patype, (int)code)
+ #define TRACE_INIT_CREDS_RESTART_FAST(c)        \
+     TRACE(c, "Restarting to upgrade to FAST")
+ #define TRACE_INIT_CREDS_RESTART_PREAUTH_FAILED(c)                      \
+@@ -269,7 +270,7 @@ void krb5int_trace(krb5_context context, const char *fmt, ...);
+ 
+ #define TRACE_PREAUTH_CONFLICT(c, name1, name2, patype)                 \
+     TRACE(c, "Preauth module {str} conflicts with module {str} for pa " \
+-          "type {int}", name1, name2, (int) patype)
++          "type {patype}", name1, name2, patype)
+ #define TRACE_PREAUTH_COOKIE(c, len, data)                      \
+     TRACE(c, "Received cookie: {lenstr}", (size_t) len, data)
+ #define TRACE_PREAUTH_ENC_TS_KEY_GAK(c, keyblock)                       \
+@@ -281,8 +282,8 @@ void krb5int_trace(krb5_context context, const char *fmt, ...);
+     TRACE(c, "Selected etype info: etype {etype}, salt \"{data}\", " \
+           "params \"{data}\"", etype, salt, s2kparams)
+ #define TRACE_PREAUTH_INFO_FAIL(c, patype, code)                        \
+-    TRACE(c, "Preauth builtin info function failure, type={int}: {kerr}", \
+-          (int) patype, code)
++    TRACE(c, "Preauth builtin info function failure, type={patype}: {kerr}", \
++          patype, code)
+ #define TRACE_PREAUTH_INPUT(c, padata)                          \
+     TRACE(c, "Processing preauth types: {patypes}", padata)
+ #define TRACE_PREAUTH_OUTPUT(c, padata)                                 \
+@@ -293,8 +294,8 @@ void krb5int_trace(krb5_context context, const char *fmt, ...);
+ #define TRACE_PREAUTH_SAM_KEY_GAK(c, keyblock)                  \
+     TRACE(c, "AS key obtained for SAM: {keyblock}", keyblock)
+ #define TRACE_PREAUTH_SALT(c, salt, patype)                          \
+-    TRACE(c, "Received salt \"{data}\" via padata type {int}", salt, \
+-          (int) patype)
++    TRACE(c, "Received salt \"{data}\" via padata type {patype}", salt, \
++          patype)
+ #define TRACE_PREAUTH_SKIP(c, name, patype)                           \
+     TRACE(c, "Skipping previously used preauth module {str} ({int})", \
+           name, (int) patype)
+diff --git a/src/lib/krb5/os/t_trace.ref b/src/lib/krb5/os/t_trace.ref
+index ca5818a1e..bd5d9b6b6 100644
+--- a/src/lib/krb5/os/t_trace.ref
++++ b/src/lib/krb5/os/t_trace.ref
+@@ -38,7 +38,7 @@ int, krb5_principal type: Windows 2000 UPN and SID
+ int, krb5_principal type: NT 4 style name
+ int, krb5_principal type: NT 4 style name and SID
+ int, krb5_principal type: ?
+-krb5_pa_data **, display list of padata type numbers: 3, 0
++krb5_pa_data **, display list of padata type numbers: PA-PW-SALT (3), 0
+ krb5_pa_data **, display list of padata type numbers: (empty)
+ krb5_enctype, display shortest name of enctype: des-cbc-crc
+ krb5_enctype *, display list of enctypes: 5, rc4-hmac-exp, 511
+diff --git a/src/lib/krb5/os/trace.c b/src/lib/krb5/os/trace.c
+index 8750b7650..5a80f5518 100644
+--- a/src/lib/krb5/os/trace.c
++++ b/src/lib/krb5/os/trace.c
+@@ -123,6 +123,49 @@ principal_type_string(krb5_int32 type)
+     }
+ }
+ 
++static char *
++padata_type_string(krb5_preauthtype type)
++{
++    switch (type) {
++    case KRB5_PADATA_TGS_REQ: return "PA-TGS-REQ";
++    case KRB5_PADATA_ENC_TIMESTAMP: return "PA-ENC-TIMESTAMP";
++    case KRB5_PADATA_PW_SALT: return "PA-PW-SALT";
++    case KRB5_PADATA_ENC_UNIX_TIME: return "PA-ENC-UNIX-TIME";
++    case KRB5_PADATA_ENC_SANDIA_SECURID: return "PA-SANDIA-SECUREID";
++    case KRB5_PADATA_SESAME: return "PA-SESAME";
++    case KRB5_PADATA_OSF_DCE: return "PA-OSF-DCE";
++    case KRB5_CYBERSAFE_SECUREID: return "PA-CYBERSAFE-SECUREID";
++    case KRB5_PADATA_AFS3_SALT: return "PA-AFS3-SALT";
++    case KRB5_PADATA_ETYPE_INFO: return "PA-ETYPE-INFO";
++    case KRB5_PADATA_SAM_CHALLENGE: return "PA-SAM-CHALLENGE";
++    case KRB5_PADATA_SAM_RESPONSE: return "PA-SAM-RESPONSE";
++    case KRB5_PADATA_PK_AS_REQ_OLD: return "PA-PK-AS-REQ_OLD";
++    case KRB5_PADATA_PK_AS_REP_OLD: return "PA-PK-AS-REP_OLD";
++    case KRB5_PADATA_PK_AS_REQ: return "PA-PK-AS-REQ";
++    case KRB5_PADATA_PK_AS_REP: return "PA-PK-AS-REP";
++    case KRB5_PADATA_ETYPE_INFO2: return "PA-ETYPE-INFO2";
++    case KRB5_PADATA_SVR_REFERRAL_INFO: return "PA-SVR-REFERRAL-INFO";
++    case KRB5_PADATA_SAM_REDIRECT: return "PA-SAM-REDIRECT";
++    case KRB5_PADATA_GET_FROM_TYPED_DATA: return "PA-GET-FROM-TYPED-DATA";
++    case KRB5_PADATA_SAM_CHALLENGE_2: return "PA-SAM-CHALLENGE2";
++    case KRB5_PADATA_SAM_RESPONSE_2: return "PA-SAM-RESPONSE2";
++    case KRB5_PADATA_PAC_REQUEST: return "PA-PAC-REQUEST";
++    case KRB5_PADATA_FOR_USER: return "PA-FOR_USER";
++    case KRB5_PADATA_S4U_X509_USER: return "PA-FOR-X509-USER";
++    case KRB5_PADATA_AS_CHECKSUM: return "PA-AS-CHECKSUM";
++    case KRB5_PADATA_FX_COOKIE: return "PA-FX-COOKIE";
++    case KRB5_PADATA_FX_FAST: return "PA-FX-FAST";
++    case KRB5_PADATA_FX_ERROR: return "PA-FX-ERROR";
++    case KRB5_PADATA_ENCRYPTED_CHALLENGE: return "PA-ENCRYPTED-CHALLENGE";
++    case KRB5_PADATA_OTP_CHALLENGE: return "PA-OTP-CHALLENGE";
++    case KRB5_PADATA_OTP_REQUEST: return "PA-OTP-REQUEST";
++    case KRB5_PADATA_OTP_PIN_CHANGE: return "PA-OTP-PIN-CHANGE";
++    case KRB5_PADATA_PKINIT_KX: return "PA-PKINIT-KX";
++    case KRB5_ENCPADATA_REQ_ENC_PA_REP: return "PA-REQ-ENC-PA-REP";
++    default: return NULL;
++    }
++}
++
+ static char *
+ trace_format(krb5_context context, const char *fmt, va_list ap)
+ {
+@@ -140,6 +183,8 @@ trace_format(krb5_context context, const char *fmt, va_list ap)
+     krb5_key key;
+     const krb5_checksum *cksum;
+     krb5_pa_data **padata;
++    krb5_preauthtype pa_type;
++    const char *name;
+     krb5_ccache ccache;
+     krb5_keytab keytab;
+     krb5_creds *creds;
+@@ -271,10 +316,23 @@ trace_format(krb5_context context, const char *fmt, va_list ap)
+             if (padata == NULL || *padata == NULL)
+                 k5_buf_add(&buf, "(empty)");
+             for (; padata != NULL && *padata != NULL; padata++) {
+-                k5_buf_add_fmt(&buf, "%d", (int)(*padata)->pa_type);
++                pa_type = (*padata)->pa_type;
++                name = padata_type_string(pa_type);
++                if (name != NULL)
++                    k5_buf_add_fmt(&buf, "%s (%d)", name, (int)pa_type);
++                else
++                    k5_buf_add_fmt(&buf, "%d", (int)pa_type);
++
+                 if (*(padata + 1) != NULL)
+                     k5_buf_add(&buf, ", ");
+             }
++        } else if (strcmp(tmpbuf, "patype") == 0) {
++            pa_type = va_arg(ap, krb5_preauthtype);
++            name = padata_type_string(pa_type);
++            if (name != NULL)
++                k5_buf_add_fmt(&buf, "%s (%d)", name, (int)pa_type);
++            else
++                k5_buf_add_fmt(&buf, "%d", (int)pa_type);
+         } else if (strcmp(tmpbuf, "etype") == 0) {
+             etype = va_arg(ap, krb5_enctype);
+             if (krb5_enctype_to_name(etype, TRUE, tmpbuf, sizeof(tmpbuf)) == 0)
+diff --git a/src/tests/t_pkinit.py b/src/tests/t_pkinit.py
+index c25475096..64ff2393a 100755
+--- a/src/tests/t_pkinit.py
++++ b/src/tests/t_pkinit.py
+@@ -161,10 +161,18 @@ realm.start_kdc()
+ realm.run([kadminl, 'delprinc', 'WELLKNOWN/ANONYMOUS'])
+ 
+ # Run the basic test - PKINIT with FILE: identity, with no password on the key.
+-realm.run(['./responder', '-x', 'pkinit=',
+-           '-X', 'X509_user_identity=%s' % file_identity, realm.user_princ])
++msgs = ('Sending unauthenticated request',
++        '/Additional pre-authentication required',
++        'Preauthenticating using KDC method data',
++        'PKINIT loading CA certs and CRLs from FILE',
++        'PKINIT client making DH request',
++        ' preauth for next request: PA-FX-COOKIE (133), PA-PK-AS-REQ (16)',
++        'PKINIT client verified DH reply',
++        'PKINIT client found id-pkinit-san in KDC cert',
++        'PKINIT client matched KDC principal krbtgt/')
+ realm.kinit(realm.user_princ,
+-            flags=['-X', 'X509_user_identity=%s' % file_identity])
++            flags=['-X', 'X509_user_identity=%s' % file_identity],
++            expected_trace=msgs)
+ realm.klist(realm.user_princ)
+ realm.run([kvno, realm.host_princ])
+ 
+@@ -181,19 +189,19 @@ minbits_kdc_conf = {'realms': {'$realm': {'pkinit_dh_min_bits': '4096'}}}
+ minbits_env = realm.special_env('restrict', True, kdc_conf=minbits_kdc_conf)
+ realm.stop_kdc()
+ realm.start_kdc(env=minbits_env)
+-expected_trace = ('Sending unauthenticated request',
+-                  '/Additional pre-authentication required',
+-                  'Preauthenticating using KDC method data',
+-                  'Preauth module pkinit (16) (real) returned: 0/Success',
+-                  'Produced preauth for next request: 133, 16',
+-                  '/Key parameters not accepted',
+-                  'Preauth tryagain input types (16): 109, 133',
+-                  'trying again with KDC-provided parameters',
+-                  'Preauth module pkinit (16) tryagain returned: 0/Success',
+-                  'Followup preauth for next request: 16, 133')
++msgs = ('Sending unauthenticated request',
++        '/Additional pre-authentication required',
++        'Preauthenticating using KDC method data',
++        'Preauth module pkinit (16) (real) returned: 0/Success',
++        ' preauth for next request: PA-FX-COOKIE (133), PA-PK-AS-REQ (16)',
++        '/Key parameters not accepted',
++        'Preauth tryagain input types (16): 109, PA-FX-COOKIE (133)',
++        'trying again with KDC-provided parameters',
++        'Preauth module pkinit (16) tryagain returned: 0/Success',
++        ' preauth for next request: PA-PK-AS-REQ (16), PA-FX-COOKIE (133)')
+ realm.kinit(realm.user_princ,
+             flags=['-X', 'X509_user_identity=%s' % file_identity],
+-            expected_trace=expected_trace)
++            expected_trace=msgs)
+ realm.stop_kdc()
+ realm.start_kdc()
+ 
+diff --git a/src/tests/t_preauth.py b/src/tests/t_preauth.py
+index 7d4d299dc..b2b0983aa 100644
+--- a/src/tests/t_preauth.py
++++ b/src/tests/t_preauth.py
+@@ -22,15 +22,15 @@ if 'no key' not in out:
+ # PA-FX-COOKIE; 2 is encrypted timestamp.
+ 
+ # Test normal preauth flow.
+-expected_trace = ('Sending unauthenticated request',
+-                  '/Additional pre-authentication required',
+-                  'Preauthenticating using KDC method data',
+-                  'Processing preauth types:',
+-                  'Preauth module test (-123) (real) returned: 0/Success',
+-                  'Produced preauth for next request: 133, -123',
+-                  'Decrypted AS reply')
++msgs = ('Sending unauthenticated request',
++        '/Additional pre-authentication required',
++        'Preauthenticating using KDC method data',
++        'Processing preauth types:',
++        'Preauth module test (-123) (real) returned: 0/Success',
++        'Produced preauth for next request: PA-FX-COOKIE (133), -123',
++        'Decrypted AS reply')
+ realm.run(['./icred', realm.user_princ, password('user')],
+-          expected_msg='testval', expected_trace=expected_trace)
++          expected_msg='testval', expected_trace=msgs)
+ 
+ # Test successful optimistic preauth.
+ expected_trace = ('Attempting optimistic preauth',
+@@ -43,136 +43,136 @@ realm.run(['./icred', '-o', '-123', realm.user_princ, password('user')],
+ 
+ # Test optimistic preauth failing on client, followed by successful
+ # preauth using the same module.
+-expected_trace = ('Attempting optimistic preauth',
+-                  'Processing preauth types: -123',
+-                  '/induced optimistic fail',
+-                  'Sending unauthenticated request',
+-                  '/Additional pre-authentication required',
+-                  'Preauthenticating using KDC method data',
+-                  'Processing preauth types:',
+-                  'Preauth module test (-123) (real) returned: 0/Success',
+-                  'Produced preauth for next request: 133, -123',
+-                  'Decrypted AS reply')
++msgs = ('Attempting optimistic preauth',
++        'Processing preauth types: -123',
++        '/induced optimistic fail',
++        'Sending unauthenticated request',
++        '/Additional pre-authentication required',
++        'Preauthenticating using KDC method data',
++        'Processing preauth types:',
++        'Preauth module test (-123) (real) returned: 0/Success',
++        'Produced preauth for next request: PA-FX-COOKIE (133), -123',
++        'Decrypted AS reply')
+ realm.run(['./icred', '-o', '-123', '-X', 'fail_optimistic', realm.user_princ,
+            password('user')], expected_msg='testval',
+-          expected_trace=expected_trace)
++          expected_trace=msgs)
+ 
+ # Test optimistic preauth failing on KDC, followed by successful preauth
+ # using the same module.
+ realm.run([kadminl, 'setstr', realm.user_princ, 'failopt', 'yes'])
+-expected_trace = ('Attempting optimistic preauth',
+-                  'Processing preauth types: -123',
+-                  'Preauth module test (-123) (real) returned: 0/Success',
+-                  'Produced preauth for next request: -123',
+-                  '/Preauthentication failed',
+-                  'Preauthenticating using KDC method data',
+-                  'Processing preauth types:',
+-                  'Preauth module test (-123) (real) returned: 0/Success',
+-                  'Produced preauth for next request: 133, -123',
+-                  'Decrypted AS reply')
++msgs = ('Attempting optimistic preauth',
++        'Processing preauth types: -123',
++        'Preauth module test (-123) (real) returned: 0/Success',
++        'Produced preauth for next request: -123',
++        '/Preauthentication failed',
++        'Preauthenticating using KDC method data',
++        'Processing preauth types:',
++        'Preauth module test (-123) (real) returned: 0/Success',
++        'Produced preauth for next request: PA-FX-COOKIE (133), -123',
++        'Decrypted AS reply')
+ realm.run(['./icred', '-o', '-123', realm.user_princ, password('user')],
+-          expected_msg='testval', expected_trace=expected_trace)
++          expected_msg='testval', expected_trace=msgs)
+ realm.run([kadminl, 'delstr', realm.user_princ, 'failopt'])
+ 
+ # Test KDC_ERR_MORE_PREAUTH_DATA_REQUIRED and secure cookies.
+ realm.run([kadminl, 'setstr', realm.user_princ, '2rt', 'secondtrip'])
+-expected_trace = ('Sending unauthenticated request',
+-                  '/Additional pre-authentication required',
+-                  'Preauthenticating using KDC method data',
+-                  'Processing preauth types:',
+-                  'Preauth module test (-123) (real) returned: 0/Success',
+-                  'Produced preauth for next request: 133, -123',
+-                  '/More preauthentication data is required',
+-                  'Continuing preauth mech -123',
+-                  'Processing preauth types: -123, 133',
+-                  'Produced preauth for next request: 133, -123',
+-                  'Decrypted AS reply')
++msgs = ('Sending unauthenticated request',
++        '/Additional pre-authentication required',
++        'Preauthenticating using KDC method data',
++        'Processing preauth types:',
++        'Preauth module test (-123) (real) returned: 0/Success',
++        'Produced preauth for next request: PA-FX-COOKIE (133), -123',
++        '/More preauthentication data is required',
++        'Continuing preauth mech -123',
++        'Processing preauth types: -123, PA-FX-COOKIE (133)',
++        'Produced preauth for next request: PA-FX-COOKIE (133), -123',
++        'Decrypted AS reply')
+ realm.run(['./icred', realm.user_princ, password('user')],
+-          expected_msg='2rt: secondtrip', expected_trace=expected_trace)
++          expected_msg='2rt: secondtrip', expected_trace=msgs)
+ 
+ # Test client-side failure after KDC_ERR_MORE_PREAUTH_DATA_REQUIRED,
+ # falling back to encrypted timestamp.
+-expected_trace = ('Sending unauthenticated request',
+-                  '/Additional pre-authentication required',
+-                  'Preauthenticating using KDC method data',
+-                  'Processing preauth types:',
+-                  'Preauth module test (-123) (real) returned: 0/Success',
+-                  'Produced preauth for next request: 133, -123',
+-                  '/More preauthentication data is required',
+-                  'Continuing preauth mech -123',
+-                  'Processing preauth types: -123, 133',
+-                  '/induced 2rt fail',
+-                  'Preauthenticating using KDC method data',
+-                  'Processing preauth types:',
+-                  'Encrypted timestamp (for ',
+-                  'module encrypted_timestamp (2) (real) returned: 0/Success',
+-                  'Produced preauth for next request: 133, 2',
+-                  'Decrypted AS reply')
++msgs = ('Sending unauthenticated request',
++        '/Additional pre-authentication required',
++        'Preauthenticating using KDC method data',
++        'Processing preauth types:',
++        'Preauth module test (-123) (real) returned: 0/Success',
++        'Produced preauth for next request: PA-FX-COOKIE (133), -123',
++        '/More preauthentication data is required',
++        'Continuing preauth mech -123',
++        'Processing preauth types: -123, PA-FX-COOKIE (133)',
++        '/induced 2rt fail',
++        'Preauthenticating using KDC method data',
++        'Processing preauth types:',
++        'Encrypted timestamp (for ',
++        'module encrypted_timestamp (2) (real) returned: 0/Success',
++        'preauth for next request: PA-FX-COOKIE (133), PA-ENC-TIMESTAMP (2)',
++        'Decrypted AS reply')
+ realm.run(['./icred', '-X', 'fail_2rt', realm.user_princ, password('user')],
+-          expected_msg='2rt: secondtrip', expected_trace=expected_trace)
++          expected_msg='2rt: secondtrip', expected_trace=msgs)
+ 
+ # Test KDC-side failure after KDC_ERR_MORE_PREAUTH_DATA_REQUIRED,
+ # falling back to encrypted timestamp.
+ realm.run([kadminl, 'setstr', realm.user_princ, 'fail2rt', 'yes'])
+-expected_trace = ('Sending unauthenticated request',
+-                  '/Additional pre-authentication required',
+-                  'Preauthenticating using KDC method data',
+-                  'Processing preauth types:',
+-                  'Preauth module test (-123) (real) returned: 0/Success',
+-                  'Produced preauth for next request: 133, -123',
+-                  '/More preauthentication data is required',
+-                  'Continuing preauth mech -123',
+-                  'Processing preauth types: -123, 133',
+-                  'Preauth module test (-123) (real) returned: 0/Success',
+-                  'Produced preauth for next request: 133, -123',
+-                  '/Preauthentication failed',
+-                  'Preauthenticating using KDC method data',
+-                  'Processing preauth types:',
+-                  'Encrypted timestamp (for ',
+-                  'module encrypted_timestamp (2) (real) returned: 0/Success',
+-                  'Produced preauth for next request: 133, 2',
+-                  'Decrypted AS reply')
++msgs = ('Sending unauthenticated request',
++        '/Additional pre-authentication required',
++        'Preauthenticating using KDC method data',
++        'Processing preauth types:',
++        'Preauth module test (-123) (real) returned: 0/Success',
++        'Produced preauth for next request: PA-FX-COOKIE (133), -123',
++        '/More preauthentication data is required',
++        'Continuing preauth mech -123',
++        'Processing preauth types: -123, PA-FX-COOKIE (133)',
++        'Preauth module test (-123) (real) returned: 0/Success',
++        'Produced preauth for next request: PA-FX-COOKIE (133), -123',
++        '/Preauthentication failed',
++        'Preauthenticating using KDC method data',
++        'Processing preauth types:',
++        'Encrypted timestamp (for ',
++        'module encrypted_timestamp (2) (real) returned: 0/Success',
++        'preauth for next request: PA-FX-COOKIE (133), PA-ENC-TIMESTAMP (2)',
++        'Decrypted AS reply')
+ realm.run(['./icred', realm.user_princ, password('user')],
+-          expected_msg='2rt: secondtrip', expected_trace=expected_trace)
++          expected_msg='2rt: secondtrip', expected_trace=msgs)
+ realm.run([kadminl, 'delstr', realm.user_princ, 'fail2rt'])
+ 
+ # Test tryagain flow by inducing a KDC_ERR_ENCTYPE_NOSUPP error on the KDC.
+ realm.run([kadminl, 'setstr', realm.user_princ, 'err', 'testagain'])
+-expected_trace = ('Sending unauthenticated request',
+-                  '/Additional pre-authentication required',
+-                  'Preauthenticating using KDC method data',
+-                  'Processing preauth types:',
+-                  'Preauth module test (-123) (real) returned: 0/Success',
+-                  'Produced preauth for next request: 133, -123',
+-                  '/KDC has no support for encryption type',
+-                  'Recovering from KDC error 14 using preauth mech -123',
+-                  'Preauth tryagain input types (-123): -123, 133',
+-                  'Preauth module test (-123) tryagain returned: 0/Success',
+-                  'Followup preauth for next request: -123, 133',
+-                  'Decrypted AS reply')
++msgs = ('Sending unauthenticated request',
++        '/Additional pre-authentication required',
++        'Preauthenticating using KDC method data',
++        'Processing preauth types:',
++        'Preauth module test (-123) (real) returned: 0/Success',
++        'Produced preauth for next request: PA-FX-COOKIE (133), -123',
++        '/KDC has no support for encryption type',
++        'Recovering from KDC error 14 using preauth mech -123',
++        'Preauth tryagain input types (-123): -123, PA-FX-COOKIE (133)',
++        'Preauth module test (-123) tryagain returned: 0/Success',
++        'Followup preauth for next request: -123, PA-FX-COOKIE (133)',
++        'Decrypted AS reply')
+ realm.run(['./icred', realm.user_princ, password('user')],
+-          expected_msg='tryagain: testagain', expected_trace=expected_trace)
++          expected_msg='tryagain: testagain', expected_trace=msgs)
+ 
+ # Test a client-side tryagain failure, falling back to encrypted
+ # timestamp.
+-expected_trace = ('Sending unauthenticated request',
+-                  '/Additional pre-authentication required',
+-                  'Preauthenticating using KDC method data',
+-                  'Processing preauth types:',
+-                  'Preauth module test (-123) (real) returned: 0/Success',
+-                  'Produced preauth for next request: 133, -123',
+-                  '/KDC has no support for encryption type',
+-                  'Recovering from KDC error 14 using preauth mech -123',
+-                  'Preauth tryagain input types (-123): -123, 133',
+-                  '/induced tryagain fail',
+-                  'Preauthenticating using KDC method data',
+-                  'Processing preauth types:',
+-                  'Encrypted timestamp (for ',
+-                  'module encrypted_timestamp (2) (real) returned: 0/Success',
+-                  'Produced preauth for next request: 133, 2',
+-                  'Decrypted AS reply')
++msgs = ('Sending unauthenticated request',
++        '/Additional pre-authentication required',
++        'Preauthenticating using KDC method data',
++        'Processing preauth types:',
++        'Preauth module test (-123) (real) returned: 0/Success',
++        'Produced preauth for next request: PA-FX-COOKIE (133), -123',
++        '/KDC has no support for encryption type',
++        'Recovering from KDC error 14 using preauth mech -123',
++        'Preauth tryagain input types (-123): -123, PA-FX-COOKIE (133)',
++        '/induced tryagain fail',
++        'Preauthenticating using KDC method data',
++        'Processing preauth types:',
++        'Encrypted timestamp (for ',
++        'module encrypted_timestamp (2) (real) returned: 0/Success',
++        'preauth for next request: PA-FX-COOKIE (133), PA-ENC-TIMESTAMP (2)',
++        'Decrypted AS reply')
+ realm.run(['./icred', '-X', 'fail_tryagain', realm.user_princ,
+-           password('user')], expected_trace=expected_trace)
++           password('user')], expected_trace=msgs)
+ 
+ # Test that multiple stepwise initial creds operations can be
+ # performed with the same krb5_context, with proper tracking of
diff --git a/SOURCES/Limit-ticket-lifetime-to-2-31-1-seconds.patch b/SOURCES/Limit-ticket-lifetime-to-2-31-1-seconds.patch
new file mode 100644
index 0000000..71cea7a
--- /dev/null
+++ b/SOURCES/Limit-ticket-lifetime-to-2-31-1-seconds.patch
@@ -0,0 +1,203 @@
+From 5802408ab53a524f40f9a83a104f1d5f19ce5db0 Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Thu, 24 Aug 2017 16:00:33 -0400
+Subject: [PATCH] Limit ticket lifetime to 2^31-1 seconds
+
+Although timestamps above 2^31-1 are now valid, intervals exceeding
+2^31-1 seconds may be treated incorrectly by comparison operations.
+
+The initially computed interval in kdc_get_ticket_endtime() could be
+negative if the requested end time is far in the future, causing the
+function to yield an incorrect result.  (With the new larger value of
+kdc_infinity, this could specifically happen if a KDC-REQ contains a
+zero till field.)  Cap the interval at the maximum valid value.
+Reported by Weijun Wang.
+
+Avoid delta comparisons in favor of timestamp comparions in
+krb5int_validate_times(), ksu's krb5_check_exp(), and clockskew
+checks.
+
+Also use a y2038-safe timestamp comparison in set_request_times() when
+comparing the requested renewable end time to the requested ticket end
+time.
+
+ticket: 8352
+(cherry picked from commit 54e58755368b58ba5894a14c1d02626da42d8003)
+---
+ src/clients/ksu/ccache.c       | 2 +-
+ src/include/k5-int.h           | 7 +++++++
+ src/kdc/kdc_util.c             | 7 ++++++-
+ src/kdc/replay.c               | 2 +-
+ src/kdc/t_replay.c             | 2 +-
+ src/lib/krb5/krb/gc_via_tkt.c  | 4 ++--
+ src/lib/krb5/krb/get_in_tkt.c  | 6 +++---
+ src/lib/krb5/krb/int-proto.h   | 3 ---
+ src/lib/krb5/krb/valid_times.c | 4 ++--
+ src/lib/krb5/os/timeofday.c    | 2 +-
+ 10 files changed, 24 insertions(+), 15 deletions(-)
+
+diff --git a/src/clients/ksu/ccache.c b/src/clients/ksu/ccache.c
+index 236313b7b..2a99521d4 100644
+--- a/src/clients/ksu/ccache.c
++++ b/src/clients/ksu/ccache.c
+@@ -282,7 +282,7 @@ krb5_error_code krb5_check_exp(context, tkt_time)
+ 
+     }
+ 
+-    if (ts_delta(currenttime, tkt_time.endtime) > context->clockskew) {
++    if (ts_after(currenttime, ts_incr(tkt_time.endtime, context->clockskew))) {
+         retval = KRB5KRB_AP_ERR_TKT_EXPIRED ;
+         return retval;
+     }
+diff --git a/src/include/k5-int.h b/src/include/k5-int.h
+index 39ffb9568..e31004a7c 100644
+--- a/src/include/k5-int.h
++++ b/src/include/k5-int.h
+@@ -2386,6 +2386,13 @@ ts_after(krb5_timestamp a, krb5_timestamp b)
+     return (uint32_t)a > (uint32_t)b;
+ }
+ 
++/* Return true if a and b are within d seconds. */
++static inline krb5_boolean
++ts_within(krb5_timestamp a, krb5_timestamp b, krb5_deltat d)
++{
++    return !ts_after(a, ts_incr(b, d)) && !ts_after(b, ts_incr(a, d));
++}
++
+ krb5_error_code KRB5_CALLCONV
+ krb5_get_credentials_for_user(krb5_context context, krb5_flags options,
+                               krb5_ccache ccache,
+diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
+index 5455e2a67..770163b94 100644
+--- a/src/kdc/kdc_util.c
++++ b/src/kdc/kdc_util.c
+@@ -1759,14 +1759,19 @@ kdc_get_ticket_endtime(kdc_realm_t *kdc_active_realm,
+                        krb5_db_entry *server,
+                        krb5_timestamp *out_endtime)
+ {
+-    krb5_timestamp until, life;
++    krb5_timestamp until;
++    krb5_deltat life;
+ 
+     if (till == 0)
+         till = kdc_infinity;
+ 
+     until = ts_min(till, endtime);
+ 
++    /* Determine the requested lifetime, capped at the maximum valid time
++     * interval. */
+     life = ts_delta(until, starttime);
++    if (ts_after(until, starttime) && life < 0)
++        life = INT32_MAX;
+ 
+     if (client != NULL && client->max_life != 0)
+         life = min(life, client->max_life);
+diff --git a/src/kdc/replay.c b/src/kdc/replay.c
+index fab39cf88..caca783bf 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) (labs(ts_delta((ptr)->timein, now)) >= STALE_TIME)
++#define STALE(ptr, now) (ts_after(now, ts_incr((ptr)->timein, STALE_TIME)))
+ 
+ /* Return x rotated to the left by r bits. */
+ static inline krb5_ui_4
+diff --git a/src/kdc/t_replay.c b/src/kdc/t_replay.c
+index 1442e0e8c..bb7e2faff 100644
+--- a/src/kdc/t_replay.c
++++ b/src/kdc/t_replay.c
+@@ -903,7 +903,7 @@ test_kdc_insert_lookaside_cache_expire(void **state)
+     assert_non_null(e);
+     e->num_hits = 5;
+ 
+-    time_return(STALE_TIME, 0);
++    time_return(STALE_TIME + 1, 0);
+     kdc_insert_lookaside(context, &req2, NULL);
+ 
+     assert_null(K5_LIST_FIRST(&hash_table[req_hash1]));
+diff --git a/src/lib/krb5/krb/gc_via_tkt.c b/src/lib/krb5/krb/gc_via_tkt.c
+index cf1ea361f..5b9bb9573 100644
+--- a/src/lib/krb5/krb/gc_via_tkt.c
++++ b/src/lib/krb5/krb/gc_via_tkt.c
+@@ -306,8 +306,8 @@ krb5int_process_tgs_reply(krb5_context context,
+         goto cleanup;
+ 
+     if (!in_cred->times.starttime &&
+-        !in_clock_skew(context, dec_rep->enc_part2->times.starttime,
+-                       timestamp)) {
++        !ts_within(dec_rep->enc_part2->times.starttime, timestamp,
++                   context->clockskew)) {
+         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 7178bd87b..ed15550f0 100644
+--- a/src/lib/krb5/krb/get_in_tkt.c
++++ b/src/lib/krb5/krb/get_in_tkt.c
+@@ -269,8 +269,8 @@ verify_as_reply(krb5_context            context,
+             return retval;
+     } else {
+         if ((request->from == 0) &&
+-            !in_clock_skew(context, as_reply->enc_part2->times.starttime,
+-                           time_now))
++            !ts_within(as_reply->enc_part2->times.starttime, time_now,
++                       context->clockskew))
+             return (KRB5_KDCREP_SKEW);
+     }
+     return 0;
+@@ -781,7 +781,7 @@ set_request_times(krb5_context context, krb5_init_creds_context ctx)
+     if (ctx->renew_life > 0) {
+         /* Don't ask for a smaller renewable time than the lifetime. */
+         ctx->request->rtime = ts_incr(from, ctx->renew_life);
+-        if (ctx->request->rtime < ctx->request->till)
++        if (ts_after(ctx->request->till, ctx->request->rtime))
+             ctx->request->rtime = ctx->request->till;
+         ctx->request->kdc_options &= ~KDC_OPT_RENEWABLE_OK;
+     } else {
+diff --git a/src/lib/krb5/krb/int-proto.h b/src/lib/krb5/krb/int-proto.h
+index 48bd9f8f7..9c746d05b 100644
+--- a/src/lib/krb5/krb/int-proto.h
++++ b/src/lib/krb5/krb/int-proto.h
+@@ -83,9 +83,6 @@ krb5int_construct_matching_creds(krb5_context context, krb5_flags options,
+                                  krb5_creds *in_creds, krb5_creds *mcreds,
+                                  krb5_flags *fields);
+ 
+-#define in_clock_skew(context, date, now)               \
+-    (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/valid_times.c b/src/lib/krb5/krb/valid_times.c
+index 9e509b2dd..294761a88 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 (ts_delta(starttime, currenttime) > context->clockskew)
++    if (ts_after(starttime, ts_incr(currenttime, context->clockskew)))
+         return KRB5KRB_AP_ERR_TKT_NYV;  /* ticket not yet valid */
+ 
+-    if (ts_delta(currenttime, times->endtime) > context->clockskew)
++    if (ts_after(currenttime, ts_incr(times->endtime, context->clockskew)))
+         return KRB5KRB_AP_ERR_TKT_EXPIRED; /* ticket expired */
+ 
+     return 0;
+diff --git a/src/lib/krb5/os/timeofday.c b/src/lib/krb5/os/timeofday.c
+index 887f24c22..d4e36b1c7 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(ts_delta(date, currenttime)) >= context->clockskew)
++    if (!ts_within(date, currenttime, context->clockskew))
+         return KRB5KRB_AP_ERR_SKEW;
+ 
+     return 0;
diff --git a/SOURCES/Log-when-non-root-ksu-authorization-fails.patch b/SOURCES/Log-when-non-root-ksu-authorization-fails.patch
new file mode 100644
index 0000000..dc631ba
--- /dev/null
+++ b/SOURCES/Log-when-non-root-ksu-authorization-fails.patch
@@ -0,0 +1,35 @@
+From d5f22f9982dca7fa157d1d9b7488a671e0df72b8 Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Mon, 7 May 2018 16:42:59 -0400
+Subject: [PATCH] Log when non-root ksu authorization fails
+
+If non-root user attempts to ksu but is denied by policy, log to
+syslog at LOG_WARNING in keeping with other failure messages.
+
+ticket: 8270
+(cherry picked from commit 6cfa5c113e981f14f70ccafa20abfa5c46b665ba)
+---
+ src/clients/ksu/main.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/src/clients/ksu/main.c b/src/clients/ksu/main.c
+index cab0c1806..7959a0cba 100644
+--- a/src/clients/ksu/main.c
++++ b/src/clients/ksu/main.c
+@@ -417,6 +417,16 @@ main (argc, argv)
+     if (hp){
+         if (gb_err) fprintf(stderr, "%s", gb_err);
+         fprintf(stderr, _("account %s: authorization failed\n"), target_user);
++
++        if (cmd != NULL) {
++            syslog(LOG_WARNING,
++                   "Account %s: authorization for %s for execution of %s failed",
++                   target_user, source_user, cmd);
++        } else {
++            syslog(LOG_WARNING, "Account %s: authorization of %s failed",
++                   target_user, source_user);
++        }
++
+         exit(1);
+     }
+ 
diff --git a/SOURCES/Make-krb5_preauth_context-a-pointer-type.patch b/SOURCES/Make-krb5_preauth_context-a-pointer-type.patch
new file mode 100644
index 0000000..aa7b15d
--- /dev/null
+++ b/SOURCES/Make-krb5_preauth_context-a-pointer-type.patch
@@ -0,0 +1,140 @@
+From 3645da2a06ee69c846823e8335b5fd8a608f059a Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Tue, 20 Dec 2016 15:25:29 -0500
+Subject: [PATCH] Make krb5_preauth_context a pointer type
+
+For consistency with krb5_context and krb5_init_creds_context, make
+krb5_preauth_context a pointer type.  In preauth2.c, use the typedef
+name rather than the structure tag except when defining the structure.
+
+(cherry picked from commit 459a081dec6e91ae480a37acb805631742afe1e2)
+---
+ src/include/k5-int.h        |  4 ++--
+ src/lib/krb5/krb/preauth2.c | 22 +++++++++++-----------
+ 2 files changed, 13 insertions(+), 13 deletions(-)
+
+diff --git a/src/include/k5-int.h b/src/include/k5-int.h
+index e31004a7c..10b034037 100644
+--- a/src/include/k5-int.h
++++ b/src/include/k5-int.h
+@@ -1198,7 +1198,7 @@ k5_plugin_free_context(krb5_context context);
+ struct _kdb5_dal_handle;        /* private, in kdb5.h */
+ typedef struct _kdb5_dal_handle kdb5_dal_handle;
+ struct _kdb_log_context;
+-typedef struct krb5_preauth_context_st krb5_preauth_context;
++typedef struct krb5_preauth_context_st *krb5_preauth_context;
+ struct ccselect_module_handle;
+ struct localauth_module_handle;
+ struct hostrealm_module_handle;
+@@ -1235,7 +1235,7 @@ struct _krb5_context {
+     struct plugin_dir_handle libkrb5_plugins;
+ 
+     /* preauth module stuff */
+-    krb5_preauth_context *preauth_context;
++    krb5_preauth_context preauth_context;
+ 
+     /* cache module stuff */
+     struct ccselect_module_handle **ccselect_handles;
+diff --git a/src/lib/krb5/krb/preauth2.c b/src/lib/krb5/krb/preauth2.c
+index ca26fb0e3..b04d14829 100644
+--- a/src/lib/krb5/krb/preauth2.c
++++ b/src/lib/krb5/krb/preauth2.c
+@@ -161,7 +161,7 @@ k5_init_preauth_context(krb5_context context)
+     list[count] = NULL;
+ 
+     /* Place the constructed preauth context into the krb5 context. */
+-    context->preauth_context = malloc(sizeof(struct krb5_preauth_context_st));
++    context->preauth_context = malloc(sizeof(*context->preauth_context));
+     if (context->preauth_context == NULL)
+         goto cleanup;
+     context->preauth_context->tried = NULL;
+@@ -181,7 +181,7 @@ cleanup:
+ void
+ k5_reset_preauth_types_tried(krb5_context context)
+ {
+-    struct krb5_preauth_context_st *pctx = context->preauth_context;
++    krb5_preauth_context pctx = context->preauth_context;
+ 
+     if (pctx == NULL)
+         return;
+@@ -196,7 +196,7 @@ k5_reset_preauth_types_tried(krb5_context context)
+ void
+ k5_free_preauth_context(krb5_context context)
+ {
+-    struct krb5_preauth_context_st *pctx = context->preauth_context;
++    krb5_preauth_context pctx = context->preauth_context;
+ 
+     if (pctx == NULL)
+         return;
+@@ -211,7 +211,7 @@ k5_free_preauth_context(krb5_context context)
+ void
+ k5_preauth_request_context_init(krb5_context context)
+ {
+-    struct krb5_preauth_context_st *pctx = context->preauth_context;
++    krb5_preauth_context pctx = context->preauth_context;
+     clpreauth_handle *hp, h;
+ 
+     if (pctx == NULL) {
+@@ -233,7 +233,7 @@ k5_preauth_request_context_init(krb5_context context)
+ void
+ k5_preauth_request_context_fini(krb5_context context)
+ {
+-    struct krb5_preauth_context_st *pctx = context->preauth_context;
++    krb5_preauth_context pctx = context->preauth_context;
+     clpreauth_handle *hp, h;
+ 
+     if (pctx == NULL)
+@@ -495,7 +495,7 @@ void
+ k5_preauth_prepare_request(krb5_context context, krb5_get_init_creds_opt *opt,
+                            krb5_kdc_req *req)
+ {
+-    struct krb5_preauth_context_st *pctx = context->preauth_context;
++    krb5_preauth_context pctx = context->preauth_context;
+     clpreauth_handle *hp, h;
+     krb5_enctype *ep;
+ 
+@@ -556,7 +556,7 @@ pa_type_allowed(krb5_init_creds_context ctx, krb5_preauthtype pa_type)
+ static krb5_boolean
+ already_tried(krb5_context context, krb5_preauthtype pa_type)
+ {
+-    struct krb5_preauth_context_st *pctx = context->preauth_context;
++    krb5_preauth_context pctx = context->preauth_context;
+     size_t count;
+     krb5_preauthtype *newptr;
+ 
+@@ -580,7 +580,7 @@ process_pa_data(krb5_context context, krb5_init_creds_context ctx,
+                 krb5_pa_data ***out_pa_list, int *out_pa_list_size,
+                 krb5_preauthtype *out_type)
+ {
+-    struct krb5_preauth_context_st *pctx = context->preauth_context;
++    krb5_preauth_context pctx = context->preauth_context;
+     struct errinfo save = EMPTY_ERRINFO;
+     krb5_pa_data *pa, **pa_ptr, **mod_pa;
+     krb5_error_code ret = 0;
+@@ -858,7 +858,7 @@ krb5_error_code
+ k5_preauth_tryagain(krb5_context context, krb5_init_creds_context ctx,
+                     krb5_pa_data **in_padata, krb5_pa_data ***padata_out)
+ {
+-    struct krb5_preauth_context_st *pctx = context->preauth_context;
++    krb5_preauth_context pctx = context->preauth_context;
+     krb5_error_code ret;
+     krb5_pa_data **mod_pa;
+     clpreauth_handle h;
+@@ -897,7 +897,7 @@ static krb5_error_code
+ fill_response_items(krb5_context context, krb5_init_creds_context ctx,
+                     krb5_pa_data **in_padata)
+ {
+-    struct krb5_preauth_context_st *pctx = context->preauth_context;
++    krb5_preauth_context pctx = context->preauth_context;
+     krb5_error_code ret;
+     krb5_pa_data *pa;
+     clpreauth_handle h;
+@@ -1004,7 +1004,7 @@ krb5_preauth_supply_preauth_data(krb5_context context,
+                                  krb5_get_init_creds_opt *opt,
+                                  const char *attr, const char *value)
+ {
+-    struct krb5_preauth_context_st *pctx = context->preauth_context;
++    krb5_preauth_context pctx = context->preauth_context;
+     clpreauth_handle *hp, h;
+     krb5_error_code ret;
+ 
diff --git a/SOURCES/Make-timestamp-manipulations-y2038-safe.patch b/SOURCES/Make-timestamp-manipulations-y2038-safe.patch
new file mode 100644
index 0000000..486d831
--- /dev/null
+++ b/SOURCES/Make-timestamp-manipulations-y2038-safe.patch
@@ -0,0 +1,1844 @@
+From e7358d93fa1cbe5db52e217d466894b1af96d95c 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)
+---
+ 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 ++--
+ .../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/Merge-duplicate-subsections-in-profile-library.patch b/SOURCES/Merge-duplicate-subsections-in-profile-library.patch
new file mode 100644
index 0000000..5acd4ab
--- /dev/null
+++ b/SOURCES/Merge-duplicate-subsections-in-profile-library.patch
@@ -0,0 +1,122 @@
+From a19917522862f26bc711fd8271940906284ff55d Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Tue, 10 Apr 2018 15:55:41 -0400
+Subject: [PATCH] Merge duplicate subsections in profile library
+
+Modify profile_add_node() to return the existing node, rather than
+making a new one, when adding subsection configuration.
+
+This fixes an issue where the first instance of a subsection will hide
+the second instance entirely.  In particular, it was previously
+impossible to split realm-specific configuration across multiple
+config files.
+
+[ghudson@mit.edu: adjusted style, added test case]
+
+(cherry picked from commit efab9fa5a6d23c486467264e20b58bf5a9c60f0c)
+
+ticket: 7863
+version_fixed: 1.16.1
+
+(cherry picked from commit 98d0061c8083af960438ad1ac088f60497694a68)
+---
+ src/util/profile/prof_test1  | 22 ++++++++++++++++++++++
+ src/util/profile/prof_tree.c | 15 +++++++++++----
+ src/util/profile/test.ini    |  6 ++++++
+ 3 files changed, 39 insertions(+), 4 deletions(-)
+
+diff --git a/src/util/profile/prof_test1 b/src/util/profile/prof_test1
+index 7e30fc12f..7d13c9389 100644
+--- a/src/util/profile/prof_test1
++++ b/src/util/profile/prof_test1
+@@ -341,6 +341,27 @@ proc test9 {} {
+     puts "OK: test9: profile_flush_to_file with no changes"
+ }
+ 
++proc test10 {} {
++    global wd verbose
++
++    # Regression test for #7863: multiply-specified subsections should
++    # be merged.
++    set p [profile_init_path $wd/test2.ini]
++    set x [profile_get_values $p {{test section 2} child_section2 child}]
++    if $verbose { puts "Read $x from profile" }
++    if ![string equal $x "slick harry {john\tb } ron"] {
++	puts stderr "Error: test10: Did not get expected merged children."
++	exit 1
++    }
++
++    set x [profile_get_string $p {test section 2} child_section2 chores]
++    if $verbose { puts "Read $x from profile" }
++    if ![string equal $x "cleaning"] {
++	puts stderr "Error: test10: Did not find expected chores."
++	exit 1
++    }
++}
++
+ test1
+ test2
+ test3
+@@ -350,5 +371,6 @@ test6
+ test7
+ test8
+ test9
++test10
+ 
+ exit 0
+diff --git a/src/util/profile/prof_tree.c b/src/util/profile/prof_tree.c
+index 081f688e4..38aadc4e5 100644
+--- a/src/util/profile/prof_tree.c
++++ b/src/util/profile/prof_tree.c
+@@ -9,7 +9,7 @@
+  *
+  * Each node may represent either a relation or a section header.
+  *
+- * A section header must have its value field set to 0, and may a one
++ * A section header must have its value field be null, and may have one
+  * or more child nodes, pointed to by first_child.
+  *
+  * A relation has as its value a pointer to allocated memory
+@@ -159,15 +159,22 @@ errcode_t profile_add_node(struct profile_node *section, const char *name,
+         return PROF_ADD_NOT_SECTION;
+ 
+     /*
+-     * Find the place to insert the new node.  We look for the
+-     * place *after* the last match of the node name, since
++     * Find the place to insert the new node.  If we are adding a subsection
++     * and already have a subsection with that name, merge them.  Otherwise,
++     * we look for the place *after* the last match of the node name, since
+      * order matters.
+      */
+     for (p=section->first_child, last = 0; p; last = p, p = p->next) {
+         int cmp;
+         cmp = strcmp(p->name, name);
+-        if (cmp > 0)
++        if (cmp > 0) {
+             break;
++        } else if (value == NULL && cmp == 0 &&
++                   p->value == NULL && p->deleted != 1) {
++            /* Found duplicate subsection, so don't make a new one. */
++            *ret_node = p;
++            return 0;
++        }
+     }
+     retval = profile_create_node(name, value, &new);
+     if (retval)
+diff --git a/src/util/profile/test.ini b/src/util/profile/test.ini
+index 23ca89677..6622df108 100644
+--- a/src/util/profile/test.ini
++++ b/src/util/profile/test.ini
+@@ -10,6 +10,12 @@ this is a comment.  Everything up to the first square brace is ignored.
+ 	}
+ 	child_section2 = foo
+ 
++[test section 2]
++	child_section2 = {
++		child = ron
++		chores = cleaning
++	}
++
+ [realms]
+ ATHENA.MIT.EDU = {
+ 	server = KERBEROS.MIT.EDU:88
diff --git a/SOURCES/Modernize-kerberos-7.patch b/SOURCES/Modernize-kerberos-7.patch
new file mode 100644
index 0000000..a4c690f
--- /dev/null
+++ b/SOURCES/Modernize-kerberos-7.patch
@@ -0,0 +1,429 @@
+From 2319336ac1f52e56d2549bd83ff40a3e7b2f281a Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Mon, 15 Oct 2018 13:20:30 -0400
+Subject: [PATCH] Modernize kerberos(7)
+
+Update environment variable descriptions, using env_variables.rst as a
+guide.  Replace the content in env_variables.rst with a pointer to
+documentation at kerberos(7) so that we don't break external links and
+don't duplicate content.
+
+Replace references to rlogin.  Clarify and modernize other language.
+
+ticket: 8755
+(cherry picked from commit cdccdefa2d74d3abf5a8ae126e423af9d467d34f)
+---
+ doc/admin/env_variables.rst       |  44 +------------
+ doc/user/user_config/kerberos.rst | 106 ++++++++++++++++++------------
+ src/man/kerberos.man              | 104 +++++++++++++++++------------
+ 3 files changed, 128 insertions(+), 126 deletions(-)
+
+diff --git a/doc/admin/env_variables.rst b/doc/admin/env_variables.rst
+index 0c146d3e3..a2d15bea8 100644
+--- a/doc/admin/env_variables.rst
++++ b/doc/admin/env_variables.rst
+@@ -1,46 +1,4 @@
+ Environment variables
+ =====================
+ 
+-The following environment variables can be used during runtime:
+-
+-**KRB5_CONFIG**
+-    Main Kerberos configuration file.  Multiple filenames can be
+-    specified, separated by a colon; all files which are present will
+-    be read.  (See :ref:`mitK5defaults` for the default path.)
+-
+-**KRB5_KDC_PROFILE**
+-    KDC configuration file.  (See :ref:`mitK5defaults` for the default
+-    name.)
+-
+-**KRB5_KTNAME**
+-    Default keytab file name.  (See :ref:`mitK5defaults` for the
+-    default name.)
+-
+-**KRB5_CLIENT_KTNAME**
+-    Default client keytab file name.  (See :ref:`mitK5defaults` for
+-    the default name.)
+-
+-**KRB5CCNAME**
+-    Default name for the credentials cache file, in the form *type*\:\
+-    *residual*.  The type of the default cache may determine the
+-    availability of a cache collection.  For instance, a default cache
+-    of type ``DIR`` causes caches within the directory to be present
+-    in the global cache collection.
+-
+-**KRB5RCACHETYPE**
+-    Default replay cache type.  Defaults to ``dfl``.  A value of
+-    ``none`` disables the replay cache.
+-
+-**KRB5RCACHEDIR**
+-    Default replay cache directory.  (See :ref:`mitK5defaults` for the
+-    default location.)
+-
+-**KPROP_PORT**
+-    :ref:`kprop(8)` port to use.  Defaults to 754.
+-
+-**KRB5_TRACE**
+-    Filename for trace-logging output (introduced in release 1.9).
+-    For example, ``env KRB5_TRACE=/dev/stdout kinit`` would send
+-    tracing information for kinit to ``/dev/stdout``.  Some programs
+-    may ignore this variable (particularly setuid or login system
+-    programs).
++This content has moved to :ref:`kerberos(7)`.
+diff --git a/doc/user/user_config/kerberos.rst b/doc/user/user_config/kerberos.rst
+index 6c4453b3b..56412f099 100644
+--- a/doc/user/user_config/kerberos.rst
++++ b/doc/user/user_config/kerberos.rst
+@@ -8,12 +8,12 @@ DESCRIPTION
+ 
+ The Kerberos system authenticates individual users in a network
+ environment.  After authenticating yourself to Kerberos, you can use
+-Kerberos-enabled programs without having to present passwords.
++Kerberos-enabled programs without having to present passwords or
++certificates to those programs.
+ 
+-If you enter your username and :ref:`kinit(1)` responds with this
+-message:
++If you receive the following response from :ref:`kinit(1)`:
+ 
+-kinit(v5): Client not found in Kerberos database while getting initial
++kinit: Client not found in Kerberos database while getting initial
+ credentials
+ 
+ you haven't been registered as a Kerberos user.  See your system
+@@ -25,10 +25,13 @@ is the **instance**, which in the case of a user is usually null.
+ Some users may have privileged instances, however, such as ``root`` or
+ ``admin``.  In the case of a service, the instance is the fully
+ qualified name of the machine on which it runs; i.e. there can be an
+-rlogin service running on the machine ABC, which is different from the
+-rlogin service running on the machine XYZ.  The third part of a
+-Kerberos name is the **realm**.  The realm corresponds to the Kerberos
+-service providing authentication for the principal.
++ssh service running on the machine ABC (ssh/ABC@REALM), which is
++different from the ssh service running on the machine XYZ
++(ssh/XYZ@REALM).  The third part of a Kerberos name is the **realm**.
++The realm corresponds to the Kerberos service providing authentication
++for the principal.  Realms are conventionally all-uppercase, and often
++match the end of hostnames in the realm (for instance, host01.example.com
++might be in realm EXAMPLE.COM).
+ 
+ When writing a Kerberos name, the principal name is separated from the
+ instance (if not null) by a slash, and the realm (if not the local
+@@ -43,64 +46,72 @@ of valid Kerberos names::
+ When you authenticate yourself with Kerberos you get an initial
+ Kerberos **ticket**.  (A Kerberos ticket is an encrypted protocol
+ message that provides authentication.)  Kerberos uses this ticket for
+-network utilities such as rlogin and rcp.  The ticket transactions are
+-done transparently, so you don't have to worry about their management.
++network utilities such as ssh.  The ticket transactions are done
++transparently, so you don't have to worry about their management.
+ 
+-Note, however, that tickets expire.  Privileged tickets, such as those
+-with the instance ``root``, expire in a few minutes, while tickets
+-that carry more ordinary privileges may be good for several hours or a
+-day, depending on the installation's policy.  If your login session
+-extends beyond the time limit, you will have to re-authenticate
+-yourself to Kerberos to get new tickets.  Use the :ref:`kinit(1)`
+-command to re-authenticate yourself.
++Note, however, that tickets expire.  Administrators may configure more
++privileged tickets, such as those with service or instance of ``root``
++or ``admin``, to expire in a few minutes, while tickets that carry
++more ordinary privileges may be good for several hours or a day.  If
++your login session extends beyond the time limit, you will have to
++re-authenticate yourself to Kerberos to get new tickets using the
++:ref:`kinit(1)` command.
+ 
+-If you use the kinit command to get your tickets, make sure you use
+-the kdestroy command to destroy your tickets before you end your login
+-session.  You should put the kdestroy command in your ``.logout`` file
+-so that your tickets will be destroyed automatically when you logout.
+-For more information about the kinit and kdestroy commands, see the
+-:ref:`kinit(1)` and :ref:`kdestroy(1)` manual pages.
++Some tickets are **renewable** beyond their initial lifetime.  This
++means that ``kinit -R`` can extend their lifetime without requiring
++you to re-authenticate.
++
++If you wish to delete your local tickets, use the :ref:`kdestroy(1)`
++command.
+ 
+ Kerberos tickets can be forwarded.  In order to forward tickets, you
+ must request **forwardable** tickets when you kinit.  Once you have
+ forwardable tickets, most Kerberos programs have a command line option
+-to forward them to the remote host.
++to forward them to the remote host.  This can be useful for, e.g.,
++running kinit on your local machine and then sshing into another to do
++work.  Note that this should not be done on untrusted machines since
++they will then have your tickets.
+ 
+ ENVIRONMENT VARIABLES
+ ---------------------
+ 
+ Several environment variables affect the operation of Kerberos-enabled
+-programs.  These inclide:
++programs.  These include:
+ 
+ **KRB5CCNAME**
+-    Specifies the location of the credential cache, in the form
+-    *TYPE*:*residual*.  If no *type* prefix is present, the **FILE**
+-    type is assumed and *residual* is the pathname of the cache file.
+-    A collection of multiple caches may be used by specifying the
+-    **dir** type and the pathname of a private directory (which must
+-    already exist).  The default cache file is /tmp/krb5cc_*uid*,
+-    where *uid* is the decimal user ID of the user.
++    Default name for the credentials cache file, in the form
++    *TYPE*:*residual*.  The type of the default cache may determine
++    the availability of a cache collection.  ``FILE`` is not a
++    collection type; ``KEYRING``, ``DIR``, and ``KCM`` are.
++
++    If not set, the value of **default_ccache_name** from
++    configuration files (see **KRB5_CONFIG**) will be used.  If that
++    is also not set, the default *type* is ``FILE``, and the
++    *residual* is the path /tmp/krb5cc_*uid*, where *uid* is the
++    decimal user ID of the user.
+ 
+ **KRB5_KTNAME**
+-    Specifies the location of the keytab file, in the form
++    Specifies the location of the default keytab file, in the form
+     *TYPE*:*residual*.  If no *type* is present, the **FILE** type is
+-    assumed and *residual* is the pathname of the keytab file.  The
+-    default keytab file is ``/etc/krb5.keytab``.
++    assumed and *residual* is the pathname of the keytab file.  If
++    unset, |keytab| will be used.
+ 
+ **KRB5_CONFIG**
+     Specifies the location of the Kerberos configuration file.  The
+-    default is ``/etc/krb5.conf``.
++    default is |sysconfdir|\ ``/krb5.conf``.  Multiple filenames can
++    be specified, separated by a colon; all files which are present
++    will be read.
+ 
+ **KRB5_KDC_PROFILE**
+     Specifies the location of the KDC configuration file, which
+     contains additional configuration directives for the Key
+     Distribution Center daemon and associated programs.  The default
+-    is ``/usr/local/var/krb5kdc/kdc.conf``.
++    is |kdcdir|\ ``/kdc.conf``.
+ 
+ **KRB5RCACHETYPE**
+     Specifies the default type of replay cache to use for servers.
+-    Valid types include **dfl** for the normal file type and **none**
+-    for no replay cache.
++    Valid types include ``dfl`` for the normal file type and ``none``
++    for no replay cache.  The default is ``dfl``.
+ 
+ **KRB5RCACHEDIR**
+     Specifies the default directory for replay caches used by servers.
+@@ -110,7 +121,17 @@ programs.  These inclide:
+ **KRB5_TRACE**
+     Specifies a filename to write trace log output to.  Trace logs can
+     help illuminate decisions made internally by the Kerberos
+-    libraries.  The default is not to write trace log output anywhere.
++    libraries.  For example, ``env KRB5_TRACE=/dev/stderr kinit``
++    would send tracing information for :ref:`kinit(1)` to
++    ``/dev/stderr``.  The default is not to write trace log output
++    anywhere.
++
++**KRB5_CLIENT_KTNAME**
++    Default client keytab file name.  If unset, |ckeytab| will be
++    used).
++
++**KPROP_PORT**
++    :ref:`kprop(8)` port to use.  Defaults to 754.
+ 
+ Most environment variables are disabled for certain programs, such as
+ login system programs and setuid programs, which are designed to be
+@@ -133,6 +154,7 @@ AUTHORS
+ | Steve Miller, MIT Project Athena/Digital Equipment Corporation
+ | Clifford Neuman, MIT Project Athena
+ | Greg Hudson, MIT Kerberos Consortium
++| Robbie Harwood, Red Hat, Inc.
+ 
+ HISTORY
+ -------
+@@ -144,5 +166,5 @@ by the MIT Kerberos Consortium.
+ RESTRICTIONS
+ ------------
+ 
+-Copyright 1985, 1986, 1989-1996, 2002, 2011 Masachusetts Institute of
+-Technology
++Copyright 1985, 1986, 1989-1996, 2002, 2011, 2018 Masachusetts
++Institute of Technology
+diff --git a/src/man/kerberos.man b/src/man/kerberos.man
+index 7b2b5d932..026f4604a 100644
+--- a/src/man/kerberos.man
++++ b/src/man/kerberos.man
+@@ -34,12 +34,12 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+ .sp
+ The Kerberos system authenticates individual users in a network
+ environment.  After authenticating yourself to Kerberos, you can use
+-Kerberos\-enabled programs without having to present passwords.
++Kerberos\-enabled programs without having to present passwords or
++certificates to those programs.
+ .sp
+-If you enter your username and kinit(1) responds with this
+-message:
++If you receive the following response from kinit(1):
+ .sp
+-kinit(v5): Client not found in Kerberos database while getting initial
++kinit: Client not found in Kerberos database while getting initial
+ credentials
+ .sp
+ you haven\(aqt been registered as a Kerberos user.  See your system
+@@ -51,10 +51,13 @@ is the \fBinstance\fP, which in the case of a user is usually null.
+ Some users may have privileged instances, however, such as \fBroot\fP or
+ \fBadmin\fP\&.  In the case of a service, the instance is the fully
+ qualified name of the machine on which it runs; i.e. there can be an
+-rlogin service running on the machine ABC, which is different from the
+-rlogin service running on the machine XYZ.  The third part of a
+-Kerberos name is the \fBrealm\fP\&.  The realm corresponds to the Kerberos
+-service providing authentication for the principal.
++ssh service running on the machine ABC (\fI\%ssh/ABC@REALM\fP), which is
++different from the ssh service running on the machine XYZ
++(\fI\%ssh/XYZ@REALM\fP).  The third part of a Kerberos name is the \fBrealm\fP\&.
++The realm corresponds to the Kerberos service providing authentication
++for the principal.  Realms are conventionally all\-uppercase, and often
++match the end of hostnames in the realm (for instance, host01.example.com
++might be in realm EXAMPLE.COM).
+ .sp
+ When writing a Kerberos name, the principal name is separated from the
+ instance (if not null) by a slash, and the realm (if not the local
+@@ -77,63 +80,71 @@ cbrown/root@FUBAR.ORG
+ When you authenticate yourself with Kerberos you get an initial
+ Kerberos \fBticket\fP\&.  (A Kerberos ticket is an encrypted protocol
+ message that provides authentication.)  Kerberos uses this ticket for
+-network utilities such as rlogin and rcp.  The ticket transactions are
+-done transparently, so you don\(aqt have to worry about their management.
++network utilities such as ssh.  The ticket transactions are done
++transparently, so you don\(aqt have to worry about their management.
+ .sp
+-Note, however, that tickets expire.  Privileged tickets, such as those
+-with the instance \fBroot\fP, expire in a few minutes, while tickets
+-that carry more ordinary privileges may be good for several hours or a
+-day, depending on the installation\(aqs policy.  If your login session
+-extends beyond the time limit, you will have to re\-authenticate
+-yourself to Kerberos to get new tickets.  Use the kinit(1)
+-command to re\-authenticate yourself.
++Note, however, that tickets expire.  Administrators may configure more
++privileged tickets, such as those with service or instance of \fBroot\fP
++or \fBadmin\fP, to expire in a few minutes, while tickets that carry
++more ordinary privileges may be good for several hours or a day.  If
++your login session extends beyond the time limit, you will have to
++re\-authenticate yourself to Kerberos to get new tickets using the
++kinit(1) command.
+ .sp
+-If you use the kinit command to get your tickets, make sure you use
+-the kdestroy command to destroy your tickets before you end your login
+-session.  You should put the kdestroy command in your \fB\&.logout\fP file
+-so that your tickets will be destroyed automatically when you logout.
+-For more information about the kinit and kdestroy commands, see the
+-kinit(1) and kdestroy(1) manual pages.
++Some tickets are \fBrenewable\fP beyond their initial lifetime.  This
++means that \fBkinit \-R\fP can extend their lifetime without requiring
++you to re\-authenticate.
++.sp
++If you wish to delete your local tickets, use the kdestroy(1)
++command.
+ .sp
+ Kerberos tickets can be forwarded.  In order to forward tickets, you
+ must request \fBforwardable\fP tickets when you kinit.  Once you have
+ forwardable tickets, most Kerberos programs have a command line option
+-to forward them to the remote host.
++to forward them to the remote host.  This can be useful for, e.g.,
++running kinit on your local machine and then sshing into another to do
++work.  Note that this should not be done on untrusted machines since
++they will then have your tickets.
+ .SH ENVIRONMENT VARIABLES
+ .sp
+ Several environment variables affect the operation of Kerberos\-enabled
+-programs.  These inclide:
++programs.  These include:
+ .INDENT 0.0
+ .TP
+ \fBKRB5CCNAME\fP
+-Specifies the location of the credential cache, in the form
+-\fITYPE\fP:\fIresidual\fP\&.  If no \fItype\fP prefix is present, the \fBFILE\fP
+-type is assumed and \fIresidual\fP is the pathname of the cache file.
+-A collection of multiple caches may be used by specifying the
+-\fBdir\fP type and the pathname of a private directory (which must
+-already exist).  The default cache file is /tmp/krb5cc_*uid*,
+-where \fIuid\fP is the decimal user ID of the user.
++Default name for the credentials cache file, in the form
++\fITYPE\fP:\fIresidual\fP\&.  The type of the default cache may determine
++the availability of a cache collection.  \fBFILE\fP is not a
++collection type; \fBKEYRING\fP, \fBDIR\fP, and \fBKCM\fP are.
++.sp
++If not set, the value of \fBdefault_ccache_name\fP from
++configuration files (see \fBKRB5_CONFIG\fP) will be used.  If that
++is also not set, the default \fItype\fP is \fBFILE\fP, and the
++\fIresidual\fP is the path /tmp/krb5cc_*uid*, where \fIuid\fP is the
++decimal user ID of the user.
+ .TP
+ \fBKRB5_KTNAME\fP
+-Specifies the location of the keytab file, in the form
++Specifies the location of the default keytab file, in the form
+ \fITYPE\fP:\fIresidual\fP\&.  If no \fItype\fP is present, the \fBFILE\fP type is
+-assumed and \fIresidual\fP is the pathname of the keytab file.  The
+-default keytab file is \fB/etc/krb5.keytab\fP\&.
++assumed and \fIresidual\fP is the pathname of the keytab file.  If
++unset, \fB@KTNAME@\fP will be used.
+ .TP
+ \fBKRB5_CONFIG\fP
+ Specifies the location of the Kerberos configuration file.  The
+-default is \fB/etc/krb5.conf\fP\&.
++default is \fB@SYSCONFDIR@\fP\fB/krb5.conf\fP\&.  Multiple filenames can
++be specified, separated by a colon; all files which are present
++will be read.
+ .TP
+ \fBKRB5_KDC_PROFILE\fP
+ Specifies the location of the KDC configuration file, which
+ contains additional configuration directives for the Key
+ Distribution Center daemon and associated programs.  The default
+-is \fB/usr/local/var/krb5kdc/kdc.conf\fP\&.
++is \fB@LOCALSTATEDIR@\fP\fB/krb5kdc\fP\fB/kdc.conf\fP\&.
+ .TP
+ \fBKRB5RCACHETYPE\fP
+ Specifies the default type of replay cache to use for servers.
+ Valid types include \fBdfl\fP for the normal file type and \fBnone\fP
+-for no replay cache.
++for no replay cache.  The default is \fBdfl\fP\&.
+ .TP
+ \fBKRB5RCACHEDIR\fP
+ Specifies the default directory for replay caches used by servers.
+@@ -143,7 +154,17 @@ or \fB/var/tmp\fP if \fBTMPDIR\fP is not set.
+ \fBKRB5_TRACE\fP
+ Specifies a filename to write trace log output to.  Trace logs can
+ help illuminate decisions made internally by the Kerberos
+-libraries.  The default is not to write trace log output anywhere.
++libraries.  For example, \fBenv KRB5_TRACE=/dev/stderr kinit\fP
++would send tracing information for kinit(1) to
++\fB/dev/stderr\fP\&.  The default is not to write trace log output
++anywhere.
++.TP
++\fBKRB5_CLIENT_KTNAME\fP
++Default client keytab file name.  If unset, \fB@CKTNAME@\fP will be
++used).
++.TP
++\fBKPROP_PORT\fP
++kprop(8) port to use.  Defaults to 754.
+ .UNINDENT
+ .sp
+ Most environment variables are disabled for certain programs, such as
+@@ -161,6 +182,7 @@ kadmind(8), kdb5_util(8), krb5kdc(8)
+ Steve Miller, MIT Project Athena/Digital Equipment Corporation
+ Clifford Neuman, MIT Project Athena
+ Greg Hudson, MIT Kerberos Consortium
++Robbie Harwood, Red Hat, Inc.
+ .fi
+ .sp
+ .SH HISTORY
+@@ -170,8 +192,8 @@ contributions from many outside parties.  It is currently maintained
+ by the MIT Kerberos Consortium.
+ .SH RESTRICTIONS
+ .sp
+-Copyright 1985, 1986, 1989\-1996, 2002, 2011 Masachusetts Institute of
+-Technology
++Copyright 1985, 1986, 1989\-1996, 2002, 2011, 2018 Masachusetts
++Institute of Technology
+ .SH AUTHOR
+ MIT
+ .SH COPYRIGHT
diff --git a/SOURCES/Prefer-TCP-to-UDP-for-password-changes.patch b/SOURCES/Prefer-TCP-to-UDP-for-password-changes.patch
new file mode 100644
index 0000000..31e62d1
--- /dev/null
+++ b/SOURCES/Prefer-TCP-to-UDP-for-password-changes.patch
@@ -0,0 +1,168 @@
+From aa346834947ef65c293a29300b0f98b1825d8508 Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Mon, 8 Oct 2018 16:02:12 -0400
+Subject: [PATCH] Prefer TCP to UDP for password changes
+
+When password changes are performed over UDP, spotty networks may
+cause the client to retransmit.  This leads to replay errors if the
+kpasswd server receives both requests, which hide the actual request
+status and make it appear that the password has not been changed, when
+it may in fact have been.  Use TCP instead with UDP fallback to avoid
+this issue.
+
+ticket: 7905
+(cherry picked from commit d7b3018d338fc9c989c3fa17505870f23c3759a8)
+---
+ src/lib/krb5/os/changepw.c | 110 ++++++++++++++-----------------------
+ 1 file changed, 42 insertions(+), 68 deletions(-)
+
+diff --git a/src/lib/krb5/os/changepw.c b/src/lib/krb5/os/changepw.c
+index e4db57084..9f968da7f 100644
+--- a/src/lib/krb5/os/changepw.c
++++ b/src/lib/krb5/os/changepw.c
+@@ -59,13 +59,12 @@ struct sendto_callback_context {
+ 
+ static krb5_error_code
+ locate_kpasswd(krb5_context context, const krb5_data *realm,
+-               struct serverlist *serverlist, krb5_boolean no_udp)
++               struct serverlist *serverlist)
+ {
+     krb5_error_code code;
+ 
+     code = k5_locate_server(context, realm, serverlist, locate_service_kpasswd,
+-                            no_udp);
+-
++                            FALSE);
+     if (code == KRB5_REALM_CANT_RESOLVE || code == KRB5_REALM_UNKNOWN) {
+         code = k5_locate_server(context, realm, serverlist,
+                                 locate_service_kadmin, TRUE);
+@@ -76,7 +75,7 @@ locate_kpasswd(krb5_context context, const krb5_data *realm,
+             for (i = 0; i < serverlist->nservers; i++) {
+                 struct server_entry *s = &serverlist->servers[i];
+ 
+-                if (!no_udp && s->transport == TCP)
++                if (s->transport == TCP)
+                     s->transport = TCP_OR_UDP;
+                 if (s->hostname != NULL)
+                     s->port = DEFAULT_KPASSWD_PORT;
+@@ -214,7 +213,6 @@ change_set_password(krb5_context context,
+                     krb5_data *result_string)
+ {
+     krb5_data                   chpw_rep;
+-    krb5_boolean                no_udp = FALSE;
+     GETSOCKNAME_ARG3_TYPE       addrlen;
+     krb5_error_code             code = 0;
+     char                        *code_string;
+@@ -246,73 +244,49 @@ change_set_password(krb5_context context,
+     callback_ctx.remote_seq_num = callback_ctx.auth_context->remote_seq_number;
+     callback_ctx.local_seq_num = callback_ctx.auth_context->local_seq_number;
+ 
+-    do {
+-        k5_transport_strategy strategy = no_udp ? NO_UDP : UDP_FIRST;
++    code = locate_kpasswd(callback_ctx.context, &creds->server->realm, &sl);
++    if (code)
++        goto cleanup;
+ 
+-        code = locate_kpasswd(callback_ctx.context, &creds->server->realm, &sl,
+-                              no_udp);
++    addrlen = sizeof(remote_addr);
++
++    callback_info.data = &callback_ctx;
++    callback_info.pfn_callback = kpasswd_sendto_msg_callback;
++    callback_info.pfn_cleanup = kpasswd_sendto_msg_cleanup;
++    krb5_free_data_contents(callback_ctx.context, &chpw_rep);
++
++    code = k5_sendto(callback_ctx.context, NULL, &creds->server->realm,
++                     &sl, UDP_LAST, &callback_info, &chpw_rep,
++                     ss2sa(&remote_addr), &addrlen, NULL, NULL, NULL);
++    if (code)
++        goto cleanup;
++
++    code = krb5int_rd_chpw_rep(callback_ctx.context,
++                               callback_ctx.auth_context,
++                               &chpw_rep, &local_result_code,
++                               result_string);
++
++    if (code)
++        goto cleanup;
++
++    if (result_code)
++        *result_code = local_result_code;
++
++    if (result_code_string) {
++        code = krb5_chpw_result_code_string(callback_ctx.context,
++                                            local_result_code,
++                                            &code_string);
+         if (code)
+-            break;
++            goto cleanup;
+ 
+-        addrlen = sizeof(remote_addr);
+-
+-        callback_info.data = &callback_ctx;
+-        callback_info.pfn_callback = kpasswd_sendto_msg_callback;
+-        callback_info.pfn_cleanup = kpasswd_sendto_msg_cleanup;
+-        krb5_free_data_contents(callback_ctx.context, &chpw_rep);
+-
+-        code = k5_sendto(callback_ctx.context, NULL, &creds->server->realm,
+-                         &sl, strategy, &callback_info, &chpw_rep,
+-                         ss2sa(&remote_addr), &addrlen, NULL, NULL, NULL);
+-        if (code) {
+-            /*
+-             * Here we may want to switch to TCP on some errors.
+-             * right?
+-             */
+-            break;
++        result_code_string->length = strlen(code_string);
++        result_code_string->data = malloc(result_code_string->length);
++        if (result_code_string->data == NULL) {
++            code = ENOMEM;
++            goto cleanup;
+         }
+-
+-        code = krb5int_rd_chpw_rep(callback_ctx.context,
+-                                   callback_ctx.auth_context,
+-                                   &chpw_rep, &local_result_code,
+-                                   result_string);
+-
+-        if (code) {
+-            if (code == KRB5KRB_ERR_RESPONSE_TOO_BIG && !no_udp) {
+-                k5_free_serverlist(&sl);
+-                no_udp = 1;
+-                continue;
+-            }
+-
+-            break;
+-        }
+-
+-        if (result_code)
+-            *result_code = local_result_code;
+-
+-        if (result_code_string) {
+-            code = krb5_chpw_result_code_string(callback_ctx.context,
+-                                                local_result_code,
+-                                                &code_string);
+-            if (code)
+-                goto cleanup;
+-
+-            result_code_string->length = strlen(code_string);
+-            result_code_string->data = malloc(result_code_string->length);
+-            if (result_code_string->data == NULL) {
+-                code = ENOMEM;
+-                goto cleanup;
+-            }
+-            strncpy(result_code_string->data, code_string, result_code_string->length);
+-        }
+-
+-        if (code == KRB5KRB_ERR_RESPONSE_TOO_BIG && !no_udp) {
+-            k5_free_serverlist(&sl);
+-            no_udp = 1;
+-        } else {
+-            break;
+-        }
+-    } while (TRUE);
++        strncpy(result_code_string->data, code_string, result_code_string->length);
++    }
+ 
+ cleanup:
+     if (callback_ctx.auth_context != NULL)
diff --git a/SOURCES/Preserve-method-data-in-get_in_tkt.c.patch b/SOURCES/Preserve-method-data-in-get_in_tkt.c.patch
new file mode 100644
index 0000000..189845f
--- /dev/null
+++ b/SOURCES/Preserve-method-data-in-get_in_tkt.c.patch
@@ -0,0 +1,222 @@
+From 5b52d5b4b1e65699dac6a53f0b6dbe545af4f689 Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Fri, 13 Jan 2017 15:35:48 -0500
+Subject: [PATCH] Preserve method data in get_in_tkt.c
+
+To continue after preauth failures, we need a persistent field in
+krb5_init_creds_context containing the METHOD-DATA from a
+KDC_PREAUTH_REQUIRED or KDC_PREAUTH_FAILED error.  If we overwrite
+this field with the padata in a KDC_MORE_PREAUTH_DATA_REQUIRED error,
+or conflate it with an optimistic padata list, we won't be able to
+correctly continue after a preauth failure.
+
+In krb5_init_creds_context, split the preauth_to_use field into
+optimistic_padata, method_padata, and more_padata.  Separately handle
+KDC_ERR_MORE_PREAUTH_DATA_REQUIRED in init_creds_step_request() and
+init_creds_step_reply(), and separately handle optimistic preauth in
+init_creds_step_request().  Do not call k5_preauth() if none of the
+padata lists are set.
+
+Also stop clearing ctx->err_reply when processing a
+KDC_ERR_PREAUTH_REQUIRED response.  Instead look for that error code
+in init_creds_step_request().  Eliminate the preauth_required field of
+krb5_init_creds_context as it can be inferred from whether we are
+performing optimistic preauth.
+
+ticket: 8537
+(cherry picked from commit 97a9b0c4ef3fc7b20e6ae592201bcb132d58bbe5)
+---
+ src/include/k5-trace.h            | 11 +++++
+ src/lib/krb5/krb/get_in_tkt.c     | 71 +++++++++++++++++++++----------
+ src/lib/krb5/krb/init_creds_ctx.h |  5 ++-
+ 3 files changed, 62 insertions(+), 25 deletions(-)
+
+diff --git a/src/include/k5-trace.h b/src/include/k5-trace.h
+index 814da3195..e60ee0b75 100644
+--- a/src/include/k5-trace.h
++++ b/src/include/k5-trace.h
+@@ -213,8 +213,19 @@ void krb5int_trace(krb5_context context, const char *fmt, ...);
+     TRACE(c, "Looked up etypes in keytab: {etypes}", etypes)
+ #define TRACE_INIT_CREDS_KEYTAB_LOOKUP_FAILED(c, code)          \
+     TRACE(c, "Couldn't lookup etypes in keytab: {kerr}", code)
++#define TRACE_INIT_CREDS_PREAUTH(c)                     \
++    TRACE(c, "Preauthenticating using KDC method data")
+ #define TRACE_INIT_CREDS_PREAUTH_DECRYPT_FAIL(c, code)                  \
+     TRACE(c, "Decrypt with preauth AS key failed: {kerr}", code)
++#define TRACE_INIT_CREDS_PREAUTH_MORE(c, patype)                \
++    TRACE(c, "Continuing preauth mech {int}", (int)patype)
++#define TRACE_INIT_CREDS_PREAUTH_NONE(c)        \
++    TRACE(c, "Sending unauthenticated request")
++#define TRACE_INIT_CREDS_PREAUTH_OPTIMISTIC(c)  \
++    TRACE(c, "Attempting optimistic preauth")
++#define TRACE_INIT_CREDS_PREAUTH_TRYAGAIN(c, patype, code)              \
++    TRACE(c, "Recovering from KDC error {int} using preauth mech {int}", \
++          (int)patype, (int)code)
+ #define TRACE_INIT_CREDS_RESTART_FAST(c)        \
+     TRACE(c, "Restarting to upgrade to FAST")
+ #define TRACE_INIT_CREDS_RESTART_PREAUTH_FAILED(c)                      \
+diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
+index bc903b6e9..8c7919e65 100644
+--- a/src/lib/krb5/krb/get_in_tkt.c
++++ b/src/lib/krb5/krb/get_in_tkt.c
+@@ -575,7 +575,9 @@ krb5_init_creds_free(krb5_context context,
+     krb5_free_data(context, ctx->inner_request_body);
+     krb5_free_data(context, ctx->encoded_previous_request);
+     krb5int_fast_free_state(context, ctx->fast_state);
+-    krb5_free_pa_data(context, ctx->preauth_to_use);
++    krb5_free_pa_data(context, ctx->optimistic_padata);
++    krb5_free_pa_data(context, ctx->method_padata);
++    krb5_free_pa_data(context, ctx->more_padata);
+     krb5_free_data_contents(context, &ctx->salt);
+     krb5_free_data_contents(context, &ctx->s2kparams);
+     krb5_free_keyblock_contents(context, &ctx->as_key);
+@@ -827,10 +829,13 @@ restart_init_creds_loop(krb5_context context, krb5_init_creds_context ctx,
+ {
+     krb5_error_code code = 0;
+ 
+-    krb5_free_pa_data(context, ctx->preauth_to_use);
++    krb5_free_pa_data(context, ctx->optimistic_padata);
++    krb5_free_pa_data(context, ctx->method_padata);
++    krb5_free_pa_data(context, ctx->more_padata);
+     krb5_free_pa_data(context, ctx->err_padata);
+     krb5_free_error(context, ctx->err_reply);
+-    ctx->preauth_to_use = ctx->err_padata = NULL;
++    ctx->optimistic_padata = ctx->method_padata = ctx->more_padata = NULL;
++    ctx->err_padata = NULL;
+     ctx->err_reply = NULL;
+     ctx->selected_preauth_type = KRB5_PADATA_NONE;
+ 
+@@ -849,7 +854,7 @@ restart_init_creds_loop(krb5_context context, krb5_init_creds_context ctx,
+     if (ctx->opt->flags & KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST) {
+         code = make_preauth_list(context, ctx->opt->preauth_list,
+                                  ctx->opt->preauth_list_length,
+-                                 &ctx->preauth_to_use);
++                                 &ctx->optimistic_padata);
+         if (code)
+             goto cleanup;
+     }
+@@ -1301,6 +1306,7 @@ init_creds_step_request(krb5_context context,
+                         krb5_data *out)
+ {
+     krb5_error_code code;
++    krb5_preauthtype pa_type;
+ 
+     if (ctx->loopcount >= MAX_IN_TKT_LOOPS) {
+         code = KRB5_GET_IN_TKT_LOOP;
+@@ -1331,17 +1337,36 @@ init_creds_step_request(krb5_context context,
+     read_cc_config_in_data(context, ctx);
+     clear_cc_config_out_data(context, ctx);
+ 
+-    if (ctx->err_reply == NULL) {
+-        /* Either our first attempt, or retrying after KDC_ERR_PREAUTH_REQUIRED
+-         * or KDC_ERR_MORE_PREAUTH_DATA_REQUIRED. */
+-        code = k5_preauth(context, ctx, ctx->preauth_to_use,
+-                          ctx->preauth_required, &ctx->request->padata,
+-                          &ctx->selected_preauth_type);
++    ctx->request->padata = NULL;
++    if (ctx->optimistic_padata != NULL) {
++        /* Our first attempt, using an optimistic padata list. */
++        TRACE_INIT_CREDS_PREAUTH_OPTIMISTIC(context);
++        code = k5_preauth(context, ctx, ctx->optimistic_padata, FALSE,
++                          &ctx->request->padata, &ctx->selected_preauth_type);
++        krb5_free_pa_data(context, ctx->optimistic_padata);
++        ctx->optimistic_padata = NULL;
+         if (code != 0)
+             goto cleanup;
+-    } else {
+-        /* Retry after an error other than PREAUTH_NEEDED, using error padata
++    } if (ctx->more_padata != NULL) {
++        /* Continuing after KDC_ERR_MORE_PREAUTH_DATA_REQUIRED. */
++        TRACE_INIT_CREDS_PREAUTH_MORE(context, ctx->selected_preauth_type);
++        code = k5_preauth(context, ctx, ctx->more_padata, TRUE,
++                          &ctx->request->padata, &pa_type);
++        if (code != 0)
++            goto cleanup;
++    } else if (ctx->err_reply != NULL &&
++               ctx->err_reply->error == KDC_ERR_PREAUTH_REQUIRED) {
++        /* Continuing after KDC_ERR_PREAUTH_REQUIRED, using method data. */
++        TRACE_INIT_CREDS_PREAUTH(context);
++        code = k5_preauth(context, ctx, ctx->method_padata, TRUE,
++                          &ctx->request->padata, &ctx->selected_preauth_type);
++        if (code != 0)
++            goto cleanup;
++    } else if (ctx->err_reply != NULL) {
++        /* Retry after an error other than PREAUTH_REQUIRED, using error padata
+          * to figure out what to change. */
++        TRACE_INIT_CREDS_PREAUTH_TRYAGAIN(context, ctx->err_reply->error,
++                                          ctx->selected_preauth_type);
+         code = k5_preauth_tryagain(context, ctx, ctx->selected_preauth_type,
+                                    ctx->err_reply, ctx->err_padata,
+                                    &ctx->request->padata);
+@@ -1351,6 +1376,8 @@ init_creds_step_request(krb5_context context,
+             goto cleanup;
+         }
+     }
++    if (ctx->request->padata == NULL)
++        TRACE_INIT_CREDS_PREAUTH_NONE(context);
+ 
+     /* Remember when we sent this request (after any preauth delay). */
+     ctx->request_time = time(NULL);
+@@ -1467,8 +1494,9 @@ init_creds_step_reply(krb5_context context,
+         ctx->request->client->type == KRB5_NT_ENTERPRISE_PRINCIPAL;
+ 
+     if (ctx->err_reply != NULL) {
++        krb5_free_pa_data(context, ctx->more_padata);
+         krb5_free_pa_data(context, ctx->err_padata);
+-        ctx->err_padata = NULL;
++        ctx->more_padata = ctx->err_padata = NULL;
+         code = krb5int_fast_process_error(context, ctx->fast_state,
+                                           &ctx->err_reply, &ctx->err_padata,
+                                           &retry);
+@@ -1494,21 +1522,18 @@ init_creds_step_reply(krb5_context context,
+              * FAST upgrade. */
+             ctx->restarted = FALSE;
+             code = restart_init_creds_loop(context, ctx, FALSE);
+-        } else if ((reply_code == KDC_ERR_MORE_PREAUTH_DATA_REQUIRED ||
+-                    reply_code == KDC_ERR_PREAUTH_REQUIRED) && retry) {
+-            krb5_free_pa_data(context, ctx->preauth_to_use);
+-            ctx->preauth_to_use = ctx->err_padata;
++        } else if (reply_code == KDC_ERR_PREAUTH_REQUIRED && retry) {
++            krb5_free_pa_data(context, ctx->method_padata);
++            ctx->method_padata = ctx->err_padata;
+             ctx->err_padata = NULL;
+             note_req_timestamp(context, ctx, ctx->err_reply->stime,
+                                ctx->err_reply->susec);
+-            /* This will trigger a new call to k5_preauth(). */
+-            krb5_free_error(context, ctx->err_reply);
+-            ctx->err_reply = NULL;
+             code = sort_krb5_padata_sequence(context,
+                                              &ctx->request->client->realm,
+-                                             ctx->preauth_to_use);
+-            ctx->preauth_required = TRUE;
+-
++                                             ctx->method_padata);
++        } else if (reply_code == KDC_ERR_MORE_PREAUTH_DATA_REQUIRED && retry) {
++            ctx->more_padata = ctx->err_padata;
++            ctx->err_padata = NULL;
+         } else if (canon_flag && is_referral(context, ctx->err_reply,
+                                              ctx->request->client)) {
+             TRACE_INIT_CREDS_REFERRAL(context, &ctx->err_reply->client->realm);
+diff --git a/src/lib/krb5/krb/init_creds_ctx.h b/src/lib/krb5/krb/init_creds_ctx.h
+index 8c8b7494b..fe769685b 100644
+--- a/src/lib/krb5/krb/init_creds_ctx.h
++++ b/src/lib/krb5/krb/init_creds_ctx.h
+@@ -50,7 +50,9 @@ struct _krb5_init_creds_context {
+     krb5_data *inner_request_body; /**< For preauth */
+     krb5_data *encoded_previous_request;
+     struct krb5int_fast_request_state *fast_state;
+-    krb5_pa_data **preauth_to_use;
++    krb5_pa_data **optimistic_padata; /* from gic options */
++    krb5_pa_data **method_padata; /* from PREAUTH_REQUIRED or PREAUTH_FAILED */
++    krb5_pa_data **more_padata; /* from MORE_PREAUTH_DATA_REQUIRED */
+     krb5_boolean default_salt;
+     krb5_data salt;
+     krb5_data s2kparams;
+@@ -58,7 +60,6 @@ struct _krb5_init_creds_context {
+     krb5_enctype etype;
+     krb5_boolean enc_pa_rep_permitted;
+     krb5_boolean restarted;
+-    krb5_boolean preauth_required;
+     struct krb5_responder_context_st rctx;
+     krb5_preauthtype selected_preauth_type;
+     krb5_preauthtype allowed_preauth_type;
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..abc663e
--- /dev/null
+++ b/SOURCES/Prevent-KDC-unset-status-assertion-failures.patch
@@ -0,0 +1,109 @@
+From 3b9e328664c92d95e7e3ec3c14cb6c7cbac4c05d 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)
+---
+ 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/Process-profile-includedir-in-sorted-order.patch b/SOURCES/Process-profile-includedir-in-sorted-order.patch
new file mode 100644
index 0000000..577bfca
--- /dev/null
+++ b/SOURCES/Process-profile-includedir-in-sorted-order.patch
@@ -0,0 +1,115 @@
+From f1f6eabb88391b796ee0eec1bb5d207002696f3e Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Wed, 6 Jun 2018 17:58:41 -0400
+Subject: [PATCH] Process profile includedir in sorted order
+
+In the profile library, use k5_dir_filenames() so that files within an
+included directory are read in a predictable order (alphanumeric
+within the C locale).
+
+ticket: 8686
+(cherry picked from commit f574eda48740ad192f51e9a382a205e2ea0e60ad)
+(cherry picked from commit 5d868264bca1771aa16abbc8cc0aefb0e1750a73)
+---
+ doc/admin/conf_files/krb5_conf.rst |  4 ++-
+ src/util/profile/prof_parse.c      | 56 +++++-------------------------
+ 2 files changed, 12 insertions(+), 48 deletions(-)
+
+diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
+index 1d9bc9e34..a959e0e60 100644
+--- a/doc/admin/conf_files/krb5_conf.rst
++++ b/doc/admin/conf_files/krb5_conf.rst
+@@ -58,7 +58,9 @@ alphanumeric characters, dashes, or underscores.  Starting in release
+ 1.15, files with names ending in ".conf" are also included, unless the
+ name begins with ".".  Included profile files are syntactically
+ independent of their parents, so each included file must begin with a
+-section header.
++section header.  Starting in release 1.17, files are read in
++alphanumeric order; in previous releases, they may be read in any
++order.
+ 
+ The krb5.conf file can specify that configuration should be obtained
+ from a loadable module, rather than the file itself, using the
+diff --git a/src/util/profile/prof_parse.c b/src/util/profile/prof_parse.c
+index 1baceea9e..531e4a099 100644
+--- a/src/util/profile/prof_parse.c
++++ b/src/util/profile/prof_parse.c
+@@ -246,59 +246,22 @@ static int valid_name(const char *filename)
+  * Include files within dirname.  Only files with names ending in ".conf", or
+  * consisting entirely of alphanumeric characters, dashes, and underscores are
+  * included.  This restriction avoids including editor backup files, .rpmsave
+- * files, and the like.
++ * files, and the like.  Files are processed in alphanumeric order.
+  */
+ static errcode_t parse_include_dir(const char *dirname,
+                                    struct profile_node *root_section)
+ {
+-#ifdef _WIN32
+-    char *wildcard = NULL, *pathname;
+-    WIN32_FIND_DATA ffd;
+-    HANDLE handle;
+     errcode_t retval = 0;
++    char **fnames, *pathname;
++    int i;
+ 
+-    if (asprintf(&wildcard, "%s\\*", dirname) < 0)
+-        return ENOMEM;
+-
+-    handle = FindFirstFile(wildcard, &ffd);
+-    if (handle == INVALID_HANDLE_VALUE) {
+-        retval = PROF_FAIL_INCLUDE_DIR;
+-        goto cleanup;
+-    }
+-
+-    do {
+-        if (!valid_name(ffd.cFileName))
+-            continue;
+-        if (asprintf(&pathname, "%s\\%s", dirname, ffd.cFileName) < 0) {
+-            retval = ENOMEM;
+-            break;
+-        }
+-        retval = parse_include_file(pathname, root_section);
+-        free(pathname);
+-        if (retval)
+-            break;
+-    } while (FindNextFile(handle, &ffd) != 0);
+-
+-    FindClose(handle);
+-
+-cleanup:
+-    free(wildcard);
+-    return retval;
+-
+-#else /* not _WIN32 */
+-
+-    DIR     *dir;
+-    char    *pathname;
+-    errcode_t retval = 0;
+-    struct dirent *ent;
+-
+-    dir = opendir(dirname);
+-    if (dir == NULL)
++    if (k5_dir_filenames(dirname, &fnames) != 0)
+         return PROF_FAIL_INCLUDE_DIR;
+-    while ((ent = readdir(dir)) != NULL) {
+-        if (!valid_name(ent->d_name))
++
++    for (i = 0; fnames != NULL && fnames[i] != NULL; i++) {
++        if (!valid_name(fnames[i]))
+             continue;
+-        if (asprintf(&pathname, "%s/%s", dirname, ent->d_name) < 0) {
++        if (asprintf(&pathname, "%s/%s", dirname, fnames[i]) < 0) {
+             retval = ENOMEM;
+             break;
+         }
+@@ -307,9 +270,8 @@ cleanup:
+         if (retval)
+             break;
+     }
+-    closedir(dir);
++    k5_free_filenames(fnames);
+     return retval;
+-#endif /* not _WIN32 */
+ }
+ 
+ static errcode_t parse_line(char *line, struct parse_state *state,
diff --git a/SOURCES/Properly-scope-per-request-preauth-data.patch b/SOURCES/Properly-scope-per-request-preauth-data.patch
new file mode 100644
index 0000000..adc77ed
--- /dev/null
+++ b/SOURCES/Properly-scope-per-request-preauth-data.patch
@@ -0,0 +1,533 @@
+From b3472e687181719dec6561c96aca6036b34865a5 Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Tue, 20 Dec 2016 16:06:24 -0500
+Subject: [PATCH] Properly scope per-request preauth data
+
+It should be possible to successfully use multiple initial credentials
+contexts with the same library context.  Create a new internal type
+krb5_preauth_req_context containing per-request preauth state,
+including the clpreauth modreq handles and the list of preauth types
+already tried.  Remove this state from clpreauth_handle and
+krb5_preauth_context.
+
+ticket: 7877
+(cherry picked from commit b061f419cfc9653b7549b905e54fbbd78deea49e)
+---
+ src/include/k5-trace.h            |   3 +
+ src/lib/krb5/krb/get_in_tkt.c     |  12 +-
+ src/lib/krb5/krb/init_creds_ctx.h |   3 +
+ src/lib/krb5/krb/int-proto.h      |   8 +-
+ src/lib/krb5/krb/preauth2.c       | 190 +++++++++++++++++++-----------
+ 5 files changed, 135 insertions(+), 81 deletions(-)
+
+diff --git a/src/include/k5-trace.h b/src/include/k5-trace.h
+index 2885408a2..f44f162d3 100644
+--- a/src/include/k5-trace.h
++++ b/src/include/k5-trace.h
+@@ -291,6 +291,9 @@ void krb5int_trace(krb5_context context, const char *fmt, ...);
+     TRACE(c, "Preauth tryagain input types: {patypes}", padata)
+ #define TRACE_PREAUTH_TRYAGAIN_OUTPUT(c, padata)                        \
+     TRACE(c, "Followup preauth for next request: {patypes}", padata)
++#define TRACE_PREAUTH_WRONG_CONTEXT(c)                                  \
++    TRACE(c, "Wrong context passed to krb5_init_creds_free(); leaking " \
++          "modreq objects")
+ 
+ #define TRACE_PROFILE_ERR(c,subsection, section, retval)             \
+     TRACE(c, "Bad value of {str} from [{str}] in conf file: {kerr}", \
+diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
+index ed15550f0..80f5e1870 100644
+--- a/src/lib/krb5/krb/get_in_tkt.c
++++ b/src/lib/krb5/krb/get_in_tkt.c
+@@ -565,7 +565,7 @@ krb5_init_creds_free(krb5_context context,
+     k5_response_items_free(ctx->rctx.items);
+     free(ctx->in_tkt_service);
+     zapfree(ctx->gakpw.storage.data, ctx->gakpw.storage.length);
+-    k5_preauth_request_context_fini(context);
++    k5_preauth_request_context_fini(context, ctx);
+     krb5_free_error(context, ctx->err_reply);
+     krb5_free_pa_data(context, ctx->err_padata);
+     krb5_free_cred_contents(context, &ctx->cred);
+@@ -816,8 +816,8 @@ restart_init_creds_loop(krb5_context context, krb5_init_creds_context ctx,
+     if (fast_upgrade)
+         ctx->fast_state->fast_state_flags |= KRB5INT_FAST_DO_FAST;
+ 
+-    k5_preauth_request_context_fini(context);
+-    k5_preauth_request_context_init(context);
++    k5_preauth_request_context_fini(context, ctx);
++    k5_preauth_request_context_init(context, ctx);
+     krb5_free_data(context, ctx->outer_request_body);
+     ctx->outer_request_body = NULL;
+     if (ctx->opt->flags & KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST) {
+@@ -1504,7 +1504,7 @@ init_creds_step_reply(krb5_context context,
+         } else if ((reply_code == KDC_ERR_MORE_PREAUTH_DATA_REQUIRED ||
+                     reply_code == KDC_ERR_PREAUTH_REQUIRED) && retry) {
+             /* reset the list of preauth types to try */
+-            k5_reset_preauth_types_tried(context);
++            k5_reset_preauth_types_tried(ctx);
+             krb5_free_pa_data(context, ctx->preauth_to_use);
+             ctx->preauth_to_use = ctx->err_padata;
+             ctx->err_padata = NULL;
+@@ -1555,7 +1555,7 @@ init_creds_step_reply(krb5_context context,
+         goto cleanup;
+ 
+     /* process any preauth data in the as_reply */
+-    k5_reset_preauth_types_tried(context);
++    k5_reset_preauth_types_tried(ctx);
+     code = krb5int_fast_process_response(context, ctx->fast_state,
+                                          ctx->reply, &strengthen_key);
+     if (code != 0)
+@@ -1640,7 +1640,7 @@ init_creds_step_reply(krb5_context context,
+             k5_prependmsg(context, code, _("Failed to store credentials"));
+     }
+ 
+-    k5_preauth_request_context_fini(context);
++    k5_preauth_request_context_fini(context, ctx);
+ 
+     /* success */
+     ctx->complete = TRUE;
+diff --git a/src/lib/krb5/krb/init_creds_ctx.h b/src/lib/krb5/krb/init_creds_ctx.h
+index 38c01c775..a7cded942 100644
+--- a/src/lib/krb5/krb/init_creds_ctx.h
++++ b/src/lib/krb5/krb/init_creds_ctx.h
+@@ -6,6 +6,8 @@
+ #include "k5-json.h"
+ #include "int-proto.h"
+ 
++typedef struct krb5_preauth_req_context_st *krb5_preauth_req_context;
++
+ struct krb5_responder_context_st {
+     k5_response_items *items;
+ };
+@@ -67,6 +69,7 @@ struct _krb5_init_creds_context {
+     krb5_timestamp pa_offset;
+     krb5_int32 pa_offset_usec;
+     enum { NO_OFFSET = 0, UNAUTH_OFFSET, AUTH_OFFSET } pa_offset_state;
++    krb5_preauth_req_context preauth_reqctx;
+ };
+ 
+ krb5_error_code
+diff --git a/src/lib/krb5/krb/int-proto.h b/src/lib/krb5/krb/int-proto.h
+index 9c746d05b..f1667c238 100644
+--- a/src/lib/krb5/krb/int-proto.h
++++ b/src/lib/krb5/krb/int-proto.h
+@@ -194,17 +194,19 @@ void
+ k5_free_preauth_context(krb5_context context);
+ 
+ void
+-k5_reset_preauth_types_tried(krb5_context context);
++k5_reset_preauth_types_tried(krb5_init_creds_context ctx);
+ 
+ void
+ k5_preauth_prepare_request(krb5_context context, krb5_get_init_creds_opt *opt,
+                            krb5_kdc_req *request);
+ 
+ void
+-k5_preauth_request_context_init(krb5_context context);
++k5_preauth_request_context_init(krb5_context context,
++                                krb5_init_creds_context ctx);
+ 
+ void
+-k5_preauth_request_context_fini(krb5_context context);
++k5_preauth_request_context_fini(krb5_context context,
++                                krb5_init_creds_context ctx);
+ 
+ krb5_error_code
+ k5_response_items_new(k5_response_items **ri_out);
+diff --git a/src/lib/krb5/krb/preauth2.c b/src/lib/krb5/krb/preauth2.c
+index b04d14829..9a178f4e3 100644
+--- a/src/lib/krb5/krb/preauth2.c
++++ b/src/lib/krb5/krb/preauth2.c
+@@ -46,14 +46,18 @@
+ typedef struct {
+     struct krb5_clpreauth_vtable_st vt;
+     krb5_clpreauth_moddata data;
+-    krb5_clpreauth_modreq req;
+ } *clpreauth_handle;
+ 
+ struct krb5_preauth_context_st {
+-    krb5_preauthtype *tried;
+     clpreauth_handle *handles;
+ };
+ 
++struct krb5_preauth_req_context_st {
++    krb5_context orig_context;
++    krb5_preauthtype *tried;
++    krb5_clpreauth_modreq *modreqs;
++};
++
+ /* Release the memory used by a list of handles. */
+ static void
+ free_handles(krb5_context context, clpreauth_handle *handles)
+@@ -71,21 +75,44 @@ free_handles(krb5_context context, clpreauth_handle *handles)
+     free(handles);
+ }
+ 
+-/* Find the handle in handles which can process pa_type. */
+-static clpreauth_handle
+-find_module(clpreauth_handle *handles, krb5_preauthtype pa_type)
++/* Return an index into handles which can process pa_type, or -1 if none is
++ * found found. */
++static int
++search_module_list(clpreauth_handle *handles, krb5_preauthtype pa_type)
+ {
+-    clpreauth_handle *hp, h;
+-    krb5_preauthtype *tp;
++    clpreauth_handle h;
++    int i, j;
+ 
+-    for (hp = handles; *hp != NULL; hp++) {
+-        h = *hp;
+-        for (tp = h->vt.pa_type_list; *tp != 0; tp++) {
+-            if (*tp == pa_type)
+-                return h;
++    for (i = 0; handles[i] != NULL; i++) {
++        h = handles[i];
++        for (j = 0; h->vt.pa_type_list[j] != 0; j++) {
++            if (h->vt.pa_type_list[j] == pa_type)
++                return i;
+         }
+     }
+-    return FALSE;
++    return -1;
++}
++
++/* Find the handle which can process pa_type, or NULL if none is found.  On
++ * success, set *modreq_out to the corresponding per-request module data. */
++static clpreauth_handle
++find_module(krb5_context context, krb5_init_creds_context ctx,
++            krb5_preauthtype pa_type, krb5_clpreauth_modreq *modreq_out)
++{
++    krb5_preauth_context pctx = context->preauth_context;
++    krb5_preauth_req_context reqctx = ctx->preauth_reqctx;
++    int i;
++
++    *modreq_out = NULL;
++    if (pctx == NULL || reqctx == NULL)
++        return NULL;
++
++    i = search_module_list(pctx->handles, pa_type);
++    if (i == -1)
++        return NULL;
++
++    *modreq_out = reqctx->modreqs[i];
++    return pctx->handles[i];
+ }
+ 
+ /* Initialize the preauth state for a krb5 context. */
+@@ -93,7 +120,8 @@ void
+ k5_init_preauth_context(krb5_context context)
+ {
+     krb5_plugin_initvt_fn *modules = NULL, *mod;
+-    clpreauth_handle *list = NULL, h, h2;
++    clpreauth_handle *list = NULL, h;
++    int i;
+     size_t count;
+     krb5_preauthtype *tp;
+ 
+@@ -140,9 +168,10 @@ k5_init_preauth_context(krb5_context context)
+ 
+         /* Check for a preauth type conflict with an existing module. */
+         for (tp = h->vt.pa_type_list; *tp != 0; tp++) {
+-            h2 = find_module(list, *tp);
+-            if (h2 != NULL) {
+-                TRACE_PREAUTH_CONFLICT(context, h->vt.name, h2->vt.name, *tp);
++            i = search_module_list(list, *tp);
++            if (i != -1) {
++                TRACE_PREAUTH_CONFLICT(context, h->vt.name, list[i]->vt.name,
++                                       *tp);
+                 break;
+             }
+         }
+@@ -164,7 +193,6 @@ k5_init_preauth_context(krb5_context context)
+     context->preauth_context = malloc(sizeof(*context->preauth_context));
+     if (context->preauth_context == NULL)
+         goto cleanup;
+-    context->preauth_context->tried = NULL;
+     context->preauth_context->handles = list;
+     list = NULL;
+ 
+@@ -179,14 +207,14 @@ cleanup:
+  * AS-REP).
+  */
+ void
+-k5_reset_preauth_types_tried(krb5_context context)
++k5_reset_preauth_types_tried(krb5_init_creds_context ctx)
+ {
+-    krb5_preauth_context pctx = context->preauth_context;
++    krb5_preauth_req_context reqctx = ctx->preauth_reqctx;
+ 
+-    if (pctx == NULL)
++    if (reqctx == NULL)
+         return;
+-    free(pctx->tried);
+-    pctx->tried = NULL;
++    free(reqctx->tried);
++    reqctx->tried = NULL;
+ }
+ 
+ 
+@@ -200,7 +228,6 @@ k5_free_preauth_context(krb5_context context)
+ 
+     if (pctx == NULL)
+         return;
+-    free(pctx->tried);
+     free_handles(context, pctx->handles);
+     free(pctx);
+     context->preauth_context = NULL;
+@@ -209,10 +236,13 @@ k5_free_preauth_context(krb5_context context)
+ /* Initialize the per-AS-REQ context. This means calling the client_req_init
+  * function to give the plugin a chance to allocate a per-request context. */
+ void
+-k5_preauth_request_context_init(krb5_context context)
++k5_preauth_request_context_init(krb5_context context,
++                                krb5_init_creds_context ctx)
+ {
+     krb5_preauth_context pctx = context->preauth_context;
+-    clpreauth_handle *hp, h;
++    clpreauth_handle h;
++    krb5_preauth_req_context reqctx;
++    size_t count, i;
+ 
+     if (pctx == NULL) {
+         k5_init_preauth_context(context);
+@@ -220,30 +250,50 @@ k5_preauth_request_context_init(krb5_context context)
+         if (pctx == NULL)
+             return;
+     }
+-    k5_reset_preauth_types_tried(context);
+-    for (hp = pctx->handles; *hp != NULL; hp++) {
+-        h = *hp;
++
++    reqctx = calloc(1, sizeof(*reqctx));
++    if (reqctx == NULL)
++        return;
++    reqctx->orig_context = context;
++
++    /* Create an array of per-request module data objects corresponding to the
++     * preauth context's array of handles. */
++    for (count = 0; pctx->handles[count] != NULL; count++);
++    reqctx->modreqs = calloc(count, sizeof(*reqctx->modreqs));
++    for (i = 0; i < count; i++) {
++        h = pctx->handles[i];
+         if (h->vt.request_init != NULL)
+-            h->vt.request_init(context, h->data, &h->req);
++            h->vt.request_init(context, h->data, &reqctx->modreqs[i]);
+     }
++    ctx->preauth_reqctx = reqctx;
+ }
+ 
+ /* Free the per-AS-REQ context. This means clearing any request-specific
+  * context which the plugin may have created. */
+ void
+-k5_preauth_request_context_fini(krb5_context context)
++k5_preauth_request_context_fini(krb5_context context,
++                                krb5_init_creds_context ctx)
+ {
+     krb5_preauth_context pctx = context->preauth_context;
+-    clpreauth_handle *hp, h;
++    krb5_preauth_req_context reqctx = ctx->preauth_reqctx;
++    size_t i;
++    clpreauth_handle h;
+ 
+-    if (pctx == NULL)
++    if (reqctx == NULL)
+         return;
+-    for (hp = pctx->handles; *hp != NULL; hp++) {
+-        h = *hp;
+-        if (h->req != NULL && h->vt.request_fini != NULL)
+-            h->vt.request_fini(context, h->data, h->req);
+-        h->req = NULL;
++    if (reqctx->orig_context == context && pctx != NULL) {
++        for (i = 0; pctx->handles[i] != NULL; i++) {
++            h = pctx->handles[i];
++            if (reqctx->modreqs[i] != NULL && h->vt.request_fini != NULL)
++                h->vt.request_fini(context, h->data, reqctx->modreqs[i]);
++        }
++    } else {
++        TRACE_PREAUTH_WRONG_CONTEXT(context);
+     }
++    free(reqctx->modreqs);
++    free(reqctx->tried);
++    free(reqctx);
++    ctx->preauth_reqctx = NULL;
+ }
+ 
+ /* Return 1 if pa_type is a real preauthentication mechanism according to the
+@@ -259,6 +309,7 @@ clpreauth_is_real(krb5_context context, clpreauth_handle h,
+ 
+ static krb5_error_code
+ clpreauth_prep_questions(krb5_context context, clpreauth_handle h,
++                         krb5_clpreauth_modreq modreq,
+                          krb5_get_init_creds_opt *opt,
+                          krb5_clpreauth_callbacks cb, krb5_clpreauth_rock rock,
+                          krb5_kdc_req *req, krb5_data *req_body,
+@@ -266,35 +317,35 @@ clpreauth_prep_questions(krb5_context context, clpreauth_handle h,
+ {
+     if (h->vt.prep_questions == NULL)
+         return 0;
+-    return h->vt.prep_questions(context, h->data, h->req, opt, cb, rock, req,
++    return h->vt.prep_questions(context, h->data, modreq, opt, cb, rock, req,
+                                 req_body, prev_req, pa_data);
+ }
+ 
+ static krb5_error_code
+ clpreauth_process(krb5_context context, clpreauth_handle h,
+-                  krb5_get_init_creds_opt *opt, krb5_clpreauth_callbacks cb,
+-                  krb5_clpreauth_rock rock, krb5_kdc_req *req,
+-                  krb5_data *req_body, krb5_data *prev_req,
++                  krb5_clpreauth_modreq modreq, krb5_get_init_creds_opt *opt,
++                  krb5_clpreauth_callbacks cb, krb5_clpreauth_rock rock,
++                  krb5_kdc_req *req, krb5_data *req_body, krb5_data *prev_req,
+                   krb5_pa_data *pa_data, krb5_prompter_fct prompter,
+                   void *prompter_data, krb5_pa_data ***pa_data_out)
+ {
+-    return h->vt.process(context, h->data, h->req, opt, cb, rock, req,
++    return h->vt.process(context, h->data, modreq, opt, cb, rock, req,
+                          req_body, prev_req, pa_data, prompter, prompter_data,
+                          pa_data_out);
+ }
+ 
+ static krb5_error_code
+ clpreauth_tryagain(krb5_context context, clpreauth_handle h,
+-                   krb5_get_init_creds_opt *opt, krb5_clpreauth_callbacks cb,
+-                   krb5_clpreauth_rock rock, krb5_kdc_req *req,
+-                   krb5_data *req_body, krb5_data *prev_req,
++                   krb5_clpreauth_modreq modreq, krb5_get_init_creds_opt *opt,
++                   krb5_clpreauth_callbacks cb, krb5_clpreauth_rock rock,
++                   krb5_kdc_req *req, krb5_data *req_body, krb5_data *prev_req,
+                    krb5_preauthtype pa_type, krb5_error *error,
+                    krb5_pa_data **error_padata, krb5_prompter_fct prompter,
+                    void *prompter_data, krb5_pa_data ***pa_data_out)
+ {
+     if (h->vt.tryagain == NULL)
+         return 0;
+-    return h->vt.tryagain(context, h->data, h->req, opt, cb, rock, req,
++    return h->vt.tryagain(context, h->data, modreq, opt, cb, rock, req,
+                           req_body, prev_req, pa_type, error, error_padata,
+                           prompter, prompter_data, pa_data_out);
+ }
+@@ -554,22 +605,22 @@ pa_type_allowed(krb5_init_creds_context ctx, krb5_preauthtype pa_type)
+  * types and return false.
+  */
+ static krb5_boolean
+-already_tried(krb5_context context, krb5_preauthtype pa_type)
++already_tried(krb5_init_creds_context ctx, krb5_preauthtype pa_type)
+ {
+-    krb5_preauth_context pctx = context->preauth_context;
+-    size_t count;
++    krb5_preauth_req_context reqctx = ctx->preauth_reqctx;
++    size_t i;
+     krb5_preauthtype *newptr;
+ 
+-    for (count = 0; pctx->tried != NULL && pctx->tried[count] != 0; count++) {
+-        if (pctx->tried[count] == pa_type)
++    for (i = 0; reqctx->tried != NULL && reqctx->tried[i] != 0; i++) {
++        if (reqctx->tried[i] == pa_type)
+             return TRUE;
+     }
+-    newptr = realloc(pctx->tried, (count + 2) * sizeof(*newptr));
++    newptr = realloc(reqctx->tried, (i + 2) * sizeof(*newptr));
+     if (newptr == NULL)
+         return FALSE;
+-    pctx->tried = newptr;
+-    pctx->tried[count] = pa_type;
+-    pctx->tried[count + 1] = ENCTYPE_NULL;
++    reqctx->tried = newptr;
++    reqctx->tried[i] = pa_type;
++    reqctx->tried[i + 1] = ENCTYPE_NULL;
+     return FALSE;
+ }
+ 
+@@ -580,16 +631,13 @@ process_pa_data(krb5_context context, krb5_init_creds_context ctx,
+                 krb5_pa_data ***out_pa_list, int *out_pa_list_size,
+                 krb5_preauthtype *out_type)
+ {
+-    krb5_preauth_context pctx = context->preauth_context;
+     struct errinfo save = EMPTY_ERRINFO;
+     krb5_pa_data *pa, **pa_ptr, **mod_pa;
+     krb5_error_code ret = 0;
++    krb5_clpreauth_modreq modreq;
+     clpreauth_handle h;
+     int real, i;
+ 
+-    if (pctx == NULL)
+-        return ENOENT;
+-
+     /* Process all informational padata types, then the first real preauth type
+      * we succeed on. */
+     for (real = 0; real <= 1; real++) {
+@@ -598,17 +646,17 @@ process_pa_data(krb5_context context, krb5_init_creds_context ctx,
+             /* Restrict real mechanisms to the chosen one if we have one. */
+             if (real && !pa_type_allowed(ctx, pa->pa_type))
+                 continue;
+-            h = find_module(pctx->handles, pa->pa_type);
++            h = find_module(context, ctx, pa->pa_type, &modreq);
+             if (h == NULL)
+                 continue;
+             /* Make sure this type is for the current pass. */
+             if (clpreauth_is_real(context, h, pa->pa_type) != real)
+                 continue;
+             /* Only try a real mechanism once per authentication. */
+-            if (real && already_tried(context, pa->pa_type))
++            if (real && already_tried(ctx, pa->pa_type))
+                 continue;
+             mod_pa = NULL;
+-            ret = clpreauth_process(context, h, ctx->opt, &callbacks,
++            ret = clpreauth_process(context, h, modreq, ctx->opt, &callbacks,
+                                     (krb5_clpreauth_rock)ctx, ctx->request,
+                                     ctx->inner_request_body,
+                                     ctx->encoded_previous_request, pa,
+@@ -858,24 +906,22 @@ krb5_error_code
+ k5_preauth_tryagain(krb5_context context, krb5_init_creds_context ctx,
+                     krb5_pa_data **in_padata, krb5_pa_data ***padata_out)
+ {
+-    krb5_preauth_context pctx = context->preauth_context;
+     krb5_error_code ret;
+     krb5_pa_data **mod_pa;
++    krb5_clpreauth_modreq modreq;
+     clpreauth_handle h;
+     int i;
+ 
+     *padata_out = NULL;
+-    if (pctx == NULL)
+-        return KRB5KRB_ERR_GENERIC;
+ 
+     TRACE_PREAUTH_TRYAGAIN_INPUT(context, in_padata);
+ 
+     for (i = 0; in_padata[i] != NULL; i++) {
+-        h = find_module(pctx->handles, in_padata[i]->pa_type);
++        h = find_module(context, ctx, in_padata[i]->pa_type, &modreq);
+         if (h == NULL)
+             continue;
+         mod_pa = NULL;
+-        ret = clpreauth_tryagain(context, h, ctx->opt, &callbacks,
++        ret = clpreauth_tryagain(context, h, modreq, ctx->opt, &callbacks,
+                                  (krb5_clpreauth_rock)ctx, ctx->request,
+                                  ctx->inner_request_body,
+                                  ctx->encoded_previous_request,
+@@ -897,9 +943,9 @@ static krb5_error_code
+ fill_response_items(krb5_context context, krb5_init_creds_context ctx,
+                     krb5_pa_data **in_padata)
+ {
+-    krb5_preauth_context pctx = context->preauth_context;
+     krb5_error_code ret;
+     krb5_pa_data *pa;
++    krb5_clpreauth_modreq modreq;
+     clpreauth_handle h;
+     int i;
+ 
+@@ -908,11 +954,11 @@ fill_response_items(krb5_context context, krb5_init_creds_context ctx,
+         pa = in_padata[i];
+         if (!pa_type_allowed(ctx, pa->pa_type))
+             continue;
+-        h = find_module(pctx->handles, pa->pa_type);
++        h = find_module(context, ctx, pa->pa_type, &modreq);
+         if (h == NULL)
+             continue;
+-        ret = clpreauth_prep_questions(context, h, ctx->opt, &callbacks,
+-                                       (krb5_clpreauth_rock)ctx,
++        ret = clpreauth_prep_questions(context, h, modreq, ctx->opt,
++                                       &callbacks, (krb5_clpreauth_rock)ctx,
+                                        ctx->request, ctx->inner_request_body,
+                                        ctx->encoded_previous_request, pa);
+         if (ret)
diff --git a/SOURCES/Remove-incomplete-PKINIT-OCSP-support.patch b/SOURCES/Remove-incomplete-PKINIT-OCSP-support.patch
new file mode 100644
index 0000000..17bb5e5
--- /dev/null
+++ b/SOURCES/Remove-incomplete-PKINIT-OCSP-support.patch
@@ -0,0 +1,134 @@
+From 771f85f6d84f1cce95c5246b700bd950295d8fb3 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)
+---
+ 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/Remove-incorrect-KDC-assertion.patch b/SOURCES/Remove-incorrect-KDC-assertion.patch
new file mode 100644
index 0000000..f4f84c8
--- /dev/null
+++ b/SOURCES/Remove-incorrect-KDC-assertion.patch
@@ -0,0 +1,60 @@
+From ba85fb83677b6e46cf35e090fbb58129adbc048b Mon Sep 17 00:00:00 2001
+From: Isaac Boukris <iboukris@gmail.com>
+Date: Sat, 15 Dec 2018 11:56:36 +0200
+Subject: [PATCH] Remove incorrect KDC assertion
+
+The assertion in return_enc_padata() is reachable because
+kdc_make_s4u2self_rep() may have previously added encrypted padata.
+It is no longer necessary because the code uses add_pa_data_element()
+instead of allocating a new list.
+
+CVE-2018-20217:
+
+In MIT krb5 1.8 or later, an authenticated user who can obtain a TGT
+using an older encryption type (DES, DES3, or RC4) can cause an
+assertion failure in the KDC by sending an S4U2Self request.
+
+[ghudson@mit.edu: rewrote commit message with CVE description]
+
+(cherry picked from commit 94e5eda5bb94d1d44733a49c3d9b6d1e42c74def)
+
+ticket: 8767
+version_fixed: 1.16.3
+
+(cherry picked from commit 56870f9456da78d77a667dfc03a6d90f948dc3a5)
+(cherry picked from commit 2a96564f6fd53f2e1e8424d865c02349bfe5b818)
+---
+ src/kdc/kdc_preauth.c     | 1 -
+ src/tests/gssapi/t_s4u.py | 7 +++++++
+ 2 files changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c
+index 81d0b8cff..787a09684 100644
+--- a/src/kdc/kdc_preauth.c
++++ b/src/kdc/kdc_preauth.c
+@@ -1640,7 +1640,6 @@ return_enc_padata(krb5_context context, krb5_data *req_pkt,
+     krb5_error_code code = 0;
+     /* This should be initialized and only used for Win2K compat and other
+      * specific standardized uses such as FAST negotiation. */
+-    assert(reply_encpart->enc_padata == NULL);
+     if (is_referral) {
+         code = return_referral_enc_padata(context, reply_encpart, server);
+         if (code)
+diff --git a/src/tests/gssapi/t_s4u.py b/src/tests/gssapi/t_s4u.py
+index 7366e3915..9f8591f6c 100755
+--- a/src/tests/gssapi/t_s4u.py
++++ b/src/tests/gssapi/t_s4u.py
+@@ -144,6 +144,13 @@ if 'auth1: user@' not in out or 'auth2: user@' not in out:
+ 
+ realm.stop()
+ 
++for realm in multipass_realms(create_host=False, get_creds=False):
++    service1 = 'service/1@%s' % realm.realm
++    realm.addprinc(service1)
++    realm.extract_keytab(service1, realm.keytab)
++    realm.kinit(service1, None, ['-k'])
++    realm.run(['./t_s4u', 'p:user', '-'])
++
+ # Exercise cross-realm S4U2Self.  The query in the foreign realm will
+ # fail, but we can check that the right server principal was used.
+ r1, r2 = cross_realms(2, create_user=False)
diff --git a/SOURCES/Remove-nodes-option-from-make-certs-scripts.patch b/SOURCES/Remove-nodes-option-from-make-certs-scripts.patch
new file mode 100644
index 0000000..572f91e
--- /dev/null
+++ b/SOURCES/Remove-nodes-option-from-make-certs-scripts.patch
@@ -0,0 +1,46 @@
+From db667872d9a4103ffc30d4bd570a378a184d7c7f Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Thu, 3 May 2018 14:40:45 -0400
+Subject: [PATCH] Remove "-nodes" option from make-certs scripts
+
+The openssl command does not recognize options after positional
+arguments, so in "openssl genrsa $KEYSIZE -nodes", the "-nodes" was
+ignored as a excess positional argument prior to OpenSSL 1.1.0h, and
+now causes an error.  "-nodes" is an option to the openssl req and
+pkcs12 subcommands, but genrsa creates unencrypted keys by default.
+
+[ghudson@mit.edu: edited commit message]
+
+(cherry picked from commit 928a36aae326d496c9a73f2cd41b4da45eef577c)
+(cherry picked from commit 83da5675551dba13fee837adc26ce885a061dbc1)
+---
+ src/tests/dejagnu/pkinit-certs/make-certs.sh | 2 +-
+ src/tests/dejagnu/proxy-certs/make-certs.sh  | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/tests/dejagnu/pkinit-certs/make-certs.sh b/src/tests/dejagnu/pkinit-certs/make-certs.sh
+index 23426af8a..fa937f449 100755
+--- a/src/tests/dejagnu/pkinit-certs/make-certs.sh
++++ b/src/tests/dejagnu/pkinit-certs/make-certs.sh
+@@ -114,7 +114,7 @@ extendedKeyUsage = $CLIENT_EKU_LIST
+ EOF
+ 
+ # Generate a private key.
+-openssl genrsa $KEYSIZE -nodes > privkey.pem
++openssl genrsa $KEYSIZE > privkey.pem
+ openssl rsa -in privkey.pem -out privkey-enc.pem -des3 -passout pass:encrypted
+ 
+ # Generate a "CA" certificate.
+diff --git a/src/tests/dejagnu/proxy-certs/make-certs.sh b/src/tests/dejagnu/proxy-certs/make-certs.sh
+index 1191bf05e..24ef91bde 100755
+--- a/src/tests/dejagnu/proxy-certs/make-certs.sh
++++ b/src/tests/dejagnu/proxy-certs/make-certs.sh
+@@ -79,7 +79,7 @@ extendedKeyUsage = $PROXY_EKU_LIST
+ EOF
+ 
+ # Generate a private key.
+-openssl genrsa $KEYSIZE -nodes > privkey.pem
++openssl genrsa $KEYSIZE > privkey.pem
+ 
+ # Generate a "CA" certificate.
+ SUBJECT=signer openssl req -config openssl.cnf -new -x509 -extensions exts_ca \
diff --git a/SOURCES/Remove-sent_nontrivial_preauth-field.patch b/SOURCES/Remove-sent_nontrivial_preauth-field.patch
new file mode 100644
index 0000000..f210bb9
--- /dev/null
+++ b/SOURCES/Remove-sent_nontrivial_preauth-field.patch
@@ -0,0 +1,56 @@
+From fd44fa60948a58634a3757be7c5c52fc671e48c7 Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Mon, 16 Jan 2017 13:42:18 -0500
+Subject: [PATCH] Remove sent_nontrivial_preauth field
+
+In krb5_init_creds_context, the selected_preauth_type field subsumes
+the need for sent_nontrivial_preauth.  Use it instead.
+
+(cherry picked from commit 5fef7aa7e43e45d227f2d53c661a23c932caafca)
+---
+ src/lib/krb5/krb/get_in_tkt.c     | 5 +----
+ src/lib/krb5/krb/init_creds_ctx.h | 1 -
+ 2 files changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
+index 988fca233..48dc00ea6 100644
+--- a/src/lib/krb5/krb/get_in_tkt.c
++++ b/src/lib/krb5/krb/get_in_tkt.c
+@@ -1359,8 +1359,6 @@ init_creds_step_request(krb5_context context,
+         krb5_free_data(context, ctx->encoded_previous_request);
+         ctx->encoded_previous_request = NULL;
+     }
+-    if (ctx->request->padata)
+-        ctx->sent_nontrivial_preauth = TRUE;
+     if (ctx->enc_pa_rep_permitted) {
+         code = add_padata(&ctx->request->padata, KRB5_ENCPADATA_REQ_ENC_PA_REP,
+                           NULL, 0);
+@@ -1485,7 +1483,7 @@ init_creds_step_reply(krb5_context context,
+             ctx->restarted = TRUE;
+             code = restart_init_creds_loop(context, ctx, TRUE);
+         } else if (!ctx->restarted && reply_code == KDC_ERR_PREAUTH_FAILED &&
+-                   !ctx->sent_nontrivial_preauth) {
++                   ctx->selected_preauth_type == KRB5_PADATA_NONE) {
+             /* The KDC didn't like our informational padata (probably a pre-1.7
+              * MIT krb5 KDC).  Retry without it. */
+             ctx->enc_pa_rep_permitted = FALSE;
+@@ -1525,7 +1523,6 @@ init_creds_step_reply(krb5_context context,
+                 goto cleanup;
+             /* Reset per-realm negotiation state. */
+             ctx->restarted = FALSE;
+-            ctx->sent_nontrivial_preauth = FALSE;
+             ctx->enc_pa_rep_permitted = TRUE;
+             code = restart_init_creds_loop(context, ctx, FALSE);
+         } else {
+diff --git a/src/lib/krb5/krb/init_creds_ctx.h b/src/lib/krb5/krb/init_creds_ctx.h
+index a7cded942..8c8b7494b 100644
+--- a/src/lib/krb5/krb/init_creds_ctx.h
++++ b/src/lib/krb5/krb/init_creds_ctx.h
+@@ -58,7 +58,6 @@ struct _krb5_init_creds_context {
+     krb5_enctype etype;
+     krb5_boolean enc_pa_rep_permitted;
+     krb5_boolean restarted;
+-    krb5_boolean sent_nontrivial_preauth;
+     krb5_boolean preauth_required;
+     struct krb5_responder_context_st rctx;
+     krb5_preauthtype selected_preauth_type;
diff --git a/SOURCES/Return-UPN-SANs-as-strings.patch b/SOURCES/Return-UPN-SANs-as-strings.patch
new file mode 100644
index 0000000..1823f9e
--- /dev/null
+++ b/SOURCES/Return-UPN-SANs-as-strings.patch
@@ -0,0 +1,204 @@
+From 0f94f224f16f196d8d3fb56cfcf4a65bdd0f20c7 Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Thu, 22 Mar 2018 20:07:17 -0400
+Subject: [PATCH] Return UPN SANs as strings
+
+(cherry picked from commit fd3c824e3be56a1fa77d140fd7e93934bfd6e565)
+---
+ src/plugins/preauth/pkinit/pkinit_crypto.h    |  4 +--
+ .../preauth/pkinit/pkinit_crypto_openssl.c    | 28 +++++++------------
+ src/plugins/preauth/pkinit/pkinit_matching.c  | 16 ++---------
+ src/plugins/preauth/pkinit/pkinit_srv.c       | 21 +++++++++-----
+ 4 files changed, 29 insertions(+), 40 deletions(-)
+
+diff --git a/src/plugins/preauth/pkinit/pkinit_crypto.h b/src/plugins/preauth/pkinit/pkinit_crypto.h
+index c14f4456a..b6e4e0ac3 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto.h
++++ b/src/plugins/preauth/pkinit/pkinit_crypto.h
+@@ -101,7 +101,7 @@ typedef struct _pkinit_cert_matching_data {
+     unsigned int ku_bits;   /* key usage information */
+     unsigned int eku_bits;  /* extended key usage information */
+     krb5_principal *sans;   /* Null-terminated array of PKINIT SANs */
+-    krb5_principal *upns;   /* Null-terimnated array of UPN SANs */
++    char **upns;	    /* Null-terimnated array of UPN SANs */
+ } pkinit_cert_matching_data;
+ 
+ /*
+@@ -253,7 +253,7 @@ krb5_error_code crypto_retrieve_cert_sans
+ 		    if non-NULL, a null-terminated array of
+ 		    id-pkinit-san values found in the certificate
+ 		    are returned */
+-	krb5_principal **upn_sans,			/* OUT
++	char ***upn_sans,				/* OUT
+ 		    if non-NULL, a null-terminated array of
+ 		    id-ms-upn-san values found in the certificate
+ 		    are returned */
+diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+index cf2f16294..3949eb9c2 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+@@ -29,6 +29,7 @@
+  * SUCH DAMAGES.
+  */
+ 
++#include "k5-int.h"
+ #include "pkinit_crypto_openssl.h"
+ #include "k5-buf.h"
+ #include <dlfcn.h>
+@@ -2095,15 +2096,14 @@ crypto_retrieve_X509_sans(krb5_context context,
+                           pkinit_plg_crypto_context plgctx,
+                           pkinit_req_crypto_context reqctx,
+                           X509 *cert,
+-                          krb5_principal **princs_ret,
+-                          krb5_principal **upn_ret,
++                          krb5_principal **princs_ret, char ***upn_ret,
+                           unsigned char ***dns_ret)
+ {
+     krb5_error_code retval = EINVAL;
+     char buf[DN_BUF_LEN];
+     int p = 0, u = 0, d = 0, ret = 0, l;
+     krb5_principal *princs = NULL;
+-    krb5_principal *upns = NULL;
++    char **upns = NULL;
+     unsigned char **dnss = NULL;
+     unsigned int i, num_found = 0, num_sans = 0;
+     X509_EXTENSION *ext = NULL;
+@@ -2153,7 +2153,7 @@ crypto_retrieve_X509_sans(krb5_context context,
+         }
+     }
+     if (upn_ret != NULL) {
+-        upns = calloc(num_sans + 1, sizeof(krb5_principal));
++        upns = calloc(num_sans + 1, sizeof(*upns));
+         if (upns == NULL) {
+             retval = ENOMEM;
+             goto cleanup;
+@@ -2196,16 +2196,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_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++;
+-                }
++                upns[u] = k5memdup0(name.data, name.length, &ret);
++                if (upns[u] == NULL)
++                    goto cleanup;
+             } else {
+                 pkiDebug("%s: unrecognized othername oid in SAN\n",
+                          __FUNCTION__);
+@@ -2257,7 +2250,7 @@ cleanup:
+         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[i]);
+     free(upns);
+     for (i = 0; dnss != NULL && dnss[i] != NULL; i++)
+         free(dnss[i]);
+@@ -2281,8 +2274,7 @@ crypto_retrieve_cert_sans(krb5_context context,
+                           pkinit_plg_crypto_context plgctx,
+                           pkinit_req_crypto_context reqctx,
+                           pkinit_identity_crypto_context idctx,
+-                          krb5_principal **princs_ret,
+-                          krb5_principal **upn_ret,
++                          krb5_principal **princs_ret, char ***upn_ret,
+                           unsigned char ***dns_ret)
+ {
+     krb5_error_code retval = EINVAL;
+@@ -5111,7 +5103,7 @@ crypto_cert_free_matching_data(krb5_context context,
+         krb5_free_principal(context, md->sans[i]);
+     free(md->sans);
+     for (i = 0; md->upns != NULL && md->upns[i] != NULL; i++)
+-        krb5_free_principal(context, md->upns[i]);
++        free(md->upns[i]);
+     free(md->upns);
+     free(md);
+ }
+diff --git a/src/plugins/preauth/pkinit/pkinit_matching.c b/src/plugins/preauth/pkinit/pkinit_matching.c
+index fe1e0f386..d929fb3c0 100644
+--- a/src/plugins/preauth/pkinit/pkinit_matching.c
++++ b/src/plugins/preauth/pkinit/pkinit_matching.c
+@@ -490,11 +490,7 @@ component_match(krb5_context context,
+                     break;
+             }
+             for (i = 0; md->upns != NULL && md->upns[i] != NULL; i++) {
+-                krb5_unparse_name_flags(context, md->upns[i],
+-                                        KRB5_PRINCIPAL_UNPARSE_NO_REALM,
+-                                        &princ_string);
+-                match = regexp_match(context, rc, princ_string);
+-                krb5_free_unparsed_name(context, princ_string);
++                match = regexp_match(context, rc, md->upns[i]);
+                 if (match)
+                     break;
+             }
+@@ -584,14 +580,8 @@ check_all_certs(krb5_context context,
+             pkiDebug("%s: PKINIT san: '%s'\n", __FUNCTION__, san_string);
+             krb5_free_unparsed_name(context, san_string);
+         }
+-        for (j = 0; md->upns != NULL && md->upns[j] != NULL; j++) {
+-            char *san_string;
+-            krb5_unparse_name_flags(context, md->upns[j],
+-                                    KRB5_PRINCIPAL_UNPARSE_NO_REALM,
+-                                    &san_string);
+-            pkiDebug("%s: UPN san: '%s'\n", __FUNCTION__, san_string);
+-            krb5_free_unparsed_name(context, san_string);
+-        }
++        for (j = 0; md->upns != NULL && md->upns[j] != NULL; j++)
++            pkiDebug("%s: UPN san: '%s'\n", __FUNCTION__, md->upns[j]);
+ #endif
+         certs_checked++;
+         for (rc = rs->crs; rc != NULL; rc = rc->next) {
+diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c
+index 143d331a2..42ad45fe4 100644
+--- a/src/plugins/preauth/pkinit/pkinit_srv.c
++++ b/src/plugins/preauth/pkinit/pkinit_srv.c
+@@ -174,8 +174,9 @@ verify_client_san(krb5_context context,
+                   int *valid_san)
+ {
+     krb5_error_code retval;
+-    krb5_principal *princs = NULL;
+-    krb5_principal *upns = NULL;
++    krb5_principal *princs = NULL, upn;
++    krb5_boolean match;
++    char **upns = NULL;
+     int i;
+ #ifdef DEBUG_SAN_INFO
+     char *client_string = NULL, *san_string;
+@@ -251,12 +252,18 @@ verify_client_san(krb5_context context,
+     pkiDebug("%s: Checking upn sans\n", __FUNCTION__);
+     for (i = 0; upns[i] != NULL; i++) {
+ #ifdef DEBUG_SAN_INFO
+-        krb5_unparse_name(context, upns[i], &san_string);
+         pkiDebug("%s: Comparing client '%s' to upn san value '%s'\n",
+-                 __FUNCTION__, client_string, san_string);
+-        krb5_free_unparsed_name(context, san_string);
++                 __FUNCTION__, client_string, upns[i]);
+ #endif
+-        if (cb->match_client(context, rock, upns[i])) {
++        retval = krb5_parse_name_flags(context, upns[i],
++                                       KRB5_PRINCIPAL_PARSE_ENTERPRISE, &upn);
++        if (retval) {
++            /* XXX trace */
++            continue;
++        }
++        match = cb->match_client(context, rock, upn);
++        krb5_free_principal(context, upn);
++        if (match) {
+             TRACE_PKINIT_SERVER_MATCHING_UPN_FOUND(context);
+             *valid_san = 1;
+             retval = 0;
+@@ -282,7 +289,7 @@ out:
+     }
+     if (upns != NULL) {
+         for (i = 0; upns[i] != NULL; i++)
+-            krb5_free_principal(context, upns[i]);
++            free(upns[i]);
+         free(upns);
+     }
+ #ifdef DEBUG_SAN_INFO
diff --git a/SOURCES/Save-SANs-separately-and-unparse-them-with-NO_REALM.patch b/SOURCES/Save-SANs-separately-and-unparse-them-with-NO_REALM.patch
new file mode 100644
index 0000000..3930589
--- /dev/null
+++ b/SOURCES/Save-SANs-separately-and-unparse-them-with-NO_REALM.patch
@@ -0,0 +1,148 @@
+From c796a84ffa455b60e08508f4b706f7ecae0054de Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Thu, 22 Mar 2018 19:46:22 -0400
+Subject: [PATCH] Save SANs separately and unparse them with NO_REALM
+
+(cherry picked from commit 23ea8d6a9617d17ae5a529c23174d77adac39055)
+---
+ src/plugins/preauth/pkinit/pkinit_crypto.h    |  4 +-
+ .../preauth/pkinit/pkinit_crypto_openssl.c    | 37 ++-----------------
+ src/plugins/preauth/pkinit/pkinit_matching.c  | 30 +++++++++++----
+ 3 files changed, 28 insertions(+), 43 deletions(-)
+
+diff --git a/src/plugins/preauth/pkinit/pkinit_crypto.h b/src/plugins/preauth/pkinit/pkinit_crypto.h
+index a0176acad..c14f4456a 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto.h
++++ b/src/plugins/preauth/pkinit/pkinit_crypto.h
+@@ -100,8 +100,8 @@ typedef struct _pkinit_cert_matching_data {
+     char *issuer_dn;	    /* rfc2253-style issuer name string */
+     unsigned int ku_bits;   /* key usage information */
+     unsigned int eku_bits;  /* extended key usage information */
+-    krb5_principal *sans;   /* Null-terminated array of subject alternative
+-			       name info (pkinit and ms-upn) */
++    krb5_principal *sans;   /* Null-terminated array of PKINIT SANs */
++    krb5_principal *upns;   /* Null-terimnated array of UPN SANs */
+ } pkinit_cert_matching_data;
+ 
+ /*
+diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+index 34ed7afaf..cf2f16294 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+@@ -5110,6 +5110,9 @@ crypto_cert_free_matching_data(krb5_context context,
+     for (i = 0; md->sans != NULL && md->sans[i] != NULL; i++)
+         krb5_free_principal(context, md->sans[i]);
+     free(md->sans);
++    for (i = 0; md->upns != NULL && md->upns[i] != NULL; i++)
++        krb5_free_principal(context, md->upns[i]);
++    free(md->upns);
+     free(md);
+ }
+ 
+@@ -5138,8 +5141,6 @@ get_matching_data(krb5_context context,
+ {
+     krb5_error_code ret = ENOMEM;
+     pkinit_cert_matching_data *md = NULL;
+-    krb5_principal *pkinit_sans = NULL, *upn_sans = NULL;
+-    size_t i, j;
+ 
+     *md_out = NULL;
+ 
+@@ -5156,40 +5157,10 @@ get_matching_data(krb5_context context,
+ 
+     /* Get the SAN data. */
+     ret = crypto_retrieve_X509_sans(context, plg_cryptoctx, req_cryptoctx,
+-                                    cert, &pkinit_sans, &upn_sans, NULL);
++                                    cert, &md->sans, &md->upns, NULL);
+     if (ret)
+         goto cleanup;
+ 
+-    j = 0;
+-    if (pkinit_sans != NULL) {
+-        for (i = 0; pkinit_sans[i] != NULL; i++)
+-            j++;
+-    }
+-    if (upn_sans != NULL) {
+-        for (i = 0; upn_sans[i] != NULL; i++)
+-            j++;
+-    }
+-    if (j != 0) {
+-        md->sans = calloc((size_t)j+1, sizeof(*md->sans));
+-        if (md->sans == NULL) {
+-            ret = ENOMEM;
+-            goto cleanup;
+-        }
+-        j = 0;
+-        if (pkinit_sans != NULL) {
+-            for (i = 0; pkinit_sans[i] != NULL; i++)
+-                md->sans[j++] = pkinit_sans[i];
+-            free(pkinit_sans);
+-        }
+-        if (upn_sans != NULL) {
+-            for (i = 0; upn_sans[i] != NULL; i++)
+-                md->sans[j++] = upn_sans[i];
+-            free(upn_sans);
+-        }
+-        md->sans[j] = NULL;
+-    } else
+-        md->sans = NULL;
+-
+     /* Get the KU and EKU data. */
+     ret = crypto_retrieve_X509_key_usage(context, plg_cryptoctx,
+                                          req_cryptoctx, cert, &md->ku_bits,
+diff --git a/src/plugins/preauth/pkinit/pkinit_matching.c b/src/plugins/preauth/pkinit/pkinit_matching.c
+index d6775dc4f..fe1e0f386 100644
+--- a/src/plugins/preauth/pkinit/pkinit_matching.c
++++ b/src/plugins/preauth/pkinit/pkinit_matching.c
+@@ -470,7 +470,6 @@ component_match(krb5_context context,
+ {
+     int match = 0;
+     int i;
+-    krb5_principal p;
+     char *princ_string;
+ 
+     switch (rc->kwval_type) {
+@@ -483,10 +482,17 @@ component_match(krb5_context context,
+             match = regexp_match(context, rc, md->issuer_dn);
+             break;
+         case kw_san:
+-            if (md->sans == NULL)
+-                break;
+-            for (i = 0, p = md->sans[i]; p != NULL; p = md->sans[++i]) {
+-                krb5_unparse_name(context, p, &princ_string);
++            for (i = 0; md->sans != NULL && md->sans[i] != NULL; i++) {
++                krb5_unparse_name(context, md->sans[i], &princ_string);
++                match = regexp_match(context, rc, princ_string);
++                krb5_free_unparsed_name(context, princ_string);
++                if (match)
++                    break;
++            }
++            for (i = 0; md->upns != NULL && md->upns[i] != NULL; i++) {
++                krb5_unparse_name_flags(context, md->upns[i],
++                                        KRB5_PRINCIPAL_UNPARSE_NO_REALM,
++                                        &princ_string);
+                 match = regexp_match(context, rc, princ_string);
+                 krb5_free_unparsed_name(context, princ_string);
+                 if (match)
+@@ -572,10 +578,18 @@ check_all_certs(krb5_context context,
+         pkiDebug("%s: subject: '%s'\n", __FUNCTION__, md->subject_dn);
+ #if 0
+         pkiDebug("%s: issuer:  '%s'\n", __FUNCTION__, md->subject_dn);
+-        for (j = 0, p = md->sans[j]; p != NULL; p = md->sans[++j]) {
++        for (j = 0; md->sans != NULL && md->sans[j] != NULL; j++) {
+             char *san_string;
+-            krb5_unparse_name(context, p, &san_string);
+-            pkiDebug("%s: san: '%s'\n", __FUNCTION__, san_string);
++            krb5_unparse_name(context, md->sans[j], &san_string);
++            pkiDebug("%s: PKINIT san: '%s'\n", __FUNCTION__, san_string);
++            krb5_free_unparsed_name(context, san_string);
++        }
++        for (j = 0; md->upns != NULL && md->upns[j] != NULL; j++) {
++            char *san_string;
++            krb5_unparse_name_flags(context, md->upns[j],
++                                    KRB5_PRINCIPAL_UNPARSE_NO_REALM,
++                                    &san_string);
++            pkiDebug("%s: UPN san: '%s'\n", __FUNCTION__, san_string);
+             krb5_free_unparsed_name(context, san_string);
+         }
+ #endif
diff --git a/SOURCES/Simplify-PKINIT-cert-iteration-and-selection.patch b/SOURCES/Simplify-PKINIT-cert-iteration-and-selection.patch
new file mode 100644
index 0000000..4035c1f
--- /dev/null
+++ b/SOURCES/Simplify-PKINIT-cert-iteration-and-selection.patch
@@ -0,0 +1,843 @@
+From 5bca501af5e28e0a8f5194088fdaea53f5fa419f Mon Sep 17 00:00:00 2001
+From: Matt Rogers <mrogers@redhat.com>
+Date: Tue, 21 Mar 2017 21:24:14 -0400
+Subject: [PATCH] Simplify PKINIT cert iteration and selection
+
+Remove the pkinit_cert_handle structures and iteration functions used
+during certificate matching.  Instead, make pkinit_matching.c obtain a
+list of matching data objects from the crypto code, and then select a
+cert based on the index into that list.
+
+Also fix a typo in the name of crypto_retrieve_X509_key_usage().
+
+[ghudson@mit.edu: simplified code]
+
+(cherry picked from commit 01b1c0e26252a00f2215408b0e473b84aa0f6a87)
+---
+ src/plugins/preauth/pkinit/pkinit_crypto.h    |  75 +---
+ .../preauth/pkinit/pkinit_crypto_openssl.c    | 383 +++++++-----------
+ .../preauth/pkinit/pkinit_crypto_openssl.h    |  19 -
+ src/plugins/preauth/pkinit/pkinit_matching.c  | 139 +------
+ 4 files changed, 194 insertions(+), 422 deletions(-)
+
+diff --git a/src/plugins/preauth/pkinit/pkinit_crypto.h b/src/plugins/preauth/pkinit/pkinit_crypto.h
+index 49b96b8ee..a0176acad 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto.h
++++ b/src/plugins/preauth/pkinit/pkinit_crypto.h
+@@ -96,7 +96,6 @@ typedef struct _pkinit_cert_iter_info *pkinit_cert_iter_handle;
+ #define PKINIT_ITER_NO_MORE	0x11111111  /* XXX */
+ 
+ typedef struct _pkinit_cert_matching_data {
+-    pkinit_cert_handle ch;  /* cert handle for this certificate */
+     char *subject_dn;	    /* rfc2253-style subject name string */
+     char *issuer_dn;	    /* rfc2253-style issuer name string */
+     unsigned int ku_bits;   /* key usage information */
+@@ -458,68 +457,38 @@ krb5_error_code crypto_free_cert_info
+ 
+ 
+ /*
+- * Get number of certificates available after crypto_load_certs()
++ * Get a null-terminated list of certificate matching data objects for the
++ * certificates loaded in id_cryptoctx.
+  */
+-krb5_error_code crypto_cert_get_count
+-	(krb5_context context,				/* IN */
+-	pkinit_plg_crypto_context plg_cryptoctx,	/* IN */
+-	pkinit_req_crypto_context req_cryptoctx,	/* IN */
+-	pkinit_identity_crypto_context id_cryptoctx,	/* IN */
+-	int *cert_count);				/* OUT */
++krb5_error_code
++crypto_cert_get_matching_data(krb5_context context,
++			      pkinit_plg_crypto_context plg_cryptoctx,
++			      pkinit_req_crypto_context req_cryptoctx,
++			      pkinit_identity_crypto_context id_cryptoctx,
++			      pkinit_cert_matching_data ***md_out);
+ 
+ /*
+- * Begin iteration over the certs loaded in crypto_load_certs()
++ * Free a matching data object.
+  */
+-krb5_error_code crypto_cert_iteration_begin
+-	(krb5_context context,				/* IN */
+-	pkinit_plg_crypto_context plg_cryptoctx,	/* IN */
+-	pkinit_req_crypto_context req_cryptoctx,	/* IN */
+-	pkinit_identity_crypto_context id_cryptoctx,	/* IN */
+-	pkinit_cert_iter_handle *iter_handle);		/* OUT */
++void
++crypto_cert_free_matching_data(krb5_context context,
++			       pkinit_cert_matching_data *md);
+ 
+ /*
+- * End iteration over the certs loaded in crypto_load_certs()
++ * Free a list of matching data objects.
+  */
+-krb5_error_code crypto_cert_iteration_end
+-	(krb5_context context,				/* IN */
+-	pkinit_cert_iter_handle iter_handle);		/* IN */
++void
++crypto_cert_free_matching_data_list(krb5_context context,
++				    pkinit_cert_matching_data **matchdata);
+ 
+ /*
+- * Get next certificate handle
++ * Choose one of the certificates loaded in idctx to use for PKINIT client
++ * operations.  cred_index must be an index into the array of matching objects
++ * returned by crypto_cert_get_matching_data().
+  */
+-krb5_error_code crypto_cert_iteration_next
+-	(krb5_context context,				/* IN */
+-	pkinit_cert_iter_handle iter_handle,		/* IN */
+-	pkinit_cert_handle *cert_handle);		/* OUT */
+-
+-/*
+- * Release cert handle
+- */
+-krb5_error_code crypto_cert_release
+-	(krb5_context context,				/* IN */
+-	pkinit_cert_handle cert_handle);		/* IN */
+-
+-/*
+- * Get certificate matching information
+- */
+-krb5_error_code crypto_cert_get_matching_data
+-	(krb5_context context,				/* IN */
+-	pkinit_cert_handle cert_handle,			/* IN */
+-	pkinit_cert_matching_data **ret_data);		/* OUT */
+-
+-/*
+- * Free certificate information
+- */
+-krb5_error_code crypto_cert_free_matching_data
+-	(krb5_context context,				/* IN */
+-	pkinit_cert_matching_data *data);		/* IN */
+-
+-/*
+- * Make the given certificate "the chosen one"
+- */
+-krb5_error_code crypto_cert_select
+-	(krb5_context context,				/* IN */
+-	pkinit_cert_matching_data *data);		/* IN */
++krb5_error_code
++crypto_cert_select(krb5_context context, pkinit_identity_crypto_context idctx,
++		   size_t cred_index);
+ 
+ /*
+  * Select the default certificate as "the chosen one"
+diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+index 6098acc6a..f70aab5b3 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+@@ -4974,136 +4974,16 @@ cleanup:
+     return retval;
+ }
+ 
+-/*
+- * Get number of certificates available after crypto_load_certs()
+- */
+-krb5_error_code
+-crypto_cert_get_count(krb5_context context,
+-                      pkinit_plg_crypto_context plg_cryptoctx,
+-                      pkinit_req_crypto_context req_cryptoctx,
+-                      pkinit_identity_crypto_context id_cryptoctx,
+-                      int *cert_count)
+-{
+-    int count;
+-
+-    if (id_cryptoctx == NULL || id_cryptoctx->creds[0] == NULL)
+-        return EINVAL;
+-
+-    for (count = 0;
+-         count <= MAX_CREDS_ALLOWED && id_cryptoctx->creds[count] != NULL;
+-         count++);
+-    *cert_count = count;
+-    return 0;
+-}
+-
+-
+-/*
+- * Begin iteration over the certs loaded in crypto_load_certs()
+- */
+-krb5_error_code
+-crypto_cert_iteration_begin(krb5_context context,
+-                            pkinit_plg_crypto_context plg_cryptoctx,
+-                            pkinit_req_crypto_context req_cryptoctx,
+-                            pkinit_identity_crypto_context id_cryptoctx,
+-                            pkinit_cert_iter_handle *ih_ret)
+-{
+-    struct _pkinit_cert_iter_data *id;
+-
+-    if (id_cryptoctx == NULL || ih_ret == NULL)
+-        return EINVAL;
+-    if (id_cryptoctx->creds[0] == NULL) /* No cred info available */
+-        return ENOENT;
+-
+-    id = calloc(1, sizeof(*id));
+-    if (id == NULL)
+-        return ENOMEM;
+-    id->magic = ITER_MAGIC;
+-    id->plgctx = plg_cryptoctx,
+-        id->reqctx = req_cryptoctx,
+-        id->idctx = id_cryptoctx;
+-    id->index = 0;
+-    *ih_ret = (pkinit_cert_iter_handle) id;
+-    return 0;
+-}
+-
+-/*
+- * End iteration over the certs loaded in crypto_load_certs()
+- */
+-krb5_error_code
+-crypto_cert_iteration_end(krb5_context context,
+-                          pkinit_cert_iter_handle ih)
+-{
+-    struct _pkinit_cert_iter_data *id = (struct _pkinit_cert_iter_data *)ih;
+-
+-    if (id == NULL || id->magic != ITER_MAGIC)
+-        return EINVAL;
+-    free(ih);
+-    return 0;
+-}
+-
+-/*
+- * Get next certificate handle
+- */
+-krb5_error_code
+-crypto_cert_iteration_next(krb5_context context,
+-                           pkinit_cert_iter_handle ih,
+-                           pkinit_cert_handle *ch_ret)
+-{
+-    struct _pkinit_cert_iter_data *id = (struct _pkinit_cert_iter_data *)ih;
+-    struct _pkinit_cert_data *cd;
+-    pkinit_identity_crypto_context id_cryptoctx;
+-
+-    if (id == NULL || id->magic != ITER_MAGIC)
+-        return EINVAL;
+-
+-    if (ch_ret == NULL)
+-        return EINVAL;
+-
+-    id_cryptoctx = id->idctx;
+-    if (id_cryptoctx == NULL)
+-        return EINVAL;
+-
+-    if (id_cryptoctx->creds[id->index] == NULL)
+-        return PKINIT_ITER_NO_MORE;
+-
+-    cd = calloc(1, sizeof(*cd));
+-    if (cd == NULL)
+-        return ENOMEM;
+-
+-    cd->magic = CERT_MAGIC;
+-    cd->plgctx = id->plgctx;
+-    cd->reqctx = id->reqctx;
+-    cd->idctx = id->idctx;
+-    cd->index = id->index;
+-    cd->cred = id_cryptoctx->creds[id->index++];
+-    *ch_ret = (pkinit_cert_handle)cd;
+-    return 0;
+-}
+-
+-/*
+- * Release cert handle
+- */
+-krb5_error_code
+-crypto_cert_release(krb5_context context,
+-                    pkinit_cert_handle ch)
+-{
+-    struct _pkinit_cert_data *cd = (struct _pkinit_cert_data *)ch;
+-    if (cd == NULL || cd->magic != CERT_MAGIC)
+-        return EINVAL;
+-    free(cd);
+-    return 0;
+-}
+-
+ /*
+  * Get certificate Key Usage and Extended Key Usage
+  */
+ static krb5_error_code
+-crypto_retieve_X509_key_usage(krb5_context context,
+-                              pkinit_plg_crypto_context plgcctx,
+-                              pkinit_req_crypto_context reqcctx,
+-                              X509 *x,
+-                              unsigned int *ret_ku_bits,
+-                              unsigned int *ret_eku_bits)
++crypto_retrieve_X509_key_usage(krb5_context context,
++                               pkinit_plg_crypto_context plgcctx,
++                               pkinit_req_crypto_context reqcctx,
++                               X509 *x,
++                               unsigned int *ret_ku_bits,
++                               unsigned int *ret_eku_bits)
+ {
+     krb5_error_code retval = 0;
+     int i;
+@@ -5202,55 +5082,99 @@ X509_NAME_oneline_ex(X509_NAME * a,
+ }
+ 
+ /*
+- * Get certificate information
++ * Get number of certificates available after crypto_load_certs()
+  */
+-krb5_error_code
+-crypto_cert_get_matching_data(krb5_context context,
+-                              pkinit_cert_handle ch,
+-                              pkinit_cert_matching_data **ret_md)
++static krb5_error_code
++crypto_cert_get_count(pkinit_identity_crypto_context id_cryptoctx,
++                      int *cert_count)
+ {
+-    krb5_error_code retval;
+-    pkinit_cert_matching_data *md;
+-    krb5_principal *pkinit_sans =NULL, *upn_sans = NULL;
+-    struct _pkinit_cert_data *cd = (struct _pkinit_cert_data *)ch;
+-    unsigned int i, j;
++    int count;
++
++    *cert_count = 0;
++    if (id_cryptoctx == NULL || id_cryptoctx->creds[0] == NULL)
++        return EINVAL;
++
++    for (count = 0;
++         count <= MAX_CREDS_ALLOWED && id_cryptoctx->creds[count] != NULL;
++         count++);
++    *cert_count = count;
++    return 0;
++}
++
++void
++crypto_cert_free_matching_data(krb5_context context,
++                               pkinit_cert_matching_data *md)
++{
++    int i;
++
++    if (md == NULL)
++        return;
++    free(md->subject_dn);
++    free(md->issuer_dn);
++    for (i = 0; md->sans != NULL && md->sans[i] != NULL; i++)
++        krb5_free_principal(context, md->sans[i]);
++    free(md->sans);
++    free(md);
++}
++
++/*
++ * Free certificate matching data.
++ */
++void
++crypto_cert_free_matching_data_list(krb5_context context,
++                                    pkinit_cert_matching_data **list)
++{
++    int i;
++
++    for (i = 0; list != NULL && list[i] != NULL; i++)
++        crypto_cert_free_matching_data(context, list[i]);
++    free(list);
++}
++
++/*
++ * Get certificate matching data for cert.
++ */
++static krb5_error_code
++get_matching_data(krb5_context context,
++                  pkinit_plg_crypto_context plg_cryptoctx,
++                  pkinit_req_crypto_context req_cryptoctx, X509 *cert,
++                  pkinit_cert_matching_data **md_out)
++{
++    krb5_error_code ret = ENOMEM;
++    pkinit_cert_matching_data *md = NULL;
++    krb5_principal *pkinit_sans = NULL, *upn_sans = NULL;
++    size_t i, j;
+     char buf[DN_BUF_LEN];
+     unsigned int bufsize = sizeof(buf);
+ 
+-    if (cd == NULL || cd->magic != CERT_MAGIC)
+-        return EINVAL;
+-    if (ret_md == NULL)
+-        return EINVAL;
++    *md_out = NULL;
+ 
+     md = calloc(1, sizeof(*md));
+     if (md == NULL)
+-        return ENOMEM;
++        goto cleanup;
+ 
+-    md->ch = ch;
+-
+-    /* get the subject name (in rfc2253 format) */
+-    X509_NAME_oneline_ex(X509_get_subject_name(cd->cred->cert),
+-                         buf, &bufsize, XN_FLAG_SEP_COMMA_PLUS);
++    /* Get the subject name (in rfc2253 format). */
++    X509_NAME_oneline_ex(X509_get_subject_name(cert), buf, &bufsize,
++                         XN_FLAG_SEP_COMMA_PLUS);
+     md->subject_dn = strdup(buf);
+     if (md->subject_dn == NULL) {
+-        retval = ENOMEM;
++        ret = ENOMEM;
+         goto cleanup;
+     }
+ 
+-    /* get the issuer name (in rfc2253 format) */
+-    X509_NAME_oneline_ex(X509_get_issuer_name(cd->cred->cert),
+-                         buf, &bufsize, XN_FLAG_SEP_COMMA_PLUS);
++    /* Get the issuer name (in rfc2253 format). */
++    X509_NAME_oneline_ex(X509_get_issuer_name(cert), buf, &bufsize,
++                         XN_FLAG_SEP_COMMA_PLUS);
+     md->issuer_dn = strdup(buf);
+     if (md->issuer_dn == NULL) {
+-        retval = ENOMEM;
++        ret = ENOMEM;
+         goto cleanup;
+     }
+ 
+-    /* get the san data */
+-    retval = crypto_retrieve_X509_sans(context, cd->plgctx, cd->reqctx,
+-                                       cd->cred->cert, &pkinit_sans,
+-                                       &upn_sans, NULL);
+-    if (retval)
++    /* Get the SAN data. */
++    ret = crypto_retrieve_X509_sans(context, plg_cryptoctx, req_cryptoctx,
++                                    cert, &pkinit_sans, &upn_sans, NULL);
++    if (ret)
+         goto cleanup;
+ 
+     j = 0;
+@@ -5265,7 +5189,7 @@ crypto_cert_get_matching_data(krb5_context context,
+     if (j != 0) {
+         md->sans = calloc((size_t)j+1, sizeof(*md->sans));
+         if (md->sans == NULL) {
+-            retval = ENOMEM;
++            ret = ENOMEM;
+             goto cleanup;
+         }
+         j = 0;
+@@ -5283,88 +5207,96 @@ crypto_cert_get_matching_data(krb5_context context,
+     } else
+         md->sans = NULL;
+ 
+-    /* get the KU and EKU data */
+-
+-    retval = crypto_retieve_X509_key_usage(context, cd->plgctx, cd->reqctx,
+-                                           cd->cred->cert,
+-                                           &md->ku_bits, &md->eku_bits);
+-    if (retval)
++    /* Get the KU and EKU data. */
++    ret = crypto_retrieve_X509_key_usage(context, plg_cryptoctx,
++                                         req_cryptoctx, cert, &md->ku_bits,
++                                         &md->eku_bits);
++    if (ret)
+         goto cleanup;
+ 
+-    *ret_md = md;
+-    retval = 0;
++    *md_out = md;
++    md = NULL;
++
+ cleanup:
+-    if (retval) {
+-        if (md)
+-            crypto_cert_free_matching_data(context, md);
++    crypto_cert_free_matching_data(context, md);
++    return ret;
++}
++
++krb5_error_code
++crypto_cert_get_matching_data(krb5_context context,
++                              pkinit_plg_crypto_context plg_cryptoctx,
++                              pkinit_req_crypto_context req_cryptoctx,
++                              pkinit_identity_crypto_context id_cryptoctx,
++                              pkinit_cert_matching_data ***md_out)
++{
++    krb5_error_code ret;
++    pkinit_cert_matching_data **md_list = NULL;
++    int count, i;
++
++    ret = crypto_cert_get_count(id_cryptoctx, &count);
++    if (ret)
++        goto cleanup;
++
++    md_list = calloc(count + 1, sizeof(*md_list));
++    if (md_list == NULL) {
++        ret = ENOMEM;
++        goto cleanup;
+     }
+-    return retval;
++
++    for (i = 0; i < count; i++) {
++        ret = get_matching_data(context, plg_cryptoctx, req_cryptoctx,
++                                id_cryptoctx->creds[i]->cert, &md_list[i]);
++        if (ret) {
++            pkiDebug("%s: crypto_cert_get_matching_data error %d, %s\n",
++                     __FUNCTION__, ret, error_message(ret));
++            goto cleanup;
++        }
++    }
++
++    *md_out = md_list;
++    md_list = NULL;
++
++cleanup:
++    crypto_cert_free_matching_data_list(context, md_list);
++    return ret;
+ }
+ 
+ /*
+- * Free certificate information
++ * Set the certificate in idctx->creds[cred_index] as the selected certificate.
+  */
+ krb5_error_code
+-crypto_cert_free_matching_data(krb5_context context,
+-                               pkinit_cert_matching_data *md)
++crypto_cert_select(krb5_context context, pkinit_identity_crypto_context idctx,
++                   size_t cred_index)
+ {
+-    krb5_principal p;
+-    int i;
++    pkinit_cred_info ci = NULL;
+ 
+-    if (md == NULL)
+-        return EINVAL;
+-    if (md->subject_dn)
+-        free(md->subject_dn);
+-    if (md->issuer_dn)
+-        free(md->issuer_dn);
+-    if (md->sans) {
+-        for (i = 0, p = md->sans[i]; p != NULL; p = md->sans[++i])
+-            krb5_free_principal(context, p);
+-        free(md->sans);
+-    }
+-    free(md);
+-    return 0;
+-}
+-
+-/*
+- * Make this matching certificate "the chosen one"
+- */
+-krb5_error_code
+-crypto_cert_select(krb5_context context,
+-                   pkinit_cert_matching_data *md)
+-{
+-    struct _pkinit_cert_data *cd;
+-    if (md == NULL)
+-        return EINVAL;
+-
+-    cd = (struct _pkinit_cert_data *)md->ch;
+-    if (cd == NULL || cd->magic != CERT_MAGIC)
+-        return EINVAL;
++    if (cred_index >= MAX_CREDS_ALLOWED || idctx->creds[cred_index] == NULL)
++        return ENOENT;
+ 
++    ci = idctx->creds[cred_index];
+     /* copy the selected cert into our id_cryptoctx */
+-    if (cd->idctx->my_certs != NULL) {
+-        sk_X509_pop_free(cd->idctx->my_certs, X509_free);
+-    }
+-    cd->idctx->my_certs = sk_X509_new_null();
+-    sk_X509_push(cd->idctx->my_certs, cd->cred->cert);
+-    free(cd->idctx->identity);
++    if (idctx->my_certs != NULL)
++        sk_X509_pop_free(idctx->my_certs, X509_free);
++    idctx->my_certs = sk_X509_new_null();
++    sk_X509_push(idctx->my_certs, ci->cert);
++    free(idctx->identity);
+     /* hang on to the selected credential name */
+-    if (cd->idctx->creds[cd->index]->name != NULL)
+-        cd->idctx->identity = strdup(cd->idctx->creds[cd->index]->name);
++    if (ci->name != NULL)
++        idctx->identity = strdup(ci->name);
+     else
+-        cd->idctx->identity = NULL;
+-    cd->idctx->creds[cd->index]->cert = NULL;       /* Don't free it twice */
+-    cd->idctx->cert_index = 0;
++        idctx->identity = NULL;
+ 
+-    if (cd->idctx->pkcs11_method != 1) {
+-        cd->idctx->my_key = cd->cred->key;
+-        cd->idctx->creds[cd->index]->key = NULL;    /* Don't free it twice */
++    ci->cert = NULL;       /* Don't free it twice */
++    idctx->cert_index = 0;
++    if (idctx->pkcs11_method != 1) {
++        idctx->my_key = ci->key;
++        ci->key = NULL;    /* Don't free it twice */
+     }
+ #ifndef WITHOUT_PKCS11
+     else {
+-        cd->idctx->cert_id = cd->cred->cert_id;
+-        cd->idctx->creds[cd->index]->cert_id = NULL; /* Don't free it twice */
+-        cd->idctx->cert_id_len = cd->cred->cert_id_len;
++        idctx->cert_id = ci->cert_id;
++        ci->cert_id = NULL; /* Don't free it twice */
++        idctx->cert_id_len = ci->cert_id_len;
+     }
+ #endif
+     return 0;
+@@ -5380,15 +5312,12 @@ crypto_cert_select_default(krb5_context context,
+                            pkinit_identity_crypto_context id_cryptoctx)
+ {
+     krb5_error_code retval;
+-    int cert_count = 0;
++    int cert_count;
+ 
+-    retval = crypto_cert_get_count(context, plg_cryptoctx, req_cryptoctx,
+-                                   id_cryptoctx, &cert_count);
+-    if (retval) {
+-        pkiDebug("%s: crypto_cert_get_count error %d, %s\n",
+-                 __FUNCTION__, retval, error_message(retval));
++    retval = crypto_cert_get_count(id_cryptoctx, &cert_count);
++    if (retval)
+         goto errout;
+-    }
++
+     if (cert_count != 1) {
+         TRACE_PKINIT_NO_DEFAULT_CERT(context, cert_count);
+         retval = EINVAL;
+diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.h b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.h
+index 2fe357c5e..7411348fa 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.h
++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.h
+@@ -115,23 +115,4 @@ struct _pkinit_req_crypto_context {
+     DH *dh;
+ };
+ 
+-#define CERT_MAGIC 0x53534c43
+-struct _pkinit_cert_data {
+-    unsigned int magic;
+-    pkinit_plg_crypto_context plgctx;
+-    pkinit_req_crypto_context reqctx;
+-    pkinit_identity_crypto_context idctx;
+-    pkinit_cred_info cred;
+-    unsigned int index;	    /* Index of this cred in the creds[] array */
+-};
+-
+-#define ITER_MAGIC 0x53534c49
+-struct _pkinit_cert_iter_data {
+-    unsigned int magic;
+-    pkinit_plg_crypto_context plgctx;
+-    pkinit_req_crypto_context reqctx;
+-    pkinit_identity_crypto_context idctx;
+-    unsigned int index;
+-};
+-
+ #endif	/* _PKINIT_CRYPTO_OPENSSL_H */
+diff --git a/src/plugins/preauth/pkinit/pkinit_matching.c b/src/plugins/preauth/pkinit/pkinit_matching.c
+index cad4c2b9a..d6775dc4f 100644
+--- a/src/plugins/preauth/pkinit/pkinit_matching.c
++++ b/src/plugins/preauth/pkinit/pkinit_matching.c
+@@ -544,7 +544,7 @@ check_all_certs(krb5_context context,
+                 rule_set *rs,   /* rule to check */
+                 pkinit_cert_matching_data **matchdata,
+                 int *match_found,
+-                pkinit_cert_matching_data **matching_cert)
++                size_t *match_index)
+ {
+     krb5_error_code retval;
+     pkinit_cert_matching_data *md;
+@@ -553,12 +553,12 @@ check_all_certs(krb5_context context,
+     int total_cert_matches = 0;
+     rule_component *rc;
+     int certs_checked = 0;
+-    pkinit_cert_matching_data *save_match = NULL;
++    size_t save_index = 0;
+ 
+-    if (match_found == NULL || matching_cert == NULL)
++    if (match_found == NULL || match_index == NULL)
+         return EINVAL;
+ 
+-    *matching_cert = NULL;
++    *match_index = 0;
+     *match_found = 0;
+ 
+     pkiDebug("%s: matching rule relation is %s with %d components\n",
+@@ -590,7 +590,7 @@ check_all_certs(krb5_context context,
+                 pkiDebug("%s: cert matches rule (OR relation)\n",
+                          __FUNCTION__);
+                 total_cert_matches++;
+-                save_match = md;
++                save_index = i;
+                 goto nextcert;
+             }
+             if (!comp_match && rs->relation == relation_and) {
+@@ -602,7 +602,7 @@ check_all_certs(krb5_context context,
+         if (rc == NULL && comp_match) {
+             pkiDebug("%s: cert matches rule (AND relation)\n", __FUNCTION__);
+             total_cert_matches++;
+-            save_match = md;
++            save_index = i;
+         }
+     nextcert:
+         continue;
+@@ -611,7 +611,7 @@ check_all_certs(krb5_context context,
+              __FUNCTION__, certs_checked, total_cert_matches);
+     if (total_cert_matches == 1) {
+         *match_found = 1;
+-        *matching_cert = save_match;
++        *match_index = save_index;
+     }
+ 
+     retval = 0;
+@@ -621,111 +621,6 @@ check_all_certs(krb5_context context,
+     return retval;
+ }
+ 
+-static krb5_error_code
+-free_all_cert_matching_data(krb5_context context,
+-                            pkinit_cert_matching_data **matchdata)
+-{
+-    krb5_error_code retval;
+-    pkinit_cert_matching_data *md;
+-    int i;
+-
+-    if (matchdata == NULL)
+-        return EINVAL;
+-
+-    for (i = 0, md = matchdata[i]; md != NULL; md = matchdata[++i]) {
+-        pkinit_cert_handle ch = md->ch;
+-        retval = crypto_cert_free_matching_data(context, md);
+-        if (retval) {
+-            pkiDebug("%s: crypto_cert_free_matching_data error %d, %s\n",
+-                     __FUNCTION__, retval, error_message(retval));
+-            goto cleanup;
+-        }
+-        retval = crypto_cert_release(context, ch);
+-        if (retval) {
+-            pkiDebug("%s: crypto_cert_release error %d, %s\n",
+-                     __FUNCTION__, retval, error_message(retval));
+-            goto cleanup;
+-        }
+-    }
+-    free(matchdata);
+-    retval = 0;
+-
+-cleanup:
+-    return retval;
+-}
+-
+-static krb5_error_code
+-obtain_all_cert_matching_data(krb5_context context,
+-                              pkinit_plg_crypto_context plg_cryptoctx,
+-                              pkinit_req_crypto_context req_cryptoctx,
+-                              pkinit_identity_crypto_context id_cryptoctx,
+-                              pkinit_cert_matching_data ***all_matching_data)
+-{
+-    krb5_error_code retval;
+-    int i, cert_count;
+-    pkinit_cert_iter_handle ih = NULL;
+-    pkinit_cert_handle ch;
+-    pkinit_cert_matching_data **matchdata = NULL;
+-
+-    retval = crypto_cert_get_count(context, plg_cryptoctx, req_cryptoctx,
+-                                   id_cryptoctx, &cert_count);
+-    if (retval) {
+-        pkiDebug("%s: crypto_cert_get_count error %d, %s\n",
+-                 __FUNCTION__, retval, error_message(retval));
+-        goto cleanup;
+-    }
+-
+-    pkiDebug("%s: crypto_cert_get_count says there are %d certs\n",
+-             __FUNCTION__, cert_count);
+-
+-    matchdata = calloc((size_t)cert_count + 1, sizeof(*matchdata));
+-    if (matchdata == NULL)
+-        return ENOMEM;
+-
+-    retval = crypto_cert_iteration_begin(context, plg_cryptoctx, req_cryptoctx,
+-                                         id_cryptoctx, &ih);
+-    if (retval) {
+-        pkiDebug("%s: crypto_cert_iteration_begin returned %d, %s\n",
+-                 __FUNCTION__, retval, error_message(retval));
+-        goto cleanup;
+-    }
+-
+-    for (i = 0; i < cert_count; i++) {
+-        retval = crypto_cert_iteration_next(context, ih, &ch);
+-        if (retval) {
+-            if (retval == PKINIT_ITER_NO_MORE)
+-                pkiDebug("%s: We thought there were %d certs, but "
+-                         "crypto_cert_iteration_next stopped after %d?\n",
+-                         __FUNCTION__, cert_count, i);
+-            else
+-                pkiDebug("%s: crypto_cert_iteration_next error %d, %s\n",
+-                         __FUNCTION__, retval, error_message(retval));
+-            goto cleanup;
+-        }
+-
+-        retval = crypto_cert_get_matching_data(context, ch, &matchdata[i]);
+-        if (retval) {
+-            pkiDebug("%s: crypto_cert_get_matching_data error %d, %s\n",
+-                     __FUNCTION__, retval, error_message(retval));
+-            goto cleanup;
+-        }
+-
+-    }
+-
+-    *all_matching_data = matchdata;
+-    retval = 0;
+-cleanup:
+-    if (ih != NULL)
+-        crypto_cert_iteration_end(context, ih);
+-    if (retval) {
+-        if (matchdata != NULL)
+-            free_all_cert_matching_data(context, matchdata);
+-    }
+-    pkiDebug("%s: returning %d, certinfo %p\n",
+-             __FUNCTION__, retval, *all_matching_data);
+-    return retval;
+-}
+-
+ krb5_error_code
+ pkinit_cert_matching(krb5_context context,
+                      pkinit_plg_crypto_context plg_cryptoctx,
+@@ -740,7 +635,7 @@ pkinit_cert_matching(krb5_context context,
+     rule_set *rs = NULL;
+     int match_found = 0;
+     pkinit_cert_matching_data **matchdata = NULL;
+-    pkinit_cert_matching_data *the_matching_cert = NULL;
++    size_t match_index = 0;
+ 
+     /* If no matching rules, select the default cert and we're done */
+     pkinit_libdefault_strings(context, krb5_princ_realm(context, princ),
+@@ -777,7 +672,7 @@ pkinit_cert_matching(krb5_context context,
+          * until we are done.
+          */
+         if (matchdata == NULL) {
+-            retval = obtain_all_cert_matching_data(context, plg_cryptoctx,
++            retval = crypto_cert_get_matching_data(context, plg_cryptoctx,
+                                                    req_cryptoctx, id_cryptoctx,
+                                                    &matchdata);
+             if (retval || matchdata == NULL) {
+@@ -790,7 +685,7 @@ pkinit_cert_matching(krb5_context context,
+ 
+         retval = check_all_certs(context, plg_cryptoctx, req_cryptoctx,
+                                  id_cryptoctx, princ, rs, matchdata,
+-                                 &match_found, &the_matching_cert);
++                                 &match_found, &match_index);
+         if (retval) {
+             pkiDebug("%s: Error %d, checking certs against rule '%s'\n",
+                      __FUNCTION__, retval, rules[x]);
+@@ -803,9 +698,9 @@ pkinit_cert_matching(krb5_context context,
+         }
+     }
+ 
+-    if (match_found && the_matching_cert != NULL) {
++    if (match_found) {
+         pkiDebug("%s: Selecting the matching cert!\n", __FUNCTION__);
+-        retval = crypto_cert_select(context, the_matching_cert);
++        retval = crypto_cert_select(context, id_cryptoctx, match_index);
+         if (retval) {
+             pkiDebug("%s: crypto_cert_select error %d, %s\n",
+                      __FUNCTION__, retval, error_message(retval));
+@@ -818,12 +713,10 @@ pkinit_cert_matching(krb5_context context,
+     }
+ 
+     retval = 0;
++
+ cleanup:
+-    if (rules != NULL)
+-        profile_free_list(rules);
+-    if (rs != NULL)
+-        free_rule_set(context, rs);
+-    if (matchdata != NULL)
+-        free_all_cert_matching_data(context, matchdata);
++    profile_free_list(rules);
++    free_rule_set(context, rs);
++    crypto_cert_free_matching_data_list(context, matchdata);
+     return retval;
+ }
diff --git a/SOURCES/Simplify-k5_preauth_tryagain.patch b/SOURCES/Simplify-k5_preauth_tryagain.patch
new file mode 100644
index 0000000..efb91ee
--- /dev/null
+++ b/SOURCES/Simplify-k5_preauth_tryagain.patch
@@ -0,0 +1,182 @@
+From e443dfe315a38607e7c9dcba219f73253d17032b Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Fri, 13 Jan 2017 20:45:48 -0500
+Subject: [PATCH] Simplify k5_preauth_tryagain()
+
+When retrying pre-authentication for an error, try only the module for
+the selected preauth type, not all preauth types in the original
+method data.  Pass the error and its padata to k5_preauth_tryagain()
+explicitly, so that those fields of krb5_init_creds_context are only
+referenced in get_in_tkt.c.  Handle a degenerate case in
+init_creds_step_reply() to simplify the code in
+init_creds_step_request().
+
+ticket: 8537
+(cherry picked from commit 27628e5d9d5e6fcfa73276106edbd8149d134dc0)
+---
+ src/include/k5-trace.h        |  7 ++--
+ src/lib/krb5/krb/get_in_tkt.c | 20 ++++-------
+ src/lib/krb5/krb/int-proto.h  |  3 +-
+ src/lib/krb5/krb/preauth2.c   | 64 +++++++++++++++++++----------------
+ 4 files changed, 48 insertions(+), 46 deletions(-)
+
+diff --git a/src/include/k5-trace.h b/src/include/k5-trace.h
+index f44f162d3..814da3195 100644
+--- a/src/include/k5-trace.h
++++ b/src/include/k5-trace.h
+@@ -287,8 +287,11 @@ void krb5int_trace(krb5_context context, const char *fmt, ...);
+ #define TRACE_PREAUTH_SKIP(c, name, patype)                           \
+     TRACE(c, "Skipping previously used preauth module {str} ({int})", \
+           name, (int) patype)
+-#define TRACE_PREAUTH_TRYAGAIN_INPUT(c, padata)                 \
+-    TRACE(c, "Preauth tryagain input types: {patypes}", padata)
++#define TRACE_PREAUTH_TRYAGAIN_INPUT(c, patype, padata)                 \
++    TRACE(c, "Preauth tryagain input types ({int}): {patypes}", patype, padata)
++#define TRACE_PREAUTH_TRYAGAIN(c, name, patype, code)                   \
++    TRACE(c, "Preauth module {str} ({int}) tryagain returned: {kerr}",  \
++          name, (int)patype, code)
+ #define TRACE_PREAUTH_TRYAGAIN_OUTPUT(c, padata)                        \
+     TRACE(c, "Followup preauth for next request: {patypes}", padata)
+ #define TRACE_PREAUTH_WRONG_CONTEXT(c)                                  \
+diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
+index da12204ac..988fca233 100644
+--- a/src/lib/krb5/krb/get_in_tkt.c
++++ b/src/lib/krb5/krb/get_in_tkt.c
+@@ -1340,17 +1340,11 @@ init_creds_step_request(krb5_context context,
+         if (code != 0)
+             goto cleanup;
+     } else {
+-        if (ctx->preauth_to_use != NULL) {
+-            /*
+-             * Retry after an error other than PREAUTH_NEEDED,
+-             * using ctx->err_padata to figure out what to change.
+-             */
+-            code = k5_preauth_tryagain(context, ctx, ctx->preauth_to_use,
+-                                       &ctx->request->padata);
+-        } else {
+-            /* No preauth supplied, so can't query the plugins. */
+-            code = KRB5KRB_ERR_GENERIC;
+-        }
++        /* Retry after an error other than PREAUTH_NEEDED, using error padata
++         * to figure out what to change. */
++        code = k5_preauth_tryagain(context, ctx, ctx->selected_preauth_type,
++                                   ctx->err_reply, ctx->err_padata,
++                                   &ctx->request->padata);
+         if (code != 0) {
+             /* couldn't come up with anything better */
+             code = ctx->err_reply->error + ERROR_TABLE_BASE_krb5;
+@@ -1535,10 +1529,10 @@ init_creds_step_reply(krb5_context context,
+             ctx->enc_pa_rep_permitted = TRUE;
+             code = restart_init_creds_loop(context, ctx, FALSE);
+         } else {
+-            if (retry) {
++            if (retry && ctx->selected_preauth_type != KRB5_PADATA_NONE) {
+                 code = 0;
+             } else {
+-                /* error + no hints = give up */
++                /* error + no hints (or no preauth mech) = give up */
+                 code = (krb5_error_code)reply_code + ERROR_TABLE_BASE_krb5;
+             }
+         }
+diff --git a/src/lib/krb5/krb/int-proto.h b/src/lib/krb5/krb/int-proto.h
+index 628f0baa8..8903df232 100644
+--- a/src/lib/krb5/krb/int-proto.h
++++ b/src/lib/krb5/krb/int-proto.h
+@@ -185,7 +185,8 @@ k5_preauth(krb5_context context, krb5_init_creds_context ctx,
+ 
+ krb5_error_code
+ k5_preauth_tryagain(krb5_context context, krb5_init_creds_context ctx,
+-                    krb5_pa_data **in_padata, krb5_pa_data ***padata_out);
++                    krb5_preauthtype pa_type, krb5_error *err,
++                    krb5_pa_data **err_padata, krb5_pa_data ***padata_out);
+ 
+ void
+ k5_init_preauth_context(krb5_context context);
+diff --git a/src/lib/krb5/krb/preauth2.c b/src/lib/krb5/krb/preauth2.c
+index cfe3dd5b0..354234a93 100644
+--- a/src/lib/krb5/krb/preauth2.c
++++ b/src/lib/krb5/krb/preauth2.c
+@@ -911,49 +911,53 @@ add_s4u_x509_user_padata(krb5_context context, krb5_s4u_userid *userid,
+ }
+ 
+ /*
+- * If one of the modules can adjust its AS_REQ data using the contents of the
+- * err_reply, return 0.  If it's the sort of correction which requires that we
+- * ask the user another question, we let the calling application deal with it.
++ * If the module for pa_type can adjust its AS_REQ data using the contents of
++ * err and err_padata, return 0 with *padata_out set to a padata list for the
++ * next request.  If it's the sort of correction which requires that we ask the
++ * user another question, we let the calling application deal with it.
+  */
+ krb5_error_code
+ k5_preauth_tryagain(krb5_context context, krb5_init_creds_context ctx,
+-                    krb5_pa_data **in_padata, krb5_pa_data ***padata_out)
++                    krb5_preauthtype pa_type, krb5_error *err,
++                    krb5_pa_data **err_padata, krb5_pa_data ***padata_out)
+ {
+     krb5_error_code ret;
+     krb5_pa_data **mod_pa;
+     krb5_clpreauth_modreq modreq;
+     clpreauth_handle h;
+-    int i, count;
++    int count;
+ 
+     *padata_out = NULL;
+ 
+-    TRACE_PREAUTH_TRYAGAIN_INPUT(context, in_padata);
++    TRACE_PREAUTH_TRYAGAIN_INPUT(context, pa_type, err_padata);
+ 
+-    for (i = 0; in_padata[i] != NULL; i++) {
+-        h = find_module(context, ctx, in_padata[i]->pa_type, &modreq);
+-        if (h == NULL)
+-            continue;
+-        mod_pa = NULL;
+-        ret = clpreauth_tryagain(context, h, modreq, ctx->opt, &callbacks,
+-                                 (krb5_clpreauth_rock)ctx, ctx->request,
+-                                 ctx->inner_request_body,
+-                                 ctx->encoded_previous_request,
+-                                 in_padata[i]->pa_type,
+-                                 ctx->err_reply, ctx->err_padata,
+-                                 ctx->prompter, ctx->prompter_data, &mod_pa);
+-        if (ret == 0 && mod_pa != NULL) {
+-            for (count = 0; mod_pa[count] != NULL; count++);
+-            ret = copy_cookie(context, ctx->err_padata, &mod_pa, &count);
+-            if (ret) {
+-                krb5_free_pa_data(context, mod_pa);
+-                return ret;
+-            }
+-            TRACE_PREAUTH_TRYAGAIN_OUTPUT(context, mod_pa);
+-            *padata_out = mod_pa;
+-            return 0;
+-        }
++    h = find_module(context, ctx, pa_type, &modreq);
++    if (h == NULL)
++        return KRB5KRB_ERR_GENERIC;
++    mod_pa = NULL;
++    ret = clpreauth_tryagain(context, h, modreq, ctx->opt, &callbacks,
++                             (krb5_clpreauth_rock)ctx, ctx->request,
++                             ctx->inner_request_body,
++                             ctx->encoded_previous_request, pa_type, err,
++                             err_padata, ctx->prompter, ctx->prompter_data,
++                             &mod_pa);
++    TRACE_PREAUTH_TRYAGAIN(context, h->vt.name, pa_type, ret);
++    if (!ret && mod_pa == NULL)
++        ret = KRB5KRB_ERR_GENERIC;
++    if (ret)
++        return ret;
++
++
++    for (count = 0; mod_pa[count] != NULL; count++);
++    ret = copy_cookie(context, err_padata, &mod_pa, &count);
++    if (ret) {
++        krb5_free_pa_data(context, mod_pa);
++        return ret;
+     }
+-    return KRB5KRB_ERR_GENERIC;
++
++    TRACE_PREAUTH_TRYAGAIN_OUTPUT(context, mod_pa);
++    *padata_out = mod_pa;
++    return 0;
+ }
+ 
+ /* Compile the set of response items for in_padata by invoke each module's
diff --git a/SOURCES/Track-preauth-failures-instead-of-tries.patch b/SOURCES/Track-preauth-failures-instead-of-tries.patch
new file mode 100644
index 0000000..b18ae37
--- /dev/null
+++ b/SOURCES/Track-preauth-failures-instead-of-tries.patch
@@ -0,0 +1,189 @@
+From 6a69660d9415bc49948143109759f36b2ad70d1b Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Fri, 13 Jan 2017 12:16:04 -0500
+Subject: [PATCH] Track preauth failures instead of tries
+
+In preauth2.c, instead of noting whenever we try a real preauth mech,
+note when a mechanism fails on our side.  Tracking only failures
+eliminates the need to reset the list for multi-step preauth exchanges
+or for processing padata in the AS-REP, but we will need the function
+later for continuing after optimistic preauth failures.
+
+ticket: 8537
+(cherry picked from commit a1dc81d22304e77edaa8388c7d7d75cade81dc80)
+---
+ src/lib/krb5/krb/get_in_tkt.c |  3 --
+ src/lib/krb5/krb/int-proto.h  |  3 ++
+ src/lib/krb5/krb/preauth2.c   | 65 ++++++++++++++++++++---------------
+ 3 files changed, 40 insertions(+), 31 deletions(-)
+
+diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
+index 48dc00ea6..bc903b6e9 100644
+--- a/src/lib/krb5/krb/get_in_tkt.c
++++ b/src/lib/krb5/krb/get_in_tkt.c
+@@ -1496,8 +1496,6 @@ init_creds_step_reply(krb5_context context,
+             code = restart_init_creds_loop(context, ctx, FALSE);
+         } else if ((reply_code == KDC_ERR_MORE_PREAUTH_DATA_REQUIRED ||
+                     reply_code == KDC_ERR_PREAUTH_REQUIRED) && retry) {
+-            /* reset the list of preauth types to try */
+-            k5_reset_preauth_types_tried(ctx);
+             krb5_free_pa_data(context, ctx->preauth_to_use);
+             ctx->preauth_to_use = ctx->err_padata;
+             ctx->err_padata = NULL;
+@@ -1547,7 +1545,6 @@ init_creds_step_reply(krb5_context context,
+         goto cleanup;
+ 
+     /* process any preauth data in the as_reply */
+-    k5_reset_preauth_types_tried(ctx);
+     code = krb5int_fast_process_response(context, ctx->fast_state,
+                                          ctx->reply, &strengthen_key);
+     if (code != 0)
+diff --git a/src/lib/krb5/krb/int-proto.h b/src/lib/krb5/krb/int-proto.h
+index 8903df232..41a69c207 100644
+--- a/src/lib/krb5/krb/int-proto.h
++++ b/src/lib/krb5/krb/int-proto.h
+@@ -197,6 +197,9 @@ k5_free_preauth_context(krb5_context context);
+ void
+ k5_reset_preauth_types_tried(krb5_init_creds_context ctx);
+ 
++krb5_error_code
++k5_preauth_note_failed(krb5_init_creds_context ctx, krb5_preauthtype pa_type);
++
+ void
+ k5_preauth_prepare_request(krb5_context context, krb5_get_init_creds_opt *opt,
+                            krb5_kdc_req *request);
+diff --git a/src/lib/krb5/krb/preauth2.c b/src/lib/krb5/krb/preauth2.c
+index 354234a93..17f2133b1 100644
+--- a/src/lib/krb5/krb/preauth2.c
++++ b/src/lib/krb5/krb/preauth2.c
+@@ -54,7 +54,7 @@ struct krb5_preauth_context_st {
+ 
+ struct krb5_preauth_req_context_st {
+     krb5_context orig_context;
+-    krb5_preauthtype *tried;
++    krb5_preauthtype *failed;
+     krb5_clpreauth_modreq *modreqs;
+ };
+ 
+@@ -201,11 +201,7 @@ cleanup:
+     free_handles(context, list);
+ }
+ 
+-/*
+- * Reset the memory of which preauth types we have already tried, because we
+- * are entering a new phase of padata processing (such as the padata in an
+- * AS-REP).
+- */
++/* Reset the memory of which preauth types we have already tried. */
+ void
+ k5_reset_preauth_types_tried(krb5_init_creds_context ctx)
+ {
+@@ -213,10 +209,27 @@ k5_reset_preauth_types_tried(krb5_init_creds_context ctx)
+ 
+     if (reqctx == NULL)
+         return;
+-    free(reqctx->tried);
+-    reqctx->tried = NULL;
++    free(reqctx->failed);
++    reqctx->failed = NULL;
+ }
+ 
++/* Add pa_type to the list of types which has previously failed. */
++krb5_error_code
++k5_preauth_note_failed(krb5_init_creds_context ctx, krb5_preauthtype pa_type)
++{
++    krb5_preauth_req_context reqctx = ctx->preauth_reqctx;
++    krb5_preauthtype *newptr;
++    size_t i;
++
++    for (i = 0; reqctx->failed != NULL && reqctx->failed[i] != 0; i++);
++    newptr = realloc(reqctx->failed, (i + 2) * sizeof(*newptr));
++    if (newptr == NULL)
++        return ENOMEM;
++    reqctx->failed = newptr;
++    reqctx->failed[i] = pa_type;
++    reqctx->failed[i + 1] = 0;
++    return 0;
++}
+ 
+ /* Free the per-krb5_context preauth_context. This means clearing any
+  * plugin-specific context which may have been created, and then
+@@ -291,7 +304,7 @@ k5_preauth_request_context_fini(krb5_context context,
+         TRACE_PREAUTH_WRONG_CONTEXT(context);
+     }
+     free(reqctx->modreqs);
+-    free(reqctx->tried);
++    free(reqctx->failed);
+     free(reqctx);
+     ctx->preauth_reqctx = NULL;
+ }
+@@ -612,28 +625,17 @@ pa_type_allowed(krb5_init_creds_context ctx, krb5_preauthtype pa_type)
+         pa_type == ctx->allowed_preauth_type;
+ }
+ 
+-/*
+- * If pa_type has already been tried as a real preauth type for this
+- * authentication, return true.  Otherwise ass pa_type to the list of tried
+- * types and return false.
+- */
++/* Return true if pa_type previously failed during this authentication. */
+ static krb5_boolean
+-already_tried(krb5_init_creds_context ctx, krb5_preauthtype pa_type)
++previously_failed(krb5_init_creds_context ctx, krb5_preauthtype pa_type)
+ {
+     krb5_preauth_req_context reqctx = ctx->preauth_reqctx;
+     size_t i;
+-    krb5_preauthtype *newptr;
+ 
+-    for (i = 0; reqctx->tried != NULL && reqctx->tried[i] != 0; i++) {
+-        if (reqctx->tried[i] == pa_type)
++    for (i = 0; reqctx->failed != NULL && reqctx->failed[i] != 0; i++) {
++        if (reqctx->failed[i] == pa_type)
+             return TRUE;
+     }
+-    newptr = realloc(reqctx->tried, (i + 2) * sizeof(*newptr));
+-    if (newptr == NULL)
+-        return FALSE;
+-    reqctx->tried = newptr;
+-    reqctx->tried[i] = pa_type;
+-    reqctx->tried[i + 1] = ENCTYPE_NULL;
+     return FALSE;
+ }
+ 
+@@ -665,8 +667,8 @@ process_pa_data(krb5_context context, krb5_init_creds_context ctx,
+             /* Make sure this type is for the current pass. */
+             if (clpreauth_is_real(context, h, pa->pa_type) != real)
+                 continue;
+-            /* Only try a real mechanism once per authentication. */
+-            if (real && already_tried(ctx, pa->pa_type))
++            /* Don't try a real mechanism again after failure. */
++            if (real && previously_failed(ctx, pa->pa_type))
+                 continue;
+             mod_pa = NULL;
+             ret = clpreauth_process(context, h, modreq, ctx->opt, &callbacks,
+@@ -694,6 +696,12 @@ process_pa_data(krb5_context context, krb5_init_creds_context ctx,
+                 /* Save the first error we get from a real preauth type. */
+                 k5_save_ctx_error(context, ret, &save);
+             }
++            if (real && ret) {
++                /* Don't try this mechanism again for this authentication. */
++                ret = k5_preauth_note_failed(ctx, pa->pa_type);
++                if (ret)
++                    goto cleanup;
++            }
+         }
+     }
+ 
+@@ -944,9 +952,10 @@ k5_preauth_tryagain(krb5_context context, krb5_init_creds_context ctx,
+     TRACE_PREAUTH_TRYAGAIN(context, h->vt.name, pa_type, ret);
+     if (!ret && mod_pa == NULL)
+         ret = KRB5KRB_ERR_GENERIC;
+-    if (ret)
++    if (ret) {
++        k5_preauth_note_failed(ctx, pa_type);
+         return ret;
+-
++    }
+ 
+     for (count = 0; mod_pa[count] != NULL; count++);
+     ret = copy_cookie(context, err_padata, &mod_pa, &count);
diff --git a/SOURCES/Update-man-pages-to-reference-kerberos-7.patch b/SOURCES/Update-man-pages-to-reference-kerberos-7.patch
new file mode 100644
index 0000000..b5cdfe6
--- /dev/null
+++ b/SOURCES/Update-man-pages-to-reference-kerberos-7.patch
@@ -0,0 +1,475 @@
+From 7bcff005db31c62b37ea5c364cd65526cfaecbf1 Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Mon, 15 Oct 2018 15:19:12 -0400
+Subject: [PATCH] Update man pages to reference kerberos(7)
+
+Remove broken references to old kerberos(1).  Reference kerberos(7)
+from all man pages, and create/update their environment section so
+that it references kerberos(7).
+
+ticket: 8755
+(cherry picked from commit 52cbe198d0d6f0085d4653b2f6a1ecc84d139118)
+[rharwood@redhat.com: git got weird about fuzz]
+---
+ doc/admin/admin_commands/k5srvutil.rst      |  9 ++++++++-
+ doc/admin/admin_commands/kadmin_local.rst   |  9 ++++++++-
+ doc/admin/admin_commands/kadmind.rst        |  9 ++++++++-
+ doc/admin/admin_commands/kdb5_ldap_util.rst |  9 ++++++++-
+ doc/admin/admin_commands/kdb5_util.rst      |  9 ++++++++-
+ doc/admin/admin_commands/kprop.rst          |  8 ++++----
+ doc/admin/admin_commands/kpropd.rst         | 10 +++++++++-
+ doc/admin/admin_commands/kproplog.rst       |  7 +++----
+ doc/admin/admin_commands/krb5kdc.rst        |  8 +++-----
+ doc/admin/admin_commands/ktutil.rst         |  9 ++++++++-
+ doc/admin/admin_commands/sserver.rst        |  9 ++++++++-
+ doc/user/user_commands/kdestroy.rst         | 13 +++----------
+ doc/user/user_commands/kinit.rst            | 14 +++-----------
+ doc/user/user_commands/klist.rst            | 13 +++----------
+ doc/user/user_commands/kpasswd.rst          |  9 ++++++++-
+ doc/user/user_commands/krb5-config.rst      |  2 +-
+ doc/user/user_commands/ksu.rst              | 13 +++++++++++++
+ doc/user/user_commands/kswitch.rst          | 14 ++++----------
+ doc/user/user_commands/kvno.rst             |  9 +++------
+ doc/user/user_commands/sclient.rst          |  8 +++++++-
+ 20 files changed, 120 insertions(+), 71 deletions(-)
+
+diff --git a/doc/admin/admin_commands/k5srvutil.rst b/doc/admin/admin_commands/k5srvutil.rst
+index b873d9077..79502cf9e 100644
+--- a/doc/admin/admin_commands/k5srvutil.rst
++++ b/doc/admin/admin_commands/k5srvutil.rst
+@@ -56,7 +56,14 @@ k5srvutil uses the :ref:`kadmin(1)` program to edit the keytab in
+ place.
+ 
+ 
++ENVIRONMENT
++-----------
++
++See :ref:`kerberos(7)` for a description of Kerberos environment
++variables.
++
++
+ SEE ALSO
+ --------
+ 
+-:ref:`kadmin(1)`, :ref:`ktutil(1)`
++:ref:`kadmin(1)`, :ref:`ktutil(1)`, :ref:`kerberos(7)`
+diff --git a/doc/admin/admin_commands/kadmin_local.rst b/doc/admin/admin_commands/kadmin_local.rst
+index 50c3b99ea..0e955faf2 100644
+--- a/doc/admin/admin_commands/kadmin_local.rst
++++ b/doc/admin/admin_commands/kadmin_local.rst
+@@ -989,7 +989,14 @@ The kadmin program was originally written by Tom Yu at MIT, as an
+ interface to the OpenVision Kerberos administration program.
+ 
+ 
++ENVIRONMENT
++-----------
++
++See :ref:`kerberos(7)` for a description of Kerberos environment
++variables.
++
++
+ SEE ALSO
+ --------
+ 
+-:ref:`kpasswd(1)`, :ref:`kadmind(8)`
++:ref:`kpasswd(1)`, :ref:`kadmind(8)`, :ref:`kerberos(7)`
+diff --git a/doc/admin/admin_commands/kadmind.rst b/doc/admin/admin_commands/kadmind.rst
+index f5b7733ea..8bfb48a32 100644
+--- a/doc/admin/admin_commands/kadmind.rst
++++ b/doc/admin/admin_commands/kadmind.rst
+@@ -116,8 +116,15 @@ OPTIONS
+     <dboptions>` in :ref:`kadmin(1)` for supported arguments.
+ 
+ 
++ENVIRONMENT
++-----------
++
++See :ref:`kerberos(7)` for a description of Kerberos environment
++variables.
++
++
+ SEE ALSO
+ --------
+ 
+ :ref:`kpasswd(1)`, :ref:`kadmin(1)`, :ref:`kdb5_util(8)`,
+-:ref:`kdb5_ldap_util(8)`, :ref:`kadm5.acl(5)`
++:ref:`kdb5_ldap_util(8)`, :ref:`kadm5.acl(5)`, :ref:`kerberos(7)`
+diff --git a/doc/admin/admin_commands/kdb5_ldap_util.rst b/doc/admin/admin_commands/kdb5_ldap_util.rst
+index cbf313f55..343df4dd9 100644
+--- a/doc/admin/admin_commands/kdb5_ldap_util.rst
++++ b/doc/admin/admin_commands/kdb5_ldap_util.rst
+@@ -456,7 +456,14 @@ Example::
+ .. _kdb5_ldap_util_list_policy_end:
+ 
+ 
++ENVIRONMENT
++-----------
++
++See :ref:`kerberos(7)` for a description of Kerberos environment
++variables.
++
++
+ SEE ALSO
+ --------
+ 
+-:ref:`kadmin(1)`
++:ref:`kadmin(1)`, :ref:`kerberos(7)`
+diff --git a/doc/admin/admin_commands/kdb5_util.rst b/doc/admin/admin_commands/kdb5_util.rst
+index 258498f0d..18a3fb627 100644
+--- a/doc/admin/admin_commands/kdb5_util.rst
++++ b/doc/admin/admin_commands/kdb5_util.rst
+@@ -491,7 +491,14 @@ Examples::
+     bar@EXAMPLE.COM	1	1	des-cbc-crc	normal	-1
+ 
+ 
++ENVIRONMENT
++-----------
++
++See :ref:`kerberos(7)` for a description of Kerberos environment
++variables.
++
++
+ SEE ALSO
+ --------
+ 
+-:ref:`kadmin(1)`
++:ref:`kadmin(1)`, :ref:`kerberos(7)`
+diff --git a/doc/admin/admin_commands/kprop.rst b/doc/admin/admin_commands/kprop.rst
+index 726c8cc2f..0bc353239 100644
+--- a/doc/admin/admin_commands/kprop.rst
++++ b/doc/admin/admin_commands/kprop.rst
+@@ -49,12 +49,12 @@ OPTIONS
+ ENVIRONMENT
+ -----------
+ 
+-*kprop* uses the following environment variable:
+-
+-* **KRB5_CONFIG**
++See :ref:`kerberos(7)` for a description of Kerberos environment
++variables.
+ 
+ 
+ SEE ALSO
+ --------
+ 
+-:ref:`kpropd(8)`, :ref:`kdb5_util(8)`, :ref:`krb5kdc(8)`
++:ref:`kpropd(8)`, :ref:`kdb5_util(8)`, :ref:`krb5kdc(8)`,
++:ref:`kerberos(7)`
+diff --git a/doc/admin/admin_commands/kpropd.rst b/doc/admin/admin_commands/kpropd.rst
+index 5e01e2f14..36ad3344c 100644
+--- a/doc/admin/admin_commands/kpropd.rst
++++ b/doc/admin/admin_commands/kpropd.rst
+@@ -124,7 +124,15 @@ kpropd.acl
+     will allow Kerberos database propagation via :ref:`kprop(8)`.
+ 
+ 
++ENVIRONMENT
++-----------
++
++See :ref:`kerberos(7)` for a description of Kerberos environment
++variables.
++
++
+ SEE ALSO
+ --------
+ 
+-:ref:`kprop(8)`, :ref:`kdb5_util(8)`, :ref:`krb5kdc(8)`, inetd(8)
++:ref:`kprop(8)`, :ref:`kdb5_util(8)`, :ref:`krb5kdc(8)`,
++:ref:`kerberos(7)`, inetd(8)
+diff --git a/doc/admin/admin_commands/kproplog.rst b/doc/admin/admin_commands/kproplog.rst
+index ed906398d..b98e1b29b 100644
+--- a/doc/admin/admin_commands/kproplog.rst
++++ b/doc/admin/admin_commands/kproplog.rst
+@@ -74,12 +74,11 @@ OPTIONS
+ ENVIRONMENT
+ -----------
+ 
+-kproplog uses the following environment variables:
+-
+-* **KRB5_KDC_PROFILE**
++See :ref:`kerberos(7)` for a description of Kerberos environment
++variables.
+ 
+ 
+ SEE ALSO
+ --------
+ 
+-:ref:`kpropd(8)`
++:ref:`kpropd(8)`, :ref:`kerberos(7)`
+diff --git a/doc/admin/admin_commands/krb5kdc.rst b/doc/admin/admin_commands/krb5kdc.rst
+index 7ec4ee4d3..4bf9e0150 100644
+--- a/doc/admin/admin_commands/krb5kdc.rst
++++ b/doc/admin/admin_commands/krb5kdc.rst
+@@ -110,14 +110,12 @@ description for further details.
+ ENVIRONMENT
+ -----------
+ 
+-krb5kdc uses the following environment variables:
+-
+-* **KRB5_CONFIG**
+-* **KRB5_KDC_PROFILE**
++See :ref:`kerberos(7)` for a description of Kerberos environment
++variables.
+ 
+ 
+ SEE ALSO
+ --------
+ 
+ :ref:`kdb5_util(8)`, :ref:`kdc.conf(5)`, :ref:`krb5.conf(5)`,
+-:ref:`kdb5_ldap_util(8)`
++:ref:`kdb5_ldap_util(8)`, :ref:`kerberos(7)`
+diff --git a/doc/admin/admin_commands/ktutil.rst b/doc/admin/admin_commands/ktutil.rst
+index d55ddc894..5a6fc31a8 100644
+--- a/doc/admin/admin_commands/ktutil.rst
++++ b/doc/admin/admin_commands/ktutil.rst
+@@ -127,7 +127,14 @@ EXAMPLE
+     ktutil:
+ 
+ 
++ENVIRONMENT
++-----------
++
++See :ref:`kerberos(7)` for a description of Kerberos environment
++variables.
++
++
+ SEE ALSO
+ --------
+ 
+-:ref:`kadmin(1)`, :ref:`kdb5_util(8)`
++:ref:`kadmin(1)`, :ref:`kdb5_util(8)`, :ref:`kerberos(7)`
+diff --git a/doc/admin/admin_commands/sserver.rst b/doc/admin/admin_commands/sserver.rst
+index b4e464466..a8dcf5d5b 100644
+--- a/doc/admin/admin_commands/sserver.rst
++++ b/doc/admin/admin_commands/sserver.rst
+@@ -99,7 +99,14 @@ COMMON ERROR MESSAGES
+    probably not installed in the proper directory.
+ 
+ 
++ENVIRONMENT
++-----------
++
++See :ref:`kerberos(7)` for a description of Kerberos environment
++variables.
++
++
+ SEE ALSO
+ --------
+ 
+-:ref:`sclient(1)`, services(5), inetd(8)
++:ref:`sclient(1)`, :ref:`kerberos(7)`, services(5), inetd(8)
+diff --git a/doc/user/user_commands/kdestroy.rst b/doc/user/user_commands/kdestroy.rst
+index b8c67aba4..c69d65667 100644
+--- a/doc/user/user_commands/kdestroy.rst
++++ b/doc/user/user_commands/kdestroy.rst
+@@ -53,15 +53,8 @@ when you log out.
+ ENVIRONMENT
+ -----------
+ 
+-kdestroy uses the following environment variable:
+-
+-**KRB5CCNAME**
+-    Location of the default Kerberos 5 credentials (ticket) cache, in
+-    the form *type*:*residual*.  If no *type* prefix is present, the
+-    **FILE** type is assumed.  The type of the default cache may
+-    determine the availability of a cache collection; for instance, a
+-    default cache of type **DIR** causes caches within the directory
+-    to be present in the collection.
++See :ref:`kerberos(7)` for a description of Kerberos environment
++variables.
+ 
+ 
+ FILES
+@@ -74,4 +67,4 @@ FILES
+ SEE ALSO
+ --------
+ 
+-:ref:`kinit(1)`, :ref:`klist(1)`
++:ref:`kinit(1)`, :ref:`klist(1)`, :ref:`kerberos(7)`
+diff --git a/doc/user/user_commands/kinit.rst b/doc/user/user_commands/kinit.rst
+index 3f9d5340f..33e6aa64f 100644
+--- a/doc/user/user_commands/kinit.rst
++++ b/doc/user/user_commands/kinit.rst
+@@ -197,19 +197,11 @@ OPTIONS
+         specify use of RSA, rather than the default Diffie-Hellman
+         protocol
+ 
+-
+ ENVIRONMENT
+ -----------
+ 
+-kinit uses the following environment variables:
+-
+-**KRB5CCNAME**
+-    Location of the default Kerberos 5 credentials cache, in the form
+-    *type*:*residual*.  If no *type* prefix is present, the **FILE**
+-    type is assumed.  The type of the default cache may determine the
+-    availability of a cache collection; for instance, a default cache
+-    of type **DIR** causes caches within the directory to be present
+-    in the collection.
++See :ref:`kerberos(7)` for a description of Kerberos environment
++variables.
+ 
+ 
+ FILES
+@@ -225,4 +217,4 @@ FILES
+ SEE ALSO
+ --------
+ 
+-:ref:`klist(1)`, :ref:`kdestroy(1)`, kerberos(1)
++:ref:`klist(1)`, :ref:`kdestroy(1)`, :ref:`kerberos(7)`
+diff --git a/doc/user/user_commands/klist.rst b/doc/user/user_commands/klist.rst
+index c24c74132..88e457846 100644
+--- a/doc/user/user_commands/klist.rst
++++ b/doc/user/user_commands/klist.rst
+@@ -105,15 +105,8 @@ value is used to locate the default ticket cache.
+ ENVIRONMENT
+ -----------
+ 
+-klist uses the following environment variable:
+-
+-**KRB5CCNAME**
+-    Location of the default Kerberos 5 credentials (ticket) cache, in
+-    the form *type*:*residual*.  If no *type* prefix is present, the
+-    **FILE** type is assumed.  The type of the default cache may
+-    determine the availability of a cache collection; for instance, a
+-    default cache of type **DIR** causes caches within the directory
+-    to be present in the collection.
++See :ref:`kerberos(7)` for a description of Kerberos environment
++variables.
+ 
+ 
+ FILES
+@@ -129,4 +122,4 @@ FILES
+ SEE ALSO
+ --------
+ 
+-:ref:`kinit(1)`, :ref:`kdestroy(1)`
++:ref:`kinit(1)`, :ref:`kdestroy(1)`, :ref:`kerberos(7)`
+diff --git a/doc/user/user_commands/kpasswd.rst b/doc/user/user_commands/kpasswd.rst
+index 1b6463265..0583bbd05 100644
+--- a/doc/user/user_commands/kpasswd.rst
++++ b/doc/user/user_commands/kpasswd.rst
+@@ -33,7 +33,14 @@ OPTIONS
+     identity of the user invoking the kpasswd command.
+ 
+ 
++ENVIRONMENT
++-----------
++
++See :ref:`kerberos(7)` for a description of Kerberos environment
++variables.
++
++
+ SEE ALSO
+ --------
+ 
+-:ref:`kadmin(1)`, :ref:`kadmind(8)`
++:ref:`kadmin(1)`, :ref:`kadmind(8)`, :ref:`kerberos(7)`
+diff --git a/doc/user/user_commands/krb5-config.rst b/doc/user/user_commands/krb5-config.rst
+index ee0fceaa3..2c09141a1 100644
+--- a/doc/user/user_commands/krb5-config.rst
++++ b/doc/user/user_commands/krb5-config.rst
+@@ -80,4 +80,4 @@ the following output::
+ SEE ALSO
+ --------
+ 
+-kerberos(1), cc(1)
++:ref:`kerberos(7)`, cc(1)
+diff --git a/doc/user/user_commands/ksu.rst b/doc/user/user_commands/ksu.rst
+index b2f9121f0..29487a838 100644
+--- a/doc/user/user_commands/ksu.rst
++++ b/doc/user/user_commands/ksu.rst
+@@ -385,3 +385,16 @@ AUTHOR OF KSU
+ -------------
+ 
+ GENNADY (ARI) MEDVINSKY
++
++
++ENVIRONMENT
++-----------
++
++See :ref:`kerberos(7)` for a description of Kerberos environment
++variables.
++
++
++SEE ALSO
++--------
++
++:ref:`kerberos(7)`, :ref:`kinit(1)`
+diff --git a/doc/user/user_commands/kswitch.rst b/doc/user/user_commands/kswitch.rst
+index 56e5915ac..010332e6a 100644
+--- a/doc/user/user_commands/kswitch.rst
++++ b/doc/user/user_commands/kswitch.rst
+@@ -32,15 +32,8 @@ OPTIONS
+ ENVIRONMENT
+ -----------
+ 
+-kswitch uses the following environment variables:
+-
+-**KRB5CCNAME**
+-    Location of the default Kerberos 5 credentials (ticket) cache, in
+-    the form *type*:*residual*.  If no *type* prefix is present, the
+-    **FILE** type is assumed.  The type of the default cache may
+-    determine the availability of a cache collection; for instance, a
+-    default cache of type **DIR** causes caches within the directory
+-    to be present in the collection.
++See :ref:`kerberos(7)` for a description of Kerberos environment
++variables.
+ 
+ 
+ FILES
+@@ -53,4 +46,5 @@ FILES
+ SEE ALSO
+ --------
+ 
+-:ref:`kinit(1)`, :ref:`kdestroy(1)`, :ref:`klist(1)`), kerberos(1)
++:ref:`kinit(1)`, :ref:`kdestroy(1)`, :ref:`klist(1)`,
++:ref:`kerberos(7)`
+diff --git a/doc/user/user_commands/kvno.rst b/doc/user/user_commands/kvno.rst
+index 31ca24460..f269fb3f9 100644
+--- a/doc/user/user_commands/kvno.rst
++++ b/doc/user/user_commands/kvno.rst
+@@ -63,14 +63,11 @@ OPTIONS
+     delegation is not requested, the service name must match the
+     credentials cache client principal.
+ 
+-
+ ENVIRONMENT
+ -----------
+ 
+-kvno uses the following environment variable:
+-
+-**KRB5CCNAME**
+-    Location of the credentials (ticket) cache.
++See :ref:`kerberos(7)` for a description of Kerberos environment
++variables.
+ 
+ 
+ FILES
+@@ -83,4 +80,4 @@ FILES
+ SEE ALSO
+ --------
+ 
+-:ref:`kinit(1)`, :ref:`kdestroy(1)`
++:ref:`kinit(1)`, :ref:`kdestroy(1)`, :ref:`kerberos(7)`
+diff --git a/doc/user/user_commands/sclient.rst b/doc/user/user_commands/sclient.rst
+index ebf797253..1e3d38f82 100644
+--- a/doc/user/user_commands/sclient.rst
++++ b/doc/user/user_commands/sclient.rst
+@@ -17,8 +17,14 @@ purposes.  It contacts a sample server :ref:`sserver(8)` and
+ authenticates to it using Kerberos version 5 tickets, then displays
+ the server's response.
+ 
++ENVIRONMENT
++-----------
++
++See :ref:`kerberos(7)` for a description of Kerberos environment
++variables.
++
+ 
+ SEE ALSO
+ --------
+ 
+-:ref:`kinit(1)`, :ref:`sserver(8)`
++:ref:`kinit(1)`, :ref:`sserver(8)`, :ref:`kerberos(7)`
diff --git a/SOURCES/Use-SHA-256-instead-of-MD5-for-audit-ticket-IDs.patch b/SOURCES/Use-SHA-256-instead-of-MD5-for-audit-ticket-IDs.patch
new file mode 100644
index 0000000..1451c55
--- /dev/null
+++ b/SOURCES/Use-SHA-256-instead-of-MD5-for-audit-ticket-IDs.patch
@@ -0,0 +1,53 @@
+From c931cdfaa3539e42cfc57caca6b67fe9a03227e2 Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Tue, 10 Jul 2018 16:17:15 -0400
+Subject: [PATCH] Use SHA-256 instead of MD5 for audit ticket IDs
+
+ticket: 8711 (new)
+(cherry picked from commit c1e1bfa26bd2f045e88e6013c500fca9428c98f3)
+---
+ src/kdc/kdc_audit.c | 21 ++++++++++-----------
+ 1 file changed, 10 insertions(+), 11 deletions(-)
+
+diff --git a/src/kdc/kdc_audit.c b/src/kdc/kdc_audit.c
+index c9a7f9f9d..f40913dc8 100644
+--- a/src/kdc/kdc_audit.c
++++ b/src/kdc/kdc_audit.c
+@@ -146,7 +146,7 @@ kau_make_tkt_id(krb5_context context,
+ {
+     krb5_error_code ret = 0;
+     char *hash = NULL, *ptr;
+-    krb5_checksum cksum;
++    uint8_t hashbytes[K5_SHA256_HASHLEN];
+     unsigned int i;
+ 
+     *out = NULL;
+@@ -154,19 +154,18 @@ kau_make_tkt_id(krb5_context context,
+     if (ticket == NULL)
+         return EINVAL;
+ 
+-    ret = krb5_c_make_checksum(context, CKSUMTYPE_RSA_MD5, NULL, 0,
+-                               &ticket->enc_part.ciphertext, &cksum);
++    ret = k5_sha256(&ticket->enc_part.ciphertext, 1, hashbytes);
+     if (ret)
+         return ret;
+ 
+-    hash = k5alloc(cksum.length * 2 + 1, &ret);
+-    if (hash != NULL) {
+-        for (i = 0, ptr = hash; i < cksum.length; i++, ptr += 2)
+-            snprintf(ptr, 3, "%02X", cksum.contents[i]);
+-        *ptr = '\0';
+-        *out = hash;
+-    }
+-    krb5_free_checksum_contents(context, &cksum);
++    hash = k5alloc(sizeof(hashbytes) * 2 + 1, &ret);
++    if (hash == NULL)
++        return ret;
++
++    for (i = 0, ptr = hash; i < sizeof(hashbytes); i++, ptr += 2)
++        snprintf(ptr, 3, "%02X", hashbytes[i]);
++    *ptr = '\0';
++    *out = hash;
+ 
+     return 0;
+ }
diff --git a/SOURCES/Use-a-hash-table-for-MEMORY-ccache-resolution.patch b/SOURCES/Use-a-hash-table-for-MEMORY-ccache-resolution.patch
new file mode 100644
index 0000000..fe0a184
--- /dev/null
+++ b/SOURCES/Use-a-hash-table-for-MEMORY-ccache-resolution.patch
@@ -0,0 +1,185 @@
+From 6e29836f794abdd91aa03d334b72b7a7f4800e92 Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Sat, 4 Aug 2018 23:55:18 -0400
+Subject: [PATCH] Use a hash table for MEMORY ccache resolution
+
+In cc_memory.c, replace the linked list of caches with a hash table,
+for better performance with large numbers of memory caches.
+
+ticket: 8722 (new)
+(cherry picked from commit 088ba228acce4fd55bbb7c30122fe2703b8beeb8)
+---
+ src/lib/krb5/ccache/cc_memory.c | 77 +++++++++++++++------------------
+ 1 file changed, 34 insertions(+), 43 deletions(-)
+
+diff --git a/src/lib/krb5/ccache/cc_memory.c b/src/lib/krb5/ccache/cc_memory.c
+index cfd5c6389..114ef6913 100644
+--- a/src/lib/krb5/ccache/cc_memory.c
++++ b/src/lib/krb5/ccache/cc_memory.c
+@@ -26,6 +26,7 @@
+ 
+ #include "cc-int.h"
+ #include "../krb/int-proto.h"
++#include "k5-hashtab.h"
+ #include <errno.h>
+ 
+ static krb5_error_code KRB5_CALLCONV krb5_mcc_close
+@@ -118,12 +119,6 @@ typedef struct _krb5_mcc_data {
+     int generation;             /* Incremented at each initialize */
+ } krb5_mcc_data;
+ 
+-/* List of memory caches.  */
+-typedef struct krb5_mcc_list_node {
+-    struct krb5_mcc_list_node *next;
+-    krb5_mcc_data *cache;
+-} krb5_mcc_list_node;
+-
+ /* Iterator over credentials in a memory cache. */
+ struct mcc_cursor {
+     int generation;
+@@ -136,10 +131,27 @@ struct krb5_mcc_ptcursor_data {
+ };
+ 
+ k5_cc_mutex krb5int_mcc_mutex = K5_CC_MUTEX_PARTIAL_INITIALIZER;
+-static krb5_mcc_list_node *mcc_head = 0;
++static struct k5_hashtab *mcc_hashtab = NULL;
+ 
+ static void update_mcc_change_time(krb5_mcc_data *);
+ 
++/* Ensure that mcc_hashtab is initialized.  Call with krb5int_mcc_mutex
++ * locked. */
++static krb5_error_code
++init_table(krb5_context context)
++{
++    krb5_error_code ret;
++    uint8_t seed[K5_HASH_SEED_LEN];
++    krb5_data d = make_data(seed, sizeof(seed));
++
++    if (mcc_hashtab != NULL)
++        return 0;
++    ret = krb5_c_random_make_octets(context, &d);
++    if (ret)
++        return ret;
++    return k5_hashtab_create(seed, 64, &mcc_hashtab);
++}
++
+ /* Remove creds from d, invalidate any existing cursors, and unset the client
+  * principal.  The caller is responsible for locking. */
+ static void
+@@ -230,21 +242,13 @@ krb5_mcc_close(krb5_context context, krb5_ccache id)
+ krb5_error_code KRB5_CALLCONV
+ krb5_mcc_destroy(krb5_context context, krb5_ccache id)
+ {
+-    krb5_mcc_list_node **curr, *node;
+     krb5_mcc_data *d = id->data;
+     krb5_boolean removed_from_table = FALSE;
+ 
++    /* Remove this node from the table if it is still present. */
+     k5_cc_mutex_lock(context, &krb5int_mcc_mutex);
+-
+-    for (curr = &mcc_head; *curr; curr = &(*curr)->next) {
+-        if ((*curr)->cache == d) {
+-            node = *curr;
+-            *curr = node->next;
+-            free(node);
+-            removed_from_table = TRUE;
+-            break;
+-        }
+-    }
++    if (k5_hashtab_remove(mcc_hashtab, d->name, strlen(d->name)))
++        removed_from_table = TRUE;
+     k5_cc_mutex_unlock(context, &krb5int_mcc_mutex);
+ 
+     /* Empty the cache and remove the reference for the table slot.  There will
+@@ -289,16 +293,13 @@ krb5_mcc_resolve (krb5_context context, krb5_ccache *id, const char *residual)
+ {
+     krb5_os_context os_ctx = &context->os_context;
+     krb5_ccache lid;
+-    krb5_mcc_list_node *ptr;
+     krb5_error_code err;
+     krb5_mcc_data *d;
+ 
+     k5_cc_mutex_lock(context, &krb5int_mcc_mutex);
+-    for (ptr = mcc_head; ptr; ptr=ptr->next)
+-        if (!strcmp(ptr->cache->name, residual))
+-            break;
+-    if (ptr != NULL) {
+-        d = ptr->cache;
++    init_table(context);
++    d = k5_hashtab_get(mcc_hashtab, residual, strlen(residual));
++    if (d != NULL) {
+         k5_cc_mutex_lock(context, &d->lock);
+         d->refcount++;
+         k5_cc_mutex_unlock(context, &d->lock);
+@@ -438,18 +439,17 @@ krb5_mcc_end_seq_get(krb5_context context, krb5_ccache id, krb5_cc_cursor *curso
+ }
+ 
+ /*
+- * Utility routine: Creates the back-end data for a memory cache, and threads
+- * it into the global linked list.  Give the new object two references, one for
+- * the table slot and one for the caller's handle.
++ * Utility routine: Creates the back-end data for a memory cache, and adds it
++ * to the global table.  Give the new object two references, one for the table
++ * slot and one for the caller's handle.
+  *
+- * Call with the global list lock held.
++ * Call with the global table lock held.
+  */
+ static krb5_error_code
+ new_mcc_data (const char *name, krb5_mcc_data **dataptr)
+ {
+     krb5_error_code err;
+     krb5_mcc_data *d;
+-    krb5_mcc_list_node *n;
+ 
+     d = malloc(sizeof(krb5_mcc_data));
+     if (d == NULL)
+@@ -476,18 +476,13 @@ new_mcc_data (const char *name, krb5_mcc_data **dataptr)
+     d->generation = 0;
+     update_mcc_change_time(d);
+ 
+-    n = malloc(sizeof(krb5_mcc_list_node));
+-    if (n == NULL) {
++    if (k5_hashtab_add(mcc_hashtab, d->name, strlen(d->name), d) != 0) {
+         free(d->name);
+         k5_cc_mutex_destroy(&d->lock);
+         free(d);
+         return KRB5_CC_NOMEM;
+     }
+ 
+-    n->cache = d;
+-    n->next = mcc_head;
+-    mcc_head = n;
+-
+     *dataptr = d;
+     return 0;
+ }
+@@ -522,11 +517,10 @@ krb5_mcc_generate_new (krb5_context context, krb5_ccache *id)
+     lid->ops = &krb5_mcc_ops;
+ 
+     k5_cc_mutex_lock(context, &krb5int_mcc_mutex);
++    init_table(context);
+ 
+     /* Check for uniqueness with mutex locked to avoid race conditions */
+     while (1) {
+-        krb5_mcc_list_node *ptr;
+-
+         err = krb5int_random_string (context, uniquename, sizeof (uniquename));
+         if (err) {
+             k5_cc_mutex_unlock(context, &krb5int_mcc_mutex);
+@@ -534,12 +528,9 @@ krb5_mcc_generate_new (krb5_context context, krb5_ccache *id)
+             return err;
+         }
+ 
+-        for (ptr = mcc_head; ptr; ptr=ptr->next) {
+-            if (!strcmp(ptr->cache->name, uniquename)) {
+-                break;  /* got a match, loop again */
+-            }
+-        }
+-        if (!ptr) break; /* got to the end without finding a match */
++        if (k5_hashtab_get(mcc_hashtab, uniquename,
++                           strlen(uniquename)) == NULL)
++            break;
+     }
+ 
+     err = new_mcc_data(uniquename, &d);
diff --git a/SOURCES/Use-krb5_timestamp-where-appropriate.patch b/SOURCES/Use-krb5_timestamp-where-appropriate.patch
new file mode 100644
index 0000000..96705ed
--- /dev/null
+++ b/SOURCES/Use-krb5_timestamp-where-appropriate.patch
@@ -0,0 +1,327 @@
+From 6eda4c6a2cd301418b2efbfd737a86079abb02e9 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)
+---
+ 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..ceedcda
--- /dev/null
+++ b/SOURCES/Use-the-canonical-client-principal-name-for-OTP.patch
@@ -0,0 +1,29 @@
+From a23d45875c03d6284f6b5b2851d3ecb8d3ec88ce 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)
+---
+ 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..018a14e
--- /dev/null
+++ b/SOURCES/kadmin.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=Kerberos 5 Password-changing and Administration
+Wants=network-online.target
+After=syslog.target network.target network-online.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..5903bd1
--- /dev/null
+++ b/SOURCES/kprop.service
@@ -0,0 +1,12 @@
+[Unit]
+Description=Kerberos 5 Propagation
+Wants=network-online.target
+After=syslog.target network.target network-online.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..4657926
--- /dev/null
+++ b/SOURCES/krb5-1.11-kpasswdtest.patch
@@ -0,0 +1,21 @@
+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
+
+---
+ 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..734341c
--- /dev/null
+++ b/SOURCES/krb5-1.11-run_user_0.patch
@@ -0,0 +1,41 @@
+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
+
+---
+ 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..ae261d5
--- /dev/null
+++ b/SOURCES/krb5-1.12-api.patch
@@ -0,0 +1,34 @@
+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
+
+---
+ 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..7127916
--- /dev/null
+++ b/SOURCES/krb5-1.12-ksu-path.patch
@@ -0,0 +1,21 @@
+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
+
+---
+ 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..d7fe63a
--- /dev/null
+++ b/SOURCES/krb5-1.12-ktany.patch
@@ -0,0 +1,363 @@
+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
+
+---
+ 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..9ea8088
--- /dev/null
+++ b/SOURCES/krb5-1.12.1-pam.patch
@@ -0,0 +1,757 @@
+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
+
+---
+ 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..4ef1afa
--- /dev/null
+++ b/SOURCES/krb5-1.13-dirsrv-accountlock.patch
@@ -0,0 +1,73 @@
+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
+
+---
+ src/aclocal.m4                                  |  9 +++++++++
+ src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c    | 17 +++++++++++++++++
+ .../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..958cfdf
--- /dev/null
+++ b/SOURCES/krb5-1.15-beta1-buildconf.patch
@@ -0,0 +1,65 @@
+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
+
+---
+ 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..2a11b20
--- /dev/null
+++ b/SOURCES/krb5-1.15-beta1-selinux-label.patch
@@ -0,0 +1,1033 @@
+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
+
+---
+ 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..7f2cfdf
--- /dev/null
+++ b/SOURCES/krb5-1.3.1-dns.patch
@@ -0,0 +1,21 @@
+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
+
+---
+ 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..c9a6499
--- /dev/null
+++ b/SOURCES/krb5-1.9-debuginfo.patch
@@ -0,0 +1,36 @@
+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
+
+---
+ 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..0e7c5d5
--- /dev/null
+++ b/SOURCES/krb5-kvno-230379.patch
@@ -0,0 +1,53 @@
+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
+
+---
+ 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..2356a60
--- /dev/null
+++ b/SOURCES/krb5.conf
@@ -0,0 +1,26 @@
+# 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
+ pkinit_anchors = FILE:/etc/pki/tls/certs/ca-bundle.crt
+# 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..806b062
--- /dev/null
+++ b/SOURCES/krb5kdc.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=Kerberos 5 KDC
+Wants=network-online.target
+After=syslog.target network.target network-online.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..249e0ca
--- /dev/null
+++ b/SPECS/krb5.spec
@@ -0,0 +1,3782 @@
+%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: 46%{?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
+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
+Patch177: Limit-ticket-lifetime-to-2-31-1-seconds.patch
+Patch178: Fix-hex-conversion-of-PKINIT-certid-strings.patch
+Patch179: Simplify-PKINIT-cert-iteration-and-selection.patch
+Patch180: Fix-PKINIT-cert-matching-data-construction.patch
+Patch181: Save-SANs-separately-and-unparse-them-with-NO_REALM.patch
+Patch182: Return-UPN-SANs-as-strings.patch
+Patch183: Fix-segfault-in-finish_dispatch.patch
+Patch184: Fix-flaws-in-LDAP-DN-checking.patch
+Patch185: Merge-duplicate-subsections-in-profile-library.patch
+Patch186: Continue-after-KRB5_CC_END-in-KCM-cache-iteration.patch
+Patch187: Exit-with-status-0-from-kadmind.patch
+Patch188: Ignore-dotfiles-in-profile-includedir.patch
+Patch189: Add-k5_dir_filenames-to-libkrb5support.patch
+Patch190: Process-profile-includedir-in-sorted-order.patch
+Patch191: Add-German-translation.patch
+Patch192: Remove-nodes-option-from-make-certs-scripts.patch
+Patch193: Make-krb5_preauth_context-a-pointer-type.patch
+Patch194: Properly-scope-per-request-preauth-data.patch
+Patch195: Add-tests-for-per-request-preauth-data-scoping.patch
+Patch196: Document-and-check-init_creds-context-requirement.patch
+Patch197: Add-test-case-for-PKINIT-DH-renegotiation.patch
+Patch198: Echo-KDC-cookies-in-preauth-tryagain.patch
+Patch199: Adjust-processing-of-pa_type-ccache-config.patch
+Patch200: Simplify-k5_preauth_tryagain.patch
+Patch201: Remove-sent_nontrivial_preauth-field.patch
+Patch202: Track-preauth-failures-instead-of-tries.patch
+Patch203: Preserve-method-data-in-get_in_tkt.c.patch
+Patch204: Continue-preauth-after-client-side-failures.patch
+Patch205: Continue-after-KDC_ERR_PREAUTH_FAILED.patch
+Patch206: Add-test-cases-for-preauth-fallback-behavior.patch
+Patch207: Include-preauth-name-in-trace-output-if-possible.patch
+Patch208: Add-vector-support-to-k5_sha256.patch
+Patch209: Use-SHA-256-instead-of-MD5-for-audit-ticket-IDs.patch
+Patch211: In-FIPS-mode-add-plaintext-fallback-for-RC4-usages-a.patch
+Patch212: Fix-bugs-with-concurrent-use-of-MEMORY-ccaches.patch
+Patch213: Don-t-include-all-MEMORY-ccaches-in-collection.patch
+Patch214: Add-libkrb5support-hex-functions-and-tests.patch
+Patch215: Add-a-hash-table-implementation-to-libkrb5support.patch
+Patch216: Use-a-hash-table-for-MEMORY-ccache-resolution.patch
+Patch217: Remove-incorrect-KDC-assertion.patch
+Patch218: Prefer-TCP-to-UDP-for-password-changes.patch
+Patch219: Bring-back-general-kerberos-man-page.patch
+Patch220: Modernize-kerberos-7.patch
+Patch221: Update-man-pages-to-reference-kerberos-7.patch
+Patch222: Log-when-non-root-ksu-authorization-fails.patch
+Patch223: Correct-kpasswd_server-description-in-krb5.conf-5.patch
+Patch224: Address-some-optimized-out-memset-calls.patch
+Patch225: Add-the-certauth-dbmatch-module.patch
+Patch226: Correct-error-handling-bug-in-prior-commit.patch
+Patch227: Add-PKINIT-test-case-for-generic-client-cert.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
+%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
+%patch177 -p1 -b .Limit-ticket-lifetime-to-2-31-1-seconds
+%patch178 -p1 -b .Fix-hex-conversion-of-PKINIT-certid-strings
+%patch179 -p1 -b .Simplify-PKINIT-cert-iteration-and-selection
+%patch180 -p1 -b .Fix-PKINIT-cert-matching-data-construction
+%patch181 -p1 -b .Save-SANs-separately-and-unparse-them-with-NO_REALM
+%patch182 -p1 -b .Return-UPN-SANs-as-strings
+%patch183 -p1 -b .Fix-segfault-in-finish_dispatch
+%patch184 -p1 -b .Fix-flaws-in-LDAP-DN-checking
+%patch185 -p1 -b .Merge-duplicate-subsections-in-profile-library
+%patch186 -p1 -b .Continue-after-KRB5_CC_END-in-KCM-cache-iteration
+%patch187 -p1 -b .Exit-with-status-0-from-kadmind
+%patch188 -p1 -b .Ignore-dotfiles-in-profile-includedir
+%patch189 -p1 -b .Add-k5_dir_filenames-to-libkrb5support
+%patch190 -p1 -b .Process-profile-includedir-in-sorted-order
+%patch191 -p1 -b .Add-German-translation
+%patch192 -p1 -b .Remove-nodes-option-from-make-certs-scripts
+%patch193 -p1 -b .Make-krb5_preauth_context-a-pointer-type
+%patch194 -p1 -b .Properly-scope-per-request-preauth-data
+%patch195 -p1 -b .Add-tests-for-per-request-preauth-data-scoping
+%patch196 -p1 -b .Document-and-check-init_creds-context-requirement
+%patch197 -p1 -b .Add-test-case-for-PKINIT-DH-renegotiation
+%patch198 -p1 -b .Echo-KDC-cookies-in-preauth-tryagain
+%patch199 -p1 -b .Adjust-processing-of-pa_type-ccache-config
+%patch200 -p1 -b .Simplify-k5_preauth_tryagain
+%patch201 -p1 -b .Remove-sent_nontrivial_preauth-field
+%patch202 -p1 -b .Track-preauth-failures-instead-of-tries
+%patch203 -p1 -b .Preserve-method-data-in-get_in_tkt.c
+%patch204 -p1 -b .Continue-preauth-after-client-side-failures
+%patch205 -p1 -b .Continue-after-KDC_ERR_PREAUTH_FAILED
+%patch206 -p1 -b .Add-test-cases-for-preauth-fallback-behavior
+%patch207 -p1 -b .Include-preauth-name-in-trace-output-if-possible
+%patch208 -p1 -b .Add-vector-support-to-k5_sha256
+%patch209 -p1 -b .Use-SHA-256-instead-of-MD5-for-audit-ticket-IDs
+%patch211 -p1 -b .In-FIPS-mode-add-plaintext-fallback-for-RC4-usages-a
+%patch212 -p1 -b .Fix-bugs-with-concurrent-use-of-MEMORY-ccaches
+%patch213 -p1 -b .Don-t-include-all-MEMORY-ccaches-in-collection
+%patch214 -p1 -b .Add-libkrb5support-hex-functions-and-tests
+%patch215 -p1 -b .Add-a-hash-table-implementation-to-libkrb5support
+%patch216 -p1 -b .Use-a-hash-table-for-MEMORY-ccache-resolution
+%patch217 -p1 -b .Remove-incorrect-KDC-assertion
+%patch218 -p1 -b .Prefer-TCP-to-UDP-for-password-changes
+%patch219 -p1 -b .Bring-back-general-kerberos-man-page
+%patch220 -p1 -b .Modernize-kerberos-7
+%patch221 -p1 -b .Update-man-pages-to-reference-kerberos-7
+%patch222 -p1 -b .Log-when-non-root-ksu-authorization-fails
+%patch223 -p1 -b .Correct-kpasswd_server-description-in-krb5.conf-5
+%patch224 -p1 -b .Address-some-optimized-out-memset-calls
+%patch225 -p1 -b .Add-the-certauth-dbmatch-module
+%patch226 -p1 -b .Correct-error-handling-bug-in-prior-commit
+%patch227 -p1 -b .Add-PKINIT-test-case-for-generic-client-cert
+
+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-crypto-impl=builtin \
+	--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*
+/%{_mandir}/man7/kerberos.7*
+%{_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
+* Mon Jul 29 2019 Robbie Harwood <rharwood@redhat.com> - 1.15.1-46
+- Add pkinit_cert_match support
+- Resolves: #1656126
+
+* Mon Jul 29 2019 Robbie Harwood <rharwood@redhat.com> - 1.15.1-45
+- Install kerberos(7)
+- Resolves: #1704726
+
+* Mon Jul 29 2019 Robbie Harwood <rharwood@redhat.com> - 1.15.1-44
+- Address some optimized-out memset() calls
+- Resolves: #1663506
+
+* Mon Jul 29 2019 Robbie Harwood <rharwood@redhat.com> - 1.15.1-43
+- Correct kpasswd_server description in krb5.conf(5)
+- Resolves: #1498347
+
+* Mon Jul 29 2019 Robbie Harwood <rharwood@redhat.com> - 1.15.1-42
+- Log when non-root ksu authorization fails
+- Resolves: #1270927
+
+* Mon Jul 29 2019 Robbie Harwood <rharwood@redhat.com> - 1.15.1-41
+- Update man pages to reference kerberos(7)
+- Resolves: #1704726
+
+* Wed Jul 24 2019 Robbie Harwood <rharwood@redhat.com> - 1.15.1-40
+- Prefer TCP to UDP for password changes
+- Resolves: #1637349
+
+* Mon Jul 22 2019 Robbie Harwood <rharwood@redhat.com> - 1.15.1-39
+- Remove incorrect KDC assertion
+- Resolves: #1673017
+
+* Mon Jul 22 2019 Robbie Harwood <rharwood@redhat.com> - 1.15.1-38
+- Add FILE prefix to pkinit_anchors field
+- Resolves: #1661338
+
+* Tue Dec 18 2018 Robbie Harwood <rharwood@redhat.com> - 1.15.1-37
+- Bring back builtin crypto (openssl broke too many FIPS setups)
+- Resolves: #1645711
+
+* Mon Dec 17 2018 Robbie Harwood <rharwood@redhat.com> - 1.15.1-36
+- Clean up MEMORY ccache behavior to match upstream more closely
+- Resolves: #1605756
+
+* Tue Dec 11 2018 Robbie Harwood <rharwood@redhat.com> - 1.15.1-35
+- Fix bugs with concurrent use of MEMORY ccaches
+- Resolves: #1605756
+
+* Wed Aug 01 2018 Robbie Harwood <rharwood@redhat.com> - 1.15.1-34
+- In FIPS mode, add plaintext fallback for RC4 usages and taint
+- Resolves: #1570600
+
+* Tue Jul 10 2018 Robbie Harwood <rharwood@redhat.com> - 1.15.1-33
+- Use SHA-256 instead of MD5 for audit ticket IDs
+- Resolves: #1570600
+
+* Mon Jun 11 2018 Robbie Harwood <rharwood@redhat.com> - 1.15.1-32
+- Include preauth name in trace output if possible
+- Update cert generation scripts to work on modern openssl
+- Fix per-request preauth scoping
+- Add test case for PKINIT DH renegotiation
+- Echo KDC cookies in preauth tryagain
+- Fall back to other preauth mechanisms after failures
+- Resolves: #1540130
+
+* Fri Jun 08 2018 Robbie Harwood <rharwood@redhat.com> - 1.15.1-31
+- Add German translation
+- Resolves: #1497301
+
+* Fri Jun 08 2018 Robbie Harwood <rharwood@redhat.com> - 1.15.1-30
+- Add default pkinit_anchors value to krb5.conf
+- Resolves: #1508081
+
+* Thu Jun 07 2018 Robbie Harwood <rharwood@redhat.com> - 1.15.1-29
+- Process profile includedir in sorted order
+- Also, ignore dotfiles in included directories
+- Resolves: #1539824
+
+* Thu Jun 07 2018 Robbie Harwood <rharwood@redhat.com> - 1.15.1-28
+- Exit with status 0 from kadmind
+- Resolves: #1373909
+
+* Thu Jun 07 2018 Robbie Harwood <rharwood@redhat.com> - 1.15.1-27
+- Continue after KRB5_CC_END in KCM cache iteration
+- Resolves: #1563166
+
+* Thu Jun 07 2018 Robbie Harwood <rharwood@redhat.com> - 1.15.1-26
+- Merge duplicate subsections in profile library
+- Resolves: #1519625
+
+* Thu Jun 07 2018 Robbie Harwood <rharwood@redhat.com> - 1.15.1-25
+- Fix service dependencies on network state
+- Resolves: #1525232
+
+* Thu Jun 07 2018 Robbie Harwood <rharwood@redhat.com> - 1.15.1-24
+- Explicitly use openssl rather than builtin crypto
+- Resolves: #1570600
+
+* Mon Apr 30 2018 Robbie Harwood <rharwood@redhat.com> - 1.15.1-23
+- Fix flaws in LDAP DN checking (CVE-2018-5729, CVE-2018-5730)
+- Resolves: #1562684
+- Resolves: #1562679
+
+* Wed Apr 18 2018 Robbie Harwood <rharwood@redhat.com> - 1.15.1-22
+- Fix segfault in finish_dispatch()
+- Resolves: #1568970
+
+* Thu Apr 05 2018 Robbie Harwood <rharwood@redhat.com> - 1.15.1-21
+- Unparse SANs with NO_REALM
+- Resolves: #1482457
+
+* Thu Mar 22 2018 Robbie Harwood <rharwood@redhat.com> - 1.15.1-20
+- Fix hex conversion of PKINIT certid strings
+- Resolves: #1538491
+
+* Fri Mar 02 2018 Robbie Harwood <rharwood@redhat.com> - 1.15.1-19
+- Limit ticket lifetime to 2^31-1 seconds
+- Resolves: #1554723
+
+* 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