diff --git a/.gitignore b/.gitignore
index d4151c9..61533df 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,4 @@
-SOURCES/krb5-1.14.1-pdfs.tar
-SOURCES/krb5-1.14.1.tar.gz
+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
index cfff662..22193ae 100644
--- a/.krb5.metadata
+++ b/.krb5.metadata
@@ -1,4 +1,4 @@
-a374c9aec97659bebf99244c83c24c069764e6a3 SOURCES/krb5-1.14.1-pdfs.tar
-f12dc3b8630fd1fefb7058cd782754489377308b SOURCES/krb5-1.14.1.tar.gz
+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-certauth-pluggable-interface.patch b/SOURCES/Add-certauth-pluggable-interface.patch
new file mode 100644
index 0000000..30a25ca
--- /dev/null
+++ b/SOURCES/Add-certauth-pluggable-interface.patch
@@ -0,0 +1,1146 @@
+From c206d6f3351d51ef3a916ef8522ab58c1a8572f7 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 ++
+ src/plugins/certauth/test/certauth_test.exports    |   2 +
+ src/plugins/certauth/test/deps                     |  14 +
+ src/plugins/certauth/test/main.c                   | 209 +++++++++++++
+ src/plugins/preauth/pkinit/pkinit_crypto.h         |   4 +
+ src/plugins/preauth/pkinit/pkinit_crypto_openssl.c |  30 ++
+ src/plugins/preauth/pkinit/pkinit_srv.c            | 335 ++++++++++++++++++---
+ src/plugins/preauth/pkinit/pkinit_trace.h          |   5 +
+ src/tests/Makefile.in                              |   1 +
+ src/tests/t_certauth.py                            |  47 +++
+ 19 files changed, 786 insertions(+), 42 deletions(-)
+ create mode 100644 doc/plugindev/certauth.rst
+ create mode 100644 src/include/krb5/certauth_plugin.h
+ create mode 100644 src/plugins/certauth/test/Makefile.in
+ create mode 100644 src/plugins/certauth/test/certauth_test.exports
+ create mode 100644 src/plugins/certauth/test/deps
+ create mode 100644 src/plugins/certauth/test/main.c
+ create mode 100644 src/tests/t_certauth.py
+
+diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
+index 653aad613..c0e4349c0 100644
+--- a/doc/admin/conf_files/krb5_conf.rst
++++ b/doc/admin/conf_files/krb5_conf.rst
+@@ -858,6 +858,27 @@ built-in modules exist for this interface:
+     This module authorizes a principal to a local account if the
+     principal name maps to the local account name.
+ 
++.. _certauth:
++
++certauth interface
++##################
++
++The certauth section (introduced in release 1.16) controls modules for
++the certificate authorization interface, which determines whether a
++certificate is allowed to preauthenticate a user via PKINIT.  The
++following built-in modules exist for this interface:
++
++**pkinit_san**
++    This module authorizes the certificate if it contains a PKINIT
++    Subject Alternative Name for the requested client principal, or a
++    Microsoft UPN SAN matching the principal if **pkinit_allow_upn**
++    is set to true for the realm.
++
++**pkinit_eku**
++    This module rejects the certificate if it does not contain an
++    Extended Key Usage attribute consistent with the
++    **pkinit_eku_checking** value for the realm.
++
+ 
+ PKINIT options
+ --------------
+diff --git a/doc/plugindev/certauth.rst b/doc/plugindev/certauth.rst
+new file mode 100644
+index 000000000..8a7f7c5eb
+--- /dev/null
++++ b/doc/plugindev/certauth.rst
+@@ -0,0 +1,27 @@
++.. _certauth_plugin:
++
++PKINIT certificate authorization interface (certauth)
++=====================================================
++
++The certauth interface was first introduced in release 1.16.  It
++allows customization of the X.509 certificate attribute requirements
++placed on certificates used by PKINIT enabled clients.  For a detailed
++description of the certauth interface, see the header file
++``<krb5/certauth_plugin.h>``
++
++A certauth module implements the **authorize** method to determine
++whether a client's certificate is authorized to authenticate a client
++principal.  **authorize** receives the DER-encoded certificate, the
++requested client principal, and a pointer to the client's
++krb5_db_entry (for modules that link against libkdb5).  It returns the
++authorization status and optionally outputs a list of authentication
++indicator strings to be added to the ticket.  A module must use its
++own internal or library-provided ASN.1 certificate decoder.
++
++A module can optionally create and destroy module data with the
++**init** and **fini** methods.  Module data objects last for the
++lifetime of the KDC process.
++
++If a module allocates and returns a list of authentication indicators
++from **authorize**, it must also implement the **free_ind** method
++to free the list.
+diff --git a/doc/plugindev/index.rst b/doc/plugindev/index.rst
+index 3fb921778..67dbc2790 100644
+--- a/doc/plugindev/index.rst
++++ b/doc/plugindev/index.rst
+@@ -31,5 +31,6 @@ Contents
+    profile.rst
+    gssapi.rst
+    internal.rst
++   certauth.rst
+ 
+ .. TODO: GSSAPI mechanism plugins
+diff --git a/src/Makefile.in b/src/Makefile.in
+index 2ebf2fb4d..b0249778c 100644
+--- a/src/Makefile.in
++++ b/src/Makefile.in
+@@ -17,6 +17,7 @@ SUBDIRS=util include lib \
+ 	plugins/pwqual/test \
+ 	plugins/authdata/greet_server \
+ 	plugins/authdata/greet_client \
++	plugins/certauth/test \
+ 	plugins/kdb/db2 \
+ 	@ldap_plugin_dir@ \
+ 	plugins/kdb/test \
+diff --git a/src/configure.in b/src/configure.in
+index acf3a458b..24f653f0d 100644
+--- a/src/configure.in
++++ b/src/configure.in
+@@ -1451,6 +1451,7 @@ dnl	ccapi ccapi/lib ccapi/lib/unix ccapi/server ccapi/server/unix ccapi/test
+ 
+ 	kdc slave config-files build-tools man doc include
+ 
++	plugins/certauth/test
+ 	plugins/hostrealm/test
+ 	plugins/localauth/test
+ 	plugins/kadm5_hook/test
+diff --git a/src/include/Makefile.in b/src/include/Makefile.in
+index f5b921833..0239338a1 100644
+--- a/src/include/Makefile.in
++++ b/src/include/Makefile.in
+@@ -140,6 +140,7 @@ install-headers-unix install: krb5/krb5.h profile.h
+ 	$(INSTALL_DATA) $(srcdir)/krb5.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5.h
+ 	$(INSTALL_DATA) $(srcdir)/kdb.h $(DESTDIR)$(KRB5_INCDIR)$(S)kdb.h
+ 	$(INSTALL_DATA) krb5/krb5.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)krb5.h
++	$(INSTALL_DATA) $(srcdir)/krb5/certauth_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)certauth_plugin.h
+ 	$(INSTALL_DATA) $(srcdir)/krb5/ccselect_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)ccselect_plugin.h
+ 	$(INSTALL_DATA) $(srcdir)/krb5/clpreauth_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)clpreauth_plugin.h
+ 	$(INSTALL_DATA) $(srcdir)/krb5/hostrealm_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)hostrealm_plugin.h
+diff --git a/src/include/k5-int.h b/src/include/k5-int.h
+index 173cb0264..cea644d0a 100644
+--- a/src/include/k5-int.h
++++ b/src/include/k5-int.h
+@@ -1156,7 +1156,8 @@ struct plugin_interface {
+ #define PLUGIN_INTERFACE_AUDIT       7
+ #define PLUGIN_INTERFACE_TLS         8
+ #define PLUGIN_INTERFACE_KDCAUTHDATA 9
+-#define PLUGIN_NUM_INTERFACES        10
++#define PLUGIN_INTERFACE_CERTAUTH    10
++#define PLUGIN_NUM_INTERFACES        11
+ 
+ /* Retrieve the plugin module of type interface_id and name modname,
+  * storing the result into module. */
+diff --git a/src/include/krb5/certauth_plugin.h b/src/include/krb5/certauth_plugin.h
+new file mode 100644
+index 000000000..f22fc1e84
+--- /dev/null
++++ b/src/include/krb5/certauth_plugin.h
+@@ -0,0 +1,103 @@
++/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
++/* include/krb5/certauth_plugin.h - certauth plugin header. */
++/*
++ * Copyright (C) 2017 by Red Hat, Inc.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * * Redistributions of source code must retain the above copyright
++ *   notice, this list of conditions and the following disclaimer.
++ *
++ * * Redistributions in binary form must reproduce the above copyright
++ *   notice, this list of conditions and the following disclaimer in
++ *   the documentation and/or other materials provided with the
++ *   distribution.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
++ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ */
++
++/*
++ * Certificate authorization plugin interface.  The PKINIT server module uses
++ * this interface to check client certificate attributes after the certificate
++ * signature has been verified.
++ */
++#ifndef KRB5_CERTAUTH_PLUGIN_H
++#define KRB5_CERTAUTH_PLUGIN_H
++
++#include <krb5/krb5.h>
++#include <krb5/plugin.h>
++
++/* Abstract module data type. */
++typedef struct krb5_certauth_moddata_st *krb5_certauth_moddata;
++
++typedef struct _krb5_db_entry_new krb5_db_entry;
++
++/*
++ * Optional: Initialize module data.
++ */
++typedef krb5_error_code
++(*krb5_certauth_init_fn)(krb5_context context,
++                         krb5_certauth_moddata *moddata_out);
++
++/*
++ * Optional: Clean up the module data.
++ */
++typedef void
++(*krb5_certauth_fini_fn)(krb5_context context, krb5_certauth_moddata moddata);
++
++/*
++ * Mandatory:
++ * Return 0 if the DER-encoded cert is authorized for PKINIT authentication by
++ * princ; otherwise return one of the following error codes:
++ * - KRB5KDC_ERR_CLIENT_NAME_MISMATCH - incorrect SAN value
++ * - KRB5KDC_ERR_INCONSISTENT_KEY_PURPOSE - incorrect EKU
++ * - KRB5KDC_ERR_CERTIFICATE_MISMATCH - other extension error
++ * - KRB5_PLUGIN_NO_HANDLE - the module has no opinion about cert
++ *
++ * - opts is used by built-in modules to receive internal data, and must be
++ *   ignored by other modules.
++ * - db_entry receives the client principal database entry, and can be ignored
++ *   by modules that do not link with libkdb5.
++ * - *authinds_out optionally returns a null-terminated list of authentication
++ *   indicator strings upon KRB5_PLUGIN_NO_HANDLE or accepted authorization.
++ */
++typedef krb5_error_code
++(*krb5_certauth_authorize_fn)(krb5_context context,
++                              krb5_certauth_moddata moddata,
++                              const uint8_t *cert, size_t cert_len,
++                              krb5_const_principal princ, const void *opts,
++                              const krb5_db_entry *db_entry,
++                              char ***authinds_out);
++
++/*
++ * Free indicators allocated by a module.  Mandatory if authorize returns
++ * authentication indicators.
++ */
++typedef void
++(*krb5_certauth_free_indicator_fn)(krb5_context context,
++                                   krb5_certauth_moddata moddata,
++                                   char **authinds);
++
++typedef struct krb5_certauth_vtable_st {
++    char *name;
++    krb5_certauth_init_fn init;
++    krb5_certauth_fini_fn fini;
++    krb5_certauth_authorize_fn authorize;
++    krb5_certauth_free_indicator_fn free_ind;
++} *krb5_certauth_vtable;
++
++#endif /* KRB5_CERTAUTH_PLUGIN_H */
+diff --git a/src/lib/krb5/krb/plugin.c b/src/lib/krb5/krb/plugin.c
+index 7d64b7c7e..17dd6bd30 100644
+--- a/src/lib/krb5/krb/plugin.c
++++ b/src/lib/krb5/krb/plugin.c
+@@ -57,7 +57,8 @@ const char *interface_names[] = {
+     "hostrealm",
+     "audit",
+     "tls",
+-    "kdcauthdata"
++    "kdcauthdata",
++    "certauth"
+ };
+ 
+ /* Return the context's interface structure for id, or NULL if invalid. */
+diff --git a/src/plugins/certauth/test/Makefile.in b/src/plugins/certauth/test/Makefile.in
+new file mode 100644
+index 000000000..d3524084c
+--- /dev/null
++++ b/src/plugins/certauth/test/Makefile.in
+@@ -0,0 +1,20 @@
++mydir=plugins$(S)certauth$(S)test
++BUILDTOP=$(REL)..$(S)..$(S)..
++
++LIBBASE=certauth_test
++LIBMAJOR=0
++LIBMINOR=0
++RELDIR=../plugins/certauth/test
++SHLIB_EXPDEPS=$(KRB5_BASE_DEPLIBS)
++SHLIB_EXPLIBS=$(KRB5_BASE_LIBS)
++
++STLIBOBJS=main.o
++
++SRCS=$(srcdir)/main.c
++
++all-unix: all-libs
++install-unix:
++clean-unix:: clean-libs clean-libobjs
++
++@libnover_frag@
++@libobj_frag@
+diff --git a/src/plugins/certauth/test/certauth_test.exports b/src/plugins/certauth/test/certauth_test.exports
+new file mode 100644
+index 000000000..1c8cd24e2
+--- /dev/null
++++ b/src/plugins/certauth/test/certauth_test.exports
+@@ -0,0 +1,2 @@
++certauth_test1_initvt
++certauth_test2_initvt
+diff --git a/src/plugins/certauth/test/deps b/src/plugins/certauth/test/deps
+new file mode 100644
+index 000000000..2974b3b57
+--- /dev/null
++++ b/src/plugins/certauth/test/deps
+@@ -0,0 +1,14 @@
++#
++# Generated makefile dependencies follow.
++#
++main.so main.po $(OUTPRE)main.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
++  $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
++  $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \
++  $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
++  $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
++  $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
++  $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
++  $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
++  $(top_srcdir)/include/krb5/certauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \
++  $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
++  main.c
+diff --git a/src/plugins/certauth/test/main.c b/src/plugins/certauth/test/main.c
+new file mode 100644
+index 000000000..7ef7377fb
+--- /dev/null
++++ b/src/plugins/certauth/test/main.c
+@@ -0,0 +1,209 @@
++/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
++/* plugins/certauth/main.c - certauth plugin test modules. */
++/*
++ * Copyright (C) 2017 by Red Hat, Inc.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * * Redistributions of source code must retain the above copyright
++ *   notice, this list of conditions and the following disclaimer.
++ *
++ * * Redistributions in binary form must reproduce the above copyright
++ *   notice, this list of conditions and the following disclaimer in
++ *   the documentation and/or other materials provided with the
++ *   distribution.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
++ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ */
++
++#include <k5-int.h>
++#include "krb5/certauth_plugin.h"
++
++struct krb5_certauth_moddata_st {
++    int initialized;
++};
++
++/* Test module 1 returns OK with an indicator. */
++static krb5_error_code
++test1_authorize(krb5_context context, krb5_certauth_moddata moddata,
++                const uint8_t *cert, size_t cert_len,
++                krb5_const_principal princ, const void *opts,
++                const krb5_db_entry *db_entry, char ***authinds_out)
++{
++    char **ais = NULL;
++
++    ais = calloc(2, sizeof(*ais));
++    assert(ais != NULL);
++    ais[0] = strdup("test1");
++    assert(ais[0] != NULL);
++    *authinds_out = ais;
++    return KRB5_PLUGIN_NO_HANDLE;
++}
++
++static void
++test_free_ind(krb5_context context, krb5_certauth_moddata moddata,
++              char **authinds)
++{
++    size_t i;
++
++    if (authinds == NULL)
++        return;
++    for (i = 0; authinds[i] != NULL; i++)
++        free(authinds[i]);
++    free(authinds);
++}
++
++/* A basic moddata test. */
++static krb5_error_code
++test2_init(krb5_context context, krb5_certauth_moddata *moddata_out)
++{
++    krb5_certauth_moddata mod;
++
++    mod = calloc(1, sizeof(*mod));
++    assert(mod != NULL);
++    mod->initialized = 1;
++    *moddata_out = mod;
++    return 0;
++}
++
++static void
++test2_fini(krb5_context context, krb5_certauth_moddata moddata)
++{
++    free(moddata);
++}
++
++/* Return true if cert appears to contain the CN name, based on a search of the
++ * DER encoding. */
++static krb5_boolean
++has_cn(krb5_context context, const uint8_t *cert, size_t cert_len,
++       const char *name)
++{
++    krb5_boolean match = FALSE;
++    uint8_t name_len, cntag[5] = "\x06\x03\x55\x04\x03";
++    const uint8_t *c;
++    struct k5buf buf;
++    size_t c_left;
++
++    /* Construct a DER search string of the CN AttributeType encoding followed
++     * by a UTF8String encoding containing name as the AttributeValue. */
++    k5_buf_init_dynamic(&buf);
++    k5_buf_add_len(&buf, cntag, sizeof(cntag));
++    k5_buf_add(&buf, "\x0C");
++    assert(strlen(name) < 128);
++    name_len = strlen(name);
++    k5_buf_add_len(&buf, &name_len, 1);
++    k5_buf_add_len(&buf, name, name_len);
++    assert(k5_buf_status(&buf) == 0);
++
++    /* Check for the CN needle in the certificate haystack. */
++    c_left = cert_len;
++    c = memchr(cert, *cntag, c_left);
++    while (c != NULL) {
++        c_left = cert_len - (c - cert);
++        if (buf.len > c_left)
++            break;
++        if (memcmp(c, buf.data, buf.len) == 0) {
++            match = TRUE;
++            break;
++        }
++        assert(c_left >= 1);
++        c = memchr(c + 1, *cntag, c_left - 1);
++    }
++
++    k5_buf_free(&buf);
++    return match;
++}
++
++/*
++ * Test module 2 returns OK if princ matches the CN part of the subject name,
++ * and returns indicators of the module name and princ.
++ */
++static krb5_error_code
++test2_authorize(krb5_context context, krb5_certauth_moddata moddata,
++                const uint8_t *cert, size_t cert_len,
++                krb5_const_principal princ, const void *opts,
++                const krb5_db_entry *db_entry, char ***authinds_out)
++{
++    krb5_error_code ret;
++    char *name = NULL, **ais = NULL;
++
++    *authinds_out = NULL;
++
++    assert(moddata != NULL && moddata->initialized);
++
++    ret = krb5_unparse_name_flags(context, princ,
++                                  KRB5_PRINCIPAL_UNPARSE_NO_REALM, &name);
++    if (ret)
++        goto cleanup;
++
++    if (!has_cn(context, cert, cert_len, name)) {
++        ret = KRB5KDC_ERR_CERTIFICATE_MISMATCH;
++        goto cleanup;
++    }
++
++    /* Create an indicator list with the module name and CN. */
++    ais = calloc(3, sizeof(*ais));
++    assert(ais != NULL);
++    ais[0] = strdup("test2");
++    ais[1] = strdup(name);
++    assert(ais[0] != NULL && ais[1] != NULL);
++    *authinds_out = ais;
++
++    ais = NULL;
++
++cleanup:
++    krb5_free_unparsed_name(context, name);
++    return ret;
++}
++
++krb5_error_code
++certauth_test1_initvt(krb5_context context, int maj_ver, int min_ver,
++                      krb5_plugin_vtable vtable);
++krb5_error_code
++certauth_test1_initvt(krb5_context context, int maj_ver, int min_ver,
++                      krb5_plugin_vtable vtable)
++{
++    krb5_certauth_vtable vt;
++
++    if (maj_ver != 1)
++        return KRB5_PLUGIN_VER_NOTSUPP;
++    vt = (krb5_certauth_vtable)vtable;
++    vt->name = "test1";
++    vt->authorize = test1_authorize;
++    vt->free_ind = test_free_ind;
++    return 0;
++}
++
++krb5_error_code
++certauth_test2_initvt(krb5_context context, int maj_ver, int min_ver,
++                      krb5_plugin_vtable vtable);
++krb5_error_code
++certauth_test2_initvt(krb5_context context, int maj_ver, int min_ver,
++                      krb5_plugin_vtable vtable)
++{
++    krb5_certauth_vtable vt;
++
++    if (maj_ver != 1)
++        return KRB5_PLUGIN_VER_NOTSUPP;
++    vt = (krb5_certauth_vtable)vtable;
++    vt->name = "test2";
++    vt->authorize = test2_authorize;
++    vt->init = test2_init;
++    vt->fini = test2_fini;
++    vt->free_ind = test_free_ind;
++    return 0;
++}
+diff --git a/src/plugins/preauth/pkinit/pkinit_crypto.h b/src/plugins/preauth/pkinit/pkinit_crypto.h
+index b483affed..49b96b8ee 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto.h
++++ b/src/plugins/preauth/pkinit/pkinit_crypto.h
+@@ -664,4 +664,8 @@ extern const size_t  krb5_pkinit_sha512_oid_len;
+  */
+ extern krb5_data const * const supported_kdf_alg_ids[];
+ 
++krb5_error_code
++crypto_encode_der_cert(krb5_context context, pkinit_req_crypto_context reqctx,
++		       uint8_t **der_out, size_t *der_len);
++
+ #endif	/* _PKINIT_CRYPTO_H */
+diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+index 8def8c542..a5b010b26 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+@@ -2137,6 +2137,7 @@ crypto_retrieve_X509_sans(krb5_context context,
+ 
+     if (!(ext = X509_get_ext(cert, l)) || !(ialt = X509V3_EXT_d2i(ext))) {
+         pkiDebug("%s: found no subject alt name extensions\n", __FUNCTION__);
++        retval = ENOENT;
+         goto cleanup;
+     }
+     num_sans = sk_GENERAL_NAME_num(ialt);
+@@ -6176,3 +6177,32 @@ crypto_get_deferred_ids(krb5_context context,
+     ret = (const pkinit_deferred_id *)deferred;
+     return ret;
+ }
++
++/* Return the received certificate as DER-encoded data. */
++krb5_error_code
++crypto_encode_der_cert(krb5_context context, pkinit_req_crypto_context reqctx,
++                       uint8_t **der_out, size_t *der_len)
++{
++    int len;
++    unsigned char *der, *p;
++
++    *der_out = NULL;
++    *der_len = 0;
++
++    if (reqctx->received_cert == NULL)
++        return EINVAL;
++    p = NULL;
++    len = i2d_X509(reqctx->received_cert, NULL);
++    if (len <= 0)
++        return EINVAL;
++    p = der = malloc(len);
++    if (p == NULL)
++        return ENOMEM;
++    if (i2d_X509(reqctx->received_cert, &p) <= 0) {
++        free(p);
++        return EINVAL;
++    }
++    *der_out = der;
++    *der_len = len;
++    return 0;
++}
+diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c
+index b5638a367..731d14eb8 100644
+--- a/src/plugins/preauth/pkinit/pkinit_srv.c
++++ b/src/plugins/preauth/pkinit/pkinit_srv.c
+@@ -31,6 +31,25 @@
+ 
+ #include <k5-int.h>
+ #include "pkinit.h"
++#include "krb5/certauth_plugin.h"
++
++/* Aliases used by the built-in certauth modules */
++struct certauth_req_opts {
++    krb5_kdcpreauth_callbacks cb;
++    krb5_kdcpreauth_rock rock;
++    pkinit_kdc_context plgctx;
++    pkinit_kdc_req_context reqctx;
++};
++
++typedef struct certauth_module_handle_st {
++    struct krb5_certauth_vtable_st vt;
++    krb5_certauth_moddata moddata;
++} *certauth_handle;
++
++struct krb5_kdcpreauth_moddata_st {
++    pkinit_kdc_context *realm_contexts;
++    certauth_handle *certauth_modules;
++};
+ 
+ static krb5_error_code
+ pkinit_init_kdc_req_context(krb5_context, pkinit_kdc_req_context *blob);
+@@ -51,6 +70,34 @@ pkinit_find_realm_context(krb5_context context,
+                           krb5_kdcpreauth_moddata moddata,
+                           krb5_principal princ);
+ 
++static void
++free_realm_contexts(krb5_context context, pkinit_kdc_context *realm_contexts)
++{
++    int i;
++
++    if (realm_contexts == NULL)
++        return;
++    for (i = 0; realm_contexts[i] != NULL; i++)
++        pkinit_server_plugin_fini_realm(context, realm_contexts[i]);
++    pkiDebug("%s: freeing context at %p\n", __FUNCTION__, realm_contexts);
++    free(realm_contexts);
++}
++
++static void
++free_certauth_handles(krb5_context context, certauth_handle *list)
++{
++    int i;
++
++    if (list == NULL)
++        return;
++    for (i = 0; list[i] != NULL; i++) {
++        if (list[i]->vt.fini != NULL)
++            list[i]->vt.fini(context, list[i]->moddata);
++        free(list[i]);
++    }
++    free(list);
++}
++
+ static krb5_error_code
+ pkinit_create_edata(krb5_context context,
+                     pkinit_plg_crypto_context plg_cryptoctx,
+@@ -123,7 +170,7 @@ verify_client_san(krb5_context context,
+                   pkinit_kdc_req_context reqctx,
+                   krb5_kdcpreauth_callbacks cb,
+                   krb5_kdcpreauth_rock rock,
+-                  krb5_principal client,
++                  krb5_const_principal client,
+                   int *valid_san)
+ {
+     krb5_error_code retval;
+@@ -134,12 +181,15 @@ verify_client_san(krb5_context context,
+     char *client_string = NULL, *san_string;
+ #endif
+ 
++    *valid_san = 0;
+     retval = crypto_retrieve_cert_sans(context, plgctx->cryptoctx,
+                                        reqctx->cryptoctx, plgctx->idctx,
+                                        &princs,
+                                        plgctx->opts->allow_upn ? &upns : NULL,
+                                        NULL);
+-    if (retval) {
++    if (retval == ENOENT) {
++        goto out;
++    } else if (retval) {
+         pkiDebug("%s: error from retrieve_certificate_sans()\n", __FUNCTION__);
+         retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
+         goto out;
+@@ -273,6 +323,73 @@ out:
+     return retval;
+ }
+ 
++
++/* Run the received, verified certificate through certauth modules, to verify
++ * that it is authorized to authenticate as client. */
++static krb5_error_code
++authorize_cert(krb5_context context, certauth_handle *certauth_modules,
++               pkinit_kdc_context plgctx, pkinit_kdc_req_context reqctx,
++               krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
++               krb5_principal client)
++{
++    krb5_error_code ret;
++    certauth_handle h;
++    struct certauth_req_opts opts;
++    krb5_boolean accepted = FALSE;
++    uint8_t *cert;
++    size_t i, cert_len;
++    void *db_ent = NULL;
++    char **ais = NULL, **ai = NULL;
++
++    /* Re-encode the received certificate into DER, which is extra work, but
++     * avoids creating an X.509 library dependency in the interface. */
++    ret = crypto_encode_der_cert(context, reqctx->cryptoctx, &cert, &cert_len);
++    if (ret)
++        goto cleanup;
++
++    /* Set options for the builtin module. */
++    opts.plgctx = plgctx;
++    opts.reqctx = reqctx;
++    opts.cb = cb;
++    opts.rock = rock;
++
++    db_ent = cb->client_entry(context, rock);
++
++    /*
++     * Check the certificate against each certauth module.  For the certificate
++     * to be authorized at least one module must return 0, and no module can an
++     * error code other than KRB5_PLUGIN_NO_HANDLE (pass).  Add indicators from
++     * modules that return 0 or pass.
++     */
++    ret = KRB5_PLUGIN_NO_HANDLE;
++    for (i = 0; certauth_modules != NULL && certauth_modules[i] != NULL; i++) {
++        h = certauth_modules[i];
++        ret = h->vt.authorize(context, h->moddata, cert, cert_len, client,
++                              &opts, db_ent, &ais);
++        if (ret == 0)
++            accepted = TRUE;
++        else if (ret != KRB5_PLUGIN_NO_HANDLE)
++            goto cleanup;
++
++        if (ais != NULL) {
++            /* Assert authentication indicators from the module. */
++            for (ai = ais; *ai != NULL; ai++) {
++                ret = cb->add_auth_indicator(context, rock, *ai);
++                if (ret)
++                    goto cleanup;
++            }
++            h->vt.free_ind(context, h->moddata, ais);
++            ais = NULL;
++        }
++    }
++
++    ret = accepted ? 0 : KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
++
++cleanup:
++    free(cert);
++    return ret;
++}
++
+ static void
+ pkinit_server_verify_padata(krb5_context context,
+                             krb5_data *req_pkt,
+@@ -295,7 +412,6 @@ pkinit_server_verify_padata(krb5_context context,
+     pkinit_kdc_req_context reqctx = NULL;
+     krb5_checksum cksum = {0, 0, 0, NULL};
+     krb5_data *der_req = NULL;
+-    int valid_eku = 0, valid_san = 0;
+     krb5_data k5data;
+     int is_signed = 1;
+     krb5_pa_data **e_data = NULL;
+@@ -388,27 +504,11 @@ pkinit_server_verify_padata(krb5_context context,
+         goto cleanup;
+     }
+     if (is_signed) {
+-
+-        retval = verify_client_san(context, plgctx, reqctx, cb, rock,
+-                                   request->client, &valid_san);
+-        if (retval)
+-            goto cleanup;
+-        if (!valid_san) {
+-            pkiDebug("%s: did not find an acceptable SAN in user "
+-                     "certificate\n", __FUNCTION__);
+-            retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
+-            goto cleanup;
+-        }
+-        retval = verify_client_eku(context, plgctx, reqctx, &valid_eku);
++        retval = authorize_cert(context, moddata->certauth_modules, plgctx,
++                                reqctx, cb, rock, request->client);
+         if (retval)
+             goto cleanup;
+ 
+-        if (!valid_eku) {
+-            pkiDebug("%s: did not find an acceptable EKU in user "
+-                     "certificate\n", __FUNCTION__);
+-            retval = KRB5KDC_ERR_INCONSISTENT_KEY_PURPOSE;
+-            goto cleanup;
+-        }
+     } else { /* !is_signed */
+         if (!krb5_principal_compare(context, request->client,
+                                     krb5_anonymous_principal())) {
+@@ -1245,11 +1345,15 @@ pkinit_find_realm_context(krb5_context context,
+                           krb5_principal princ)
+ {
+     int i;
+-    pkinit_kdc_context *realm_contexts = (pkinit_kdc_context *)moddata;
++    pkinit_kdc_context *realm_contexts;
+ 
+     if (moddata == NULL)
+         return NULL;
+ 
++    realm_contexts = moddata->realm_contexts;
++    if (realm_contexts == NULL)
++        return NULL;
++
+     for (i = 0; realm_contexts[i] != NULL; i++) {
+         pkinit_kdc_context p = realm_contexts[i];
+ 
+@@ -1331,6 +1435,155 @@ errout:
+     return retval;
+ }
+ 
++static krb5_error_code
++pkinit_san_authorize(krb5_context context, krb5_certauth_moddata moddata,
++                     const uint8_t *cert, size_t cert_len,
++                     krb5_const_principal princ, const void *opts,
++                     const krb5_db_entry *db_entry, char ***authinds_out)
++{
++    krb5_error_code ret;
++    int valid_san;
++    const struct certauth_req_opts *req_opts = opts;
++
++    *authinds_out = NULL;
++
++    ret = verify_client_san(context, req_opts->plgctx, req_opts->reqctx,
++                            req_opts->cb, req_opts->rock, princ, &valid_san);
++    if (ret == ENOENT)
++        return KRB5_PLUGIN_NO_HANDLE;
++    else if (ret)
++        return ret;
++
++    if (!valid_san) {
++        pkiDebug("%s: did not find an acceptable SAN in user certificate\n",
++                 __FUNCTION__);
++        return KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
++    }
++
++    return 0;
++}
++
++static krb5_error_code
++pkinit_eku_authorize(krb5_context context, krb5_certauth_moddata moddata,
++                     const uint8_t *cert, size_t cert_len,
++                     krb5_const_principal princ, const void *opts,
++                     const krb5_db_entry *db_entry, char ***authinds_out)
++{
++    krb5_error_code ret;
++    int valid_eku;
++    const struct certauth_req_opts *req_opts = opts;
++
++    *authinds_out = NULL;
++
++    /* Verify the client EKU. */
++    ret = verify_client_eku(context, req_opts->plgctx, req_opts->reqctx,
++                            &valid_eku);
++    if (ret)
++        return ret;
++
++    if (!valid_eku) {
++        pkiDebug("%s: did not find an acceptable EKU in user certificate\n",
++                 __FUNCTION__);
++        return KRB5KDC_ERR_INCONSISTENT_KEY_PURPOSE;
++    }
++
++    return 0;
++}
++
++static krb5_error_code
++certauth_pkinit_san_initvt(krb5_context context, int maj_ver, int min_ver,
++                           krb5_plugin_vtable vtable)
++{
++    krb5_certauth_vtable vt;
++
++    if (maj_ver != 1)
++        return KRB5_PLUGIN_VER_NOTSUPP;
++    vt = (krb5_certauth_vtable)vtable;
++    vt->name = "pkinit_san";
++    vt->authorize = pkinit_san_authorize;
++    return 0;
++}
++
++static krb5_error_code
++certauth_pkinit_eku_initvt(krb5_context context, int maj_ver, int min_ver,
++                           krb5_plugin_vtable vtable)
++{
++    krb5_certauth_vtable vt;
++
++    if (maj_ver != 1)
++        return KRB5_PLUGIN_VER_NOTSUPP;
++    vt = (krb5_certauth_vtable)vtable;
++    vt->name = "pkinit_eku";
++    vt->authorize = pkinit_eku_authorize;
++    return 0;
++}
++
++static krb5_error_code
++load_certauth_plugins(krb5_context context, certauth_handle **handle_out)
++{
++    krb5_error_code ret;
++    krb5_plugin_initvt_fn *modules = NULL, *mod;
++    certauth_handle *list = NULL, h;
++    size_t count;
++
++    /* Register the builtin modules. */
++    ret = k5_plugin_register(context, PLUGIN_INTERFACE_CERTAUTH,
++                             "pkinit_san", certauth_pkinit_san_initvt);
++    if (ret)
++        goto cleanup;
++
++    ret = k5_plugin_register(context, PLUGIN_INTERFACE_CERTAUTH,
++                             "pkinit_eku", certauth_pkinit_eku_initvt);
++    if (ret)
++        goto cleanup;
++
++    ret = k5_plugin_load_all(context, PLUGIN_INTERFACE_CERTAUTH, &modules);
++    if (ret)
++        goto cleanup;
++
++    /* Allocate handle list. */
++    for (count = 0; modules[count]; count++);
++    list = k5calloc(count + 1, sizeof(*list), &ret);
++    if (list == NULL)
++        goto cleanup;
++
++    /* Initialize each module, ignoring ones that fail. */
++    count = 0;
++    for (mod = modules; *mod != NULL; mod++) {
++        h = k5calloc(1, sizeof(*h), &ret);
++        if (h == NULL)
++            goto cleanup;
++
++        ret = (*mod)(context, 1, 1, (krb5_plugin_vtable)&h->vt);
++        if (ret) {
++            TRACE_CERTAUTH_VTINIT_FAIL(context, ret);
++            free(h);
++            continue;
++        }
++        h->moddata = NULL;
++        if (h->vt.init != NULL) {
++            ret = h->vt.init(context, &h->moddata);
++            if (ret) {
++                TRACE_CERTAUTH_INIT_FAIL(context, h->vt.name, ret);
++                free(h);
++                continue;
++            }
++        }
++        list[count++] = h;
++        list[count] = NULL;
++    }
++    list[count] = NULL;
++
++    ret = 0;
++    *handle_out = list;
++    list = NULL;
++
++cleanup:
++    k5_plugin_free_modules(context, modules);
++    free_certauth_handles(context, list);
++    return ret;
++}
++
+ static int
+ pkinit_server_plugin_init(krb5_context context,
+                           krb5_kdcpreauth_moddata *moddata_out,
+@@ -1338,6 +1591,8 @@ pkinit_server_plugin_init(krb5_context context,
+ {
+     krb5_error_code retval = ENOMEM;
+     pkinit_kdc_context plgctx, *realm_contexts = NULL;
++    certauth_handle *certauth_modules = NULL;
++    krb5_kdcpreauth_moddata moddata;
+     size_t  i, j;
+     size_t numrealms;
+ 
+@@ -1368,16 +1623,22 @@ pkinit_server_plugin_init(krb5_context context,
+         goto errout;
+     }
+ 
+-    *moddata_out = (krb5_kdcpreauth_moddata)realm_contexts;
+-    retval = 0;
+-    pkiDebug("%s: returning context at %p\n", __FUNCTION__, realm_contexts);
++    retval = load_certauth_plugins(context, &certauth_modules);
++    if (retval)
++        goto errout;
++
++    moddata = k5calloc(1, sizeof(*moddata), &retval);
++    if (moddata == NULL)
++        goto errout;
++    moddata->realm_contexts = realm_contexts;
++    moddata->certauth_modules = certauth_modules;
++    *moddata_out = moddata;
++    pkiDebug("%s: returning context at %p\n", __FUNCTION__, moddata);
++    return 0;
+ 
+ errout:
+-    if (retval) {
+-        pkinit_server_plugin_fini(context,
+-                                  (krb5_kdcpreauth_moddata)realm_contexts);
+-    }
+-
++    free_realm_contexts(context, realm_contexts);
++    free_certauth_handles(context, certauth_modules);
+     return retval;
+ }
+ 
+@@ -1405,17 +1666,11 @@ static void
+ pkinit_server_plugin_fini(krb5_context context,
+                           krb5_kdcpreauth_moddata moddata)
+ {
+-    pkinit_kdc_context *realm_contexts = (pkinit_kdc_context *)moddata;
+-    int i;
+-
+-    if (realm_contexts == NULL)
++    if (moddata == NULL)
+         return;
+-
+-    for (i = 0; realm_contexts[i] != NULL; i++) {
+-        pkinit_server_plugin_fini_realm(context, realm_contexts[i]);
+-    }
+-    pkiDebug("%s: freeing context at %p\n", __FUNCTION__, realm_contexts);
+-    free(realm_contexts);
++    free_realm_contexts(context, moddata->realm_contexts);
++    free_certauth_handles(context, moddata->certauth_modules);
++    free(moddata);
+ }
+ 
+ static krb5_error_code
+diff --git a/src/plugins/preauth/pkinit/pkinit_trace.h b/src/plugins/preauth/pkinit/pkinit_trace.h
+index b3f5cbb20..458d0961e 100644
+--- a/src/plugins/preauth/pkinit/pkinit_trace.h
++++ b/src/plugins/preauth/pkinit/pkinit_trace.h
+@@ -91,4 +91,9 @@
+ #define TRACE_PKINIT_OPENSSL_ERROR(c, msg)              \
+     TRACE(c, "PKINIT OpenSSL error: {str}", msg)
+ 
++#define TRACE_CERTAUTH_VTINIT_FAIL(c, ret)                              \
++    TRACE(c, "certauth module failed to init vtable: {kerr}", ret)
++#define TRACE_CERTAUTH_INIT_FAIL(c, name, ret)                          \
++    TRACE(c, "certauth module {str} failed to init: {kerr}", name, ret)
++
+ #endif /* PKINIT_TRACE_H */
+diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in
+index b55469146..0e93d6b59 100644
+--- a/src/tests/Makefile.in
++++ b/src/tests/Makefile.in
+@@ -167,6 +167,7 @@ check-pytests: localauth plugorder rdreq responder s2p s4u2proxy unlockiter
+ 	$(RUNPYTEST) $(srcdir)/t_preauth.py $(PYTESTFLAGS)
+ 	$(RUNPYTEST) $(srcdir)/t_princflags.py $(PYTESTFLAGS)
+ 	$(RUNPYTEST) $(srcdir)/t_tabdump.py $(PYTESTFLAGS)
++	$(RUNPYTEST) $(srcdir)/t_certauth.py $(PYTESTFLAGS)
+ 
+ clean:
+ 	$(RM) adata etinfo forward gcred hist hooks hrealm icred kdbtest
+diff --git a/src/tests/t_certauth.py b/src/tests/t_certauth.py
+new file mode 100644
+index 000000000..e64a57b0d
+--- /dev/null
++++ b/src/tests/t_certauth.py
+@@ -0,0 +1,47 @@
++#!/usr/bin/python
++from k5test import *
++
++# Skip this test if pkinit wasn't built.
++if not os.path.exists(os.path.join(plugins, 'preauth', 'pkinit.so')):
++    skip_rest('certauth tests', 'PKINIT module not built')
++
++certs = os.path.join(srctop, 'tests', 'dejagnu', 'pkinit-certs')
++ca_pem = os.path.join(certs, 'ca.pem')
++kdc_pem = os.path.join(certs, 'kdc.pem')
++privkey_pem = os.path.join(certs, 'privkey.pem')
++user_pem = os.path.join(certs, 'user.pem')
++
++modpath = os.path.join(buildtop, 'plugins', 'certauth', 'test',
++                       'certauth_test.so')
++pkinit_krb5_conf = {'realms': {'$realm': {
++            'pkinit_anchors': 'FILE:%s' % ca_pem}},
++            'plugins': {'certauth': {'module': ['test1:' + modpath,
++                                                'test2:' + modpath],
++                                     'enable_only': ['test1', 'test2']}}}
++pkinit_kdc_conf = {'realms': {'$realm': {
++            'default_principal_flags': '+preauth',
++            'pkinit_eku_checking': 'none',
++            'pkinit_identity': 'FILE:%s,%s' % (kdc_pem, privkey_pem),
++            'pkinit_indicator': ['indpkinit1', 'indpkinit2']}}}
++
++file_identity = 'FILE:%s,%s' % (user_pem, privkey_pem)
++
++realm = K5Realm(krb5_conf=pkinit_krb5_conf, kdc_conf=pkinit_kdc_conf,
++                get_creds=False)
++
++# Let the test module match user to CN=user, with indicators.
++realm.kinit(realm.user_princ,
++            flags=['-X', 'X509_user_identity=%s' % file_identity])
++realm.klist(realm.user_princ)
++realm.run([kvno, realm.host_princ])
++realm.run(['./adata', realm.host_princ],
++          expected_msg='+97: [test1, test2, user, indpkinit1, indpkinit2]')
++
++# Let the test module mismatch with user2 to CN=user.
++realm.addprinc("user2@KRBTEST.COM")
++out = realm.kinit("user2@KRBTEST.COM",
++                  flags=['-X', 'X509_user_identity=%s' % file_identity],
++                  expected_code=1,
++                  expected_msg='kinit: Certificate mismatch')
++
++success("certauth tests")
diff --git a/SOURCES/Add-the-client_name-kdcpreauth-callback.patch b/SOURCES/Add-the-client_name-kdcpreauth-callback.patch
new file mode 100644
index 0000000..7cd1b67
--- /dev/null
+++ b/SOURCES/Add-the-client_name-kdcpreauth-callback.patch
@@ -0,0 +1,58 @@
+From b0f389ad69cbd68f2825fe32556e4b4a599a0ac3 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/Correct-error-handling-bug-in-prior-commit.patch b/SOURCES/Correct-error-handling-bug-in-prior-commit.patch
new file mode 100644
index 0000000..e080091
--- /dev/null
+++ b/SOURCES/Correct-error-handling-bug-in-prior-commit.patch
@@ -0,0 +1,32 @@
+From e9a48c7c89def99b0e60a8b83646a345966c077c 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 a5b010b26..90c30dbf5 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+@@ -6196,10 +6196,10 @@ crypto_encode_der_cert(krb5_context context, pkinit_req_crypto_context reqctx,
+     if (len <= 0)
+         return EINVAL;
+     p = der = malloc(len);
+-    if (p == NULL)
++    if (der == NULL)
+         return ENOMEM;
+     if (i2d_X509(reqctx->received_cert, &p) <= 0) {
+-        free(p);
++        free(der);
+         return EINVAL;
+     }
+     *der_out = der;
diff --git a/SOURCES/Deindent-crypto_retrieve_X509_sans.patch b/SOURCES/Deindent-crypto_retrieve_X509_sans.patch
new file mode 100644
index 0000000..330820d
--- /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)
+---
+ src/plugins/preauth/pkinit/pkinit_crypto_openssl.c | 224 +++++++++++----------
+ 1 file changed, 114 insertions(+), 110 deletions(-)
+
+diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+index bc6e7662e..8def8c542 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+@@ -2101,11 +2101,21 @@ crypto_retrieve_X509_sans(krb5_context context,
+ {
+     krb5_error_code retval = EINVAL;
+     char buf[DN_BUF_LEN];
+-    int p = 0, u = 0, d = 0, l;
++    int p = 0, u = 0, d = 0, ret = 0, l;
+     krb5_principal *princs = NULL;
+     krb5_principal *upns = NULL;
+     unsigned char **dnss = NULL;
+-    unsigned int i, num_found = 0;
++    unsigned int i, num_found = 0, num_sans = 0;
++    X509_EXTENSION *ext = NULL;
++    GENERAL_NAMES *ialt = NULL;
++    GENERAL_NAME *gen = NULL;
++
++    if (princs_ret != NULL)
++        *princs_ret = NULL;
++    if (upn_ret != NULL)
++        *upn_ret = NULL;
++    if (dns_ret != NULL)
++        *dns_ret = NULL;
+ 
+     if (princs_ret == NULL && upn_ret == NULL && dns_ret == NULL) {
+         pkiDebug("%s: nowhere to return any values!\n", __FUNCTION__);
+@@ -2121,118 +2131,112 @@ crypto_retrieve_X509_sans(krb5_context context,
+                       buf, sizeof(buf));
+     pkiDebug("%s: looking for SANs in cert = %s\n", __FUNCTION__, buf);
+ 
+-    if ((l = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1)) >= 0) {
+-        X509_EXTENSION *ext = NULL;
+-        GENERAL_NAMES *ialt = NULL;
+-        GENERAL_NAME *gen = NULL;
+-        int ret = 0;
+-        unsigned int num_sans = 0;
++    l = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
++    if (l < 0)
++        return 0;
+ 
+-        if (!(ext = X509_get_ext(cert, l)) || !(ialt = X509V3_EXT_d2i(ext))) {
+-            pkiDebug("%s: found no subject alt name extensions\n",
+-                     __FUNCTION__);
++    if (!(ext = X509_get_ext(cert, l)) || !(ialt = X509V3_EXT_d2i(ext))) {
++        pkiDebug("%s: found no subject alt name extensions\n", __FUNCTION__);
++        goto cleanup;
++    }
++    num_sans = sk_GENERAL_NAME_num(ialt);
++
++    pkiDebug("%s: found %d subject alt name extension(s)\n", __FUNCTION__,
++             num_sans);
++
++    /* OK, we're likely returning something. Allocate return values */
++    if (princs_ret != NULL) {
++        princs = calloc(num_sans + 1, sizeof(krb5_principal));
++        if (princs == NULL) {
++            retval = ENOMEM;
+             goto cleanup;
+         }
+-        num_sans = sk_GENERAL_NAME_num(ialt);
+-
+-        pkiDebug("%s: found %d subject alt name extension(s)\n",
+-                 __FUNCTION__, num_sans);
+-
+-        /* OK, we're likely returning something. Allocate return values */
+-        if (princs_ret != NULL) {
+-            princs = calloc(num_sans + 1, sizeof(krb5_principal));
+-            if (princs == NULL) {
+-                retval = ENOMEM;
+-                goto cleanup;
+-            }
+-        }
+-        if (upn_ret != NULL) {
+-            upns = calloc(num_sans + 1, sizeof(krb5_principal));
+-            if (upns == NULL) {
+-                retval = ENOMEM;
+-                goto cleanup;
+-            }
+-        }
+-        if (dns_ret != NULL) {
+-            dnss = calloc(num_sans + 1, sizeof(*dnss));
+-            if (dnss == NULL) {
+-                retval = ENOMEM;
+-                goto cleanup;
+-            }
+-        }
+-
+-        for (i = 0; i < num_sans; i++) {
+-            krb5_data name = { 0, 0, NULL };
+-
+-            gen = sk_GENERAL_NAME_value(ialt, i);
+-            switch (gen->type) {
+-            case GEN_OTHERNAME:
+-                name.length = gen->d.otherName->value->value.sequence->length;
+-                name.data = (char *)gen->d.otherName->value->value.sequence->data;
+-                if (princs != NULL
+-                    && OBJ_cmp(plgctx->id_pkinit_san,
+-                               gen->d.otherName->type_id) == 0) {
+-#ifdef DEBUG_ASN1
+-                    print_buffer_bin((unsigned char *)name.data, name.length,
+-                                     "/tmp/pkinit_san");
+-#endif
+-                    ret = k5int_decode_krb5_principal_name(&name, &princs[p]);
+-                    if (ret) {
+-                        pkiDebug("%s: failed decoding pkinit san value\n",
+-                                 __FUNCTION__);
+-                    } else {
+-                        p++;
+-                        num_found++;
+-                    }
+-                } else if (upns != NULL
+-                           && OBJ_cmp(plgctx->id_ms_san_upn,
+-                                      gen->d.otherName->type_id) == 0) {
+-                    /* Prevent abuse of embedded null characters. */
+-                    if (memchr(name.data, '\0', name.length))
+-                        break;
+-                    ret = krb5_parse_name_flags(context, name.data,
+-                                                KRB5_PRINCIPAL_PARSE_ENTERPRISE,
+-                                                &upns[u]);
+-                    if (ret) {
+-                        pkiDebug("%s: failed parsing ms-upn san value\n",
+-                                 __FUNCTION__);
+-                    } else {
+-                        u++;
+-                        num_found++;
+-                    }
+-                } else {
+-                    pkiDebug("%s: unrecognized othername oid in SAN\n",
+-                             __FUNCTION__);
+-                    continue;
+-                }
+-
+-                break;
+-            case GEN_DNS:
+-                if (dnss != NULL) {
+-                    /* Prevent abuse of embedded null characters. */
+-                    if (memchr(gen->d.dNSName->data, '\0',
+-                               gen->d.dNSName->length))
+-                        break;
+-                    pkiDebug("%s: found dns name = %s\n",
+-                             __FUNCTION__, gen->d.dNSName->data);
+-                    dnss[d] = (unsigned char *)
+-                        strdup((char *)gen->d.dNSName->data);
+-                    if (dnss[d] == NULL) {
+-                        pkiDebug("%s: failed to duplicate dns name\n",
+-                                 __FUNCTION__);
+-                    } else {
+-                        d++;
+-                        num_found++;
+-                    }
+-                }
+-                break;
+-            default:
+-                pkiDebug("%s: SAN type = %d expecting %d\n",
+-                         __FUNCTION__, gen->type, GEN_OTHERNAME);
+-            }
+-        }
+-        sk_GENERAL_NAME_pop_free(ialt, GENERAL_NAME_free);
+     }
++    if (upn_ret != NULL) {
++        upns = calloc(num_sans + 1, sizeof(krb5_principal));
++        if (upns == NULL) {
++            retval = ENOMEM;
++            goto cleanup;
++        }
++    }
++    if (dns_ret != NULL) {
++        dnss = calloc(num_sans + 1, sizeof(*dnss));
++        if (dnss == NULL) {
++            retval = ENOMEM;
++            goto cleanup;
++        }
++    }
++
++    for (i = 0; i < num_sans; i++) {
++        krb5_data name = { 0, 0, NULL };
++
++        gen = sk_GENERAL_NAME_value(ialt, i);
++        switch (gen->type) {
++        case GEN_OTHERNAME:
++            name.length = gen->d.otherName->value->value.sequence->length;
++            name.data = (char *)gen->d.otherName->value->value.sequence->data;
++            if (princs != NULL &&
++                OBJ_cmp(plgctx->id_pkinit_san,
++                        gen->d.otherName->type_id) == 0) {
++#ifdef DEBUG_ASN1
++                print_buffer_bin((unsigned char *)name.data, name.length,
++                                 "/tmp/pkinit_san");
++#endif
++                ret = k5int_decode_krb5_principal_name(&name, &princs[p]);
++                if (ret) {
++                    pkiDebug("%s: failed decoding pkinit san value\n",
++                             __FUNCTION__);
++                } else {
++                    p++;
++                    num_found++;
++                }
++            } else if (upns != NULL &&
++                       OBJ_cmp(plgctx->id_ms_san_upn,
++                               gen->d.otherName->type_id) == 0) {
++                /* Prevent abuse of embedded null characters. */
++                if (memchr(name.data, '\0', name.length))
++                    break;
++                ret = krb5_parse_name_flags(context, name.data,
++                                            KRB5_PRINCIPAL_PARSE_ENTERPRISE,
++                                            &upns[u]);
++                if (ret) {
++                    pkiDebug("%s: failed parsing ms-upn san value\n",
++                             __FUNCTION__);
++                } else {
++                    u++;
++                    num_found++;
++                }
++            } else {
++                pkiDebug("%s: unrecognized othername oid in SAN\n",
++                         __FUNCTION__);
++                continue;
++            }
++
++            break;
++        case GEN_DNS:
++            if (dnss != NULL) {
++                /* Prevent abuse of embedded null characters. */
++                if (memchr(gen->d.dNSName->data, '\0', gen->d.dNSName->length))
++                    break;
++                pkiDebug("%s: found dns name = %s\n", __FUNCTION__,
++                         gen->d.dNSName->data);
++                dnss[d] = (unsigned char *)
++                    strdup((char *)gen->d.dNSName->data);
++                if (dnss[d] == NULL) {
++                    pkiDebug("%s: failed to duplicate dns name\n",
++                             __FUNCTION__);
++                } else {
++                    d++;
++                    num_found++;
++                }
++            }
++            break;
++        default:
++            pkiDebug("%s: SAN type = %d expecting %d\n", __FUNCTION__,
++                     gen->type, GEN_OTHERNAME);
++        }
++    }
++    sk_GENERAL_NAME_pop_free(ialt, GENERAL_NAME_free);
+ 
+     retval = 0;
+     if (princs)
diff --git a/SOURCES/Improve-PKINIT-UPN-SAN-matching.patch b/SOURCES/Improve-PKINIT-UPN-SAN-matching.patch
new file mode 100644
index 0000000..d4d45c6
--- /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 ++++++++++++++++++++--
+ src/plugins/preauth/pkinit/pkinit_crypto_openssl.c |  4 +++-
+ src/plugins/preauth/pkinit/pkinit_srv.c            | 10 ++++----
+ 4 files changed, 48 insertions(+), 7 deletions(-)
+
+diff --git a/src/include/krb5/kdcpreauth_plugin.h b/src/include/krb5/kdcpreauth_plugin.h
+index f455effae..92aa5a5a5 100644
+--- a/src/include/krb5/kdcpreauth_plugin.h
++++ b/src/include/krb5/kdcpreauth_plugin.h
+@@ -221,6 +221,19 @@ typedef struct krb5_kdcpreauth_callbacks_st {
+ 
+     /* End of version 3 kdcpreauth callbacks. */
+ 
++    /*
++     * Return true if princ matches the principal named in the request or the
++     * client principal (possibly canonicalized).  If princ does not match,
++     * attempt a database lookup of princ with aliases allowed and compare the
++     * result to the client principal, returning true if it matches.
++     * Otherwise, return false.
++     */
++    krb5_boolean (*match_client)(krb5_context context,
++                                 krb5_kdcpreauth_rock rock,
++                                 krb5_principal princ);
++
++    /* End of version 4 kdcpreauth callbacks. */
++
+ } *krb5_kdcpreauth_callbacks;
+ 
+ /* Optional: preauth plugin initialization function. */
+diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c
+index 605fcb7ad..0ce79c667 100644
+--- a/src/kdc/kdc_preauth.c
++++ b/src/kdc/kdc_preauth.c
+@@ -568,8 +568,31 @@ set_cookie(krb5_context context, krb5_kdcpreauth_rock rock,
+     return kdc_fast_set_cookie(rock->rstate, pa_type, data);
+ }
+ 
++static krb5_boolean
++match_client(krb5_context context, krb5_kdcpreauth_rock rock,
++             krb5_principal princ)
++{
++    krb5_db_entry *ent;
++    krb5_boolean match = FALSE;
++    krb5_principal req_client = rock->request->client;
++    krb5_principal client = rock->client->princ;
++
++    /* Check for a direct match against the request principal or
++     * the post-canon client principal. */
++    if (krb5_principal_compare_flags(context, princ, req_client,
++                                     KRB5_PRINCIPAL_COMPARE_ENTERPRISE) ||
++        krb5_principal_compare(context, princ, client))
++        return TRUE;
++
++    if (krb5_db_get_principal(context, princ, KRB5_KDB_FLAG_ALIAS_OK, &ent))
++        return FALSE;
++    match = krb5_principal_compare(context, ent->princ, client);
++    krb5_db_free_principal(context, ent);
++    return match;
++}
++
+ static struct krb5_kdcpreauth_callbacks_st callbacks = {
+-    3,
++    4,
+     max_time_skew,
+     client_keys,
+     free_keys,
+@@ -583,7 +606,8 @@ static struct krb5_kdcpreauth_callbacks_st callbacks = {
+     client_keyblock,
+     add_auth_indicator,
+     get_cookie,
+-    set_cookie
++    set_cookie,
++    match_client
+ };
+ 
+ static krb5_error_code
+diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+index 74fffbf32..bc6e7662e 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+@@ -2190,7 +2190,9 @@ crypto_retrieve_X509_sans(krb5_context context,
+                     /* Prevent abuse of embedded null characters. */
+                     if (memchr(name.data, '\0', name.length))
+                         break;
+-                    ret = krb5_parse_name(context, name.data, &upns[u]);
++                    ret = krb5_parse_name_flags(context, name.data,
++                                                KRB5_PRINCIPAL_PARSE_ENTERPRISE,
++                                                &upns[u]);
+                     if (ret) {
+                         pkiDebug("%s: failed parsing ms-upn san value\n",
+                                  __FUNCTION__);
+diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c
+index 295be25e1..b5638a367 100644
+--- a/src/plugins/preauth/pkinit/pkinit_srv.c
++++ b/src/plugins/preauth/pkinit/pkinit_srv.c
+@@ -121,6 +121,8 @@ static krb5_error_code
+ verify_client_san(krb5_context context,
+                   pkinit_kdc_context plgctx,
+                   pkinit_kdc_req_context reqctx,
++                  krb5_kdcpreauth_callbacks cb,
++                  krb5_kdcpreauth_rock rock,
+                   krb5_principal client,
+                   int *valid_san)
+ {
+@@ -171,7 +173,7 @@ verify_client_san(krb5_context context,
+                  __FUNCTION__, client_string, san_string);
+         krb5_free_unparsed_name(context, san_string);
+ #endif
+-        if (krb5_principal_compare(context, princs[i], client)) {
++        if (cb->match_client(context, rock, princs[i])) {
+             pkiDebug("%s: pkinit san match found\n", __FUNCTION__);
+             *valid_san = 1;
+             retval = 0;
+@@ -199,7 +201,7 @@ verify_client_san(krb5_context context,
+                  __FUNCTION__, client_string, san_string);
+         krb5_free_unparsed_name(context, san_string);
+ #endif
+-        if (krb5_principal_compare(context, upns[i], client)) {
++        if (cb->match_client(context, rock, upns[i])) {
+             pkiDebug("%s: upn san match found\n", __FUNCTION__);
+             *valid_san = 1;
+             retval = 0;
+@@ -387,8 +389,8 @@ pkinit_server_verify_padata(krb5_context context,
+     }
+     if (is_signed) {
+ 
+-        retval = verify_client_san(context, plgctx, reqctx, request->client,
+-                                   &valid_san);
++        retval = verify_client_san(context, plgctx, reqctx, cb, rock,
++                                   request->client, &valid_san);
+         if (retval)
+             goto cleanup;
+         if (!valid_san) {
diff --git a/SOURCES/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..2089450
--- /dev/null
+++ b/SOURCES/Use-the-canonical-client-principal-name-for-OTP.patch
@@ -0,0 +1,29 @@
+From 7c922602fe8fec44c55558daa32061cea86355cb 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/kprop.service b/SOURCES/kprop.service
index 4ed2247..da6a6b8 100644
--- a/SOURCES/kprop.service
+++ b/SOURCES/kprop.service
@@ -4,7 +4,8 @@ After=syslog.target network.target
 
 [Service]
 Type=forking
-ExecStart=/usr/sbin/_kpropd
+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/krb5-1.11-kpasswdtest.patch b/SOURCES/krb5-1.11-kpasswdtest.patch
index f07b225..4657926 100644
--- a/SOURCES/krb5-1.11-kpasswdtest.patch
+++ b/SOURCES/krb5-1.11-kpasswdtest.patch
@@ -1,6 +1,17 @@
---- krb5-1.11.3/src/kadmin/testing/proto/krb5.conf.proto
-+++ krb5-1.11.3/src/kadmin/testing/proto/krb5.conf.proto
-@@ -7,6 +7,7 @@
+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
diff --git a/SOURCES/krb5-1.11-run_user_0.patch b/SOURCES/krb5-1.11-run_user_0.patch
index 6be760a..734341c 100644
--- a/SOURCES/krb5-1.11-run_user_0.patch
+++ b/SOURCES/krb5-1.11-run_user_0.patch
@@ -1,9 +1,16 @@
-A hack: if we're looking at creating a ccache directory directly below
-the /run/user/0 directory, and /run/user/0 doesn't exist, try to create
-it, too.
+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
 
---- krb5/src/lib/krb5/ccache/cc_dir.c
-+++ krb5/src/lib/krb5/ccache/cc_dir.c
+---
+ 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>
@@ -13,7 +20,7 @@ it, too.
  extern const krb5_cc_ops krb5_dcc_ops;
  extern const krb5_cc_ops krb5_fcc_ops;
  
-@@ -239,6 +241,18 @@
+@@ -237,6 +239,18 @@ verify_dir(krb5_context context, const char *dirname)
  
      if (stat(dirname, &st) < 0) {
          if (errno == ENOENT) {
diff --git a/SOURCES/krb5-1.12-api.patch b/SOURCES/krb5-1.12-api.patch
index f5432a3..ae261d5 100644
--- a/SOURCES/krb5-1.12-api.patch
+++ b/SOURCES/krb5-1.12-api.patch
@@ -1,10 +1,17 @@
-Reference docs don't define what happens if you call krb5_realm_compare() with
-malformed krb5_principal structures.  Define a behavior which keeps it from
-crashing if applications don't check ahead of time.
+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
 
---- krb5/src/lib/krb5/krb/princ_comp.c
-+++ krb5/src/lib/krb5/krb/princ_comp.c
-@@ -41,6 +41,10 @@ realm_compare_flags(krb5_context context
+---
+ 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;
  
@@ -15,7 +22,7 @@ crashing if applications don't check ahead of time.
      if (realm1->length != realm2->length)
          return FALSE;
      if (realm1->length == 0)
-@@ -92,6 +98,9 @@ krb5_principal_compare_flags(krb5_contex
+@@ -88,6 +92,9 @@ krb5_principal_compare_flags(krb5_context context,
      krb5_principal upn2 = NULL;
      krb5_boolean ret = FALSE;
  
diff --git a/SOURCES/krb5-1.12-buildconf.patch b/SOURCES/krb5-1.12-buildconf.patch
deleted file mode 100644
index 11b816f..0000000
--- a/SOURCES/krb5-1.12-buildconf.patch
+++ /dev/null
@@ -1,54 +0,0 @@
-Build binaries in this package as RELRO PIEs, libraries as partial RELRO,
-and install shared libraries with the execute bit set on them.  Prune out
-the -L/usr/lib* and PIE flags where they might leak out and affect
-apps which just want to link with the libraries. FIXME: needs to check and
-not just assume that the compiler supports using these flags.
-
---- krb5/src/config/shlib.conf
-+++ krb5/src/config/shlib.conf
-@@ -419,7 +419,7 @@ mips-*-netbsd*)
- 	SHLIBEXT=.so
- 	# Linux ld doesn't default to stuffing the SONAME field...
- 	# Use objdump -x to examine the fields of the library
--	LDCOMBINE='$(CC) -shared -fPIC -Wl,-h,$(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT),--no-undefined'
-+	LDCOMBINE='$(CC) -shared -fPIC -Wl,-h,$(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT),--no-undefined -Wl,-z,relro -Wl,--warn-shared-textrel'
- 	# 
- 	LDCOMBINE_TAIL='-Wl,--version-script binutils.versions && $(PERL) -w $(top_srcdir)/util/export-check.pl $(SHLIB_EXPORT_FILE) $@'
- 	SHLIB_EXPORT_FILE_DEP=binutils.versions
-@@ -430,7 +430,8 @@
- 	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)'
---- krb5/src/build-tools/krb5-config.in
-+++ krb5/src/build-tools/krb5-config.in
-@@ -189,6 +189,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
---- krb5/src/config/pre.in
-+++ krb5/src/config/pre.in
-@@ -188,7 +188,7 @@
- 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/SOURCES/krb5-1.12-ksu-path.patch b/SOURCES/krb5-1.12-ksu-path.patch
index 65552c9..7127916 100644
--- a/SOURCES/krb5-1.12-ksu-path.patch
+++ b/SOURCES/krb5-1.12-ksu-path.patch
@@ -1,7 +1,16 @@
-Set the default PATH to the one set by login.
+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
 
---- krb5/src/clients/ksu/Makefile.in
-+++ krb5/src/clients/ksu/Makefile.in
+---
+ 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)..
diff --git a/SOURCES/krb5-1.12-ktany.patch b/SOURCES/krb5-1.12-ktany.patch
index 88f1a7e..a518ebf 100644
--- a/SOURCES/krb5-1.12-ktany.patch
+++ b/SOURCES/krb5-1.12-ktany.patch
@@ -1,10 +1,48 @@
-Adds an "ANY" keytab type which is a list of other keytab locations to search
-when searching for a specific entry.  When iterated through, it only presents
-the contents of the first keytab.
+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
 
-diff -up /dev/null krb5-1.7/src/lib/krb5/keytab/kt_any.c
---- /dev/null	2009-06-04 10:34:55.169007373 -0400
-+++ krb5-1.7/src/lib/krb5/keytab/kt_any.c	2009-06-04 13:54:36.000000000 -0400
+---
+ 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
@@ -298,10 +336,11 @@ diff -up /dev/null krb5-1.7/src/lib/krb5/keytab/kt_any.c
 +    free(data->choices);
 +    free(data);
 +}
-diff -up krb5-1.7/src/lib/krb5/keytab/ktbase.c krb5-1.7/src/lib/krb5/keytab/ktbase.c
---- krb5-1.7/src/lib/krb5/keytab/ktbase.c	2009-02-18 13:18:56.000000000 -0500
-+++ krb5-1.7/src/lib/krb5/keytab/ktbase.c	2009-06-04 13:54:36.000000000 -0400
-@@ -59,14 +59,19 @@ extern const krb5_kt_ops krb5_ktf_ops;
+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;
@@ -322,30 +361,3 @@ diff -up krb5-1.7/src/lib/krb5/keytab/ktbase.c krb5-1.7/src/lib/krb5/keytab/ktba
  };
  const static struct krb5_kt_typelist krb5_kt_typelist_memory = {
      &krb5_mkt_ops,
-diff -up krb5-1.7/src/lib/krb5/keytab/Makefile.in krb5-1.7/src/lib/krb5/keytab/Makefile.in
---- krb5-1.7/src/lib/krb5/keytab/Makefile.in	2009-01-05 15:27:53.000000000 -0500
-+++ krb5-1.7/src/lib/krb5/keytab/Makefile.in	2009-06-04 13:54:36.000000000 -0400
-@@ -19,6 +19,7 @@ STLIBOBJS= \
- 	ktfr_entry.o	\
- 	ktremove.o	\
- 	ktfns.o		\
-+	kt_any.o	\
- 	kt_file.o	\
- 	kt_memory.o	\
- 	kt_srvtab.o	\
-@@ -31,6 +32,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)	\
-@@ -43,6 +45,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/SOURCES/krb5-1.12.1-pam.patch b/SOURCES/krb5-1.12.1-pam.patch
index 5a8e65e..87eeec9 100644
--- a/SOURCES/krb5-1.12.1-pam.patch
+++ b/SOURCES/krb5-1.12.1-pam.patch
@@ -1,21 +1,24 @@
-Modify ksu so that it performs account and session management on behalf of
-the target user account, mimicking the action of regular su.  The default
-service name is "ksu", because on Fedora at least the configuration used
-is determined by whether or not a login shell is being opened, and so
-this may need to vary, too.  At run-time, ksu's behavior can be reset to
-the earlier, non-PAM behavior by setting "use_pam" to false in the [ksu]
-section of /etc/krb5.conf.
+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
 
-When enabled, ksu gains a dependency on libpam.
+---
+ 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
 
-Originally RT#5939, though it's changed since then to perform the account
-and session management before dropping privileges, and to apply on top of
-changes we're proposing for how it handles cache collections.
-
-diff -up krb5/src/aclocal.m4.pam krb5/src/aclocal.m4
---- krb5/src/aclocal.m4.pam	2009-11-22 12:00:45.000000000 -0500
-+++ krb5/src/aclocal.m4	2010-03-05 10:48:08.000000000 -0500
-@@ -1703,3 +1703,70 @@ AC_DEFUN(KRB5_AC_KEYRING_CCACHE,[
+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
@@ -86,9 +89,48 @@ diff -up krb5/src/aclocal.m4.pam krb5/src/aclocal.m4
 +AC_SUBST(PAM_MAN)
 +AC_SUBST(NON_PAM_MAN)
 +])dnl
-diff -up krb5/src/clients/ksu/main.c.pam krb5/src/clients/ksu/main.c
---- krb5/src/clients/ksu/main.c.pam	2009-11-02 22:27:56.000000000 -0500
-+++ krb5/src/clients/ksu/main.c	2010-03-05 10:48:08.000000000 -0500
+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
   */
@@ -116,7 +158,7 @@ diff -up krb5/src/clients/ksu/main.c.pam krb5/src/clients/ksu/main.c
  /***********/
  
  #define KS_TEMPORARY_CACHE "MEMORY:_ksu"
-@@ -586,6 +592,23 @@ main (argc, argv)
+@@ -515,6 +521,23 @@ main (argc, argv)
                 prog_name,target_user,client_name,
                 source_user,ontty());
  
@@ -140,7 +182,7 @@ diff -up krb5/src/clients/ksu/main.c.pam krb5/src/clients/ksu/main.c
          /* Run authorization as target.*/
          if (krb5_seteuid(target_uid)) {
              com_err(prog_name, errno, _("while switching to target for "
-@@ -651,6 +676,24 @@
+@@ -575,6 +598,24 @@ main (argc, argv)
  
              exit(1);
          }
@@ -165,7 +207,7 @@ diff -up krb5/src/clients/ksu/main.c.pam krb5/src/clients/ksu/main.c
      }
  
      if( some_rest_copy){
-@@ -720,6 +745,30 @@
+@@ -632,6 +673,30 @@ main (argc, argv)
          exit(1);
      }
  
@@ -196,7 +238,7 @@ diff -up krb5/src/clients/ksu/main.c.pam krb5/src/clients/ksu/main.c
      /* set permissions */
      if (setgid(target_pwd->pw_gid) < 0) {
          perror("ksu: setgid");
-@@ -792,7 +817,7 @@ main (argc, argv)
+@@ -729,7 +794,7 @@ main (argc, argv)
          fprintf(stderr, "program to be execed %s\n",params[0]);
      }
  
@@ -205,7 +247,7 @@ diff -up krb5/src/clients/ksu/main.c.pam krb5/src/clients/ksu/main.c
          execv(params[0], params);
          com_err(prog_name, errno, _("while trying to execv %s"), params[0]);
          sweep_up(ksu_context, cc_target);
-@@ -823,16 +875,35 @@ main (argc, argv)
+@@ -759,16 +824,35 @@ main (argc, argv)
              if (ret_pid == -1) {
                  com_err(prog_name, errno, _("while calling waitpid"));
              }
@@ -242,46 +284,11 @@ diff -up krb5/src/clients/ksu/main.c.pam krb5/src/clients/ksu/main.c
              exit (1);
          }
      }
-diff -up krb5/src/clients/ksu/Makefile.in.pam krb5/src/clients/ksu/Makefile.in
---- krb5/src/clients/ksu/Makefile.in.pam	2009-11-22 13:13:29.000000000 -0500
-+++ krb5/src/clients/ksu/Makefile.in	2010-03-05 11:55:14.000000000 -0500
-@@ -7,12 +7,14 @@
- 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
-@@ -21,13 +23,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 -up krb5/src/clients/ksu/pam.c.pam krb5/src/clients/ksu/pam.c
---- krb5/src/clients/ksu/pam.c.pam	2010-03-05 10:48:08.000000000 -0500
-+++ krb5/src/clients/ksu/pam.c	2010-03-05 10:48:08.000000000 -0500
+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
@@ -672,9 +679,11 @@ diff -up krb5/src/clients/ksu/pam.c.pam krb5/src/clients/ksu/pam.c
 +	return ret;
 +}
 +#endif
-diff -up krb5/src/clients/ksu/pam.h.pam krb5/src/clients/ksu/pam.h
---- krb5/src/clients/ksu/pam.h.pam	2010-03-05 10:48:08.000000000 -0500
-+++ krb5/src/clients/ksu/pam.h	2010-03-05 10:48:08.000000000 -0500
+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
@@ -733,10 +742,11 @@ diff -up krb5/src/clients/ksu/pam.h.pam krb5/src/clients/ksu/pam.h
 +int appl_pam_cred_init(void);
 +void appl_pam_cleanup(void);
 +#endif
-diff -up krb5/src/configure.in.pam krb5/src/configure.in
---- krb5/src/configure.in.pam	2009-12-31 18:13:56.000000000 -0500
-+++ krb5/src/configure.in	2010-03-05 10:48:08.000000000 -0500
-@@ -1051,6 +1051,8 @@ if test "$ac_cv_lib_socket" = "yes" -a "
+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)
  
diff --git a/SOURCES/krb5-1.13-dirsrv-accountlock.patch b/SOURCES/krb5-1.13-dirsrv-accountlock.patch
index 0a6661c..1c7182a 100644
--- a/SOURCES/krb5-1.13-dirsrv-accountlock.patch
+++ b/SOURCES/krb5-1.13-dirsrv-accountlock.patch
@@ -1,10 +1,19 @@
-Treat 'nsAccountLock: true' the same as 'loginDisabled: true'.  Updated from
-original version filed as RT#5891.
+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
 
-diff -up krb5-1.8/src/aclocal.m4.dirsrv-accountlock krb5-1.8/src/aclocal.m4
---- krb5-1.8/src/aclocal.m4.dirsrv-accountlock	2010-03-05 11:03:09.000000000 -0500
-+++ krb5-1.8/src/aclocal.m4	2010-03-05 11:03:10.000000000 -0500
-@@ -1656,6 +1656,15 @@ if test $with_ldap = yes; then
+---
+ src/aclocal.m4                                    |  9 +++++++++
+ src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c      | 17 +++++++++++++++++
+ src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c |  3 +++
+ 3 files changed, 29 insertions(+)
+
+diff --git a/src/aclocal.m4 b/src/aclocal.m4
+index f5667c35f..2bfb99496 100644
+--- a/src/aclocal.m4
++++ b/src/aclocal.m4
+@@ -1656,6 +1656,15 @@ if test "$with_ldap" = yes; then
    AC_MSG_NOTICE(enabling OpenLDAP database backend module support)
    OPENLDAP_PLUGIN=yes
  fi
@@ -20,10 +29,11 @@ diff -up krb5-1.8/src/aclocal.m4.dirsrv-accountlock krb5-1.8/src/aclocal.m4
  ])dnl
  dnl
  dnl If libkeyutils exists (on Linux) include it and use keyring ccache
-diff -up krb5-1.8/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c.dirsrv-accountlock krb5-1.8/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c
---- krb5-1.8/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c.dirsrv-accountlock	2009-11-24 18:52:25.000000000 -0500
-+++ krb5-1.8/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c	2010-03-05 11:03:10.000000000 -0500
-@@ -1546,6 +1546,23 @@ populate_krb5_db_entry(krb5_context cont
+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;
@@ -47,11 +57,11 @@ diff -up krb5-1.8/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c.dirsrv-accountloc
  
      ret = krb5_read_tkt_policy(context, ldap_context, entry, tktpolname);
      if (ret)
-         goto cleanup;
-diff -up krb5-1.8/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c.dirsrv-accountlock krb5-1.8/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c
---- krb5-1.8/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c.dirsrv-accountlock	2009-11-24 18:52:25.000000000 -0500
-+++ krb5-1.8/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c	2010-03-05 11:03:10.000000000 -0500
-@@ -59,6 +59,9 @@ char     *principal_attributes[] = { "kr
+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",
@@ -60,4 +70,4 @@ diff -up krb5-1.8/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c.dirsrv-accou
 +#endif
                                       "krbLastPwdChange",
                                       "krbLastAdminUnlock",
-                                      "krbExtraData",
+                                      "krbPrincipalAuthInd",
diff --git a/SOURCES/krb5-1.14.1-selinux-label.patch b/SOURCES/krb5-1.14.1-selinux-label.patch
deleted file mode 100644
index e3585c7..0000000
--- a/SOURCES/krb5-1.14.1-selinux-label.patch
+++ /dev/null
@@ -1,1065 +0,0 @@
-From f9a89d1c197897707ebf13a7bb99a0d495686c93 Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Mon, 18 Apr 2016 16:05:22 -0400
-Subject: [PATCH] krb5-1.14.1-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/gss-kernel-lib/Makefile.in                |   5 +-
- src/util/profile/prof_file.c                       |   3 +-
- src/util/support/Makefile.in                       |   3 +-
- src/util/support/selinux.c                         | 407 +++++++++++++++++++++
- 26 files changed, 592 insertions(+), 22 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 ce045ab..2b47aee 100644
---- a/src/aclocal.m4
-+++ b/src/aclocal.m4
-@@ -87,6 +87,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
-@@ -1739,3 +1740,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 f6184da..c17cb5e 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 b0d9015..63271e7 100644
---- a/src/config/pre.in
-+++ b/src/config/pre.in
-@@ -174,6 +174,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=
-@@ -395,7 +396,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 8846ca0..9ec8d84 100644
---- a/src/configure.in
-+++ b/src/configure.in
-@@ -1329,6 +1329,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 41c3d1b..6b7b2e3 100644
---- a/src/include/k5-int.h
-+++ b/src/include/k5-int.h
-@@ -129,6 +129,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 0000000..dfaaa84
---- /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 851cea3..2a814e5 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 07f62e9..5562d7e 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 82dfc0e..936f46b 100644
---- a/src/kdc/main.c
-+++ b/src/kdc/main.c
-@@ -847,7 +847,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 19c4355..64f9641 100644
---- a/src/lib/kadm5/logger.c
-+++ b/src/lib/kadm5/logger.c
-@@ -423,7 +423,7 @@ krb5_klog_init(krb5_context kcontext, char *ename, char *whoami, krb5_boolean do
-                      * Check for append/overwrite, then open the file.
-                      */
-                     if (cp[4] == ':' || cp[4] == '=') {
--                        f = fopen(&cp[5], (cp[4] == ':') ? "a" : "w");
-+                        f = WRITABLEFOPEN(&cp[5], (cp[4] == ':') ? "a" : "w");
-                         if (f) {
-                             set_cloexec_file(f);
-                             log_control.log_entries[i].lfu_filep = f;
-@@ -959,7 +959,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 d377a20..74aa523 100644
---- a/src/lib/kdb/kdb_log.c
-+++ b/src/lib/kdb/kdb_log.c
-@@ -480,7 +480,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 b00a6bb..4a218c3 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 ace654d..c9580ca 100644
---- a/src/lib/krb5/keytab/kt_file.c
-+++ b/src/lib/krb5/keytab/kt_file.c
-@@ -1030,7 +1030,7 @@ 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) ?
-                         fopen_mode_rbplus : fopen_mode_rb);
-     if (!KTFILEP(id)) {
-@@ -1038,7 +1038,7 @@ krb5_ktfileint_open(krb5_context context, krb5_keytab id, int mode)
-             /* try making it first time around */
-             k5_create_secure_file(context, KTFILENAME(id));
-             errno = 0;
--            KTFILEP(id) = fopen(KTFILENAME(id), fopen_mode_rbplus);
-+            KTFILEP(id) = WRITABLEFOPEN(KTFILENAME(id), fopen_mode_rbplus);
-             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 83c8d4d..a192461 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 2fb6aa0..c453189 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 9bad905..90df3b0 100644
---- a/src/plugins/kdb/db2/adb_openclose.c
-+++ b/src/plugins/kdb/db2/adb_openclose.c
-@@ -147,7 +147,7 @@ osa_adb_init_db(osa_adb_db_t *dbp, char *filename, char *lockfilename,
-          * POSIX systems
-          */
-         lockp->lockinfo.filename = strdup(lockfilename);
--        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 1b7bc16..9d449c0 100644
---- a/src/plugins/kdb/db2/kdb_db2.c
-+++ b/src/plugins/kdb/db2/kdb_db2.c
-@@ -695,8 +695,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 2977b17..d5809a5 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 2a5b4f8..7239d03 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 d8b26e7..b0daa7c 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 64d0f91..5d5c0a6 100644
---- a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
-+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
-@@ -178,7 +178,7 @@ done:
- 
-     /* 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));
-@@ -219,6 +219,9 @@ done:
-          * Delete the existing entry and add the new entry
-          */
-         FILE *newfile;
-+#ifdef USE_SELINUX
-+        void *selabel;
-+#endif
- 
-         mode_t omask;
- 
-@@ -230,7 +233,13 @@ done:
-         }
- 
-         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 1383156..a950924 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/gss-kernel-lib/Makefile.in b/src/util/gss-kernel-lib/Makefile.in
-index f70f3c6..7a2f9cc 100644
---- a/src/util/gss-kernel-lib/Makefile.in
-+++ b/src/util/gss-kernel-lib/Makefile.in
-@@ -61,6 +61,7 @@ HEADERS= \
- 	gssapi_err_generic.h \
- 	k5-int.h \
- 	k5-int-pkinit.h \
-+	k5-label.h \
- 	k5-thread.h \
- 	k5-platform.h \
- 	k5-buf.h \
-@@ -162,10 +163,12 @@ gssapi_generic.h: $(GSS_GENERIC)/gssapi_generic.h
- 	$(CP) $(GSS_GENERIC)/gssapi_generic.h $@
- gssapi_err_generic.h: $(GSS_GENERIC_BUILD)/gssapi_err_generic.h
- 	$(CP) $(GSS_GENERIC_BUILD)/gssapi_err_generic.h $@
--k5-int.h: $(INCLUDE)/k5-int.h
-+k5-int.h: $(INCLUDE)/k5-int.h k5-label.h
- 	$(CP) $(INCLUDE)/k5-int.h $@
- k5-int-pkinit.h: $(INCLUDE)/k5-int-pkinit.h
- 	$(CP) $(INCLUDE)/k5-int-pkinit.h $@
-+k5-label.h: $(INCLUDE)/k5-label.h
-+	$(CP) $(INCLUDE)/k5-label.h $@
- k5-thread.h: $(INCLUDE)/k5-thread.h
- 	$(CP) $(INCLUDE)/k5-thread.h $@
- k5-platform.h: $(INCLUDE)/k5-platform.h
-diff --git a/src/util/profile/prof_file.c b/src/util/profile/prof_file.c
-index d774593..ccc671b 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 5181762..f77acd4 100644
---- a/src/util/support/Makefile.in
-+++ b/src/util/support/Makefile.in
-@@ -59,6 +59,7 @@ IPC_SYMS= \
- 
- STLIBOBJS= \
- 	threads.o \
-+	selinux.o \
- 	init-addrinfo.o \
- 	plugins.o \
- 	errors.o \
-@@ -131,7 +132,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 0000000..6cf1b0c
---- /dev/null
-+++ b/src/util/support/selinux.c
-@@ -0,0 +1,407 @@
-+/*
-+ * 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 */
--- 
-2.8.0.rc3
-
diff --git a/SOURCES/krb5-1.14.1.tar.gz.asc b/SOURCES/krb5-1.14.1.tar.gz.asc
deleted file mode 100644
index e42bf86..0000000
--- a/SOURCES/krb5-1.14.1.tar.gz.asc
+++ /dev/null
@@ -1,14 +0,0 @@
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v1
-
-iQGcBAABAgAGBQJW1KZzAAoJEKMvF/0AVcMF9cQMAKZNlrtrB6ZS6CLFqGpRPfG2
-T6WbhJ5GEYl4kmdINbJ/RQUMk2APwxMSmsl7q8VNM1JIxQVAL7cBZTu+7cfs3mZE
-z9eCMmQsKdhZ3bnF52KB5LM2JfNUMidGEqzvOwK7mUgMXaPihiqYA0f2P10paOZl
-cW1as0bvTbjWrnAO+jpW3AuW50h7zOpicX4F8gmD0gaqzcKZO9uZA3p6bjIgVRsO
-XzofLkv0NxKWqcdLWocsVb2s4gezsQuRNIWmvpnR7ZFS2tfTuqrmdRNTm9t/yWMV
-5YmTBKE0/R9JRRmqLm/IglIqrq7G/ZYRHSYpT5oSu72iZRrf5pKQ/jwB0jpFMN00
-7xORKTWNwiGmAvIBBZqH+3emyIrcIdIw/3MN+HEZaLisJ1K/4bWJLB+0ju9dEcU/
-naNhagonxFbVfE7SrlW/WflZpun2PVZ4c9WTG6z1OWPXZkXMLqdv+mNSoCHcvpOt
-Z2+3HnWWanFncCn81oSLo/Zp3/0k7XBXtjp2Pb18CQ==
-=Py+v
------END PGP SIGNATURE-----
diff --git a/SOURCES/krb5-1.14.2-log_file_mode.patch b/SOURCES/krb5-1.14.2-log_file_mode.patch
deleted file mode 100644
index 0fb965c..0000000
--- a/SOURCES/krb5-1.14.2-log_file_mode.patch
+++ /dev/null
@@ -1,63 +0,0 @@
-From 9914b93516bbce9b1123ed5f9f796b7028944892 Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Thu, 17 Dec 2015 13:31:39 -0500
-Subject: [PATCH] Create KDC and kadmind log files with mode 0640
-
-In krb5_klog_init(), use open() and fdopen() to open log files so that
-we can specify a mode.  Specify a mode which doesn't include the
-group-write, other-read, or other-write bits even if the process umask
-allows them.
-
-[ghudson@mit.edu: wrote commit message, de-indented post-open setup
-code]
-[rharwood@redhat.com: backport not clean due to SELinux patching]
-
-ticket: 8344 (new)
----
- src/lib/kadm5/logger.c | 21 ++++++++++++---------
- 1 file changed, 12 insertions(+), 9 deletions(-)
-
-diff --git a/src/lib/kadm5/logger.c b/src/lib/kadm5/logger.c
-index 19c4355..f4a9387 100644
-
---- a/src/lib/kadm5/logger.c	2016-01-21 18:52:52.529544902 +0000
-+++ b/src/lib/kadm5/logger.c	2016-01-21 18:57:22.923972419 +0000
-@@ -354,7 +354,7 @@
-     const char  *logging_profent[3];
-     const char  *logging_defent[3];
-     char        **logging_specs;
--    int         i, ngood;
-+    int         i, ngood, fd, append;
-     char        *cp, *cp2;
-     char        savec = '\0';
-     int         error;
-@@ -422,18 +422,21 @@
-                     /*
-                      * Check for append/overwrite, then open the file.
-                      */
--                    if (cp[4] == ':' || cp[4] == '=') {
--                        f = WRITABLEFOPEN(&cp[5], (cp[4] == ':') ? "a" : "w");
--                        if (f) {
--                            set_cloexec_file(f);
--                            log_control.log_entries[i].lfu_filep = f;
--                            log_control.log_entries[i].log_type = K_LOG_FILE;
--                            log_control.log_entries[i].lfu_fname = &cp[5];
--                        } else {
-+                    append = (cp[4] == ':') ? O_APPEND : 0;
-+                    if (append || cp[4] == '=') {
-+                        fd = THREEPARAMOPEN(&cp[5], O_CREAT | O_WRONLY | append,
-+                                  S_IRUSR | S_IWUSR | S_IRGRP);
-+                        if (fd != -1)
-+                            f = fdopen(fd, append ? "a" : "w");
-+                        if (fd == -1 || f == NULL) {
-                             fprintf(stderr,"Couldn't open log file %s: %s\n",
-                                     &cp[5], error_message(errno));
-                             continue;
-                         }
-+                        set_cloexec_file(f);
-+                        log_control.log_entries[i].lfu_filep = f;
-+                        log_control.log_entries[i].log_type = K_LOG_FILE;
-+                        log_control.log_entries[i].lfu_fname = &cp[5];
-                     }
-                 }
- #ifdef  HAVE_SYSLOG
diff --git a/SOURCES/krb5-1.14.2-skip_unnecessary_mech_inquire_cred.patch b/SOURCES/krb5-1.14.2-skip_unnecessary_mech_inquire_cred.patch
deleted file mode 100644
index b3e9af6..0000000
--- a/SOURCES/krb5-1.14.2-skip_unnecessary_mech_inquire_cred.patch
+++ /dev/null
@@ -1,79 +0,0 @@
-From ff5eb892910eeac335d989ae14020da4ffbcc8ec Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Mon, 29 Feb 2016 16:51:22 -0500
-Subject: [PATCH] Skip unnecessary mech calls in gss_inquire_cred()
-
-If the caller does not request a name, lifetime, or cred_usage when
-calling gss_inquire_cred(), service the call by copying the mechanism
-list (if requested) but do not call into the mech.
-
-This change alleviates an issue (reported by Adam Bernstein) where
-SPNEGO can fail in the presence of expired krb5 credentials rather
-than proceeding with a different mechanism, or can resolve a krb5
-credential without the benefit of the target name.
-
-ticket: 8373
-target_version: 1.14-next
-target_version: 1.13-next
-tags: pullup
----
- src/lib/gssapi/mechglue/g_inq_cred.c | 39 ++++++++++++++++++++----------------
- 1 file changed, 22 insertions(+), 17 deletions(-)
-
-diff --git a/src/lib/gssapi/mechglue/g_inq_cred.c b/src/lib/gssapi/mechglue/g_inq_cred.c
-index c5577d4..9111962 100644
---- a/src/lib/gssapi/mechglue/g_inq_cred.c
-+++ b/src/lib/gssapi/mechglue/g_inq_cred.c
-@@ -92,27 +92,32 @@ gss_OID_set *		mechanisms;
- 	mech_cred = GSS_C_NO_CREDENTIAL;
- 	mech = gssint_get_mechanism(GSS_C_NULL_OID);
-     }
--    if (mech == NULL)
--	return (GSS_S_DEFECTIVE_CREDENTIAL);
--    if (!mech->gss_inquire_cred)
--	return (GSS_S_UNAVAILABLE);
- 
--    status = mech->gss_inquire_cred(minor_status, mech_cred,
--				    name ? &mech_name : NULL,
--				    lifetime, cred_usage, NULL);
--    if (status != GSS_S_COMPLETE) {
--	map_error(minor_status, mech);
--	return(status);
--    }
-+    /* Skip the call into the mech if the caller doesn't care about any of the
-+     * values we would ask for. */
-+    if (name != NULL || lifetime != NULL || cred_usage != NULL) {
-+	if (mech == NULL)
-+	    return (GSS_S_DEFECTIVE_CREDENTIAL);
-+	if (!mech->gss_inquire_cred)
-+	    return (GSS_S_UNAVAILABLE);
- 
--    if (name) {
--	/* Convert mech_name into a union_name equivalent. */
--	status = gssint_convert_name_to_union_name(&temp_minor_status,
--						   mech, mech_name, name);
-+	status = mech->gss_inquire_cred(minor_status, mech_cred,
-+					name ? &mech_name : NULL,
-+					lifetime, cred_usage, NULL);
- 	if (status != GSS_S_COMPLETE) {
--	    *minor_status = temp_minor_status;
- 	    map_error(minor_status, mech);
--	    return (status);
-+	    return(status);
-+	}
-+
-+	if (name) {
-+	    /* Convert mech_name into a union_name equivalent. */
-+	    status = gssint_convert_name_to_union_name(&temp_minor_status,
-+						       mech, mech_name, name);
-+	    if (status != GSS_S_COMPLETE) {
-+		*minor_status = temp_minor_status;
-+		map_error(minor_status, mech);
-+		return (status);
-+	    }
- 	}
-     }
- 
--- 
-2.8.0.rc3
-
diff --git a/SOURCES/krb5-1.14.3-fix_otp_as_key.patch b/SOURCES/krb5-1.14.3-fix_otp_as_key.patch
deleted file mode 100644
index 0a47bf0..0000000
--- a/SOURCES/krb5-1.14.3-fix_otp_as_key.patch
+++ /dev/null
@@ -1,50 +0,0 @@
-From 9929130f03f6a7f8a5f1acc23e92a609c8f27938 Mon Sep 17 00:00:00 2001
-From: Nathaniel McCallum <npmccallum@redhat.com>
-Date: Thu, 26 May 2016 16:54:29 -0400
-Subject: [PATCH] Avoid setting AS key when OTP preauth fails
-
-In otp_client_process(), call cb->set_as_key() later in the function
-after the OTP request has been created.  The previous position of this
-call caused the AS key to be replaced even when later code in the
-function failed, preventing other preauth mechanisms from retrieving
-the correct AS key.
-
-ticket: 8421 (new)
-target_version: 1.14-new
-target_version: 1.13-new
-tags: pullup
----
- src/lib/krb5/krb/preauth_otp.c | 10 +++++-----
- 1 file changed, 5 insertions(+), 5 deletions(-)
-
-diff --git a/src/lib/krb5/krb/preauth_otp.c b/src/lib/krb5/krb/preauth_otp.c
-index d9ddc8b..3de528b 100644
---- a/src/lib/krb5/krb/preauth_otp.c
-+++ b/src/lib/krb5/krb/preauth_otp.c
-@@ -1081,11 +1081,6 @@ otp_client_process(krb5_context context, krb5_clpreauth_moddata moddata,
-     if (as_key == NULL)
-         return ENOENT;
- 
--    /* Use FAST armor key as response key. */
--    retval = cb->set_as_key(context, rock, as_key);
--    if (retval != 0)
--        return retval;
--
-     /* Attempt to get token selection from the responder. */
-     pin = empty_data();
-     value = empty_data();
-@@ -1115,6 +1110,11 @@ otp_client_process(krb5_context context, krb5_clpreauth_moddata moddata,
-     if (retval != 0)
-         goto error;
- 
-+    /* Use FAST armor key as response key. */
-+    retval = cb->set_as_key(context, rock, as_key);
-+    if (retval != 0)
-+        goto error;
-+
-     /* Encode the request into the pa_data output. */
-     retval = set_pa_data(req, pa_data_out);
- error:
--- 
-2.8.1
-
diff --git a/SOURCES/krb5-1.14.3-krad-recv.patch b/SOURCES/krb5-1.14.3-krad-recv.patch
deleted file mode 100644
index 9016c88..0000000
--- a/SOURCES/krb5-1.14.3-krad-recv.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-From c969e8a37617e9c7743a28177dd3808f7d08cee9 Mon Sep 17 00:00:00 2001
-From: Nathaniel McCallum <npmccallum@redhat.com>
-Date: Tue, 21 Jun 2016 16:12:36 -0400
-Subject: [PATCH] Fix incorrect recv() size calculation in libkrad
-
-Before this patch libkrad would always subtract the existing buffer
-length from pktlen before passing it to recv().  In the case of stream
-sockets, this is incorrect since krad_packet_bytes_needed() already
-performs this calculation.  Subtracting the buffer length twice could
-cause integer underflow on the len parameter to recv().
-
-ticket: 8430 (new)
-target_version: 1.14-next
-target_version: 1.13-next
-tags: pullup
----
- src/lib/krad/remote.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/src/lib/krad/remote.c b/src/lib/krad/remote.c
-index aaabffd..df3de3a 100644
---- a/src/lib/krad/remote.c
-+++ b/src/lib/krad/remote.c
-@@ -315,7 +315,7 @@ on_io_read(krad_remote *rr)
-     request *tmp, *r;
-     int i;
- 
--    pktlen = sizeof(rr->buffer_);
-+    pktlen = sizeof(rr->buffer_) - rr->buffer.length;
-     if (rr->info->ai_socktype == SOCK_STREAM) {
-         pktlen = krad_packet_bytes_needed(&rr->buffer);
-         if (pktlen < 0) {
-@@ -328,7 +328,7 @@ on_io_read(krad_remote *rr)
- 
-     /* Read the packet. */
-     i = recv(verto_get_fd(rr->io), rr->buffer.data + rr->buffer.length,
--             pktlen - rr->buffer.length, 0);
-+             pktlen, 0);
-     if (i < 0) {
-         /* Should we try again? */
-         if (errno == EWOULDBLOCK || errno == EAGAIN || errno == EINTR)
--- 
-2.8.1
-
diff --git a/SOURCES/krb5-1.14.3-ksu_root_prompt.patch b/SOURCES/krb5-1.14.3-ksu_root_prompt.patch
deleted file mode 100644
index 356f2c7..0000000
--- a/SOURCES/krb5-1.14.3-ksu_root_prompt.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-From 324342ebf3a6b6e6d69268dc8640c642fdb25778 Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Thu, 28 Apr 2016 16:20:22 -0400
-Subject: [PATCH] krb5-1.14.3-ksu_root_prompt.patch
-
-Backport: 2f8b9ef90829b031448d4547190c72438a69aacd
----
- src/clients/ksu/main.c | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
-diff --git a/src/clients/ksu/main.c b/src/clients/ksu/main.c
-index 1b2ca83..cab0c18 100644
---- a/src/clients/ksu/main.c
-+++ b/src/clients/ksu/main.c
-@@ -122,7 +122,7 @@ main (argc, argv)
-     extern char * getpass(), *crypt();
-     int pargc;
-     char ** pargv;
--    krb5_boolean stored = FALSE, cc_reused = FALSE;
-+    krb5_boolean stored = FALSE, cc_reused = FALSE, given_princ = FALSE;
-     krb5_boolean zero_password;
-     krb5_boolean restrict_creds;
-     krb5_deltat lifetime, rlife;
-@@ -244,6 +244,7 @@ main (argc, argv)
-                 com_err(prog_name, retval, _("when parsing name %s"), optarg);
-                 errflg++;
-             }
-+            given_princ = TRUE;
-             break;
- #ifdef DEBUG
-         case 'D':
-@@ -468,7 +469,7 @@ main (argc, argv)
- 
-     if ((source_uid == 0) || (target_uid == source_uid)){
- #ifdef GET_TGT_VIA_PASSWD
--        if ((!all_rest_copy) && client != NULL && (stored == FALSE)){
-+        if (!all_rest_copy && given_princ && client != NULL && !stored) {
-             fprintf(stderr, _("WARNING: Your password may be exposed if you "
-                               "enter it here and are logged\n"));
-             fprintf(stderr, _("         in remotely using an unsecure "
--- 
-2.8.0.rc3
-
diff --git a/SOURCES/krb5-1.14.4-CVE-2016-3120.patch b/SOURCES/krb5-1.14.4-CVE-2016-3120.patch
deleted file mode 100644
index fa412aa..0000000
--- a/SOURCES/krb5-1.14.4-CVE-2016-3120.patch
+++ /dev/null
@@ -1,57 +0,0 @@
-From 93b4a6306a0026cf1cc31ac4bd8a49ba5d034ba7 Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Tue, 19 Jul 2016 11:00:28 -0400
-Subject: [PATCH] Fix S4U2Self KDC crash when anon is restricted
-
-In validate_as_request(), when enforcing restrict_anonymous_to_tgt,
-use client.princ instead of request->client; the latter is NULL when
-validating S4U2Self requests.
-
-CVE-2016-3120:
-
-In MIT krb5 1.9 and later, an authenticated attacker can cause krb5kdc
-to dereference a null pointer if the restrict_anonymous_to_tgt option
-is set to true, by making an S4U2Self request.
-
-  CVSSv2 Vector: AV:N/AC:H/Au:S/C:N/I:N/A:C/E:H/RL:OF/RC:C
-
-ticket: 8458 (new)
-target_version: 1.14-next
-target_version: 1.13-next
----
- src/kdc/kdc_util.c    | 2 +-
- src/tests/t_pkinit.py | 5 +++++
- 2 files changed, 6 insertions(+), 1 deletion(-)
-
-diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
-index 776e130..29f9dbb 100644
---- a/src/kdc/kdc_util.c
-+++ b/src/kdc/kdc_util.c
-@@ -739,7 +739,7 @@ validate_as_request(kdc_realm_t *kdc_active_realm,
-         return(KDC_ERR_MUST_USE_USER2USER);
-     }
- 
--    if (check_anon(kdc_active_realm, request->client, request->server) != 0) {
-+    if (check_anon(kdc_active_realm, client.princ, request->server) != 0) {
-         *status = "ANONYMOUS NOT ALLOWED";
-         return(KDC_ERR_POLICY);
-     }
-diff --git a/src/tests/t_pkinit.py b/src/tests/t_pkinit.py
-index b66c458..f0214b6 100755
---- a/src/tests/t_pkinit.py
-+++ b/src/tests/t_pkinit.py
-@@ -93,6 +93,11 @@ out = realm.run([kvno, realm.host_princ], expected_code=1)
- if 'KDC policy rejects request' not in out:
-     fail('Wrong error for restricted anonymous PKINIT')
- 
-+# Regression test for #8458: S4U2Self requests crash the KDC if
-+# anonymous is restricted.
-+realm.kinit(realm.host_princ, flags=['-k'])
-+realm.run([kvno, '-U', 'user', realm.host_princ])
-+
- # Go back to a normal KDC and disable anonymous PKINIT.
- realm.stop_kdc()
- realm.start_kdc()
--- 
-2.8.1
-
diff --git a/SOURCES/krb5-1.14.4-Fix-responder-without-preauth.patch b/SOURCES/krb5-1.14.4-Fix-responder-without-preauth.patch
deleted file mode 100644
index c6693c4..0000000
--- a/SOURCES/krb5-1.14.4-Fix-responder-without-preauth.patch
+++ /dev/null
@@ -1,86 +0,0 @@
-From c45c43a82491f5c4487087cb424381e884559433 Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Fri, 5 Aug 2016 12:28:03 -0400
-Subject: [PATCH] Use responder for non-preauth AS requests
-
-If no AS reply key is computed during pre-authentication (typically
-because no pre-authentication was required by the KDC), ask for the
-password using the responder before calling gak_fct for the key, and
-supply any resulting responder items to gak_fct.
-
-ticket: 8454
-target_version: 1.14-next
-target_version: 1.13-next
-tags: pullup
----
- src/lib/krb5/krb/get_in_tkt.c | 24 +++++++++++++++++++++++-
- src/tests/t_general.py        |  5 +++++
- 2 files changed, 28 insertions(+), 1 deletion(-)
-
-diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
-index 24cd970..4290d0c 100644
---- a/src/lib/krb5/krb/get_in_tkt.c
-+++ b/src/lib/krb5/krb/get_in_tkt.c
-@@ -1391,6 +1391,8 @@ init_creds_step_reply(krb5_context context,
-     krb5_keyblock encrypting_key;
-     krb5_boolean fast_avail;
-     krb5_ccache out_ccache = k5_gic_opt_get_out_ccache(ctx->opt);
-+    krb5_responder_fn responder;
-+    void *responder_data;
- 
-     encrypting_key.length = 0;
-     encrypting_key.contents = NULL;
-@@ -1549,13 +1551,33 @@ init_creds_step_reply(krb5_context context,
-         code = -1;
- 
-     if (code != 0) {
-+        /* If a responder was provided and we are using a password, ask for the
-+         * password using the responder before falling back to the prompter. */
-+        k5_gic_opt_get_responder(ctx->opt, &responder, &responder_data);
-+        if (responder != NULL && !ctx->as_key.length) {
-+            /* Indicate a need for the AS key by calling the gak_fct with a
-+             * NULL as_key. */
-+            code = ctx->gak_fct(context, ctx->request->client, ctx->etype,
-+                                NULL, NULL, NULL, NULL, NULL, ctx->gak_data,
-+                                ctx->rctx.items);
-+            if (code != 0)
-+                goto cleanup;
-+
-+            /* If that produced a responder question, invoke the responder. */
-+            if (!k5_response_items_empty(ctx->rctx.items)) {
-+                code = (*responder)(context, responder_data, &ctx->rctx);
-+                if (code != 0)
-+                    goto cleanup;
-+            }
-+        }
-+
-         /* if we haven't get gotten a key, get it now */
-         TRACE_INIT_CREDS_GAK(context, &ctx->salt, &ctx->s2kparams);
-         code = (*ctx->gak_fct)(context, ctx->request->client,
-                                ctx->reply->enc_part.enctype,
-                                ctx->prompter, ctx->prompter_data,
-                                &ctx->salt, &ctx->s2kparams,
--                               &ctx->as_key, ctx->gak_data, NULL);
-+                               &ctx->as_key, ctx->gak_data, ctx->rctx.items);
-         if (code != 0)
-             goto cleanup;
-         TRACE_INIT_CREDS_AS_KEY_GAK(context, &ctx->as_key);
-diff --git a/src/tests/t_general.py b/src/tests/t_general.py
-index fbdeddf..6d523fe 100755
---- a/src/tests/t_general.py
-+++ b/src/tests/t_general.py
-@@ -34,6 +34,11 @@ realm.stop()
- 
- realm = K5Realm(create_host=False)
- 
-+# Regression test for #8454 (responder callback isn't used when
-+# preauth is not required).
-+realm.run(['./responder', '-r', 'password=%s' % password('user'),
-+           realm.user_princ])
-+
- # Test that WRONG_REALM responses aren't treated as referrals unless
- # they contain a crealm field pointing to a different realm.
- # (Regression test for #8060.)
--- 
-2.8.1
-
diff --git a/SOURCES/krb5-1.14.4-SNI-HTTP-Host.patch b/SOURCES/krb5-1.14.4-SNI-HTTP-Host.patch
deleted file mode 100644
index a34faad..0000000
--- a/SOURCES/krb5-1.14.4-SNI-HTTP-Host.patch
+++ /dev/null
@@ -1,108 +0,0 @@
-From 69c8662190bcd46f2300d0cea139681001ea5b26 Mon Sep 17 00:00:00 2001
-From: Christian Heimes <cheimes@redhat.com>
-Date: Mon, 8 Aug 2016 12:38:17 +0200
-Subject: [PATCH] Add Host HTTP header to MS-KKDCP requests
-
-Some web servers require a Host HTTP header for TLS connections with
-SNI (server name indicator).  It is also required for virtual hosts.
-
-ticket: 8472 (new)
-target_version: 1.14-next
-tags: pullup
----
- src/lib/krb5/os/sendto_kdc.c | 18 +++++++++++++-----
- 1 file changed, 13 insertions(+), 5 deletions(-)
-
-diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c
-index c85fdba..a2b7359 100644
---- a/src/lib/krb5/os/sendto_kdc.c
-+++ b/src/lib/krb5/os/sendto_kdc.c
-@@ -78,6 +78,7 @@
- #define MAX_PASS                    3
- #define DEFAULT_UDP_PREF_LIMIT   1465
- #define HARD_UDP_LIMIT          32700 /* could probably do 64K-epsilon ? */
-+#define PORT_LENGTH                 6 /* decimal repr of UINT16_MAX */
- 
- /* Select state flags.  */
- #define SSF_READ 0x01
-@@ -138,6 +139,7 @@ struct conn_state {
-     struct {
-         const char *uri_path;
-         const char *servername;
-+        char port[PORT_LENGTH];
-         char *https_request;
-         k5_tls_handle tls;
-     } http;
-@@ -611,6 +613,8 @@ make_proxy_request(struct conn_state *state, const krb5_data *realm,
-     k5_buf_init_dynamic(&buf);
-     uri_path = (state->http.uri_path != NULL) ? state->http.uri_path : "";
-     k5_buf_add_fmt(&buf, "POST /%s HTTP/1.0\r\n", uri_path);
-+    k5_buf_add_fmt(&buf, "Host: %s:%s\r\n", state->http.servername,
-+                   state->http.port);
-     k5_buf_add(&buf, "Cache-Control: no-cache\r\n");
-     k5_buf_add(&buf, "Pragma: no-cache\r\n");
-     k5_buf_add(&buf, "User-Agent: kerberos/1.0\r\n");
-@@ -673,7 +677,7 @@ static krb5_error_code
- add_connection(struct conn_state **conns, k5_transport transport,
-                krb5_boolean defer, struct addrinfo *ai, size_t server_index,
-                const krb5_data *realm, const char *hostname,
--               const char *uri_path, char **udpbufp)
-+               const char *port, const char *uri_path, char **udpbufp)
- {
-     struct conn_state *state, **tailptr;
- 
-@@ -695,11 +699,13 @@ add_connection(struct conn_state **conns, k5_transport transport,
-         state->service_write = service_tcp_write;
-         state->service_read = service_tcp_read;
-     } else if (transport == HTTPS) {
-+        assert(hostname != NULL && port != NULL);
-         state->service_connect = service_tcp_connect;
-         state->service_write = service_https_write;
-         state->service_read = service_https_read;
-         state->http.uri_path = uri_path;
-         state->http.servername = hostname;
-+        strlcpy(state->http.port, port, PORT_LENGTH);
-     } else {
-         state->service_connect = NULL;
-         state->service_write = NULL;
-@@ -785,7 +791,7 @@ resolve_server(krb5_context context, const krb5_data *realm,
-     struct addrinfo *addrs, *a, hint, ai;
-     krb5_boolean defer;
-     int err, result;
--    char portbuf[64];
-+    char portbuf[PORT_LENGTH];
- 
-     /* Skip UDP entries if we don't want UDP. */
-     if (strategy == NO_UDP && entry->transport == UDP)
-@@ -800,7 +806,7 @@ resolve_server(krb5_context context, const krb5_data *realm,
-         ai.ai_addr = (struct sockaddr *)&entry->addr;
-         defer = (entry->transport != transport);
-         return add_connection(conns, entry->transport, defer, &ai, ind, realm,
--                              NULL, entry->uri_path, udpbufp);
-+                              NULL, NULL, entry->uri_path, udpbufp);
-     }
- 
-     /* If the entry has a specified transport, use it. */
-@@ -826,7 +832,8 @@ resolve_server(krb5_context context, const krb5_data *realm,
-     retval = 0;
-     for (a = addrs; a != 0 && retval == 0; a = a->ai_next) {
-         retval = add_connection(conns, transport, FALSE, a, ind, realm,
--                                entry->hostname, entry->uri_path, udpbufp);
-+                                entry->hostname, portbuf, entry->uri_path,
-+                                udpbufp);
-     }
- 
-     /* For TCP_OR_UDP entries, add each address again with the non-preferred
-@@ -836,7 +843,8 @@ resolve_server(krb5_context context, const krb5_data *realm,
-         for (a = addrs; a != 0 && retval == 0; a = a->ai_next) {
-             a->ai_socktype = socktype_for_transport(transport);
-             retval = add_connection(conns, transport, TRUE, a, ind, realm,
--                                    entry->hostname, entry->uri_path, udpbufp);
-+                                    entry->hostname, portbuf,
-+                                    entry->uri_path, udpbufp);
-         }
-     }
-     freeaddrinfo(addrs);
--- 
-2.8.1
-
diff --git a/SOURCES/krb5-1.15-NTLM_SPNEGO.patch b/SOURCES/krb5-1.15-NTLM_SPNEGO.patch
deleted file mode 100644
index 9a61843..0000000
--- a/SOURCES/krb5-1.15-NTLM_SPNEGO.patch
+++ /dev/null
@@ -1,97 +0,0 @@
-From a7e899281f24aadec536f3cb0adf7340683c27cb Mon Sep 17 00:00:00 2001
-From: Simo Sorce <simo@redhat.com>
-Date: Wed, 30 Mar 2016 13:00:19 -0400
-Subject: [PATCH] Add SPNEGO special case for NTLMSSP+MechListMIC
-
-MS-SPNG section 3.3.5.1 documents an odd behavior the SPNEGO layer
-needs to implement specifically for the NTLMSSP mechanism.  This is
-required for compatibility with Windows services.
-
-ticket: 8423 (new)
----
- src/lib/gssapi/spnego/spnego_mech.c | 48 +++++++++++++++++++++++++++++++++----
- 1 file changed, 43 insertions(+), 5 deletions(-)
-
-diff --git a/src/lib/gssapi/spnego/spnego_mech.c b/src/lib/gssapi/spnego/spnego_mech.c
-index bb754d9..b76f7d6 100644
---- a/src/lib/gssapi/spnego/spnego_mech.c
-+++ b/src/lib/gssapi/spnego/spnego_mech.c
-@@ -520,6 +520,45 @@ mech_requires_mechlistMIC(spnego_gss_ctx_id_t sc)
- 	return result;
- }
- 
-+/* iso(1) org(3) dod(6) internet(1) private(4) enterprises(1) Microsoft(311)
-+ * security(2) mechanisms(2) NTLM(10) */
-+static const gss_OID_desc gss_mech_ntlmssp_oid =
-+	{ 10, "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a" };
-+
-+/* iso(1) org(3) dod(6) internet(1) private(4) enterprises(1) samba(7165)
-+ * gssntlmssp(655) controls(1) ntlmssp_reset_crypto(3) */
-+static const gss_OID_desc ntlmssp_reset_crypto_oid =
-+	{ 11, "\x2B\x06\x01\x04\x01\xB7\x7D\x85\x0F\x01\x03" };
-+
-+/*
-+ * MS-SPNG section 3.3.5.1 warns that the NTLM mechanism requires special
-+ * handling of the crypto state to interop with Windows.  If the mechanism for
-+ * sc is SPNEGO, invoke a mechanism-specific operation on the context to reset
-+ * the RC4 state after producing or verifying a MIC.  Ignore a result of
-+ * GSS_S_UNAVAILABLE for compatibility with older versions of the mechanism
-+ * that do not support this functionality.
-+ */
-+static OM_uint32
-+ntlmssp_reset_crypto_state(OM_uint32 *minor_status, spnego_gss_ctx_id_t sc,
-+			   OM_uint32 verify)
-+{
-+	OM_uint32 major, minor;
-+	gss_buffer_desc value;
-+
-+	if (!g_OID_equal(sc->internal_mech, &gss_mech_ntlmssp_oid))
-+		return GSS_S_COMPLETE;
-+
-+	value.length = sizeof(verify);
-+	value.value = &verify;
-+	major = gss_set_sec_context_option(&minor, &sc->ctx_handle,
-+					   (gss_OID)&ntlmssp_reset_crypto_oid,
-+					   &value);
-+	if (major == GSS_S_UNAVAILABLE)
-+		return GSS_S_COMPLETE;
-+	*minor_status = minor;
-+	return major;
-+}
-+
- /*
-  * Both initiator and acceptor call here to verify and/or create mechListMIC,
-  * and to consistency-check the MIC state.  handle_mic is invoked only if the
-@@ -601,6 +640,8 @@ process_mic(OM_uint32 *minor_status, gss_buffer_t mic_in,
- 		ret = gss_verify_mic(minor_status, sc->ctx_handle,
- 				     &sc->DER_mechTypes,
- 				     mic_in, &qop_state);
-+		if (ret == GSS_S_COMPLETE)
-+			ret = ntlmssp_reset_crypto_state(minor_status, sc, 1);
- 		if (ret != GSS_S_COMPLETE) {
- 			*negState = REJECT;
- 			*tokflag = ERROR_TOKEN_SEND;
-@@ -615,6 +656,8 @@ process_mic(OM_uint32 *minor_status, gss_buffer_t mic_in,
- 				  GSS_C_QOP_DEFAULT,
- 				  &sc->DER_mechTypes,
- 				  &tmpmic);
-+		if (ret == GSS_S_COMPLETE)
-+			ret = ntlmssp_reset_crypto_state(minor_status, sc, 0);
- 		if (ret != GSS_S_COMPLETE) {
- 			gss_release_buffer(&tmpmin, &tmpmic);
- 			*tokflag = NO_TOKEN_SEND;
-@@ -820,11 +863,6 @@ init_ctx_nego(OM_uint32 *minor_status, spnego_gss_ctx_id_t sc,
- 	return ret;
- }
- 
--/* iso(1) org(3) dod(6) internet(1) private(4) enterprise(1) Microsoft(311)
-- * security(2) mechanisms(2) NTLM(10) */
--static const gss_OID_desc gss_mech_ntlmssp_oid =
--	{ 10, "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a" };
--
- /*
-  * Handle acceptor's counter-proposal of an alternative mechanism.
-  */
--- 
-2.8.1
-
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..0e79ce9
--- /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-fix_t_kprop.patch b/SOURCES/krb5-1.15-fix_t_kprop.patch
deleted file mode 100644
index c43fdbe..0000000
--- a/SOURCES/krb5-1.15-fix_t_kprop.patch
+++ /dev/null
@@ -1,51 +0,0 @@
-From 9bcb30c91723e63c16c8a2cdbcd94f61f370a6a9 Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Wed, 10 Feb 2016 11:50:54 -0500
-Subject: [PATCH 1/3] Fix and adjust t_kprop.py
-
-The listprincs check was at the wrong indentation level and had the
-wrong argument grouping; fix it so we actually verify the propagation.
-
-Stop using the -t (runonce) flag to kpropd, so that kpropd continues
-to run until k5test.py terminates it.  Quit out of the read loop when
-we see that the load process is completed, instead of looking for end
-of input.  This change is needed in order to add hooks in k5test.py
-for checking daemons for memory leaks before terminating them.
----
- src/tests/t_kprop.py | 10 +++++-----
- 1 file changed, 5 insertions(+), 5 deletions(-)
-
-diff --git a/src/tests/t_kprop.py b/src/tests/t_kprop.py
-index e2026c8..d625627 100755
---- a/src/tests/t_kprop.py
-+++ b/src/tests/t_kprop.py
-@@ -24,21 +24,21 @@ for realm in multipass_realms(create_user=False):
-     realm.addprinc('wakawaka')
- 
-     # Start kpropd.
--    kpropd = realm.start_kpropd(slave, ['-d', '-t'])
-+    kpropd = realm.start_kpropd(slave, ['-d'])
- 
-     realm.run([kdb5_util, 'dump', dumpfile])
-     realm.run([kprop, '-f', dumpfile, '-P', str(realm.kprop_port()), hostname])
-     output('*** kpropd output follows\n')
-     while True:
-         line = kpropd.stdout.readline()
--        if line == '':
-+        if 'Database load process for full propagation completed' in line:
-             break
-         output('kpropd: ' + line)
-         if 'Rejected connection' in line:
-             fail('kpropd rejected connection from kprop')
- 
--            out = realm.run([kadminl, 'listprincs', slave])
--            if 'wakawaka' not in out:
--                fail('Slave does not have all principals from master')
-+    out = realm.run([kadminl, 'listprincs'], slave)
-+    if 'wakawaka' not in out:
-+        fail('Slave does not have all principals from master')
- 
- success('kprop tests')
--- 
-2.8.1
-
diff --git a/SOURCES/krb5-1.15-hide_deperecated_on_indicate.patch b/SOURCES/krb5-1.15-hide_deperecated_on_indicate.patch
deleted file mode 100644
index dc9db7a..0000000
--- a/SOURCES/krb5-1.15-hide_deperecated_on_indicate.patch
+++ /dev/null
@@ -1,89 +0,0 @@
-From a5e1c99acf3b7260ce9baa29d0bfbb350d026bb6 Mon Sep 17 00:00:00 2001
-From: Robbie Harwood <rharwood@redhat.com>
-Date: Thu, 19 May 2016 20:31:38 -0400
-Subject: [PATCH] Do not indicate deprecated GSS mechanisms
-
-The mechanisms themeselves will continue to work if requested, but will
-not be included in the gss_indicate_mech() list.  This works around a
-bug in some legacy applications that cannot cope with deprecated mechs
-being returned.
-
-ticket: 8419 (new)
----
- src/lib/gssapi/mechglue/g_initialize.c | 47 ++++++++++++++++++++++++++++++++++
- 1 file changed, 47 insertions(+)
-
-diff --git a/src/lib/gssapi/mechglue/g_initialize.c b/src/lib/gssapi/mechglue/g_initialize.c
-index b7e8a8d..213ea19 100644
---- a/src/lib/gssapi/mechglue/g_initialize.c
-+++ b/src/lib/gssapi/mechglue/g_initialize.c
-@@ -202,12 +202,55 @@ gss_OID *oid;
- 	return (generic_gss_release_oid(minor_status, oid));
- } /* gss_release_oid */
- 
-+/*
-+ * Wrapper around inquire_attrs_for_mech to determine whether a mechanism has
-+ * the deprecated attribute.  Must be called without g_mechSetLock since it
-+ * will call into the mechglue.
-+ */
-+static int
-+is_deprecated(gss_OID element)
-+{
-+	OM_uint32 major, minor;
-+	gss_OID_set mech_attrs = GSS_C_NO_OID_SET;
-+	int deprecated = 0;
-+
-+	major = gss_inquire_attrs_for_mech(&minor, element, &mech_attrs, NULL);
-+	if (major == GSS_S_COMPLETE) {
-+		gss_test_oid_set_member(&minor, (gss_OID)GSS_C_MA_DEPRECATED,
-+					mech_attrs, &deprecated);
-+	}
-+
-+	if (mech_attrs != GSS_C_NO_OID_SET)
-+		gss_release_oid_set(&minor, &mech_attrs);
-+
-+	return deprecated;
-+}
-+
-+/*
-+ * Removes mechs with the deprecated attribute from an OID set.  Must be
-+ * called without g_mechSetLock held since it calls into the mechglue.
-+ */
-+static void
-+prune_deprecated(gss_OID_set mech_set)
-+{
-+	OM_uint32 i, j;
-+
-+	j = 0;
-+	for (i = 0; i < mech_set->count; i++) {
-+	    if (!is_deprecated(&mech_set->elements[i]))
-+		mech_set->elements[j++] = mech_set->elements[i];
-+	    else
-+		gssalloc_free(mech_set->elements[i].elements);
-+	}
-+	mech_set->count = j;
-+}
- 
- /*
-  * this function will return an oid set indicating available mechanisms.
-  * The set returned is based on configuration file entries and
-  * NOT on the loaded mechanisms.  This function does not check if any
-  * of these can actually be loaded.
-+ * Deprecated mechanisms will not be returned.
-  * This routine needs direct access to the mechanism list.
-  * To avoid reading the configuration file each call, we will save a
-  * a mech oid set, and only update it once the file has changed.
-@@ -245,6 +288,10 @@ gss_OID_set *mechSet_out;
- 	k5_mutex_lock(&g_mechSetLock);
- 	status = generic_gss_copy_oid_set(minorStatus, &g_mechSet, mechSet_out);
- 	k5_mutex_unlock(&g_mechSetLock);
-+
-+	if (*mechSet_out != GSS_C_NO_OID_SET)
-+		prune_deprecated(*mechSet_out);
-+
- 	return (status);
- } /* gss_indicate_mechs */
- 
--- 
-2.8.1
-
diff --git a/SOURCES/krb5-1.15-kadmin-kprop-port-test.patch b/SOURCES/krb5-1.15-kadmin-kprop-port-test.patch
deleted file mode 100644
index c96a851..0000000
--- a/SOURCES/krb5-1.15-kadmin-kprop-port-test.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From 77c3f655f684761efe957722e500887f3199fc5f Mon Sep 17 00:00:00 2001
-From: Matt Rogers <mrogers@redhat.com>
-Date: Fri, 15 Jul 2016 10:32:51 -0400
-Subject: [PATCH] Update iprop tests for kadmind -k
-
-Test the use of the -k kprop-port option.
-
-ticket: 8456
----
- src/tests/t_iprop.py | 5 ++---
- 1 file changed, 2 insertions(+), 3 deletions(-)
-
-diff --git a/src/tests/t_iprop.py b/src/tests/t_iprop.py
-index 63ed118..e64fdd2 100755
---- a/src/tests/t_iprop.py
-+++ b/src/tests/t_iprop.py
-@@ -223,10 +223,9 @@ if 'Attributes: DISALLOW_ALL_TIX' not in out:
- slave1_out_dump_path = os.path.join(realm.testdir, 'dump.slave1.out')
- slave2_in_dump_path = os.path.join(realm.testdir, 'dump.slave2.in')
- slave2_kprop_port = str(realm.portbase + 9)
--slave1m['KPROP_PORT'] = slave2_kprop_port
- realm.start_server([kadmind, '-r', realm.realm, '-nofork', '-proponly', '-W',
--                    '-p', kdb5_util, '-K', kprop, '-F', slave1_out_dump_path],
--                   'starting...', slave1m)
-+                    '-p', kdb5_util, '-K', kprop, '-k', slave2_kprop_port,
-+                    '-F', slave1_out_dump_path], 'starting...', slave1m)
- 
- # Test similar default_realm and domain_realm map settings with -r realm.
- slave3_in_dump_path = os.path.join(realm.testdir, 'dump.slave3.in')
--- 
-2.8.1
-
diff --git a/SOURCES/krb5-1.15-kadmin-kprop-port.patch b/SOURCES/krb5-1.15-kadmin-kprop-port.patch
deleted file mode 100644
index 2f5f6e8..0000000
--- a/SOURCES/krb5-1.15-kadmin-kprop-port.patch
+++ /dev/null
@@ -1,111 +0,0 @@
-From 7ed18b1e5a11a514461be2281ff884e8173299b1 Mon Sep 17 00:00:00 2001
-From: Matt Rogers <mrogers@redhat.com>
-Date: Fri, 15 Jul 2016 10:17:45 -0400
-Subject: [PATCH] Add the kprop-port option to kadmind
-
-The -k option for kadmind sets the port number that kprop is spawned
-with during an iprop full resync.  Fall back to checking the
-KPROP_PORT environment variable if the option is not set.
-
-ticket: 8456 (new)
----
- doc/admin/admin_commands/kadmind.rst |  6 ++++++
- src/kadmin/server/ipropd_svc.c       |  6 +++---
- src/kadmin/server/ovsec_kadmd.c      | 11 ++++++++++-
- 3 files changed, 19 insertions(+), 4 deletions(-)
-
-diff --git a/doc/admin/admin_commands/kadmind.rst b/doc/admin/admin_commands/kadmind.rst
-index acf25e3..f5b7733 100644
---- a/doc/admin/admin_commands/kadmind.rst
-+++ b/doc/admin/admin_commands/kadmind.rst
-@@ -16,6 +16,7 @@ SYNOPSIS
- [**-P** *pid_file*]
- [**-p** *kdb5_util_path*]
- [**-K** *kprop_path*]
-+[**-k** *kprop_port*]
- [**-F** *dump_file*]
- 
- DESCRIPTION
-@@ -101,6 +102,11 @@ OPTIONS
-     specifies the path to the kprop command to use to send full dumps
-     to slaves in response to full resync requests.
- 
-+**-k** *kprop_port*
-+    specifies the port by which the kprop process that is spawned by kadmind
-+    connects to the slave kpropd, in order to transfer the dump file during
-+    an iprop full resync request.
-+
- **-F** *dump_file*
-     specifies the file path to be used for dumping the KDB in response
-     to full resync requests when iprop is enabled.
-diff --git a/src/kadmin/server/ipropd_svc.c b/src/kadmin/server/ipropd_svc.c
-index 62a0a2b..76d3fda 100644
---- a/src/kadmin/server/ipropd_svc.c
-+++ b/src/kadmin/server/ipropd_svc.c
-@@ -36,6 +36,7 @@ extern short l_port;
- extern char *kdb5_util;
- extern char *kprop;
- extern char *dump_file;
-+extern char *kprop_port;
- 
- static char *reply_ok_str	= "UPDATE_OK";
- static char *reply_err_str	= "UPDATE_ERROR";
-@@ -392,10 +393,9 @@ ipropx_resync(uint32_t vers, struct svc_req *rqstp)
- 
- 	DPRINT("%s: exec `kprop -r %s -f %s %s' ...\n",
- 	       whoami, handle->params.realm, dump_file, clhost);
--	/* XXX Yuck!  */
--	if (getenv("KPROP_PORT")) {
-+	if (kprop_port != NULL) {
- 	    pret = execl(kprop, "kprop", "-r", handle->params.realm, "-f",
--			 dump_file, "-P", getenv("KPROP_PORT"), clhost, NULL);
-+			 dump_file, "-P", kprop_port, clhost, NULL);
- 	} else {
- 	    pret = execl(kprop, "kprop", "-r", handle->params.realm, "-f",
- 			 dump_file, clhost, NULL);
-diff --git a/src/kadmin/server/ovsec_kadmd.c b/src/kadmin/server/ovsec_kadmd.c
-index 89bf4e6..bf780dc 100644
---- a/src/kadmin/server/ovsec_kadmd.c
-+++ b/src/kadmin/server/ovsec_kadmd.c
-@@ -72,6 +72,7 @@ int nofork = 0;
- char *kdb5_util = KPROPD_DEFAULT_KDB5_UTIL;
- char *kprop = KPROPD_DEFAULT_KPROP;
- char *dump_file = KPROP_DEFAULT_FILE;
-+char *kprop_port = NULL;
- 
- static krb5_context context;
- static char *progname;
-@@ -86,7 +87,7 @@ usage()
-     fprintf(stderr, _("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"
-+                      "\t\t[-K path-to-kprop] [-k kprop-port] [-P pid_file]\n"
-                       "\nwhere,\n\t[-x db_args]* - any number of database "
-                       "specific arguments.\n"
-                       "\t\t\tLook at each database documentation for "
-@@ -433,6 +434,11 @@ main(int argc, char *argv[])
-             if (!argc)
-                 usage();
-             kprop = *argv;
-+        } else if (strcmp(*argv, "-k") == 0) {
-+            argc--, argv++;
-+            if (!argc)
-+                usage();
-+            kprop_port = *argv;
-         } else {
-             break;
-         }
-@@ -529,6 +535,9 @@ main(int argc, char *argv[])
-         }
-     }
- 
-+    if (kprop_port == NULL)
-+        kprop_port = getenv("KPROP_PORT");
-+
-     krb5_klog_syslog(LOG_INFO, _("starting"));
-     if (nofork)
-         fprintf(stderr, _("%s: starting...\n"), progname);
--- 
-2.8.1
-
diff --git a/SOURCES/krb5-1.15-kprop-debug-argument-order.patch b/SOURCES/krb5-1.15-kprop-debug-argument-order.patch
deleted file mode 100644
index f17e495..0000000
--- a/SOURCES/krb5-1.15-kprop-debug-argument-order.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From e76c5f0b08da7129746fc8549c9a01d0af8d9ffa Mon Sep 17 00:00:00 2001
-From: Matt Rogers <mrogers@redhat.com>
-Date: Mon, 20 Jun 2016 09:21:28 -0400
-Subject: [PATCH] Fix argument order for kprop debug message
-
-ticket: 8277
----
- src/kadmin/server/ipropd_svc.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/kadmin/server/ipropd_svc.c b/src/kadmin/server/ipropd_svc.c
-index 336e5de..62a0a2b 100644
---- a/src/kadmin/server/ipropd_svc.c
-+++ b/src/kadmin/server/ipropd_svc.c
-@@ -391,7 +391,7 @@ ipropx_resync(uint32_t vers, struct svc_req *rqstp)
- 	}
- 
- 	DPRINT("%s: exec `kprop -r %s -f %s %s' ...\n",
--	       handle->params.realm, whoami, dump_file, clhost);
-+	       whoami, handle->params.realm, dump_file, clhost);
- 	/* XXX Yuck!  */
- 	if (getenv("KPROP_PORT")) {
- 	    pret = execl(kprop, "kprop", "-r", handle->params.realm, "-f",
--- 
-2.8.1
-
diff --git a/SOURCES/krb5-1.15-kprop-iprop-default_realm-tests.patch b/SOURCES/krb5-1.15-kprop-iprop-default_realm-tests.patch
deleted file mode 100644
index 854bddd..0000000
--- a/SOURCES/krb5-1.15-kprop-iprop-default_realm-tests.patch
+++ /dev/null
@@ -1,319 +0,0 @@
-From b133e1613751fbb2ce6ed2ba3b63bf45805968a5 Mon Sep 17 00:00:00 2001
-From: Matt Rogers <mrogers@redhat.com>
-Date: Fri, 22 Apr 2016 12:23:37 -0400
-Subject: [PATCH 3/3] Add kprop and iprop default_realm tests
-
-Add tests to t_iprop.py and t_kprop.py that exercise cases where
-default_realm and domain_realm maps differ, as well as overriding the
-default realm with the -r argument.  This includes the testing of -r
-with kadmind, and an update of expected ulog numbers for tests following
-the addition of an incremental test.  Also refactor some common code in
-t_kprop.py to use in the new tests.
-
-ticket: 8277
----
- src/tests/t_iprop.py | 114 ++++++++++++++++++++++++++++++++++++++++-----------
- src/tests/t_kprop.py |  77 ++++++++++++++++++++++++++++------
- 2 files changed, 155 insertions(+), 36 deletions(-)
-
-diff --git a/src/tests/t_iprop.py b/src/tests/t_iprop.py
-index 6b38b8a..71f5415 100755
---- a/src/tests/t_iprop.py
-+++ b/src/tests/t_iprop.py
-@@ -127,11 +127,35 @@ conf_slave2 = {'realms': {'$realm': {'iprop_slave_poll': '600',
-                                      'iprop_port': '$port8'}},
-                'dbmodules': {'db': {'database_name': '$testdir/db.slave2'}}}
- 
-+conf_foo = {'libdefaults': {'default_realm': 'FOO'},
-+            'domain_realm': {hostname: 'FOO'}}
-+
- realm = K5Realm(kdc_conf=conf, create_user=False, start_kadmind=True)
- slave1 = realm.special_env('slave1', True, kdc_conf=conf_slave1)
--slave1m = realm.special_env('slave1m', True, kdc_conf=conf_slave1m)
-+slave1m = realm.special_env('slave1m', True, krb5_conf=conf_foo,
-+                            kdc_conf=conf_slave1m)
- slave2 = realm.special_env('slave2', True, kdc_conf=conf_slave2)
- 
-+# A default_realm and domain_realm that do not match the KDC's realm.
-+# The FOO realm iprop_logfile setting is needed to run kproplog during
-+# a slave3 test, since kproplog has no realm option.
-+conf_slave3 = {'realms': {'$realm': {'iprop_slave_poll': '600',
-+                                     'iprop_logfile': '$testdir/ulog.slave3',
-+                                     'iprop_port': '$port8'},
-+                          'FOO': {'iprop_logfile': '$testdir/ulog.slave3'}},
-+               'dbmodules': {'db': {'database_name': '$testdir/db.slave3'}}}
-+slave3 = realm.special_env('slave3', True, krb5_conf=conf_foo,
-+                           kdc_conf=conf_slave3)
-+
-+# A default realm and a domain realm map that differ.
-+krb5_conf_slave4 = {'domain_realm': {hostname: 'FOO'}}
-+conf_slave4 = {'realms': {'$realm': {'iprop_slave_poll': '600',
-+                                     'iprop_logfile': '$testdir/ulog.slave4',
-+                                     'iprop_port': '$port8'}},
-+               'dbmodules': {'db': {'database_name': '$testdir/db.slave4'}}}
-+slave4 = realm.special_env('slave4', True, krb5_conf=krb5_conf_slave4,
-+                            kdc_conf=conf_slave4)
-+
- # Define some principal names.  pr3 is long enough to cause internal
- # reallocs, but not long enough to grow the basic ulog entry size.
- pr1 = 'wakawaka@' + realm.realm
-@@ -155,11 +179,13 @@ if not os.path.exists(ulog):
- kiprop_princ = 'kiprop/' + hostname
- realm.extract_keytab(kiprop_princ, realm.keytab)
- 
--# Create the initial slave1 and slave2 databases.
-+# Create the initial slave databases.
- dumpfile = os.path.join(realm.testdir, 'dump')
- realm.run([kdb5_util, 'dump', dumpfile])
- realm.run([kdb5_util, 'load', dumpfile], slave1)
- realm.run([kdb5_util, 'load', dumpfile], slave2)
-+realm.run([kdb5_util, '-r', realm.realm, 'load', dumpfile], slave3)
-+realm.run([kdb5_util, 'load', dumpfile], slave4)
- 
- # Reinitialize the master ulog so we know exactly what to expect in
- # it.
-@@ -198,9 +224,49 @@ slave1_out_dump_path = os.path.join(realm.testdir, 'dump.slave1.out')
- slave2_in_dump_path = os.path.join(realm.testdir, 'dump.slave2.in')
- slave2_kprop_port = str(realm.portbase + 9)
- slave1m['KPROP_PORT'] = slave2_kprop_port
--realm.start_server([kadmind, '-nofork', '-proponly', '-W', '-p', kdb5_util,
--                    '-K', kprop, '-F', slave1_out_dump_path], 'starting...',
--                   slave1m)
-+realm.start_server([kadmind, '-r', realm.realm, '-nofork', '-proponly', '-W',
-+                    '-p', kdb5_util, '-K', kprop, '-F', slave1_out_dump_path],
-+                   'starting...', slave1m)
-+
-+# Test similar default_realm and domain_realm map settings with -r realm.
-+slave3_in_dump_path = os.path.join(realm.testdir, 'dump.slave3.in')
-+kpropd3 = realm.start_server([kpropd, '-d', '-D', '-r', realm.realm, '-P',
-+                              slave2_kprop_port, '-f', slave3_in_dump_path,
-+                              '-p', kdb5_util, '-a', acl_file, '-A', hostname],
-+                             'ready', slave3)
-+wait_for_prop(kpropd3, True, 1, 7)
-+out = realm.run([kadminl, '-r', realm.realm, 'listprincs'], env=slave3)
-+if pr1 not in out or pr2 not in out or pr3 not in out:
-+    fail('slave3 does not have all principals from slave1')
-+check_ulog(1, 7, 7, [None], env=slave3)
-+
-+# Test an incremental propagation for the kpropd -r case.
-+realm.run([kadminl, 'modprinc', '-maxlife', '20 minutes', pr1])
-+check_ulog(8, 1, 8, [None, pr1, pr3, pr2, pr2, pr2, pr2, pr1])
-+kpropd1.send_signal(signal.SIGUSR1)
-+wait_for_prop(kpropd1, False, 7, 8)
-+check_ulog(3, 6, 8, [None, pr2, pr1], slave1)
-+out = realm.run([kadminl, 'getprinc', pr1], env=slave1)
-+if 'Maximum ticket life: 0 days 00:20:00' not in out:
-+    fail('slave1 does not have modification from master')
-+kpropd3.send_signal(signal.SIGUSR1)
-+wait_for_prop(kpropd3, False, 7, 8)
-+check_ulog(2, 7, 8, [None, pr1], slave3)
-+out = realm.run([kadminl, '-r', realm.realm, 'getprinc', pr1], env=slave3)
-+if 'Maximum ticket life: 0 days 00:20:00' not in out:
-+    fail('slave3 does not have modification from slave1')
-+stop_daemon(kpropd3)
-+
-+# Test dissimilar default_realm and domain_realm map settings (no -r realm).
-+slave4_in_dump_path = os.path.join(realm.testdir, 'dump.slave4.in')
-+kpropd4 = realm.start_server([kpropd, '-d', '-D', '-P', slave2_kprop_port,
-+                              '-f', slave4_in_dump_path, '-p', kdb5_util,
-+                              '-a', acl_file, '-A', hostname], 'ready', slave4)
-+wait_for_prop(kpropd4, True, 1, 8)
-+out = realm.run([kadminl, 'listprincs'], env=slave4)
-+if pr1 not in out or pr2 not in out or pr3 not in out:
-+    fail('slave4 does not have all principals from slave1')
-+stop_daemon(kpropd4)
- 
- # Start kpropd for slave2.  The -A option isn't needed since we're
- # talking to the same host as master (we specify it anyway to exercise
-@@ -209,8 +275,8 @@ realm.start_server([kadmind, '-nofork', '-proponly', '-W', '-p', kdb5_util,
- kpropd2 = realm.start_server([kpropd, '-d', '-D', '-P', slave2_kprop_port,
-                               '-f', slave2_in_dump_path, '-p', kdb5_util,
-                               '-a', acl_file, '-A', hostname], 'ready', slave2)
--wait_for_prop(kpropd2, True, 1, 7)
--check_ulog(1, 7, 7, [None], slave2)
-+wait_for_prop(kpropd2, True, 1, 8)
-+check_ulog(2, 7, 8, [None, pr1], slave2)
- out = realm.run([kadminl, 'listprincs'], env=slave1)
- if pr1 not in out or pr2 not in out or pr3 not in out:
-     fail('slave2 does not have all principals from slave1')
-@@ -218,16 +284,16 @@ if pr1 not in out or pr2 not in out or pr3 not in out:
- # Make another change and check that it propagates incrementally to
- # both slaves.
- realm.run([kadminl, 'modprinc', '-maxrenewlife', '22 hours', pr1])
--check_ulog(8, 1, 8, [None, pr1, pr3, pr2, pr2, pr2, pr2, pr1])
-+check_ulog(9, 1, 9, [None, pr1, pr3, pr2, pr2, pr2, pr2, pr1, pr1])
- kpropd1.send_signal(signal.SIGUSR1)
--wait_for_prop(kpropd1, False, 7, 8)
--check_ulog(3, 6, 8, [None, pr2, pr1], slave1)
-+wait_for_prop(kpropd1, False, 8, 9)
-+check_ulog(4, 6, 9, [None, pr2, pr1, pr1], slave1)
- out = realm.run([kadminl, 'getprinc', pr1], env=slave1)
- if 'Maximum renewable life: 0 days 22:00:00\n' not in out:
-     fail('slave1 does not have modification from master')
- kpropd2.send_signal(signal.SIGUSR1)
--wait_for_prop(kpropd2, False, 7, 8)
--check_ulog(2, 7, 8, [None, pr1], slave2)
-+wait_for_prop(kpropd2, False, 8, 9)
-+check_ulog(3, 7, 9, [None, pr1, pr1], slave2)
- out = realm.run([kadminl, 'getprinc', pr1], env=slave2)
- if 'Maximum renewable life: 0 days 22:00:00\n' not in out:
-     fail('slave2 does not have modification from slave1')
-@@ -239,25 +305,25 @@ if 'Maximum renewable life: 0 days 22:00:00\n' not in out:
- realm.run([kproplog, '-R'], slave1)
- check_ulog(1, 1, 1, [None], slave1)
- kpropd1.send_signal(signal.SIGUSR1)
--wait_for_prop(kpropd1, True, 1, 8)
--check_ulog(3, 6, 8, [None, pr2, pr1], slave1)
-+wait_for_prop(kpropd1, True, 1, 9)
-+check_ulog(4, 6, 9, [None, pr2, pr1, pr1], slave1)
- kpropd2.send_signal(signal.SIGUSR1)
--wait_for_prop(kpropd2, False, 8, 8)
--check_ulog(2, 7, 8, [None, pr1], slave2)
-+wait_for_prop(kpropd2, False, 9, 9)
-+check_ulog(3, 7, 9, [None, pr1, pr1], slave2)
- 
- # Make another change and check that it propagates incrementally to
- # both slaves.
--realm.run([kadminl, 'modprinc', '+allow_tix', 'w'])
--check_ulog(9, 1, 9, [None, pr1, pr3, pr2, pr2, pr2, pr2, pr1, pr2])
-+realm.run([kadminl, 'modprinc', '+allow_tix', pr2])
-+check_ulog(10, 1, 10, [None, pr1, pr3, pr2, pr2, pr2, pr2, pr1, pr1, pr2])
- kpropd1.send_signal(signal.SIGUSR1)
--wait_for_prop(kpropd1, False, 8, 9)
--check_ulog(4, 6, 9, [None, pr2, pr1, pr2], slave1)
-+wait_for_prop(kpropd1, False, 9, 10)
-+check_ulog(5, 6, 10, [None, pr2, pr1, pr1, pr2], slave1)
- out = realm.run([kadminl, 'getprinc', pr2], env=slave1)
- if 'Attributes:\n' not in out:
-     fail('slave1 does not have modification from master')
- kpropd2.send_signal(signal.SIGUSR1)
--wait_for_prop(kpropd2, False, 8, 9)
--check_ulog(3, 7, 9, [None, pr1, pr2], slave2)
-+wait_for_prop(kpropd2, False, 9, 10)
-+check_ulog(4, 7, 10, [None, pr1, pr1, pr2], slave2)
- out = realm.run([kadminl, 'getprinc', pr2], env=slave2)
- if 'Attributes:\n' not in out:
-     fail('slave2 does not have modification from slave1')
-@@ -266,13 +332,13 @@ if 'Attributes:\n' not in out:
- realm.run([kadminl, 'addpol', '-minclasses', '2', 'testpol'])
- check_ulog(1, 1, 1, [None])
- kpropd1.send_signal(signal.SIGUSR1)
--wait_for_prop(kpropd1, True, 9, 1)
-+wait_for_prop(kpropd1, True, 10, 1)
- check_ulog(1, 1, 1, [None], slave1)
- out = realm.run([kadminl, 'getpol', 'testpol'], env=slave1)
- if 'Minimum number of password character classes: 2' not in out:
-     fail('slave1 does not have policy from master')
- kpropd2.send_signal(signal.SIGUSR1)
--wait_for_prop(kpropd2, True, 9, 1)
-+wait_for_prop(kpropd2, True, 10, 1)
- check_ulog(1, 1, 1, [None], slave2)
- out = realm.run([kadminl, 'getpol', 'testpol'], env=slave2)
- if 'Minimum number of password character classes: 2' not in out:
-diff --git a/src/tests/t_kprop.py b/src/tests/t_kprop.py
-index d625627..02cdfee 100755
---- a/src/tests/t_kprop.py
-+++ b/src/tests/t_kprop.py
-@@ -3,16 +3,29 @@ from k5test import *
- 
- conf_slave = {'dbmodules': {'db': {'database_name': '$testdir/db.slave'}}}
- 
-+def setup_acl(realm):
-+    acl_file = os.path.join(realm.testdir, 'kpropd-acl')
-+    acl = open(acl_file, 'w')
-+    acl.write(realm.host_princ + '\n')
-+    acl.close()
-+
-+def check_output(kpropd):
-+    output('*** kpropd output follows\n')
-+    while True:
-+        line = kpropd.stdout.readline()
-+        if 'Database load process for full propagation completed' in line:
-+            break
-+        output('kpropd: ' + line)
-+        if 'Rejected connection' in line:
-+            fail('kpropd rejected connection from kprop')
-+
- # kprop/kpropd are the only users of krb5_auth_con_initivector, so run
- # this test over all enctypes to exercise mkpriv cipher state.
- for realm in multipass_realms(create_user=False):
-     slave = realm.special_env('slave', True, kdc_conf=conf_slave)
- 
-     # Set up the kpropd acl file.
--    acl_file = os.path.join(realm.testdir, 'kpropd-acl')
--    acl = open(acl_file, 'w')
--    acl.write(realm.host_princ + '\n')
--    acl.close()
-+    setup_acl(realm)
- 
-     # Create the slave db.
-     dumpfile = os.path.join(realm.testdir, 'dump')
-@@ -28,17 +41,57 @@ for realm in multipass_realms(create_user=False):
- 
-     realm.run([kdb5_util, 'dump', dumpfile])
-     realm.run([kprop, '-f', dumpfile, '-P', str(realm.kprop_port()), hostname])
--    output('*** kpropd output follows\n')
--    while True:
--        line = kpropd.stdout.readline()
--        if 'Database load process for full propagation completed' in line:
--            break
--        output('kpropd: ' + line)
--        if 'Rejected connection' in line:
--            fail('kpropd rejected connection from kprop')
-+    check_output(kpropd)
- 
-     out = realm.run([kadminl, 'listprincs'], slave)
-     if 'wakawaka' not in out:
-         fail('Slave does not have all principals from master')
- 
-+# default_realm tests follow.
-+# default_realm and domain_realm different than realm.realm (test -r argument).
-+conf_slave2 = {'dbmodules': {'db': {'database_name': '$testdir/db.slave2'}}}
-+krb5_conf_slave2 = {'libdefaults': {'default_realm': 'FOO'},
-+                    'domain_realm': {hostname: 'FOO'}}
-+# default_realm and domain_realm map differ.
-+conf_slave3 = {'dbmodules': {'db': {'database_name': '$testdir/db.slave3'}}}
-+krb5_conf_slave3 = {'domain_realm':  {hostname: 'BAR'}}
-+
-+realm = K5Realm(create_user=False)
-+slave2 = realm.special_env('slave2', True, kdc_conf=conf_slave2,
-+                           krb5_conf=krb5_conf_slave2)
-+slave3 = realm.special_env('slave3', True, kdc_conf=conf_slave3,
-+                           krb5_conf=krb5_conf_slave3)
-+
-+setup_acl(realm)
-+
-+# Create the slave db.
-+dumpfile = os.path.join(realm.testdir, 'dump')
-+realm.run([kdb5_util, 'dump', dumpfile])
-+realm.run([kdb5_util, '-r', realm.realm, 'load', dumpfile], slave2)
-+realm.run([kdb5_util, 'load', dumpfile], slave3)
-+
-+# Make some changes to the master db.
-+realm.addprinc('wakawaka')
-+
-+# Test override of default_realm with -r realm argument.
-+kpropd = realm.start_kpropd(slave2, ['-r', realm.realm, '-d'])
-+realm.run([kdb5_util, 'dump', dumpfile])
-+realm.run([kprop, '-r', realm.realm, '-f', dumpfile, '-P',
-+           str(realm.kprop_port()), hostname])
-+check_output(kpropd)
-+out = realm.run([kadminl, '-r', realm.realm, 'listprincs'], slave2)
-+if 'wakawaka' not in out:
-+    fail('Slave does not have all principals from master')
-+
-+stop_daemon(kpropd)
-+
-+# Test default_realm and domain_realm mismatch.
-+kpropd = realm.start_kpropd(slave3, ['-d'])
-+realm.run([kdb5_util, 'dump', dumpfile])
-+realm.run([kprop, '-f', dumpfile, '-P', str(realm.kprop_port()), hostname])
-+check_output(kpropd)
-+out = realm.run([kadminl, 'listprincs'], slave3)
-+if 'wakawaka' not in out:
-+    fail('Slave does not have all principals from master')
-+
- success('kprop tests')
--- 
-2.8.1
-
diff --git a/SOURCES/krb5-1.15-kprop-kpropd-realm.patch b/SOURCES/krb5-1.15-kprop-kpropd-realm.patch
deleted file mode 100644
index d7c1242..0000000
--- a/SOURCES/krb5-1.15-kprop-kpropd-realm.patch
+++ /dev/null
@@ -1,366 +0,0 @@
-From dc89bf06626ab322cac50d94fa7ba361a5f29a67 Mon Sep 17 00:00:00 2001
-From: Matt Rogers <mrogers@redhat.com>
-Date: Thu, 25 Feb 2016 10:38:07 -0500
-Subject: [PATCH 2/3] Fix kprop and kpropd realm handling
-
-Add the sn2princ_with_realm() helper function (currently duplicated in
-kprop.c and kpropd.c) to simplify principal realm substitution.  Use
-sn2princ_with_realm() in kprop.c and kpropd.c in place of
-krb5_sname_to_principal(), with the default realm if -r is not provided.
-If a realm is given to kpropd, set it as the default realm on the
-kpropd_context, allowing a later call of ulog_replay() to open the
-correct database.
-
-Remove referral realm code in kprop.c and kpropd.c.  Pass the realm
-(default or provided) to the kdb5_util and kprop commands called by
-kadmind.
-
-ticket: 8277
----
- src/kadmin/server/ipropd_svc.c | 15 +++----
- src/slave/kprop.c              | 80 ++++++++++++++++++++++--------------
- src/slave/kpropd.c             | 93 +++++++++++++++++++++++-------------------
- 3 files changed, 109 insertions(+), 79 deletions(-)
-
-diff --git a/src/kadmin/server/ipropd_svc.c b/src/kadmin/server/ipropd_svc.c
-index 7c7f850..336e5de 100644
---- a/src/kadmin/server/ipropd_svc.c
-+++ b/src/kadmin/server/ipropd_svc.c
-@@ -335,8 +335,8 @@ ipropx_resync(uint32_t vers, struct svc_req *rqstp)
-      * and timestamp are in the ulog (then the slaves can get the
-      * subsequent updates very iprop).
-      */
--    if (asprintf(&ubuf, "%s dump -i%d -c %s",
--		 kdb5_util, vers, dump_file) < 0) {
-+    if (asprintf(&ubuf, "%s -r %s dump -i%d -c %s", kdb5_util,
-+		 handle->params.realm, vers, dump_file) < 0) {
- 	krb5_klog_syslog(LOG_ERR,
- 			 _("%s: cannot construct kdb5 util dump string too long; out of memory"),
- 			 whoami);
-@@ -390,14 +390,15 @@ ipropx_resync(uint32_t vers, struct svc_req *rqstp)
- 	    _exit(1);
- 	}
- 
--	DPRINT("%s: exec `kprop -f %s %s' ...\n",
--		whoami, dump_file, clhost);
-+	DPRINT("%s: exec `kprop -r %s -f %s %s' ...\n",
-+	       handle->params.realm, whoami, dump_file, clhost);
- 	/* XXX Yuck!  */
- 	if (getenv("KPROP_PORT")) {
--	    pret = execl(kprop, "kprop", "-f", dump_file, "-P",
--			 getenv("KPROP_PORT"), clhost, NULL);
-+	    pret = execl(kprop, "kprop", "-r", handle->params.realm, "-f",
-+			 dump_file, "-P", getenv("KPROP_PORT"), clhost, NULL);
- 	} else {
--	    pret = execl(kprop, "kprop", "-f", dump_file, clhost, NULL);
-+	    pret = execl(kprop, "kprop", "-r", handle->params.realm, "-f",
-+			 dump_file, clhost, NULL);
- 	}
- 	perror(whoami);
- 	krb5_klog_syslog(LOG_ERR,
-diff --git a/src/slave/kprop.c b/src/slave/kprop.c
-index 696e89c..955db50 100644
---- a/src/slave/kprop.c
-+++ b/src/slave/kprop.c
-@@ -52,6 +52,7 @@ static int debug = 0;
- static char *srvtab = NULL;
- static char *slave_host;
- static char *realm = NULL;
-+static char *def_realm = NULL;
- static char *file = KPROP_DEFAULT_FILE;
- 
- /* The Kerberos principal we'll be sending as, initialized in get_tickets. */
-@@ -63,7 +64,7 @@ static krb5_address *receiver_addr;
- static const char *port = KPROP_SERVICE;
- static char *dbpathname;
- 
--static void parse_args(int argc, char **argv);
-+static void parse_args(krb5_context context, int argc, char **argv);
- static void get_tickets(krb5_context context);
- static void usage(void);
- static void open_connection(krb5_context context, char *host, int *fd_out);
-@@ -101,7 +102,7 @@ main(int argc, char **argv)
-         com_err(argv[0], retval, _("while initializing krb5"));
-         exit(1);
-     }
--    parse_args(argc, argv);
-+    parse_args(context, argc, argv);
-     get_tickets(context);
- 
-     database_fd = open_database(context, file, &database_size);
-@@ -113,13 +114,15 @@ main(int argc, char **argv)
-     printf(_("Database propagation to %s: SUCCEEDED\n"), slave_host);
-     krb5_free_cred_contents(context, my_creds);
-     close_database(context, database_fd);
-+    krb5_free_default_realm(context, def_realm);
-     exit(0);
- }
- 
- static void
--parse_args(int argc, char **argv)
-+parse_args(krb5_context context, int argc, char **argv)
- {
-     char *word, ch;
-+    krb5_error_code ret;
- 
-     progname = *argv++;
-     while (--argc && (word = *argv++) != NULL) {
-@@ -168,51 +171,66 @@ parse_args(int argc, char **argv)
-     }
-     if (slave_host == NULL)
-         usage();
-+
-+    if (realm == NULL) {
-+        ret = krb5_get_default_realm(context, &def_realm);
-+        if (ret) {
-+            com_err(progname, errno, _("while getting default realm"));
-+            exit(1);
-+        }
-+        realm = def_realm;
-+    }
-+}
-+
-+/* Runs krb5_sname_to_principal with a substitute realm
-+ * Duplicated in kpropd.c, sharing TBD */
-+static krb5_error_code
-+sn2princ_with_realm(krb5_context context, const char *hostname,
-+                    const char *sname, krb5_int32 type, const char *rrealm,
-+                    krb5_principal *princ_out)
-+{
-+    krb5_error_code ret;
-+    krb5_principal princ = NULL;
-+
-+    *princ_out = NULL;
-+
-+    if (rrealm == NULL)
-+        return EINVAL;
-+
-+    ret = krb5_sname_to_principal(context, hostname, sname, type, &princ);
-+    if (ret)
-+        return ret;
-+
-+    ret = krb5_set_principal_realm(context, princ, rrealm);
-+    if (ret) {
-+        krb5_free_principal(context, princ);
-+        return ret;
-+    }
-+
-+    *princ_out = princ;
-+    return 0;
- }
- 
- static void
- get_tickets(krb5_context context)
- {
--    char *def_realm, *server;
-+    char *server;
-     krb5_error_code retval;
-     krb5_keytab keytab = NULL;
-     krb5_principal server_princ = NULL;
- 
-     /* Figure out what tickets we'll be using to send. */
--    retval = krb5_sname_to_principal(context, NULL, NULL, KRB5_NT_SRV_HST,
--                                     &my_principal);
-+    retval = sn2princ_with_realm(context, NULL, NULL, KRB5_NT_SRV_HST, realm,
-+                                 &my_principal);
-     if (retval) {
-         com_err(progname, errno, _("while setting client principal name"));
-         exit(1);
-     }
--    if (realm != NULL) {
--        retval = krb5_set_principal_realm(context, my_principal, realm);
--        if (retval) {
--            com_err(progname, errno,
--                    _("while setting client principal realm"));
--            exit(1);
--        }
--    } else if (krb5_is_referral_realm(krb5_princ_realm(context,
--                                                       my_principal))) {
--        /* We're going to use this as a client principal, so it can't have the
--         * referral realm.  Use the default realm instead. */
--        retval = krb5_get_default_realm(context, &def_realm);
--        if (retval) {
--            com_err(progname, errno, _("while getting default realm"));
--            exit(1);
--        }
--        retval = krb5_set_principal_realm(context, my_principal, def_realm);
--        if (retval) {
--            com_err(progname, errno,
--                    _("while setting client principal realm"));
--            exit(1);
--        }
--    }
- 
-     /* Construct the principal name for the slave host. */
-     memset(&creds, 0, sizeof(creds));
--    retval = krb5_sname_to_principal(context, slave_host, KPROP_SERVICE_NAME,
--                                     KRB5_NT_SRV_HST, &server_princ);
-+    retval = sn2princ_with_realm(context, slave_host, KPROP_SERVICE_NAME,
-+                                 KRB5_NT_SRV_HST, realm, &server_princ);
-     if (retval) {
-         com_err(progname, errno, _("while setting server principal name"));
-         exit(1);
-diff --git a/src/slave/kpropd.c b/src/slave/kpropd.c
-index a950924..41ab446 100644
---- a/src/slave/kpropd.c
-+++ b/src/slave/kpropd.c
-@@ -90,7 +90,6 @@ extern int daemon(int, int);
- 
- #define SYSLOG_CLASS LOG_DAEMON
- 
--char *def_realm = NULL;
- int runonce = 0;
- 
- /*
-@@ -128,6 +127,7 @@ static krb5_principal client;   /* This is who we're talking to */
- static krb5_context kpropd_context;
- static krb5_auth_context auth_context;
- static char *realm = NULL;      /* Our realm */
-+static char *def_realm = NULL;  /* Ref pointer for default realm */
- static char *file = KPROPD_DEFAULT_FILE;
- static char *temp_file_name;
- static char *kdb5_util = KPROPD_DEFAULT_KDB5_UTIL;
-@@ -610,6 +610,34 @@ full_resync(CLIENT *clnt)
-     return (status == RPC_SUCCESS) ? &clnt_res : NULL;
- }
- 
-+/* Runs krb5_sname_to_principal with a substitute realm.
-+ * Duplicated in kprop.c, sharing TBD */
-+static krb5_error_code
-+sn2princ_with_realm(krb5_context context, const char *hostname,
-+                    const char *sname, krb5_int32 type, const char *rrealm,
-+                    krb5_principal *princ_out)
-+{
-+    krb5_error_code ret;
-+    krb5_principal princ = NULL;
-+
-+    *princ_out = NULL;
-+
-+    if (rrealm == NULL)
-+        return EINVAL;
-+
-+    ret = krb5_sname_to_principal(context, hostname, sname, type, &princ);
-+    if (ret)
-+        return ret;
-+
-+    ret = krb5_set_principal_realm(context, princ, rrealm);
-+    if (ret) {
-+        krb5_free_principal(context, princ);
-+        return ret;
-+    }
-+
-+    *princ_out = princ;
-+    return 0;
-+}
- /*
-  * Beg for incrementals from the KDC.
-  *
-@@ -640,53 +668,26 @@ do_iprop()
-     if (pollin == 0)
-         pollin = 10;
- 
--    /* Grab the realm info and check if iprop is enabled. */
--    if (def_realm == NULL) {
--        retval = krb5_get_default_realm(kpropd_context, &def_realm);
--        if (retval) {
--            com_err(progname, retval, _("Unable to get default realm"));
--            return retval;
--        }
--    }
--
--    params.mask |= KADM5_CONFIG_REALM;
--    params.realm = def_realm;
--
-     if (master_svc_princstr == NULL) {
--        retval = kadm5_get_kiprop_host_srv_name(kpropd_context, def_realm,
-+        retval = kadm5_get_kiprop_host_srv_name(kpropd_context, realm,
-                                                 &master_svc_princstr);
-         if (retval) {
-             com_err(progname, retval,
-                     _("%s: unable to get kiprop host based "
-                       "service name for realm %s\n"),
--                    progname, def_realm);
-+                    progname, realm);
-             return retval;
-         }
-     }
- 
--    retval = krb5_sname_to_principal(kpropd_context, NULL, KIPROP_SVC_NAME,
--                                     KRB5_NT_SRV_HST, &iprop_svc_principal);
-+    retval = sn2princ_with_realm(kpropd_context, NULL, KIPROP_SVC_NAME,
-+                                 KRB5_NT_SRV_HST, realm, &iprop_svc_principal);
-     if (retval) {
-         com_err(progname, retval,
-                 _("while trying to construct host service principal"));
-         return retval;
-     }
- 
--    /* XXX referrals? */
--    if (krb5_is_referral_realm(krb5_princ_realm(kpropd_context,
--                                                iprop_svc_principal))) {
--        krb5_data *r = krb5_princ_realm(kpropd_context,
--                                        iprop_svc_principal);
--        assert(def_realm != NULL);
--        r->length = strlen(def_realm);
--        r->data = strdup(def_realm);
--        if (r->data == NULL) {
--            com_err(progname, retval,
--                    _("while determining local service principal name"));
--            return retval;
--        }
--        /* XXX Memory leak: Old r->data value.  */
--    }
-     retval = krb5_unparse_name(kpropd_context, iprop_svc_principal,
-                                &iprop_svc_princstr);
-     if (retval) {
-@@ -1166,21 +1167,29 @@ parse_args(char **argv)
-     if (!debug)
-         set_com_err_hook(kpropd_com_err_proc);
- 
-+    if (realm == NULL) {
-+        retval = krb5_get_default_realm(kpropd_context, &def_realm);
-+        if (retval) {
-+            com_err(progname, retval, _("Unable to get default realm"));
-+            exit(1);
-+        }
-+        realm = def_realm;
-+    } else {
-+        retval = krb5_set_default_realm(kpropd_context, realm);
-+        if (retval) {
-+            com_err(progname, retval, _("Unable to set default realm"));
-+            exit(1);
-+        }
-+    }
-+
-     /* Construct service name from local hostname. */
--    retval = krb5_sname_to_principal(kpropd_context, NULL, KPROP_SERVICE_NAME,
--                                     KRB5_NT_SRV_HST, &server);
-+    retval = sn2princ_with_realm(kpropd_context, NULL, KPROP_SERVICE_NAME,
-+                                 KRB5_NT_SRV_HST, realm, &server);
-     if (retval) {
-         com_err(progname, retval,
-                 _("while trying to construct my service name"));
-         exit(1);
-     }
--    if (realm != NULL) {
--        retval = krb5_set_principal_realm(kpropd_context, server, realm);
--        if (retval) {
--            com_err(progname, errno, _("while constructing my service realm"));
--            exit(1);
--        }
--    }
- 
-     /* Construct the name of the temporary file. */
-     if (asprintf(&temp_file_name, "%s.temp", file) < 0) {
-@@ -1189,6 +1198,8 @@ parse_args(char **argv)
-         exit(1);
-     }
- 
-+    params.realm = realm;
-+    params.mask |= KADM5_CONFIG_REALM;
-     retval = kadm5_get_config_params(kpropd_context, 1, &params, &params);
-     if (retval) {
-         com_err(progname, retval, _("while initializing"));
--- 
-2.8.1
-
diff --git a/SOURCES/krb5-1.15-krad-eof.patch b/SOURCES/krb5-1.15-krad-eof.patch
deleted file mode 100644
index 6ed72ea..0000000
--- a/SOURCES/krb5-1.15-krad-eof.patch
+++ /dev/null
@@ -1,49 +0,0 @@
-From 7fd9fc07cbccef7a6e682057e1560e5b343cb9ff Mon Sep 17 00:00:00 2001
-From: Nathaniel McCallum <npmccallum@redhat.com>
-Date: Fri, 30 Sep 2016 10:03:33 -0400
-Subject: [PATCH] Properly handle EOF condition on libkrad sockets
-
-In the previous code, when the remote peer performed an orderly shutdown
-on the socket, libkrad would enter a state in which all future requests
-timed out.  Instead, if the peer shuts down its socket, we need to
-attempt to reopen it.
-
-ticket: 8504 (new)
-target_version: 1.14-next
-tags: pullup
-
-(cherry picked from commit 248497427d5a45225817b6c22e9224e8ad969872)
----
- src/lib/krad/remote.c | 13 ++++++-------
- 1 file changed, 6 insertions(+), 7 deletions(-)
-
-diff --git a/src/lib/krad/remote.c b/src/lib/krad/remote.c
-index df3de3a..68cd16f 100644
---- a/src/lib/krad/remote.c
-+++ b/src/lib/krad/remote.c
-@@ -329,16 +329,15 @@ on_io_read(krad_remote *rr)
-     /* Read the packet. */
-     i = recv(verto_get_fd(rr->io), rr->buffer.data + rr->buffer.length,
-              pktlen, 0);
--    if (i < 0) {
--        /* Should we try again? */
--        if (errno == EWOULDBLOCK || errno == EAGAIN || errno == EINTR)
--            return;
- 
--        /* The socket is unrecoverable. */
-+    /* On these errors, try again. */
-+    if (i < 0 && (errno == EWOULDBLOCK || errno == EAGAIN || errno == EINTR))
-+        return;
-+
-+    /* On any other errors or on EOF, the socket is unrecoverable. */
-+    if (i <= 0) {
-         remote_shutdown(rr);
-         return;
--    } else if (i == 0) {
--        remote_del_flags(rr, FLAGS_READ);
-     }
- 
-     /* If we have a partial read or just the header, try again. */
--- 
-2.10.1
-
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
index 5d27689..7f2cfdf 100644
--- a/SOURCES/krb5-1.3.1-dns.patch
+++ b/SOURCES/krb5-1.3.1-dns.patch
@@ -1,8 +1,17 @@
-We want to be able to use --with-netlib and --enable-dns at the same time.
-RT#2022
---- krb5-1.3.1/src/aclocal.m4	2003-11-24 11:17:30.000000000 -0500
-+++ krb5-1.3.1/src/aclocal.m4	2003-11-24 11:18:45.000000000 -0500
-@@ -647,6 +647,7 @@
+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
diff --git a/SOURCES/krb5-1.9-debuginfo.patch b/SOURCES/krb5-1.9-debuginfo.patch
index ae81f7c..c9a6499 100644
--- a/SOURCES/krb5-1.9-debuginfo.patch
+++ b/SOURCES/krb5-1.9-debuginfo.patch
@@ -1,10 +1,18 @@
-We want to keep these y.tab.c files around because the debuginfo points to
-them.  It would be more elegant at the end to use symbolic links, but that
-could mess up people working in the tree on other things.
+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
-+++ src/kadmin/cli/Makefile.in
-@@ -43,3 +43,8 @@ clean-unix::
+---
+ 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
@@ -13,14 +21,16 @@ could mess up people working in the tree on other things.
 +	$(RM) y.tab.c $@
 +	$(YACC.y) $< 
 +	$(CP) y.tab.c $@
---- src/plugins/kdb/ldap/ldap_util/Makefile.in
-+++ src/plugins/kdb/ldap/ldap_util/Makefile.in
-@@ -22,7 +22,7 @@ $(PROG): $(OBJS) $(KADMSRV_DEPLIBS) $(KR
+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:
  	$(INSTALL_PROGRAM) $(PROG) ${DESTDIR}$(ADMIN_BINDIR)/$(PROG)
diff --git a/SOURCES/krb5-CVE-2016-3119.patch b/SOURCES/krb5-CVE-2016-3119.patch
deleted file mode 100644
index 2624d57..0000000
--- a/SOURCES/krb5-CVE-2016-3119.patch
+++ /dev/null
@@ -1,41 +0,0 @@
-From 08c642c09c38a9c6454ab43a9b53b2a89b9eef99 Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Mon, 14 Mar 2016 17:26:34 -0400
-Subject: [PATCH] Fix LDAP null deref on empty arg [CVE-2016-3119]
-
-In the LDAP KDB module's process_db_args(), strtok_r() may return NULL
-if there is an empty string in the db_args array.  Check for this case
-and avoid dereferencing a null pointer.
-
-CVE-2016-3119:
-
-In MIT krb5 1.6 and later, an authenticated attacker with permission
-to modify a principal entry can cause kadmind to dereference a null
-pointer by supplying an empty DB argument to the modify_principal
-command, if kadmind is configured to use the LDAP KDB module.
-
-    CVSSv2 Vector: AV:N/AC:H/Au:S/C:N/I:N/A:C/E:H/RL:OF/RC:ND
-
-ticket: 8383 (new)
-target_version: 1.14-next
-target_version: 1.13-next
-tags: pullup
----
- src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c
-index 6e591e1..79c4cf0 100644
---- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c
-+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c
-@@ -296,6 +296,7 @@ process_db_args(krb5_context context, char **db_args, xargs_t *xargs,
-     if (db_args) {
-         for (i=0; db_args[i]; ++i) {
-             arg = strtok_r(db_args[i], "=", &arg_val);
-+            arg = (arg != NULL) ? arg : "";
-             if (strcmp(arg, TKTPOLICY_ARG) == 0) {
-                 dptr = &xargs->tktpolicydn;
-             } else {
--- 
-2.8.1
-
diff --git a/SOURCES/krb5-acquire_cred_interposer.patch b/SOURCES/krb5-acquire_cred_interposer.patch
deleted file mode 100644
index fa1c532..0000000
--- a/SOURCES/krb5-acquire_cred_interposer.patch
+++ /dev/null
@@ -1,222 +0,0 @@
-From b3901af6970fb7bde88eb16d51c8d05db6f37746 Mon Sep 17 00:00:00 2001
-From: Simo Sorce <simo@redhat.com>
-Date: Fri, 13 Nov 2015 14:54:11 -0500
-Subject: [PATCH] Fix impersonate_name to work with interposers
-
-This follows the same modifications applied to
-gss_acquire_cred_with_password() when interposer plugins were
-introduced.
-
-[ghudson@mit.edu: minor whitespace changes; initialize out_mcred in
-spnego_gss_acquire_cred_impersonate_name() since it is released in the
-cleanup handler]
-
-ticket: 8280 (new)
----
- src/lib/gssapi/mechglue/g_acquire_cred_imp_name.c | 58 +++++++++++++++--------
- src/lib/gssapi/spnego/spnego_mech.c               | 35 +++++++-------
- 2 files changed, 54 insertions(+), 39 deletions(-)
-
-diff --git a/src/lib/gssapi/mechglue/g_acquire_cred_imp_name.c b/src/lib/gssapi/mechglue/g_acquire_cred_imp_name.c
-index 0dd4f87..9eab25e 100644
---- a/src/lib/gssapi/mechglue/g_acquire_cred_imp_name.c
-+++ b/src/lib/gssapi/mechglue/g_acquire_cred_imp_name.c
-@@ -334,6 +334,8 @@ gss_add_cred_impersonate_name(OM_uint32 *minor_status,
-     gss_cred_id_t	cred = NULL;
-     gss_OID		new_mechs_array = NULL;
-     gss_cred_id_t *	new_cred_array = NULL;
-+    gss_OID_set		target_mechs = GSS_C_NO_OID_SET;
-+    gss_OID		selected_mech = GSS_C_NO_OID;
- 
-     status = val_add_cred_impersonate_name_args(minor_status,
- 						input_cred_handle,
-@@ -350,7 +352,12 @@ gss_add_cred_impersonate_name(OM_uint32 *minor_status,
-     if (status != GSS_S_COMPLETE)
- 	return (status);
- 
--    mech = gssint_get_mechanism(desired_mech);
-+    status = gssint_select_mech_type(minor_status, desired_mech,
-+				     &selected_mech);
-+    if (status != GSS_S_COMPLETE)
-+	return status;
-+
-+    mech = gssint_get_mechanism(selected_mech);
-     if (!mech)
- 	return GSS_S_BAD_MECH;
-     else if (!mech->gss_acquire_cred_impersonate_name)
-@@ -367,27 +374,26 @@ gss_add_cred_impersonate_name(OM_uint32 *minor_status,
- 	internal_name = GSS_C_NO_NAME;
-     } else {
- 	union_cred = (gss_union_cred_t)input_cred_handle;
--	if (gssint_get_mechanism_cred(union_cred, desired_mech) !=
-+	if (gssint_get_mechanism_cred(union_cred, selected_mech) !=
- 	    GSS_C_NO_CREDENTIAL)
- 	    return (GSS_S_DUPLICATE_ELEMENT);
-     }
- 
-     mech_impersonator_cred =
- 	gssint_get_mechanism_cred((gss_union_cred_t)impersonator_cred_handle,
--				  desired_mech);
-+				  selected_mech);
-     if (mech_impersonator_cred == GSS_C_NO_CREDENTIAL)
- 	return (GSS_S_NO_CRED);
- 
-     /* may need to create a mechanism specific name */
-     union_name = (gss_union_name_t)desired_name;
-     if (union_name->mech_type &&
--	g_OID_equal(union_name->mech_type,
--		    &mech->mech_type))
-+	g_OID_equal(union_name->mech_type, selected_mech))
- 	internal_name = union_name->mech_name;
-     else {
- 	if (gssint_import_internal_name(minor_status,
--				        &mech->mech_type, union_name,
--				        &allocated_name) != GSS_S_COMPLETE)
-+					selected_mech, union_name,
-+					&allocated_name) != GSS_S_COMPLETE)
- 	    return (GSS_S_BAD_NAME);
- 	internal_name = allocated_name;
-     }
-@@ -402,11 +408,21 @@ gss_add_cred_impersonate_name(OM_uint32 *minor_status,
-     else
- 	time_req = 0;
- 
-+    status = gss_create_empty_oid_set(minor_status, &target_mechs);
-+    if (status != GSS_S_COMPLETE)
-+	goto errout;
-+
-+    status = gss_add_oid_set_member(minor_status,
-+				    gssint_get_public_oid(selected_mech),
-+				    &target_mechs);
-+    if (status != GSS_S_COMPLETE)
-+	goto errout;
-+
-     status = mech->gss_acquire_cred_impersonate_name(minor_status,
- 						     mech_impersonator_cred,
- 						     internal_name,
- 						     time_req,
--						     GSS_C_NULL_OID_SET,
-+						     target_mechs,
- 						     cred_usage,
- 						     &cred,
- 						     NULL,
-@@ -445,19 +461,15 @@ gss_add_cred_impersonate_name(OM_uint32 *minor_status,
- 
-     new_cred_array[union_cred->count] = cred;
-     if ((new_mechs_array[union_cred->count].elements =
--	 malloc(mech->mech_type.length)) == NULL)
-+	 malloc(selected_mech->length)) == NULL)
- 	goto errout;
- 
--    g_OID_copy(&new_mechs_array[union_cred->count],
--	       &mech->mech_type);
-+    g_OID_copy(&new_mechs_array[union_cred->count], selected_mech);
- 
-     if (actual_mechs != NULL) {
--	gss_OID_set_desc oids;
--
--	oids.count = union_cred->count + 1;
--	oids.elements = new_mechs_array;
--
--	status = generic_gss_copy_oid_set(minor_status, &oids, actual_mechs);
-+	status = gssint_make_public_oid_set(minor_status, new_mechs_array,
-+					    union_cred->count + 1,
-+					    actual_mechs);
- 	if (GSS_ERROR(status)) {
- 	    free(new_mechs_array[union_cred->count].elements);
- 	    goto errout;
-@@ -486,10 +498,12 @@ gss_add_cred_impersonate_name(OM_uint32 *minor_status,
-     /* We're done with the internal name. Free it if we allocated it. */
- 
-     if (allocated_name)
--	(void) gssint_release_internal_name(&temp_minor_status,
--					   &mech->mech_type,
-+	(void) gssint_release_internal_name(&temp_minor_status, selected_mech,
- 					   &allocated_name);
- 
-+    if (target_mechs)
-+	(void) gss_release_oid_set(&temp_minor_status, &target_mechs);
-+
-     return (GSS_S_COMPLETE);
- 
- errout:
-@@ -503,8 +517,10 @@ errout:
- 
-     if (allocated_name)
- 	(void) gssint_release_internal_name(&temp_minor_status,
--					   &mech->mech_type,
--					   &allocated_name);
-+					    selected_mech, &allocated_name);
-+
-+    if (target_mechs)
-+	(void) gss_release_oid_set(&temp_minor_status, &target_mechs);
- 
-     if (input_cred_handle == GSS_C_NO_CREDENTIAL && union_cred)
- 	free(union_cred);
-diff --git a/src/lib/gssapi/spnego/spnego_mech.c b/src/lib/gssapi/spnego/spnego_mech.c
-index e6703eb..28fb9b1 100644
---- a/src/lib/gssapi/spnego/spnego_mech.c
-+++ b/src/lib/gssapi/spnego/spnego_mech.c
-@@ -2619,10 +2619,10 @@ spnego_gss_acquire_cred_impersonate_name(OM_uint32 *minor_status,
- 					 gss_OID_set *actual_mechs,
- 					 OM_uint32 *time_rec)
- {
--	OM_uint32 status;
-+	OM_uint32 status, tmpmin;
- 	gss_OID_set amechs = GSS_C_NULL_OID_SET;
- 	spnego_gss_cred_id_t imp_spcred = NULL, out_spcred = NULL;
--	gss_cred_id_t imp_mcred, out_mcred;
-+	gss_cred_id_t imp_mcred, out_mcred = GSS_C_NO_CREDENTIAL;
- 
- 	dsyslog("Entering spnego_gss_acquire_cred_impersonate_name\n");
- 
-@@ -2634,31 +2634,30 @@ spnego_gss_acquire_cred_impersonate_name(OM_uint32 *minor_status,
- 
- 	imp_spcred = (spnego_gss_cred_id_t)impersonator_cred_handle;
- 	imp_mcred = imp_spcred ? imp_spcred->mcred : GSS_C_NO_CREDENTIAL;
--	if (desired_mechs == GSS_C_NO_OID_SET) {
--		status = gss_inquire_cred(minor_status, imp_mcred, NULL, NULL,
--					  NULL, &amechs);
--		if (status != GSS_S_COMPLETE)
--			return status;
--
--		desired_mechs = amechs;
--	}
-+	status = gss_inquire_cred(minor_status, imp_mcred, NULL, NULL,
-+				  NULL, &amechs);
-+	if (status != GSS_S_COMPLETE)
-+		return status;
- 
- 	status = gss_acquire_cred_impersonate_name(minor_status, imp_mcred,
- 						   desired_name, time_req,
--						   desired_mechs, cred_usage,
-+						   amechs, cred_usage,
- 						   &out_mcred, actual_mechs,
- 						   time_rec);
--
--	if (amechs != GSS_C_NULL_OID_SET)
--		(void) gss_release_oid_set(minor_status, &amechs);
-+	if (status != GSS_S_COMPLETE)
-+		goto cleanup;
- 
- 	status = create_spnego_cred(minor_status, out_mcred, &out_spcred);
--	if (status != GSS_S_COMPLETE) {
--		gss_release_cred(minor_status, &out_mcred);
--		return (status);
--	}
-+	if (status != GSS_S_COMPLETE)
-+		goto cleanup;
-+
-+	out_mcred = GSS_C_NO_CREDENTIAL;
- 	*output_cred_handle = (gss_cred_id_t)out_spcred;
- 
-+cleanup:
-+	(void) gss_release_oid_set(&tmpmin, &amechs);
-+	(void) gss_release_cred(&tmpmin, &out_mcred);
-+
- 	dsyslog("Leaving spnego_gss_acquire_cred_impersonate_name\n");
- 	return (status);
- }
--- 
-2.6.2
-
diff --git a/SOURCES/krb5-kadm5clntmit_libsoname_version_downgrade.patch b/SOURCES/krb5-kadm5clntmit_libsoname_version_downgrade.patch
index 7ecb9f1..c3a7290 100644
--- a/SOURCES/krb5-kadm5clntmit_libsoname_version_downgrade.patch
+++ b/SOURCES/krb5-kadm5clntmit_libsoname_version_downgrade.patch
@@ -1,13 +1,22 @@
-This patch is a hack so that we can rebase krb5 without breaking all
-of our stricter dependents.
+From 6fbda5af22095ed1b8ca690bc8269cad04e25034 Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Fri, 22 Apr 2016 10:03:56 -0400
+Subject: [PATCH] krb5-kadm5clntmit_libsoname_version_downgrade.patch
 
+[rharwood@redhat.com: Adjust for 1.15]
+---
+ src/lib/kadm5/clnt/Makefile.in | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/lib/kadm5/clnt/Makefile.in b/src/lib/kadm5/clnt/Makefile.in
+index a180e85cd..b9aa7aa49 100644
 --- a/src/lib/kadm5/clnt/Makefile.in
 +++ b/src/lib/kadm5/clnt/Makefile.in
-@@ -3,7 +3,7 @@
+@@ -3,7 +3,7 @@ BUILDTOP=$(REL)..$(S)..$(S)..
  LOCALINCLUDES = -I$(BUILDTOP)/include/kadm5
  
  LIBBASE=kadm5clnt_mit
--LIBMAJOR=10
+-LIBMAJOR=11
 +LIBMAJOR=8
  LIBMINOR=0
  STOBJLISTS=../OBJS.ST OBJS.ST
diff --git a/SOURCES/krb5-kvno-230379.patch b/SOURCES/krb5-kvno-230379.patch
index 46eda22..0e7c5d5 100644
--- a/SOURCES/krb5-kvno-230379.patch
+++ b/SOURCES/krb5-kvno-230379.patch
@@ -1,20 +1,18 @@
-From patch attached to http://krbdev.mit.edu/rt/Ticket/Display.html?id=3349,
-at http://krbdev.mit.edu/rt/Ticket/Attachment/23851/13214/kvno.diff, adjusted
-as needed to apply to 1.10.  FIXME: I'd like to better handle cases where we
-have a new key with the right version stored later in the keytab file.
-Currently, we're setting up to overlook that possibility.
+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
 
-Note that this only affects the path taken when krb5_rd_rep() is passed a
-server principal name, as without a server principal name it already tries
-all of the keys it finds in the keytab, regardless of version numbers.
+---
+ src/kadmin/ktutil/ktutil.c    | 5 +++--
+ src/lib/krb5/keytab/kt_file.c | 2 +-
+ 2 files changed, 4 insertions(+), 3 deletions(-)
 
-[rharwood@redhat.com Modify patch to apply to 1.14.1]
-
-Index: krb5/src/kadmin/ktutil/ktutil.c
-===================================================================
---- krb5/src/kadmin/ktutil/ktutil.c	(revision 3367)
-+++ krb5/src/kadmin/ktutil/ktutil.c	(working copy)
-@@ -155,7 +155,7 @@
+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;
@@ -23,7 +21,7 @@ Index: krb5/src/kadmin/ktutil/ktutil.c
  
      for (i = 1; i < argc; i++) {
          if ((strlen(argv[i]) == 2) && !strncmp(argv[i], "-p", 2)) {
-@@ -164,6 +164,7 @@
+@@ -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]);
@@ -31,7 +29,7 @@ Index: krb5/src/kadmin/ktutil/ktutil.c
              continue;
          }
          if ((strlen(argv[i]) == 2) && !strncmp(argv[i], "-e", 2)) {
-@@ -180,7 +181,7 @@
+@@ -165,7 +166,7 @@ void ktutil_add_entry(argc, argv)
          }
      }
  
@@ -40,11 +38,11 @@ Index: krb5/src/kadmin/ktutil/ktutil.c
          fprintf(stderr, _("usage: %s (-key | -password) -p principal "
                            "-k kvno -e enctype\n"), argv[0]);
          return;
-Index: krb5/src/lib/krb5/keytab/kt_file.c
-===================================================================
---- krb5/src/lib/krb5/keytab/kt_file.c	(revision 3367)
-+++ krb5/src/lib/krb5/keytab/kt_file.c	(working copy)
-@@ -349,7 +349,7 @@
+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.
               */
diff --git a/SPECS/krb5.spec b/SPECS/krb5.spec
index 1351a7e..47b8fe9 100644
--- a/SPECS/krb5.spec
+++ b/SPECS/krb5.spec
@@ -12,8 +12,8 @@
 
 Summary: The Kerberos network authentication system
 Name: krb5
-Version: 1.14.1
-Release: 27%{?dist}
+Version: 1.15.1
+Release: 8%{?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
@@ -33,6 +33,7 @@ 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
@@ -49,38 +50,25 @@ Source100: nss_wrapper-0.0-20140204195100.git3d58327.tar.xz
 Source101: noport.c
 Source102: socket_wrapper-0.0-20140204194748.gitf3b2ece.tar.xz
 
-Patch6: krb5-1.12-ksu-path.patch
-Patch12: krb5-1.12-ktany.patch
-Patch16: krb5-1.12-buildconf.patch
-Patch23: krb5-1.3.1-dns.patch
-Patch39: krb5-1.12-api.patch
-Patch60: krb5-1.12.1-pam.patch
-Patch63: krb5-1.14.1-selinux-label.patch
-Patch71: krb5-1.13-dirsrv-accountlock.patch
-Patch86: krb5-1.9-debuginfo.patch
-Patch105: krb5-kvno-230379.patch
-Patch129: krb5-1.11-run_user_0.patch
-Patch134: krb5-1.11-kpasswdtest.patch
-Patch139: krb5-kadm5clntmit_libsoname_version_downgrade.patch
-Patch135: krb5-1.14.2-log_file_mode.patch
-Patch136: krb5-acquire_cred_interposer.patch
-Patch137: krb5-1.14.2-skip_unnecessary_mech_inquire_cred.patch
-Patch138: krb5-1.14.3-ksu_root_prompt.patch
-Patch140: krb5-CVE-2016-3119.patch
-Patch141: krb5-1.14.3-fix_otp_as_key.patch
-Patch142: krb5-1.15-hide_deperecated_on_indicate.patch
-Patch143: krb5-1.15-NTLM_SPNEGO.patch
-Patch144: krb5-1.15-fix_t_kprop.patch
-Patch145: krb5-1.15-kprop-kpropd-realm.patch
-Patch146: krb5-1.15-kprop-iprop-default_realm-tests.patch
-Patch147: krb5-1.14.3-krad-recv.patch
-Patch148: krb5-1.15-kprop-debug-argument-order.patch
-Patch149: krb5-1.15-kadmin-kprop-port.patch
-Patch150: krb5-1.15-kadmin-kprop-port-test.patch
-Patch151: krb5-1.14.4-CVE-2016-3120.patch
-Patch152: krb5-1.14.4-SNI-HTTP-Host.patch
-Patch153: krb5-1.14.4-Fix-responder-without-preauth.patch
-Patch154: krb5-1.15-krad-eof.patch
+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
+Patch151: krb5-kadm5clntmit_libsoname_version_downgrade.patch
+Patch152: Add-certauth-pluggable-interface.patch
+Patch153: Correct-error-handling-bug-in-prior-commit.patch
+Patch154: Add-the-client_name-kdcpreauth-callback.patch
+Patch155: Use-the-canonical-client-principal-name-for-OTP.patch
 
 License: MIT
 URL: http://web.mit.edu/kerberos/www/
@@ -260,55 +248,34 @@ 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
+%patch151 -p1 -b .krb5-kadm5clntmit_libsoname_version_downgrade
+%patch152 -p1 -b .Add-certauth-pluggable-interface
+%patch153 -p1 -b .Correct-error-handling-bug-in-prior-commit
+%patch154 -p1 -b .Add-the-client_name-kdcpreauth-callback
+%patch155 -p1 -b .Use-the-canonical-client-principal-name-for-OTP
+
 ln NOTICE LICENSE
 
 chmod u+x src/util/paste-kdcproxy.py
-
-%patch60 -p1 -b .pam
-
-%patch63 -p1 -b .selinux-label
-
-%patch6  -p1 -b .ksu-path
-%patch12 -p1 -b .ktany
-%patch16 -p1 -b .buildconf %{?_rawbuild}
-%patch23 -p1 -b .dns %{?_rawbuild}
-%patch39 -p1 -b .api
-%patch71 -p1 -b .dirsrv-accountlock %{?_rawbuild}
-%patch86 -p0 -b .debuginfo
-%patch105 -p1 -b .kvno
-
-# Apply when the hard-wired or configured default location is
-# DIR:/run/user/%%{uid}/krb5cc.
-%patch129 -p1 -b .run_user_0
-
-%patch134 -p1 -b .kpasswdtest
-%patch139 -p1 -b .kadm5clntmit_libsoname_version_downgrade
-%patch135 -p1 -b .log_file_mode
-%patch136 -p1 -b .acquire_cred_interposer
-%patch137 -p1 -b .skip_unnecessary_mech_inquire_cred
-%patch138 -p1 -b .ksu_root_prompt
-%patch140 -p1 -b .CVE-2016-3119
-%patch141 -p1 -b .fix_otp_as_key
-%patch142 -p1 -b .hide_deperecated_on_indicate
-%patch143 -p1 -b .NTLM_SPNEGO
-
-%patch144 -p1 -b .fix_t_kprop
-%patch145 -p1 -b .kprop-kpropd-realm
-%patch146 -p1 -b .kprop-iprop-default_realm-tests
-
-%patch147 -p1 -b .krad-recv
-
-%patch148 -p1 -b .kprop-debug-argument-order
-%patch149 -p1 -b .kadmin-kprop-port
-%patch150 -p1 -b .kadmin-kprop-port-test
-%patch151 -p1 -b .CVE-2016-3120
-%patch152 -p1 -b .SNI-HTTP-Host
-%patch153 -p1 -b .Fix-responder-without-preauth
-%patch154 -p1 -b .krad-eof
-
 # Take the execute bit off of documentation.
-chmod -x doc/krb5-protocol/*.txt doc/ccapi/*.html
+chmod -x doc/ccapi/*.html
 
 # Generate an FDS-compatible LDIF file.
 inldif=src/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif
@@ -323,9 +290,7 @@ touch -r $inldif 60kerberos.ldif
 
 # Rebuild the configure scripts.
 pushd src
-#autoheader
-#autoconf
-./util/reconf --verbose
+autoreconf -fiv
 popd
 
 # Create build spaces for the test wrappers.
@@ -392,7 +357,8 @@ CPPFLAGS="`echo $DEFINES $INCLUDES`"
 	--with-tls-impl=openssl \
 	--with-system-verto \
 	--with-pam \
-	--with-selinux
+	--with-selinux \
+        --with-prng-alg=os
 # Now build it.
 make
 popd
@@ -520,7 +486,8 @@ mkdir -p $RPM_BUILD_ROOT/%{_localstatedir}/run/krb5kdc
 mkdir -p $RPM_BUILD_ROOT/etc/sysconfig
 for sysconfig in \
 	%{SOURCE19}\
-	%{SOURCE20} ; do
+	%{SOURCE20}\
+	%{SOURCE21} ; do
 	install -pm 644 ${sysconfig} \
 	$RPM_BUILD_ROOT/etc/sysconfig/`basename ${sysconfig} .sysconfig`
 done
@@ -716,6 +683,7 @@ exit 0
 %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
 
@@ -752,8 +720,8 @@ exit 0
 %{_sbindir}/krb5kdc
 %{_mandir}/man8/krb5kdc.8*
 
-# This is here for people who want to test their server, and also
-# included in devel package for similar reasons.
+# 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
@@ -815,8 +783,6 @@ exit 0
 %files devel
 %defattr(-,root,root,-)
 %docdir %{_mandir}
-%doc doc/krb5-protocol
-%doc build-pdf/appdev.pdf build-pdf/plugindev.pdf
 
 %{_includedir}/*
 %{_libdir}/libgssapi_krb5.so
@@ -829,11 +795,7 @@ exit 0
 %{_libdir}/pkgconfig/*
 
 %{_bindir}/krb5-config
-%{_bindir}/sclient
 %{_mandir}/man1/krb5-config.1*
-%{_mandir}/man1/sclient.1*
-%{_mandir}/man8/sserver.8*
-%{_sbindir}/sserver
 
 # Protocol test clients.
 %{_bindir}/sim_client
@@ -855,6 +817,52 @@ exit 0
 %{_libdir}/libkadm5srv_mit.so.*
 
 %changelog
+* 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