]> git.ipfire.org Git - people/ms/ipfire-3.x.git/commitdiff
krb5: New package.
authorStefan Schantl <stefan.schantl@ipfire.org>
Sun, 27 Jan 2013 13:37:21 +0000 (14:37 +0100)
committerStefan Schantl <stefan.schantl@ipfire.org>
Sun, 27 Jan 2013 13:37:21 +0000 (14:37 +0100)
Fixes #10288.

34 files changed:
krb5/kadm5.acl [new file with mode: 0644]
krb5/kdc.conf [new file with mode: 0644]
krb5/krb5.conf [new file with mode: 0644]
krb5/krb5.nm [new file with mode: 0644]
krb5/ksu.pam [new file with mode: 0644]
krb5/logrotate/kadmind.logrotate [new file with mode: 0644]
krb5/logrotate/krb5kdc.logrotate [new file with mode: 0644]
krb5/patches/krb5-1.10-buildconf.patch [new file with mode: 0644]
krb5/patches/krb5-1.10-doublelog.patch [new file with mode: 0644]
krb5/patches/krb5-1.10-gcc47.patch0 [new file with mode: 0644]
krb5/patches/krb5-1.10-kpasswd_tcp.patch [new file with mode: 0644]
krb5/patches/krb5-1.10-kprop-mktemp.patch [new file with mode: 0644]
krb5/patches/krb5-1.10-ksu-access.patch [new file with mode: 0644]
krb5/patches/krb5-1.10-ksu-path.patch [new file with mode: 0644]
krb5/patches/krb5-1.10.2-keytab-etype.patch [new file with mode: 0644]
krb5/patches/krb5-1.10.2-manpaths.patch [new file with mode: 0644]
krb5/patches/krb5-1.10.2-pam.patch [new file with mode: 0644]
krb5/patches/krb5-1.10.2-selinux-label.patch [new file with mode: 0644]
krb5/patches/krb5-1.3.1-dns.patch [new file with mode: 0644]
krb5/patches/krb5-1.3.4-send-pr-tempfile.patch [new file with mode: 0644]
krb5/patches/krb5-1.6.3-kdc_listen_all.patch0 [new file with mode: 0644]
krb5/patches/krb5-1.7-ktany.patch [new file with mode: 0644]
krb5/patches/krb5-1.8-api.patch [new file with mode: 0644]
krb5/patches/krb5-1.9-debuginfo.patch0 [new file with mode: 0644]
krb5/patches/krb5-1.9-dirsrv-accountlock.patch [new file with mode: 0644]
krb5/patches/krb5-kvno-230379.patch [new file with mode: 0644]
krb5/patches/krb5-tex-pdf.sh [new file with mode: 0644]
krb5/patches/krb5-trunk-7046.patch [new file with mode: 0644]
krb5/patches/krb5-trunk-7047.patch [new file with mode: 0644]
krb5/patches/krb5-trunk-7048.patch [new file with mode: 0644]
krb5/patches/krb5-trunk-pkinit-anchorsign.patch [new file with mode: 0644]
krb5/systemd/kadmin.service [new file with mode: 0644]
krb5/systemd/kprop.service [new file with mode: 0644]
krb5/systemd/krb5kdc.service [new file with mode: 0644]

diff --git a/krb5/kadm5.acl b/krb5/kadm5.acl
new file mode 100644 (file)
index 0000000..dc93eb0
--- /dev/null
@@ -0,0 +1 @@
+*/admin@EXAMPLE.COM    *
diff --git a/krb5/kdc.conf b/krb5/kdc.conf
new file mode 100644 (file)
index 0000000..a4f5901
--- /dev/null
@@ -0,0 +1,12 @@
+[kdcdefaults]
+ kdc_ports = 88
+ kdc_tcp_ports = 88
+
+[realms]
+ EXAMPLE.COM = {
+  #master_key_type = aes256-cts
+  acl_file = /var/kerberos/krb5kdc/kadm5.acl
+  dict_file = /usr/share/dict/words
+  admin_keytab = /var/kerberos/krb5kdc/kadm5.keytab
+  supported_enctypes = aes256-cts:normal aes128-cts:normal des3-hmac-sha1:normal arcfour-hmac:normal des-hmac-sha1:normal des-cbc-md5:normal des-cbc-crc:normal
+ }
diff --git a/krb5/krb5.conf b/krb5/krb5.conf
new file mode 100644 (file)
index 0000000..c452621
--- /dev/null
@@ -0,0 +1,21 @@
+[logging]
+ default = FILE:/var/log/krb5libs.log
+ kdc = FILE:/var/log/krb5kdc.log
+ admin_server = FILE:/var/log/kadmind.log
+
+[libdefaults]
+ dns_lookup_realm = false
+ ticket_lifetime = 24h
+ renew_lifetime = 7d
+ forwardable = true
+# default_realm = EXAMPLE.COM
+
+[realms]
+# EXAMPLE.COM = {
+#  kdc = kerberos.example.com
+#  admin_server = kerberos.example.com
+# }
+
+[domain_realm]
+# .example.com = EXAMPLE.COM
+# example.com = EXAMPLE.COM
diff --git a/krb5/krb5.nm b/krb5/krb5.nm
new file mode 100644 (file)
index 0000000..a80872d
--- /dev/null
@@ -0,0 +1,245 @@
+###############################################################################
+# IPFire.org    - An Open Source Firewall Solution                            #
+# Copyright (C) - IPFire Development Team <info@ipfire.org>                   #
+###############################################################################
+
+name       = krb5
+version    = %{version_maj}.%{version_min}
+version_maj= 1.10
+version_min= 2
+release    = 1
+
+groups     = System/Libraries
+url        = http://web.mit.edu/kerberos/www/
+license    = MIT
+summary    = The Kerberos network authentication system.
+
+description
+       Kerberos V5 is a trusted-third-party network authentication system,
+       which can improve your network's security by eliminating the insecure
+       practice of sending passwords over the network in unencrypted form.
+end
+
+# Upstream only provides a "signed" tarball which contains the actual
+# tar archive.
+#source_dl  = http://we1b.mit.edu/kerberos/dist/krb5/%{version_maj}/
+#sources    = %{thisapp}-signed.tar
+
+patches
+       krb5-1.10.2-pam.patch
+       krb5-1.10.2-manpaths.patch
+       krb5-1.10.2-selinux-label.patch
+       krb5-1.3.1-dns.patch
+       krb5-1.3.4-send-pr-tempfile.patch
+       krb5-1.7-ktany.patch
+       krb5-1.8-api.patch
+       krb5-1.9-debuginfo.patch0
+       krb5-1.9-dirsrv-accountlock.patch
+       krb5-1.10-buildconf.patch
+       krb5-1.10-doublelog.patch
+       krb5-1.10-gcc47.patch0
+       krb5-1.10-kpasswd_tcp.patch
+       krb5-1.10-kprop-mktemp.patch
+       krb5-1.10-ksu-access.patch
+       krb5-1.10-ksu-path.patch
+       krb5-1.10.2-keytab-etype.patch
+       krb5-kvno-230379.patch
+       krb5-tex-pdf.sh
+       krb5-trunk-7046.patch
+       krb5-trunk-7047.patch
+       krb5-trunk-7048.patch
+       krb5-trunk-pkinit-anchorsign.patch
+end
+
+build
+       requires
+               autoconf
+               automake
+               bison
+               dejagnu
+               e2fsprogs-devel
+               flex
+               gettext
+               libselinux-devel
+               ncurses-devel
+               openldap-devel
+               openssl-devel
+               pam-devel
+               perl
+               systemd-units
+               tcl-devel
+               texinfo
+       end
+
+       prepare_cmds
+               pushd src
+               for file in appl/sample/sserver/sserver.M \
+                               config-files/kdc.conf.M \
+                               config-files/krb5.conf.M \
+                               gen-manpages/kerberos.M \
+                               kadmin/cli/kadmin.M \
+                               slave/kpropd.M \
+                               slave/kprop.M; do
+                       mv -v ${file} ${file}.in
+               done
+
+               rm -vf lib/krb5/krb/deltat.c
+
+               # Regenerate configure scripts.
+               autoheader
+               autoconf
+               popd
+       end
+
+       configure_options += \
+               --enable-shared \
+               --disable-rpath \
+               --localstatedir=/var/kerberos \
+               --with-system-et \
+               --with-system-ss \
+               --with-netlib=-lresolv \
+               --with-tcl \
+               --enable-dns-for-realm \
+               --with-dirsrv \
+               --enable-pkinit \
+               --with-crypto-impl=openssl \
+               --with-pam \
+               --with-selinux
+
+       # Don't use strlcpy that comes with glibc.
+       configure_options += \
+               ac_cv_func_strlcpy=no
+
+       build
+               cd %{DIR_APP}/src
+               ./configure \
+                       %{configure_options}
+
+               make %{PARALLELISMFLAGS}
+       end
+
+       test
+               make -C src fake-install
+               tmpdir=$(mktemp -d)
+
+               # Disable the following tests, because the don't work in the chroot env.
+               #make -C src/lib check TMPDIR=${tmpdir}
+               #make -C src/kdc check TMPDIR=${tmpdir}
+       end
+
+       install
+               # Install krb5.
+               make -C src install DESTDIR=%{BUILDROOT}
+
+               # Sample KDC config files (bundled kdc.conf and kadm5.acl).
+               mkdir -pv %{BUILDROOT}%{localstatedir}/kerberos/krb5kdc
+               install -pm 600 %{DIR_SOURCE}/kdc.conf %{BUILDROOT}%{localstatedir}/kerberos/krb5kdc/
+               install -pm 600 %{DIR_SOURCE}/kadm5.acl %{BUILDROOT}%{localstatedir}/kerberos/krb5kdc/
+
+               # Default configuration file for everything.
+               mkdir -pv %{BUILDROOT}/etc
+               install -pm 644 %{DIR_SOURCE}/krb5.conf %{BUILDROOT}/etc/krb5.conf
+
+               # Plug-in directories.
+               install -pdm 755 %{BUILDROOT}%{libdir}/krb5/plugins/preauth
+               install -pdm 755 %{BUILDROOT}%{libdir}/krb5/plugins/kdb
+               install -pdm 755 %{BUILDROOT}%{libdir}/krb5/plugins/authdata
+       end
+end
+
+packages
+       package %{name}-server
+               summary = The KDC and related programs for Kerberos 5.
+               description
+                       Kerberos is a network authentication system. The krb5-server package
+                       contains the programs that must be installed on a Kerberos 5 key
+                       distribution center (KDC).  If you are installing a Kerberos 5 KDC,
+                       you need to install this package.
+               end
+
+               requires
+                       %{name}-libs = %{thisver}
+               end
+
+               script postin
+                       /usr/bin/systemctl daemon-reload >/dev/null 2>&1 || :
+               end
+
+               script preun
+                       /usr/bin/systemctl --no-reload disable kadmin.service  >/dev/null 2>&1 || :
+                       /usr/bin/systemctl --no-reload disable kprop.service >/dev/null 2>&1 || :
+                       /usr/bin/systemctl --no-reload disable krb5kdc.service >/dev/null 2>&1 || :
+                       /usr/bin/systemctl stop kadmin.service >/dev/null 2>&1 || :
+                       /usr/bin/systemctl stop kprop.service >/dev/null 2>&1 || :
+                       /usr/bin/systemctl stop krb5kdc.service >/dev/null 2>&1 || :
+               end
+
+               script postun
+                       /usr/bin/systemctl daemon-reload >/dev/null 2>&1 || :
+               end
+
+               script postup
+                       /usr/bin/systemctl daemon-reload >/dev/null 2>&1 || :
+                       /usr/bin/systemctl try-restart kadmin.service >/dev/null 2>&1 || :
+                       /usr/bin/systemctl try-restart kprop.service >/dev/null 2>&1 || :
+                       /usr/bin/systemctl try-restart krb5kdc.service >/dev/null 2>&1 || :
+               end
+       end
+
+       package %{name}-workstation
+               summary = Kerberos 5 programs for use on workstations.
+               description
+                       Kerberos is a network authentication system. The krb5-workstation
+                       package contains the basic Kerberos programs (kinit, klist, kdestroy,
+                       kpasswd). If your network uses Kerberos, this package should be
+                       installed on every workstation.
+               end
+
+               requires
+                       %{name}-libs = %{thisver}
+               end
+
+               files
+                       %{bindir}/kdestroy
+                       %{bindir}/kinit
+                       %{bindir}/klist
+                       %{bindir}/kpassword
+                       %{bindir}/kswitch
+                       %{bindir}/kvno
+                       %{bindir}/kadmin
+                       %{bindir}/k5srvutil
+                       %{bindir}/kutil
+                       %{bindir}/ksu
+                       %{bindir}/krb5-send-pr
+
+                       %{sysconfdir}/pam.d
+
+                       %{mandir}/man1/kdestroy.*
+                       %{mandir}/man1/kinit.*
+                       %{mandir}/man1/klist.*
+                       %{mandir}/man1/kpassword.*
+                       %{mandir}/man1/kswitch.*
+                       %{mandir}/man1/kvno.*
+                       %{mandir}/man1/kadmin.*
+                       %{mandir}/man1/k5srvutil.*
+                       %{mandir}/man1/kutil.*
+                       %{mandir}/man1/ksu.*
+               end
+       end
+
+       package %{name}-libs
+               template LIBS
+       end
+
+       package %{name}-devel
+               template DEVEL
+
+               requires
+                       libselinux-devel
+               end
+       end
+
+       package %{name}-debuginfo
+               template DEBUGINFO
+       end
+end
diff --git a/krb5/ksu.pam b/krb5/ksu.pam
new file mode 100644 (file)
index 0000000..66f5b2c
--- /dev/null
@@ -0,0 +1,4 @@
+#%PAM-1.0
+auth    include  su
+account include  su
+session include  su
diff --git a/krb5/logrotate/kadmind.logrotate b/krb5/logrotate/kadmind.logrotate
new file mode 100644 (file)
index 0000000..52a66c4
--- /dev/null
@@ -0,0 +1,9 @@
+/var/log/kadmind.log {
+    missingok
+    notifempty
+    monthly
+    rotate 12
+    postrotate
+       /bin/kill -HUP `cat /var/run/kadmind.pid 2>/dev/null` 2> /dev/null || true
+    endscript
+}
diff --git a/krb5/logrotate/krb5kdc.logrotate b/krb5/logrotate/krb5kdc.logrotate
new file mode 100644 (file)
index 0000000..1100ed3
--- /dev/null
@@ -0,0 +1,9 @@
+/var/log/krb5kdc.log {
+    missingok
+    notifempty
+    monthly
+    rotate 12
+    postrotate
+       /bin/kill -HUP `cat /var/run/krb5kdc.pid 2>/dev/null` 2> /dev/null || true
+    endscript
+}
diff --git a/krb5/patches/krb5-1.10-buildconf.patch b/krb5/patches/krb5-1.10-buildconf.patch
new file mode 100644 (file)
index 0000000..25b05ac
--- /dev/null
@@ -0,0 +1,54 @@
+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'
+       # 
+       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/krb5-config.in
++++ krb5/src/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/krb5/patches/krb5-1.10-doublelog.patch b/krb5/patches/krb5-1.10-doublelog.patch
new file mode 100644 (file)
index 0000000..c20075c
--- /dev/null
@@ -0,0 +1,14 @@
+Don't double-log (actually, don't process /etc/krb5.conf twice) just
+because we built with --sysconfdir=/etc.  RT#3277
+
+--- krb5/src/include/Makefile.in
++++ krb5/src/include/Makefile.in
+@@ -67,6 +67,8 @@ PROCESS_REPLACE = -e "s+@KRB5RCTMPDIR+$(
+                 -e "s+@GSSMODULEDIR+$(GSS_MODULE_DIR)+" \
+                 -e 's+@LOCALSTATEDIR+$(LOCALSTATEDIR)+' \
+                 -e 's+@SYSCONFDIR+$(SYSCONFDIR)+' \
++                -e 's+:/etc/krb5.conf:/etc/krb5.conf"+:/etc/krb5.conf"+' \
++                -e 's+"/etc/krb5.conf:/etc/krb5.conf"+"/etc/krb5.conf"+' \
+                 -e 's+@DYNOBJEXT+$(DYNOBJEXT)+'
+ OSCONFSRC = $(srcdir)/osconf.hin
diff --git a/krb5/patches/krb5-1.10-gcc47.patch0 b/krb5/patches/krb5-1.10-gcc47.patch0
new file mode 100644 (file)
index 0000000..b973442
--- /dev/null
@@ -0,0 +1,12 @@
+This file also triggers the maybe-uninitialized warning/error. RT#7080
+
+--- src/lib/krb5/krb/x-deltat.y
++++ src/lib/krb5/krb/x-deltat.y
+@@ -44,6 +44,7 @@
+ #ifdef __GNUC__
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wuninitialized"
++#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+ #endif
+ #include <ctype.h>
diff --git a/krb5/patches/krb5-1.10-kpasswd_tcp.patch b/krb5/patches/krb5-1.10-kpasswd_tcp.patch
new file mode 100644 (file)
index 0000000..fd8da8e
--- /dev/null
@@ -0,0 +1,32 @@
+Fall back to TCP on kdc-unresolvable/unreachable errors.  We still have
+to wait for UDP to fail, so this might not be ideal.  RT #5868.
+
+--- krb5/src/lib/krb5/os/changepw.c
++++ krb5/src/lib/krb5/os/changepw.c
+@@ -270,10 +270,22 @@ change_set_password(krb5_context context
+                          &callback_info, &chpw_rep, ss2sa(&remote_addr),
+                          &addrlen, NULL, NULL, NULL);
+         if (code) {
+-            /*
+-             * Here we may want to switch to TCP on some errors.
+-             * right?
+-             */
++            /* if we're not using a stream socket, and it's an error which
++             * might reasonably be specific to a datagram "connection", try
++             * again with a stream socket */
++            if (!use_tcp) {
++                switch (code) {
++                case KRB5_KDC_UNREACH:
++                case KRB5_REALM_CANT_RESOLVE:
++                case KRB5KRB_ERR_RESPONSE_TOO_BIG:
++                /* should we do this for more result codes than these? */
++                    k5_free_serverlist (&sl);
++                    use_tcp = 1;
++                    continue;
++                default:
++                    break;
++                }
++            }
+             break;
+         }
diff --git a/krb5/patches/krb5-1.10-kprop-mktemp.patch b/krb5/patches/krb5-1.10-kprop-mktemp.patch
new file mode 100644 (file)
index 0000000..62178df
--- /dev/null
@@ -0,0 +1,28 @@
+Use an in-memory ccache to silence a compiler warning, for RT#6414.
+
+--- krb5/src/slave/kprop.c
++++ krb5/src/slave/kprop.c
+@@ -202,9 +202,8 @@ void PRS(argc, argv)
+ void get_tickets(context)
+     krb5_context context;
+ {
+-    char   buf[BUFSIZ], *def_realm;
++    char buf[] = "MEMORY:_kproptkt", *def_realm;
+     krb5_error_code retval;
+-    static char tkstring[] = "/tmp/kproptktXXXXXX";
+     krb5_keytab keytab = NULL;
+     /*
+@@ -229,11 +228,8 @@ void get_tickets(context)
+ #endif
+     /*
+-     * Initialize cache file which we're going to be using
++     * Initialize an in-memory cache for temporary use
+      */
+-    (void) mktemp(tkstring);
+-    snprintf(buf, sizeof(buf), "FILE:%s", tkstring);
+-
+     retval = krb5_cc_resolve(context, buf, &ccache);
+     if (retval) {
+         com_err(progname, retval, _("while opening credential cache %s"), buf);
diff --git a/krb5/patches/krb5-1.10-ksu-access.patch b/krb5/patches/krb5-1.10-ksu-access.patch
new file mode 100644 (file)
index 0000000..ca155f7
--- /dev/null
@@ -0,0 +1,47 @@
+The idea is to not complain about problems in the default ticket file if we
+couldn't read it, because the client would be able to tell if it's there or
+not, and we're implicitly letting the client tell us where it is.  Still needs
+work, I think.
+
+--- krb5/src/clients/ksu/ccache.c
++++ krb5/src/clients/ksu/ccache.c
+@@ -78,7 +78,7 @@ krb5_error_code krb5_ccache_copy (contex
+     cc_def_name = krb5_cc_get_name(context, cc_def);
+     cc_other_name = krb5_cc_get_name(context, *cc_other);
+-    if ( ! stat(cc_def_name, &st_temp)){
++    if ( ! access(cc_def_name, R_OK) && ! stat(cc_def_name, &st_temp)){
+         if((retval = krb5_get_nonexp_tkts(context,cc_def,&cc_def_creds_arr))){
+             return retval;
+         }
+--- krb5/src/clients/ksu/heuristic.c
++++ krb5/src/clients/ksu/heuristic.c
+@@ -409,7 +409,7 @@ krb5_error_code find_either_ticket (cont
+     cc_source_name = krb5_cc_get_name(context, cc);
+-    if ( ! stat(cc_source_name, &st_temp)){
++    if ( ! access(cc_source_name, F_OK | R_OK) && ! stat(cc_source_name, &st_temp)){
+         retval = find_ticket(context, cc, client, end_server, &temp_found);
+         if (retval)
+@@ -569,7 +569,7 @@ krb5_error_code get_best_princ_for_targe
+     cc_source_name = krb5_cc_get_name(context, cc_source);
+-    if (! stat(cc_source_name, &st_temp)) {
++    if (! access(cc_source_name, F_OK | R_OK) && ! stat(cc_source_name, &st_temp)) {
+         retval = krb5_cc_get_principal(context, cc_source, &cc_def_princ);
+         if (retval)
+             return retval;
+--- krb5/src/clients/ksu/main.c
++++ krb5/src/clients/ksu/main.c
+@@ -270,7 +270,7 @@ main (argc, argv)
+                 if ( strchr(cc_source_tag, ':')){
+                     cc_source_tag_tmp = strchr(cc_source_tag, ':') + 1;
+-                    if( stat( cc_source_tag_tmp, &st_temp)){
++                    if( access( cc_source_tag_tmp, F_OK | R_OK) || stat( cc_source_tag_tmp, &st_temp)){
+                         com_err(prog_name, errno,
+                                 _("while looking for credentials file %s"),
+                                 cc_source_tag_tmp);
diff --git a/krb5/patches/krb5-1.10-ksu-path.patch b/krb5/patches/krb5-1.10-ksu-path.patch
new file mode 100644 (file)
index 0000000..48443ef
--- /dev/null
@@ -0,0 +1,12 @@
+Set the default PATH to the one set by login.
+
+--- krb5/src/clients/ksu/Makefile.in
++++ krb5/src/clients/ksu/Makefile.in
+@@ -1,6 +1,6 @@
+ mydir=clients$(S)ksu
+ BUILDTOP=$(REL)..$(S)..
+-DEFINES = -DGET_TGT_VIA_PASSWD -DPRINC_LOOK_AHEAD -DCMD_PATH='"/bin /local/bin"'
++DEFINES = -DGET_TGT_VIA_PASSWD -DPRINC_LOOK_AHEAD -DCMD_PATH='"/usr/local/sbin /usr/local/bin /sbin /bin /usr/sbin /usr/bin"'
+ DEFS=
+ PROG_LIBPATH=-L$(TOPLIBD)
diff --git a/krb5/patches/krb5-1.10.2-keytab-etype.patch b/krb5/patches/krb5-1.10.2-keytab-etype.patch
new file mode 100644 (file)
index 0000000..4750a5c
--- /dev/null
@@ -0,0 +1,332 @@
+(Had to drop the changes to src/tests/t_keytab.py, which didn't exist in 1.10.)
+
+commit d1da158f47ea604bed4d5db5e98a976a9e54ccd0
+Author: Greg Hudson <ghudson@mit.edu>
+Date:   Thu Apr 19 17:55:10 2012 +0000
+
+    Unify krb5_get_init_creds_keytab code paths
+    
+    Use krb5_init_creds_set_keytab in krb5_get_init_creds_keytab, so that
+    processing added to the former will be used by the latter.  This is
+    slightly awkward because of the way we do the use_master fallback, in
+    that we have to duplicate some of krb5int_get_init_creds.
+    
+    Based on a patch from Stef Walter.
+    
+    git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25817 dc483132-0cff-0310-8789-dd5450dbe970
+
+diff --git a/src/lib/krb5/krb/deps b/src/lib/krb5/krb/deps
+index fe2d54c..8c4db77 100644
+--- a/src/lib/krb5/krb/deps
++++ b/src/lib/krb5/krb/deps
+@@ -473,7 +473,8 @@ gic_keytab.so gic_keytab.po $(OUTPRE)gic_keytab.$(OBJEXT): \
+   $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+   $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+   $(top_srcdir)/include/krb5/preauth_plugin.h $(top_srcdir)/include/port-sockets.h \
+-  $(top_srcdir)/include/socket-utils.h gic_keytab.c init_creds_ctx.h
++  $(top_srcdir)/include/socket-utils.h gic_keytab.c init_creds_ctx.h \
++  int-proto.h
+ gic_opt.so gic_opt.po $(OUTPRE)gic_opt.$(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 \
+diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
+index aaabc4e..681b648 100644
+--- a/src/lib/krb5/krb/get_in_tkt.c
++++ b/src/lib/krb5/krb/get_in_tkt.c
+@@ -542,10 +542,9 @@ krb5_init_creds_free(krb5_context context,
+     free(ctx);
+ }
+-static krb5_error_code
+-init_creds_get(krb5_context context,
+-               krb5_init_creds_context ctx,
+-               int *use_master)
++krb5_error_code
++k5_init_creds_get(krb5_context context, krb5_init_creds_context ctx,
++                  int *use_master)
+ {
+     krb5_error_code code;
+     krb5_data request;
+@@ -599,7 +598,7 @@ krb5_init_creds_get(krb5_context context,
+ {
+     int use_master = 0;
+-    return init_creds_get(context, ctx, &use_master);
++    return k5_init_creds_get(context, ctx, &use_master);
+ }
+ krb5_error_code KRB5_CALLCONV
+@@ -1664,7 +1663,7 @@ krb5int_get_init_creds(krb5_context context,
+             goto cleanup;
+     }
+-    code = init_creds_get(context, ctx, use_master);
++    code = k5_init_creds_get(context, ctx, use_master);
+     if (code != 0)
+         goto cleanup;
+diff --git a/src/lib/krb5/krb/gic_keytab.c b/src/lib/krb5/krb/gic_keytab.c
+index 88de6a8..e59177f 100644
+--- a/src/lib/krb5/krb/gic_keytab.c
++++ b/src/lib/krb5/krb/gic_keytab.c
+@@ -26,6 +26,7 @@
+ #ifndef LEAN_CLIENT
+ #include "k5-int.h"
++#include "int-proto.h"
+ #include "init_creds_ctx.h"
+ static krb5_error_code
+@@ -87,6 +88,44 @@ krb5_init_creds_set_keytab(krb5_context context,
+     return 0;
+ }
++static krb5_error_code
++get_init_creds_keytab(krb5_context context, krb5_creds *creds,
++                      krb5_principal client, krb5_keytab keytab,
++                      krb5_deltat start_time, char *in_tkt_service,
++                      krb5_get_init_creds_opt *options, int *use_master)
++{
++    krb5_error_code ret;
++    krb5_init_creds_context ctx = NULL;
++
++    ret = krb5_init_creds_init(context, client, NULL, NULL, start_time,
++                               options, &ctx);
++    if (ret != 0)
++        goto cleanup;
++
++    if (in_tkt_service) {
++        ret = krb5_init_creds_set_service(context, ctx, in_tkt_service);
++        if (ret != 0)
++            goto cleanup;
++    }
++
++    ret = krb5_init_creds_set_keytab(context, ctx, keytab);
++    if (ret != 0)
++        goto cleanup;
++
++    ret = k5_init_creds_get(context, ctx, use_master);
++    if (ret != 0)
++        goto cleanup;
++
++    ret = krb5_init_creds_get_creds(context, ctx, creds);
++    if (ret != 0)
++        goto cleanup;
++
++cleanup:
++    krb5_init_creds_free(context, ctx);
++
++    return ret;
++}
++
+ krb5_error_code KRB5_CALLCONV
+ krb5_get_init_creds_keytab(krb5_context context,
+                            krb5_creds *creds,
+@@ -111,10 +150,8 @@ krb5_get_init_creds_keytab(krb5_context context,
+     /* first try: get the requested tkt from any kdc */
+-    ret = krb5int_get_init_creds(context, creds, client, NULL, NULL,
+-                                 start_time, in_tkt_service, options,
+-                                 get_as_key_keytab, (void *) keytab,
+-                                 &use_master,NULL);
++    ret = get_init_creds_keytab(context, creds, client, keytab, start_time,
++                                in_tkt_service, options, &use_master);
+     /* check for success */
+@@ -132,10 +169,9 @@ krb5_get_init_creds_keytab(krb5_context context,
+     if (!use_master) {
+         use_master = 1;
+-        ret2 = krb5int_get_init_creds(context, creds, client, NULL, NULL,
+-                                      start_time, in_tkt_service, options,
+-                                      get_as_key_keytab, (void *) keytab,
+-                                      &use_master, NULL);
++        ret2 = get_init_creds_keytab(context, creds, client, keytab,
++                                     start_time, in_tkt_service, options,
++                                     &use_master);
+         if (ret2 == 0) {
+             ret = 0;
+diff --git a/src/lib/krb5/krb/int-proto.h b/src/lib/krb5/krb/int-proto.h
+index 6b16095..899579f 100644
+--- a/src/lib/krb5/krb/int-proto.h
++++ b/src/lib/krb5/krb/int-proto.h
+@@ -196,4 +196,8 @@ krb5int_mk_setpw_req(krb5_context context, krb5_auth_context auth_context,
+ void
+ k5_ccselect_free_context(krb5_context context);
++krb5_error_code
++k5_init_creds_get(krb5_context context, krb5_init_creds_context ctx,
++                  int *use_master);
++
+ #endif /* KRB5_INT_FUNC_PROTO__ */
+
+commit 8230c4b7b7323cdef2a6c877deb710a15380f40f
+Author: Greg Hudson <ghudson@mit.edu>
+Date:   Thu Apr 19 17:55:14 2012 +0000
+
+    Use etypes from keytab in krb5_gic_keytab
+    
+    When getting initial credentials with a keytab, filter the list of
+    request enctypes based on the keys in the keytab.
+    
+    Based on a patch from Stef Walter.
+    
+    ticket: 2131
+    
+    git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25818 dc483132-0cff-0310-8789-dd5450dbe970
+
+diff --git a/src/include/k5-trace.h b/src/include/k5-trace.h
+index 3749cf9..36eb23b 100644
+--- a/src/include/k5-trace.h
++++ b/src/include/k5-trace.h
+@@ -187,6 +187,10 @@
+ #define TRACE_INIT_CREDS_GAK(c, salt, s2kparams)                        \
+     TRACE(c, (c, "Getting AS key, salt \"{data}\", params \"{data}\"",  \
+               salt, s2kparams))
++#define TRACE_INIT_CREDS_KEYTAB_LOOKUP(c, etypes)                       \
++    TRACE(c, (c, "Looked up etypes in keytab: {etypes}", etypes))
++#define TRACE_INIT_CREDS_KEYTAB_LOOKUP_FAILED(c, code)                  \
++    TRACE(c, (c, "Couldn't lookup etypes in keytab: {kerr}", code))
+ #define TRACE_INIT_CREDS_PREAUTH_DECRYPT_FAIL(c, code)                  \
+     TRACE(c, (c, "Decrypt with preauth AS key failed: {kerr}", code))
+ #define TRACE_INIT_CREDS_RESTART_FAST(c)                \
+diff --git a/src/lib/krb5/krb/gic_keytab.c b/src/lib/krb5/krb/gic_keytab.c
+index e59177f..3554b25 100644
+--- a/src/lib/krb5/krb/gic_keytab.c
++++ b/src/lib/krb5/krb/gic_keytab.c
+@@ -77,14 +77,132 @@ get_as_key_keytab(krb5_context context,
+     return(ret);
+ }
++/* Return the list of etypes available for client in keytab. */
++static krb5_error_code
++lookup_etypes_for_keytab(krb5_context context, krb5_keytab keytab,
++                         krb5_principal client, krb5_enctype **etypes_out)
++{
++    krb5_kt_cursor cursor;
++    krb5_keytab_entry entry;
++    krb5_enctype *p, *etypes = NULL;
++    krb5_kvno max_kvno = 0;
++    krb5_error_code ret;
++    size_t count = 0;
++
++    *etypes_out = NULL;
++
++    if (keytab->ops->start_seq_get == NULL)
++        return EINVAL;
++    ret = krb5_kt_start_seq_get(context, keytab, &cursor);
++    if (ret != 0)
++        return ret;
++
++    for (;;) {
++        ret = krb5_kt_next_entry(context, keytab, &entry, &cursor);
++        if (ret == KRB5_KT_END)
++            break;
++        if (ret)
++            goto cleanup;
++
++        if (!krb5_c_valid_enctype(entry.key.enctype))
++            continue;
++        if (!krb5_principal_compare(context, entry.principal, client))
++            continue;
++        /* Make sure our list is for the highest kvno found for client. */
++        if (entry.vno > max_kvno) {
++            free(etypes);
++            etypes = NULL;
++            count = 0;
++            max_kvno = entry.vno;
++        } else if (entry.vno != max_kvno)
++            continue;
++
++        /* Leave room for the terminator and possibly a second entry. */
++        p = realloc(etypes, (count + 3) * sizeof(*etypes));
++        if (p == NULL) {
++            ret = ENOMEM;
++            goto cleanup;
++        }
++        etypes = p;
++        etypes[count++] = entry.key.enctype;
++        /* All DES key types work with des-cbc-crc, which is more likely to be
++         * accepted by the KDC (since MIT KDCs refuse des-cbc-md5). */
++        if (entry.key.enctype == ENCTYPE_DES_CBC_MD5 ||
++            entry.key.enctype == ENCTYPE_DES_CBC_MD4)
++            etypes[count++] = ENCTYPE_DES_CBC_CRC;
++        etypes[count] = 0;
++    }
++
++    ret = 0;
++    *etypes_out = etypes;
++    etypes = NULL;
++cleanup:
++    krb5_kt_end_seq_get(context, keytab, &cursor);
++    free(etypes);
++    return ret;
++}
++
++/* Return true if search_for is in etype_list. */
++static krb5_boolean
++check_etypes_have(krb5_enctype *etype_list, krb5_enctype search_for)
++{
++    int i;
++
++    if (!etype_list)
++        return FALSE;
++
++    for (i = 0; etype_list[i] != 0; i++) {
++        if (etype_list[i] == search_for)
++            return TRUE;
++    }
++
++    return FALSE;
++}
++
+ krb5_error_code KRB5_CALLCONV
+ krb5_init_creds_set_keytab(krb5_context context,
+                            krb5_init_creds_context ctx,
+                            krb5_keytab keytab)
+ {
++    krb5_enctype *etype_list;
++    krb5_error_code ret;
++    int i, j;
++    char *name;
++
+     ctx->gak_fct = get_as_key_keytab;
+     ctx->gak_data = keytab;
++    ret = lookup_etypes_for_keytab(context, keytab, ctx->request->client,
++                                   &etype_list);
++    if (ret) {
++        TRACE_INIT_CREDS_KEYTAB_LOOKUP_FAILED(context, ret);
++        return 0;
++    }
++
++    TRACE_INIT_CREDS_KEYTAB_LOOKUP(context, etype_list);
++
++    /* Filter the ktypes list based on what's in the keytab */
++    for (i = 0, j = 0; i < ctx->request->nktypes; i++) {
++        if (check_etypes_have(etype_list, ctx->request->ktype[i])) {
++            ctx->request->ktype[j] = ctx->request->ktype[i];
++            j++;
++        }
++    }
++    ctx->request->nktypes = j;
++    free(etype_list);
++
++    /* Error out now if there's no overlap. */
++    if (ctx->request->nktypes == 0) {
++        ret = krb5_unparse_name(context, ctx->request->client, &name);
++        if (ret == 0) {
++            krb5_set_error_message(context, KRB5_KT_NOTFOUND,
++                                   _("Keytab contains no suitable keys for "
++                                     "%s"), name);
++        }
++        krb5_free_unparsed_name(context, name);
++        return KRB5_KT_NOTFOUND;
++    }
++
+     return 0;
+ }
diff --git a/krb5/patches/krb5-1.10.2-manpaths.patch b/krb5/patches/krb5-1.10.2-manpaths.patch
new file mode 100644 (file)
index 0000000..2ef0a83
--- /dev/null
@@ -0,0 +1,190 @@
+Change the absolute paths included in the man pages so that the correct
+values can be dropped in by config.status.  After applying this patch,
+these files should be renamed to their ".in" counterparts, and then the
+configure scripts should be rebuilt.  Originally RT#6525
+
+--- krb5/src/aclocal.m4
++++ krb5/src/aclocal.m4
+@@ -1770,3 +1770,24 @@ AC_SUBST(PAM_LIBS)
+ AC_SUBST(PAM_MAN)
+ AC_SUBST(NON_PAM_MAN)
+ ])dnl
++AC_DEFUN(V5_AC_OUTPUT_MANPAGE,[
++mansysconfdir=$sysconfdir
++mansysconfdir=`eval echo $mansysconfdir | sed -e "s,NONE,$prefix,g"`
++mansysconfdir=`eval echo $mansysconfdir | sed -e "s,NONE,$ac_default_prefix,g"`
++mansbindir=$sbindir
++mansbindir=`eval echo $mansbindir | sed -e "s,NONE,$exec_prefix,g"`
++mansbindir=`eval echo $mansbindir | sed -e "s,NONE,$prefix,g"`
++mansbindir=`eval echo $mansbindir | sed -e "s,NONE,$ac_default_prefix,g"`
++manlocalstatedir=$localstatedir
++manlocalstatedir=`eval echo $manlocalstatedir | sed -e "s,NONE,$prefix,g"`
++manlocalstatedir=`eval echo $manlocalstatedir | sed -e "s,NONE,$ac_default_prefix,g"`
++manlibexecdir=$libexecdir
++manlibexecdir=`eval echo $manlibexecdir | sed -e "s,NONE,$exec_prefix,g"`
++manlibexecdir=`eval echo $manlibexecdir | sed -e "s,NONE,$prefix,g"`
++manlibexecdir=`eval echo $manlibexecdir | sed -e "s,NONE,$ac_default_prefix,g"`
++AC_SUBST(mansysconfdir)
++AC_SUBST(mansbindir)
++AC_SUBST(manlocalstatedir)
++AC_SUBST(manlibexecdir)
++AC_CONFIG_FILES($1)
++])
+--- krb5/src/configure.in
++++ krb5/src/configure.in
+@@ -1054,6 +1054,17 @@ fi
+ AC_SUBST(localedir)
+ AC_CONFIG_FILES(krb5-config, [chmod +x krb5-config])
++
++V5_AC_OUTPUT_MANPAGE([
++      appl/sample/sserver/sserver.M
++      config-files/kdc.conf.M
++      config-files/krb5.conf.M
++      gen-manpages/kerberos.M
++      kadmin/cli/kadmin.M
++      slave/kpropd.M
++      slave/kprop.M
++])
++
+ V5_AC_OUTPUT_MAKEFILE(.
+       util util/support util/profile util/profile/testmod util/send-pr
+--- krb5/src/appl/sample/sserver/sserver.M
++++ krb5/src/appl/sample/sserver/sserver.M
+@@ -59,7 +59,7 @@ option allows for a different keytab tha
+ using a line in
+ /etc/inetd.conf that looks like this:
+ .PP
+-sample  stream  tcp     nowait  root /usr/local/sbin/sserver  sserver
++sample  stream  tcp     nowait  root @mansbindir@/sserver     sserver
+ .PP
+ Since \fBsample\fP is normally not a port defined in /etc/services, you will
+ usually have to add a line to /etc/services which looks like this:
+--- krb5/src/config-files/kdc.conf.M
++++ krb5/src/config-files/kdc.conf.M
+@@ -82,14 +82,14 @@ This
+ .B string
+ specifies the location of the access control list (acl) file that
+ kadmin uses to determine which principals are allowed which permissions
+-on the database. The default value is /usr/local/var/krb5kdc/kadm5.acl.
++on the database. The default value is @manlocalstatedir@/krb5kdc/kadm5.acl.
+ .IP admin_keytab
+ This
+ .B string
+ Specifies the location of the keytab file that kadmin uses to
+ authenticate to the database.  The default value is
+-/usr/local/var/krb5kdc/kadm5.keytab.
++@manlocalstatedir@/krb5kdc/kadm5.keytab.
+ .IP database_name
+ This
+@@ -254,7 +254,7 @@ tickets should be checked against the tr
+ realm names and the [capaths] section of its krb5.conf file
+ .SH FILES 
+-/usr/local/var/krb5kdc/kdc.conf
++@manlocalstatedir@/krb5kdc/kdc.conf
+ .SH SEE ALSO
+ krb5.conf(5), krb5kdc(8)
+--- krb5/src/config-files/krb5.conf.M
++++ krb5/src/config-files/krb5.conf.M
+@@ -808,6 +808,6 @@ is whitespace-separated. The LDAP server
+ This module implements the encrypted timestamp mechanism.
+ .SH FILES 
+-/etc/krb5.conf
++@mansysconfdir@/krb5.conf
+ .SH SEE ALSO
+ syslog(3)
+--- krb5/src/gen-manpages/kerberos.M
++++ krb5/src/gen-manpages/kerberos.M
+@@ -126,7 +126,7 @@
+ Specifies the location of the KDC configuration file, which contains
+ additional configuration directives for the Key Distribution Center
+ daemon and associated programs.  The default is
+-/usr/local/var/krb5kdc/kdc.conf.
++@manlocalstatedir@/krb5kdc/kdc.conf.
+ .TP
+ .B KRB5RCACHETYPE
+ Specifies the default type of replay cache to use for servers.  Valid
+--- krb5/src/kadmin/cli/kadmin.M
++++ krb5/src/kadmin/cli/kadmin.M
+@@ -869,9 +869,9 @@ option is specified, less verbose status
+ .RS
+ .TP
+ EXAMPLE:
+-kadmin: ktremove -k /usr/local/var/krb5kdc/kadmind.keytab kadmin/admin
++kadmin: ktremove -k @manlocalstatedir@/krb5kdc/kadmind.keytab kadmin/admin
+ Entry for principal kadmin/admin with kvno 3 removed
+-      from keytab WRFILE:/usr/local/var/krb5kdc/kadmind.keytab.
++      from keytab WRFILE:@manlocalstatedir@/krb5kdc/kadmind.keytab.
+ kadmin:
+ .RE
+ .fi
+--- krb5/src/slave/kpropd.M
++++ krb5/src/slave/kpropd.M
+@@ -74,7 +74,7 @@ Normally, kpropd is invoked out of 
+ This is done by adding a line to the inetd.conf file which looks like
+ this:
+-kprop stream  tcp     nowait  root    /usr/local/sbin/kpropd  kpropd
++kprop stream  tcp     nowait  root    @mansbindir@/kpropd     kpropd
+ However, kpropd can also run as a standalone daemon, if the
+ .B \-S
+@@ -111,13 +111,13 @@ is used.
+ \fB\-f\fP \fIfile\fP
+ specifies the filename where the dumped principal database file is to be
+ stored; by default the dumped database file is KPROPD_DEFAULT_FILE
+-(normally /usr/local/var/krb5kdc/from_master).
++(normally @manlocalstatedir@/krb5kdc/from_master).
+ .TP
+ .B \-p
+ allows the user to specify the pathname to the
+ .IR kdb5_util (8)
+ program; by default the pathname used is KPROPD_DEFAULT_KDB5_UTIL
+-(normally /usr/local/sbin/kdb5_util).
++(normally @mansbindir@/kdb5_util).
+ .TP
+ .B \-S
+ turn on standalone mode.  Normally, kpropd is invoked out of
+@@ -148,14 +148,14 @@ mode.
+ allows the user to specify the path to the
+ kpropd.acl
+ file; by default the path used is KPROPD_ACL_FILE
+-(normally /usr/local/var/krb5kdc/kpropd.acl).
++(normally @manlocalstatedir@/krb5kdc/kpropd.acl).
+ .SH FILES
+ .TP "\w'kpropd.acl\ \ 'u"
+ kpropd.acl
+ Access file for
+ .BR kpropd ;
+ the default location is KPROPD_ACL_FILE (normally
+-/usr/local/var/krb5kdc/kpropd.acl).
++@manlocalstatedir@/krb5kdc/kpropd.acl).
+ Each entry is a line containing the principal of a host from which the
+ local machine will allow Kerberos database propagation via kprop.
+ .SH SEE ALSO
+--- krb5/src/slave/kprop.M
++++ krb5/src/slave/kprop.M
+@@ -39,7 +39,7 @@ Kerberos server to a slave Kerberos serv
+ This is done by transmitting the dumped database file to the slave
+ server over an encrypted, secure channel.  The dump file must be created
+ by kdb5_util, and is normally KPROP_DEFAULT_FILE
+-(/usr/local/var/krb5kdc/slave_datatrans).
++(@manlocalstatedir@/krb5kdc/slave_datatrans).
+ .SH OPTIONS
+ .TP
+ \fB\-r\fP \fIrealm\fP
+@@ -51,7 +51,7 @@ is used.
+ \fB\-f\fP \fIfile\fP
+ specifies the filename where the dumped principal database file is to be
+ found; by default the dumped database file is KPROP_DEFAULT_FILE
+-(normally /usr/local/var/krb5kdc/slave_datatrans).
++(normally @manlocalstatedir@/krb5kdc/slave_datatrans).
+ .TP
+ \fB\-P\fP \fIport\fP
+ specifies the port to use to contact the
diff --git a/krb5/patches/krb5-1.10.2-pam.patch b/krb5/patches/krb5-1.10.2-pam.patch
new file mode 100644 (file)
index 0000000..4d7c054
--- /dev/null
@@ -0,0 +1,752 @@
+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.
+
+When enabled, ksu gains a dependency on libpam.
+
+Originally RT#5939, though it's changed since then to perform the account
+and session management before dropping privileges.
+
+diff -up krb5-1.8/src/aclocal.m4.pam krb5-1.8/src/aclocal.m4
+--- krb5-1.8/src/aclocal.m4.pam        2009-11-22 12:00:45.000000000 -0500
++++ krb5-1.8/src/aclocal.m4    2010-03-05 10:48:08.000000000 -0500
+@@ -1703,3 +1703,70 @@ AC_DEFUN(KRB5_AC_KEYRING_CCACHE,[
+       ]))
+ ])dnl
+ dnl
++dnl
++dnl Use PAM instead of local crypt() compare for checking local passwords,
++dnl and perform PAM account, session management, and password-changing where
++dnl appropriate.
++dnl 
++AC_DEFUN(KRB5_WITH_PAM,[
++AC_ARG_WITH(pam,[AC_HELP_STRING(--with-pam,[compile with PAM support])],
++          withpam="$withval",withpam=auto)
++AC_ARG_WITH(pam-ksu-service,[AC_HELP_STRING(--with-ksu-service,[PAM service name for ksu ["ksu"]])],
++          withksupamservice="$withval",withksupamservice=ksu)
++old_LIBS="$LIBS"
++if test "$withpam" != no ; then
++      AC_MSG_RESULT([checking for PAM...])
++      PAM_LIBS=
++
++      AC_CHECK_HEADERS(security/pam_appl.h)
++      if test "x$ac_cv_header_security_pam_appl_h" != xyes ; then
++              if test "$withpam" = auto ; then
++                      AC_MSG_RESULT([Unable to locate security/pam_appl.h.])
++                      withpam=no
++              else
++                      AC_MSG_ERROR([Unable to locate security/pam_appl.h.])
++              fi
++      fi
++
++      LIBS=
++      unset ac_cv_func_pam_start
++      AC_CHECK_FUNCS(putenv pam_start)
++      if test "x$ac_cv_func_pam_start" = xno ; then
++              unset ac_cv_func_pam_start
++              AC_CHECK_LIB(dl,dlopen)
++              AC_CHECK_FUNCS(pam_start)
++              if test "x$ac_cv_func_pam_start" = xno ; then
++                      AC_CHECK_LIB(pam,pam_start)
++                      unset ac_cv_func_pam_start
++                      unset ac_cv_func_pam_getenvlist
++                      AC_CHECK_FUNCS(pam_start pam_getenvlist)
++                      if test "x$ac_cv_func_pam_start" = xyes ; then
++                              PAM_LIBS="$LIBS"
++                      else
++                              if test "$withpam" = auto ; then
++                                      AC_MSG_RESULT([Unable to locate libpam.])
++                                      withpam=no
++                              else
++                                      AC_MSG_ERROR([Unable to locate libpam.])
++                              fi
++                      fi
++              fi
++      fi
++      if test "$withpam" != no ; then
++              AC_MSG_NOTICE([building with PAM support])
++              AC_DEFINE(USE_PAM,1,[Define if Kerberos-aware tools should support PAM])
++              AC_DEFINE_UNQUOTED(KSU_PAM_SERVICE,"$withksupamservice",
++                                 [Define to the name of the PAM service name to be used by ksu.])
++              PAM_LIBS="$LIBS"
++              NON_PAM_MAN=".\\\" "
++              PAM_MAN=
++      else
++              PAM_MAN=".\\\" "
++              NON_PAM_MAN=
++      fi
++fi
++LIBS="$old_LIBS"
++AC_SUBST(PAM_LIBS)
++AC_SUBST(PAM_MAN)
++AC_SUBST(NON_PAM_MAN)
++])dnl
+diff -up krb5-1.8/src/clients/ksu/main.c.pam krb5-1.8/src/clients/ksu/main.c
+--- krb5-1.8/src/clients/ksu/main.c.pam        2009-11-02 22:27:56.000000000 -0500
++++ krb5-1.8/src/clients/ksu/main.c    2010-03-05 10:48:08.000000000 -0500
+@@ -26,6 +26,7 @@
+  * KSU was writen by:  Ari Medvinsky, ari@isi.edu
+  */
++#include "autoconf.h"
+ #include "ksu.h"
+ #include "adm_proto.h"
+ #include <sys/types.h>
+@@ -33,6 +34,10 @@
+ #include <signal.h>
+ #include <grp.h>
++#ifdef USE_PAM
++#include "pam.h"
++#endif
++
+ /* globals */
+ char * prog_name;
+ int auth_debug =0;
+@@ -40,6 +45,7 @@ char k5login_path[MAXPATHLEN];
+ char k5users_path[MAXPATHLEN];
+ char * gb_err = NULL;
+ int quiet = 0;
++int force_fork = 0;
+ /***********/
+ #define _DEF_CSH "/bin/csh"
+@@ -586,6 +592,25 @@ main (argc, argv)
+                prog_name,target_user,client_name,
+                source_user,ontty());
++#ifdef USE_PAM
++        if (appl_pam_enabled(ksu_context, "ksu")) {
++            if (appl_pam_acct_mgmt(KSU_PAM_SERVICE, 1, target_user, NULL,
++                                   NULL, source_user,
++                                   ttyname(STDERR_FILENO)) != 0) {
++                fprintf(stderr, "Access denied for %s.\n", target_user);
++                sweep_up(ksu_context, cc_target);
++                exit(1);
++            }
++            if (appl_pam_requires_chauthtok()) {
++                fprintf(stderr, "Password change required for %s.\n",
++                        target_user);
++                sweep_up(ksu_context, cc_target);
++                exit(1);
++            }
++            force_fork++;
++        }
++#endif
++
+         /* Run authorization as target.*/
+         if (krb5_seteuid(target_uid)) {
+             com_err(prog_name, errno, _("while switching to target for "
+@@ -651,6 +676,26 @@
+             sweep_up(ksu_context, cc_target);
+             exit(1);
+         }
++#ifdef USE_PAM
++    } else {
++        /* we always do PAM account management, even for root */
++        if (appl_pam_enabled(ksu_context, "ksu")) {
++            if (appl_pam_acct_mgmt(KSU_PAM_SERVICE, 1, target_user, NULL,
++                                   NULL, source_user,
++                                   ttyname(STDERR_FILENO)) != 0) {
++                fprintf(stderr, "Access denied for %s.\n", target_user);
++                sweep_up(ksu_context, cc_target);
++                exit(1);
++            }
++            if (appl_pam_requires_chauthtok()) {
++                fprintf(stderr, "Password change required for %s.\n",
++                        target_user);
++                sweep_up(ksu_context, cc_target);
++                exit(1);
++            }
++            force_fork++;
++        }
++#endif
+     }
+     if( some_rest_copy){
+@@ -720,6 +745,32 @@
+         exit(1);
+     }
++#ifdef USE_PAM
++    if (appl_pam_enabled(ksu_context, "ksu")) {
++        if (appl_pam_session_open() != 0) {
++            fprintf(stderr, "Error opening session for %s.\n", target_user);
++            sweep_up(ksu_context, cc_target);
++            exit(1);
++        }
++#ifdef DEBUG
++        if (auth_debug){
++            printf(" Opened PAM session.\n");
++        }
++#endif
++        if (appl_pam_cred_init()) {
++            fprintf(stderr, "Error initializing credentials for %s.\n",
++                    target_user);
++            sweep_up(ksu_context, cc_target);
++            exit(1);
++        }
++#ifdef DEBUG
++        if (auth_debug){
++            printf(" Initialized PAM credentials.\n");
++        }
++#endif
++    }
++#endif
++
+     /* set permissions */
+     if (setgid(target_pwd->pw_gid) < 0) {
+         perror("ksu: setgid");
+@@ -792,7 +817,7 @@ main (argc, argv)
+         fprintf(stderr, "program to be execed %s\n",params[0]);
+     }
+-    if( keep_target_cache ) {
++    if( keep_target_cache && !force_fork ) {
+         execv(params[0], params);
+         com_err(prog_name, errno, _("while trying to execv %s"), params[0]);
+         sweep_up(ksu_context, cc_target);
+@@ -823,16 +875,35 @@ main (argc, argv)
+             if (ret_pid == -1) {
+                 com_err(prog_name, errno, _("while calling waitpid"));
+             }
+-            sweep_up(ksu_context, cc_target);
++            if( !keep_target_cache ) {
++                sweep_up(ksu_context, cc_target);
++            }
+             exit (statusp);
+         case -1:
+             com_err(prog_name, errno, _("while trying to fork."));
+             sweep_up(ksu_context, cc_target);
+             exit (1);
+         case 0:
++#ifdef USE_PAM
++            if (appl_pam_enabled(ksu_context, "ksu")) {
++                if (appl_pam_setenv() != 0) {
++                    fprintf(stderr, "Error setting up environment for %s.\n",
++                            target_user);
++                    exit (1);
++                }
++#ifdef DEBUG
++                if (auth_debug){
++                    printf(" Set up PAM environment.\n");
++                }
++#endif
++            }
++#endif
+             execv(params[0], params);
+             com_err(prog_name, errno, _("while trying to execv %s"),
+                     params[0]);
++            if( keep_target_cache ) {
++                sweep_up(ksu_context, cc_target);
++            }
+             exit (1);
+         }
+     }
+diff -up krb5-1.8/src/clients/ksu/Makefile.in.pam krb5-1.8/src/clients/ksu/Makefile.in
+--- krb5-1.8/src/clients/ksu/Makefile.in.pam   2009-11-22 13:13:29.000000000 -0500
++++ krb5-1.8/src/clients/ksu/Makefile.in       2010-03-05 11:55:14.000000000 -0500
+@@ -7,12 +7,14 @@
+ PROG_RPATH=$(KRB5_LIBDIR)
+ 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-1.8/src/clients/ksu/pam.c.pam krb5-1.8/src/clients/ksu/pam.c
+--- krb5-1.8/src/clients/ksu/pam.c.pam 2010-03-05 10:48:08.000000000 -0500
++++ krb5-1.8/src/clients/ksu/pam.c     2010-03-05 10:48:08.000000000 -0500
+@@ -0,0 +1,389 @@
++/*
++ * src/clients/ksu/pam.c
++ *
++ * Copyright 2007,2009,2010 Red Hat, Inc.
++ *
++ * All Rights Reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ *
++ *  Redistributions of source code must retain the above copyright notice, this
++ *  list of conditions and the following disclaimer.
++ *
++ *  Redistributions in binary form must reproduce the above copyright notice,
++ *  this list of conditions and the following disclaimer in the documentation
++ *  and/or other materials provided with the distribution.
++ *
++ *  Neither the name of Red Hat, Inc. nor the names of its contributors may be
++ *  used to endorse or promote products derived from this software without
++ *  specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++ * POSSIBILITY OF SUCH DAMAGE.
++ * 
++ * Convenience wrappers for using PAM.
++ */
++
++#include "autoconf.h"
++#ifdef USE_PAM
++#include <sys/types.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++#include "k5-int.h"
++#include "pam.h"
++
++#ifndef MAXPWSIZE
++#define MAXPWSIZE 128
++#endif
++
++static int appl_pam_started;
++static pid_t appl_pam_starter = -1;
++static int appl_pam_session_opened;
++static int appl_pam_creds_initialized;
++static int appl_pam_pwchange_required;
++static pam_handle_t *appl_pamh;
++static struct pam_conv appl_pam_conv;
++static char *appl_pam_user;
++struct appl_pam_non_interactive_args {
++      const char *user;
++      const char *password;
++};
++
++int
++appl_pam_enabled(krb5_context context, const char *section)
++{
++      int enabled = 1;
++      if ((context != NULL) && (context->profile != NULL)) {
++              if (profile_get_boolean(context->profile,
++                                      section,
++                                      USE_PAM_CONFIGURATION_KEYWORD,
++                                      NULL,
++                                      enabled, &enabled) != 0) {
++                      enabled = 1;
++              }
++      }
++      return enabled;
++}
++
++void
++appl_pam_cleanup(void)
++{
++      if (getpid() != appl_pam_starter) {
++              return;
++      }
++#ifdef DEBUG
++      printf("Called to clean up PAM.\n");
++#endif
++      if (appl_pam_creds_initialized) {
++#ifdef DEBUG
++              printf("Deleting PAM credentials.\n");
++#endif
++              pam_setcred(appl_pamh, PAM_DELETE_CRED);
++              appl_pam_creds_initialized = 0;
++      }
++      if (appl_pam_session_opened) {
++#ifdef DEBUG
++              printf("Closing PAM session.\n");
++#endif
++              pam_close_session(appl_pamh, 0);
++              appl_pam_session_opened = 0;
++      }
++      appl_pam_pwchange_required = 0;
++      if (appl_pam_started) {
++#ifdef DEBUG
++              printf("Shutting down PAM.\n");
++#endif
++              pam_end(appl_pamh, 0);
++              appl_pam_started = 0;
++              appl_pam_starter = -1;
++              free(appl_pam_user);
++              appl_pam_user = NULL;
++      }
++}
++static int
++appl_pam_interactive_converse(int num_msg, const struct pam_message **msg,
++                            struct pam_response **presp, void *appdata_ptr)
++{
++      const struct pam_message *message;
++      struct pam_response *resp;
++      int i, code;
++      char *pwstring, pwbuf[MAXPWSIZE];
++      unsigned int pwsize;
++      resp = malloc(sizeof(struct pam_response) * num_msg);
++      if (resp == NULL) {
++              return PAM_BUF_ERR;
++      }
++      memset(resp, 0, sizeof(struct pam_response) * num_msg);
++      code = PAM_SUCCESS;
++      for (i = 0; i < num_msg; i++) {
++              message = &(msg[0][i]); /* XXX */
++              message = msg[i]; /* XXX */
++              pwstring = NULL;
++              switch (message->msg_style) {
++              case PAM_TEXT_INFO:
++              case PAM_ERROR_MSG:
++                      printf("[%s]\n", message->msg ? message->msg : "");
++                      fflush(stdout);
++                      resp[i].resp = NULL;
++                      resp[i].resp_retcode = PAM_SUCCESS;
++                      break;
++              case PAM_PROMPT_ECHO_ON:
++              case PAM_PROMPT_ECHO_OFF:
++                      if (message->msg_style == PAM_PROMPT_ECHO_ON) {
++                              if (fgets(pwbuf, sizeof(pwbuf),
++                                        stdin) != NULL) {
++                                      pwbuf[strcspn(pwbuf, "\r\n")] = '\0';
++                                      pwstring = pwbuf;
++                              }
++                      } else {
++                              pwstring = getpass(message->msg ?
++                                                 message->msg :
++                                                 "");
++                      }
++                      if ((pwstring != NULL) && (pwstring[0] != '\0')) {
++                              pwsize = strlen(pwstring);
++                              resp[i].resp = malloc(pwsize + 1);
++                              if (resp[i].resp == NULL) {
++                                      resp[i].resp_retcode = PAM_BUF_ERR;
++                              } else {
++                                      memcpy(resp[i].resp, pwstring, pwsize);
++                                      resp[i].resp[pwsize] = '\0';
++                                      resp[i].resp_retcode = PAM_SUCCESS;
++                              }
++                      } else {
++                              resp[i].resp_retcode = PAM_CONV_ERR;
++                              code = PAM_CONV_ERR;
++                      }
++                      break;
++              default:
++                      break;
++              }
++      }
++      *presp = resp;
++      return code;
++}
++static int
++appl_pam_non_interactive_converse(int num_msg,
++                                const struct pam_message **msg,
++                                struct pam_response **presp,
++                                void *appdata_ptr)
++{
++      const struct pam_message *message;
++      struct pam_response *resp;
++      int i, code;
++      unsigned int pwsize;
++      struct appl_pam_non_interactive_args *args;
++      const char *pwstring;
++      resp = malloc(sizeof(struct pam_response) * num_msg);
++      if (resp == NULL) {
++              return PAM_BUF_ERR;
++      }
++      args = appdata_ptr;
++      memset(resp, 0, sizeof(struct pam_response) * num_msg);
++      code = PAM_SUCCESS;
++      for (i = 0; i < num_msg; i++) {
++              message = &((*msg)[i]);
++              message = msg[i];
++              pwstring = NULL;
++              switch (message->msg_style) {
++              case PAM_TEXT_INFO:
++              case PAM_ERROR_MSG:
++                      break;
++              case PAM_PROMPT_ECHO_ON:
++              case PAM_PROMPT_ECHO_OFF:
++                      if (message->msg_style == PAM_PROMPT_ECHO_ON) {
++                              /* assume "user" */
++                              pwstring = args->user;
++                      } else {
++                              /* assume "password" */
++                              pwstring = args->password;
++                      }
++                      if ((pwstring != NULL) && (pwstring[0] != '\0')) {
++                              pwsize = strlen(pwstring);
++                              resp[i].resp = malloc(pwsize + 1);
++                              if (resp[i].resp == NULL) {
++                                      resp[i].resp_retcode = PAM_BUF_ERR;
++                              } else {
++                                      memcpy(resp[i].resp, pwstring, pwsize);
++                                      resp[i].resp[pwsize] = '\0';
++                                      resp[i].resp_retcode = PAM_SUCCESS;
++                              }
++                      } else {
++                              resp[i].resp_retcode = PAM_CONV_ERR;
++                              code = PAM_CONV_ERR;
++                      }
++                      break;
++              default:
++                      break;
++              }
++      }
++      *presp = resp;
++      return code;
++}
++static int
++appl_pam_start(const char *service, int interactive,
++             const char *login_username,
++             const char *non_interactive_password,
++             const char *hostname,
++             const char *ruser,
++             const char *tty)
++{
++      static int exit_handler_registered;
++      static struct appl_pam_non_interactive_args args;
++      int ret = 0;
++      if (appl_pam_started &&
++          (strcmp(login_username, appl_pam_user) != 0)) {
++              appl_pam_cleanup();
++              appl_pam_user = NULL;
++      }
++      if (!appl_pam_started) {
++#ifdef DEBUG
++              printf("Starting PAM up (service=\"%s\",user=\"%s\").\n",
++                     service, login_username);
++#endif
++              memset(&appl_pam_conv, 0, sizeof(appl_pam_conv));
++              appl_pam_conv.conv = interactive ?
++                                   &appl_pam_interactive_converse :
++                                   &appl_pam_non_interactive_converse;
++              memset(&args, 0, sizeof(args));
++              args.user = strdup(login_username);
++              args.password = non_interactive_password ?
++                              strdup(non_interactive_password) :
++                              NULL;
++              appl_pam_conv.appdata_ptr = &args;
++              ret = pam_start(service, login_username,
++                              &appl_pam_conv, &appl_pamh);
++              if (ret == 0) {
++                      if (hostname != NULL) {
++#ifdef DEBUG
++                              printf("Setting PAM_RHOST to \"%s\".\n", hostname);
++#endif
++                              pam_set_item(appl_pamh, PAM_RHOST, hostname);
++                      }
++                      if (ruser != NULL) {
++#ifdef DEBUG
++                              printf("Setting PAM_RUSER to \"%s\".\n", ruser);
++#endif
++                              pam_set_item(appl_pamh, PAM_RUSER, ruser);
++                      }
++                      if (tty != NULL) {
++#ifdef DEBUG
++                              printf("Setting PAM_TTY to \"%s\".\n", tty);
++#endif
++                              pam_set_item(appl_pamh, PAM_TTY, tty);
++                      }
++                      if (!exit_handler_registered &&
++                          (atexit(appl_pam_cleanup) != 0)) {
++                              pam_end(appl_pamh, 0);
++                              appl_pamh = NULL;
++                              ret = -1;
++                      } else {
++                              appl_pam_started = 1;
++                              appl_pam_starter = getpid();
++                              appl_pam_user = strdup(login_username);
++                              exit_handler_registered = 1;
++                      }
++              }
++      }
++      return ret;
++}
++int
++appl_pam_acct_mgmt(const char *service, int interactive,
++                 const char *login_username,
++                 const char *non_interactive_password,
++                 const char *hostname,
++                 const char *ruser,
++                 const char *tty)
++{
++      int ret;
++      appl_pam_pwchange_required = 0;
++      ret = appl_pam_start(service, interactive, login_username,
++                           non_interactive_password, hostname, ruser, tty);
++      if (ret == 0) {
++#ifdef DEBUG
++              printf("Calling pam_acct_mgmt().\n");
++#endif
++              ret = pam_acct_mgmt(appl_pamh, 0);
++              switch (ret) {
++              case PAM_IGNORE:
++                      ret = 0;
++                      break;
++              case PAM_NEW_AUTHTOK_REQD:
++                      appl_pam_pwchange_required = 1;
++                      ret = 0;
++                      break;
++              default:
++                      break;
++              }
++      }
++      return ret;
++}
++int
++appl_pam_requires_chauthtok(void)
++{
++      return appl_pam_pwchange_required;
++}
++int
++appl_pam_session_open(void)
++{
++      int ret = 0;
++      if (appl_pam_started) {
++#ifdef DEBUG
++              printf("Opening PAM session.\n");
++#endif
++              ret = pam_open_session(appl_pamh, 0);
++              if (ret == 0) {
++                      appl_pam_session_opened = 1;
++              }
++      }
++      return ret;
++}
++int
++appl_pam_setenv(void)
++{
++      int ret = 0;
++#ifdef HAVE_PAM_GETENVLIST
++#ifdef HAVE_PUTENV
++      int i;
++      char **list;
++      if (appl_pam_started) {
++              list = pam_getenvlist(appl_pamh);
++              for (i = 0; ((list != NULL) && (list[i] != NULL)); i++) {
++#ifdef DEBUG
++                      printf("Setting \"%s\" in environment.\n", list[i]);
++#endif
++                      putenv(list[i]);
++              }
++      }
++#endif
++#endif
++      return ret;
++}
++int
++appl_pam_cred_init(void)
++{
++      int ret = 0;
++      if (appl_pam_started) {
++#ifdef DEBUG
++              printf("Initializing PAM credentials.\n");
++#endif
++              ret = pam_setcred(appl_pamh, PAM_ESTABLISH_CRED);
++              if (ret == 0) {
++                      appl_pam_creds_initialized = 1;
++              }
++      }
++      return ret;
++}
++#endif
+diff -up krb5-1.8/src/clients/ksu/pam.h.pam krb5-1.8/src/clients/ksu/pam.h
+--- krb5-1.8/src/clients/ksu/pam.h.pam 2010-03-05 10:48:08.000000000 -0500
++++ krb5-1.8/src/clients/ksu/pam.h     2010-03-05 10:48:08.000000000 -0500
+@@ -0,0 +1,57 @@
++/*
++ * src/clients/ksu/pam.h
++ *
++ * Copyright 2007,2009,2010 Red Hat, Inc.
++ *
++ * All Rights Reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ *
++ *  Redistributions of source code must retain the above copyright notice, this
++ *  list of conditions and the following disclaimer.
++ *
++ *  Redistributions in binary form must reproduce the above copyright notice,
++ *  this list of conditions and the following disclaimer in the documentation
++ *  and/or other materials provided with the distribution.
++ *
++ *  Neither the name of Red Hat, Inc. nor the names of its contributors may be
++ *  used to endorse or promote products derived from this software without
++ *  specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++ * POSSIBILITY OF SUCH DAMAGE.
++ * 
++ * Convenience wrappers for using PAM.
++ */
++
++#include <krb5.h>
++#ifdef HAVE_SECURITY_PAM_APPL_H
++#include <security/pam_appl.h>
++#endif
++
++#define USE_PAM_CONFIGURATION_KEYWORD "use_pam"
++
++#ifdef USE_PAM
++int appl_pam_enabled(krb5_context context, const char *section);
++int appl_pam_acct_mgmt(const char *service, int interactive,
++                     const char *local_username,
++                     const char *non_interactive_password,
++                     const char *hostname,
++                     const char *ruser,
++                     const char *tty);
++int appl_pam_requires_chauthtok(void);
++int appl_pam_session_open(void);
++int appl_pam_setenv(void);
++int appl_pam_cred_init(void);
++void appl_pam_cleanup(void);
++#endif
+diff -up krb5-1.8/src/configure.in.pam krb5-1.8/src/configure.in
+--- krb5-1.8/src/configure.in.pam      2009-12-31 18:13:56.000000000 -0500
++++ krb5-1.8/src/configure.in  2010-03-05 10:48:08.000000000 -0500
+@@ -1051,6 +1051,8 @@ if test "$ac_cv_lib_socket" = "yes" -a "
+ AC_SUBST([VERTO_LIBS])
+ AC_SUBST([VERTO_VERSION])
++KRB5_WITH_PAM
++
+ # Make localedir work in autoconf 2.5x.
+ if test "${localedir+set}" != set; then
+     localedir='$(datadir)/locale'
diff --git a/krb5/patches/krb5-1.10.2-selinux-label.patch b/krb5/patches/krb5-1.10.2-selinux-label.patch
new file mode 100644 (file)
index 0000000..448aaec
--- /dev/null
@@ -0,0 +1,950 @@
+SELinux bases access to files on the domain of the requesting process,
+the operation being performed, and the context applied to the file.
+
+In many cases, applications needn't be SELinux aware to work properly,
+because SELinux can apply a default label to a file based on the label
+of the directory in which it's created.
+
+In the case of files such as /etc/krb5.keytab, however, this isn't
+sufficient, as /etc/krb5.keytab will almost always need to be given a
+label which differs from that of /etc/issue or /etc/resolv.conf.  The
+the kdb stash file needs a different label than the database for which
+it's holding a master key, even though both typically live in the same
+directory.
+
+To give the file the correct label, we can either force a "restorecon"
+call to fix a file's label after it's created, or create the file with
+the right label, as we attempt to do here.  We lean on THREEPARAMOPEN
+and define a similar macro named WRITABLEFOPEN with which we replace
+several uses of fopen().
+
+The file creation context that we're manipulating here is a process-wide
+attribute.  While for the most part, applications which need to label
+files when they're created have tended to be single-threaded, there's
+not much we can do to avoid interfering with an application that
+manipulates the creation context directly.  Right now we're mediating
+access using a library-local mutex, but that can only work for consumers
+that are part of this package -- an unsuspecting application will still
+stomp all over us.
+
+The selabel APIs for looking up the context should be thread-safe (per
+Red Hat #273081), so switching to using them instead of matchpathcon(),
+which we used earlier, is some improvement.
+
+--- krb5/src/aclocal.m4
++++ krb5/src/aclocal.m4
+@@ -103,6 +103,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
+@@ -1791,3 +1792,51 @@ AC_SUBST(manlocalstatedir)
+ AC_SUBST(manlibexecdir)
+ AC_CONFIG_FILES($1)
+ ])
++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
+--- krb5/src/config/pre.in
++++ krb5/src/config/pre.in
+@@ -180,6 +180,7 @@ LD_UNRESOLVED_PREFIX = @LD_UNRESOLVED_PREFIX@
+ LD_SHLIBDIR_PREFIX = @LD_SHLIBDIR_PREFIX@
+ LDARGS = @LDARGS@
+ LIBS = @LIBS@
++SELINUX_LIBS=@SELINUX_LIBS@
+ INSTALL=@INSTALL@
+ INSTALL_STRIP=
+@@ -379,7 +380,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!
+--- krb5/src/configure.in
++++ krb5/src/configure.in
+@@ -1053,6 +1053,8 @@ fi
+ KRB5_WITH_PAM
++KRB5_WITH_SELINUX
++
+ # Make localedir work in autoconf 2.5x.
+ if test "${localedir+set}" != set; then
+     localedir='$(datadir)/locale'
+--- krb5/src/include/k5-int.h
++++ krb5/src/include/k5-int.h
+@@ -133,6 +133,7 @@ typedef unsigned char   u_char;
+ typedef UINT64_TYPE krb5_ui_8;
+ typedef INT64_TYPE krb5_int64;
++#include "k5-label.h"
+ #define DEFAULT_PWD_STRING1 "Enter password"
+ #define DEFAULT_PWD_STRING2 "Re-enter password for verification"
+--- krb5/src/include/k5-label.h
++++ krb5/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
+--- krb5/src/include/krb5/krb5.hin
++++ krb5/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>
+--- krb5/src/kadmin/dbutil/dump.c
++++ krb5/src/kadmin/dbutil/dump.c
+@@ -346,7 +346,7 @@
+         exit_status++;
+         return;
+     }
+-    if ((fd = open(file_ok, O_WRONLY|O_CREAT|O_TRUNC, 0600)) < 0) {
++    if ((fd = THREEPARAMOPEN(file_ok, O_WRONLY|O_CREAT|O_TRUNC, 0600)) < 0) {
+         com_err(progname, errno, _("while creating 'ok' file, '%s'"),
+                 file_ok);
+         exit_status++;
+@@ -1274,7 +1274,7 @@ dump_db(argc, argv)
+          * want to get into.
+          */
+         unlink(ofile);
+-        if (!(f = fopen(ofile, "w"))) {
++        if (!(f = WRITABLEFOPEN(ofile, "w"))) {
+             fprintf(stderr, ofopen_error,
+                     progname, ofile, error_message(errno));
+             exit_status++;
+--- krb5/src/krb5-config.in
++++ krb5/src/krb5-config.in
+@@ -38,6 +38,7 @@ RPATH_FLAG='@RPATH_FLAG@'
+ PROG_RPATH_FLAGS='@PROG_RPATH_FLAGS@'
+ PTHREAD_CFLAGS='@PTHREAD_CFLAGS@'
+ DL_LIB='@DL_LIB@'
++SELINUX_LIBS='@SELINUX_LIBS@'
+ LIBS='@LIBS@'
+ GEN_LIB=@GEN_LIB@
+@@ -218,7 +219,7 @@
+     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
+--- krb5/src/lib/kadm5/logger.c
++++ krb5/src/lib/kadm5/logger.c
+@@ -425,7 +425,7 @@ krb5_klog_init(krb5_context kcontext, ch
+                      * 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;
+@@ -961,7 +961,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;
+--- krb5/src/lib/krb5/keytab/kt_file.c
++++ krb5/src/lib/krb5/keytab/kt_file.c
+@@ -1050,7 +1050,7 @@ krb5_ktfileint_open(krb5_context context
+     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)) {
+@@ -1058,7 +1058,7 @@ krb5_ktfileint_open(krb5_context context
+             /* try making it first time around */
+             krb5_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;
+--- krb5/src/plugins/kdb/db2/adb_openclose.c
++++ krb5/src/plugins/kdb/db2/adb_openclose.c
+@@ -201,7 +201,7 @@ osa_adb_init_db(osa_adb_db_t *dbp, char 
+          * 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?
+--- krb5/src/plugins/kdb/db2/libdb2/btree/bt_open.c
++++ krb5/src/plugins/kdb/db2/libdb2/btree/bt_open.c
+@@ -60,6 +60,7 @@ static char sccsid[] = "@(#)bt_open.c        8.
+ #include "k5-platform.h"      /* mkstemp? */
++#include "k5-int.h"
+ #include "db-int.h"
+ #include "btree.h"
+@@ -203,7 +204,7 @@ __bt_open(fname, flags, mode, openinfo, 
+                       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 {
+--- krb5/src/plugins/kdb/db2/libdb2/hash/hash.c
++++ krb5/src/plugins/kdb/db2/libdb2/hash/hash.c
+@@ -51,6 +51,7 @@ static char sccsid[] = "@(#)hash.c   8.12 
+ #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
+               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);
+       }
+--- krb5/src/plugins/kdb/db2/libdb2/test/Makefile.in
++++ krb5/src/plugins/kdb/db2/libdb2/test/Makefile.in
+@@ -12,7 +12,8 @@ PROG_RPATH=$(KRB5_LIBDIR)
+ KRB5_RUN_ENV= @KRB5_RUN_ENV@
+-DB_LIB                = -ldb
++DB_LIB                = -ldb $(SUPPORT_DEPLIB)
++
+ DB_DEPLIB     = ../libdb$(DEPLIBEXT)
+ all::
+--- krb5/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
++++ krb5/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
+@@ -1091,7 +1091,7 @@
+     /* Create a temporary file which contains all the entries except the
+        entry for the given service dn */
+-    pfile = fopen(file_name, "r+");
++    pfile = WRITABLEFOPEN(file_name, "r+");
+     if (pfile == NULL) {
+         com_err(me, errno, "while deleting entry from file %s", file_name);
+         goto cleanup;
+@@ -1108,7 +1108,7 @@
+     snprintf (tmp_file, strlen(file_name) + 4 + 1, "%s%s", file_name, ".tmp");
+-    tmpfd = creat(tmp_file, S_IRUSR|S_IWUSR);
++    tmpfd = THREEPARAMOPEN(tmp_file, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR);
+     umask(omask);
+     if (tmpfd == -1) {
+         com_err(me, errno, "while deleting entry from file\n");
+@@ -1728,7 +1728,7 @@
+             printf("File does not exist. Creating the file %s...\n", file_name);
+             omask = umask(077);
+-            fd = creat(file_name, S_IRUSR|S_IWUSR);
++            fd = THREEPARAMOPEN(file_name, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR);
+             umask(omask);
+             if (fd == -1) {
+                 com_err(me, errno, "Error creating file %s", file_name);
+@@ -1756,7 +1756,7 @@
+     /* TODO: file lock for the service password file */
+     /* set password in the file */
+-    pfile = fopen(file_name, "r+");
++    pfile = WRITABLEFOPEN(file_name, "r+");
+     if (pfile == NULL) {
+         com_err(me, errno, "Failed to open file %s", file_name);
+         goto cleanup;
+@@ -1797,7 +1797,7 @@
+         }
+         omask = umask(077);
+-        newfile = fopen(tmp_file, "w+");
++        newfile = WRITABLEFOPEN(tmp_file, "w+");
+         umask(omask);
+         if (newfile == NULL) {
+             com_err(me, errno, "Error creating file %s", tmp_file);
+@@ -2019,7 +2019,7 @@
+     /* 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));
+@@ -2069,7 +2069,7 @@
+         }
+         omask = umask(077);
+-        newfile = fopen(tmp_file, "w");
++        newfile = WRITABLEFOPEN(tmp_file, "w");
+         umask (omask);
+         if (newfile == NULL) {
+             com_err(me, errno, _("Error creating file %s"), tmp_file);
+--- krb5/src/slave/kpropd.c
++++ krb5/src/slave/kpropd.c
+@@ -328,7 +328,7 @@ retry:
+     if (!debug && iproprole != IPROP_SLAVE)
+         daemon(1, 0);
+ #ifdef PID_FILE
+-    if ((pidfile = fopen(PID_FILE, "w")) != NULL) {
++    if ((pidfile = WRITABLEFOPEN(PID_FILE, "w")) != NULL) {
+         fprintf(pidfile, "%d\n", getpid());
+         fclose(pidfile);
+     } else
+@@ -437,6 +437,9 @@ void doit(fd)
+     krb5_enctype etype;
+     int database_fd;
+     char host[INET6_ADDRSTRLEN+1];
++#ifdef USE_SELINUX
++    void *selabel;
++#endif
+     if (kpropd_context->kdblog_context &&
+         kpropd_context->kdblog_context->iproprole == IPROP_SLAVE) {
+@@ -515,9 +518,15 @@ void doit(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) {
+--- krb5/src/util/profile/prof_file.c
++++ krb5/src/util/profile/prof_file.c
+@@ -30,6 +30,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 */
+@@ -418,7 +419,7 @@ static errcode_t write_data_to_file(prf_
+     errno = 0;
+-    f = fopen(new_file, "w");
++    f = WRITABLEFOPEN(new_file, "w");
+     if (!f) {
+         retval = errno;
+         if (retval == 0)
+--- krb5/src/util/support/Makefile.in
++++ krb5/src/util/support/Makefile.in
+@@ -54,6 +54,7 @@ IPC_SYMS= \
+ STLIBOBJS= \
+       threads.o \
++      selinux.o \
+       init-addrinfo.o \
+       plugins.o \
+       errors.o \
+@@ -108,7 +109,7 @@ SRCS=\
+ SHLIB_EXPDEPS =
+ # Add -lm if dumping thread stats, for sqrt.
+-SHLIB_EXPLIBS= $(LIBS) $(DL_LIB)
++SHLIB_EXPLIBS= $(LIBS) $(SELINUX_LIBS) $(DL_LIB)
+ SHLIB_DIRS=
+ SHLIB_RDIRS=$(KRB5_LIBDIR)
+--- krb5/src/util/support/selinux.c
++++ krb5/src/util/support/selinux.c
+@@ -0,0 +1,373 @@
++/*
++ * Copyright 2007,2008,2009,2011,2012 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-thread.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>
++#ifdef HAVE_SELINUX_LABEL_H
++#include <selinux/label.h>
++#endif
++
++/* #define DEBUG 1 */
++
++/* 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 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;
++#ifdef HAVE_SELINUX_LABEL_H
++      struct selabel_handle *ctx;
++#endif
++
++      previous = NULL;
++      if (is_selinux_enabled()) {
++              if (getfscreatecon(&previous) == 0) {
++                      char *genpath;
++                      genpath = NULL;
++                      if (pathname[0] != '/') {
++                              char *wd;
++                              size_t len;
++                              len = 0;
++                              wd = getcwd(NULL, len);
++                              if (wd == NULL) {
++                                      if (previous != NULL) {
++                                              freecon(previous);
++                                      }
++                                      return NULL;
++                              }
++                              len = strlen(wd) + 1 + strlen(pathname) + 1;
++                              genpath = malloc(len);
++                              if (genpath == NULL) {
++                                      free(wd);
++                                      if (previous != NULL) {
++                                              freecon(previous);
++                                      }
++                                      return NULL;
++                              }
++                              sprintf(genpath, "%s/%s", wd, pathname);
++                              free(wd);
++                              fullpath = genpath;
++                      } else {
++                              fullpath = pathname;
++                      }
++#ifdef DEBUG
++                      if (isatty(fileno(stderr))) {
++                              fprintf(stderr, "Looking up context for "
++                                      "\"%s\"(%05o).\n", fullpath, mode);
++                      }
++#endif
++                      configuredsc = NULL;
++#ifdef HAVE_SELINUX_LABEL_H
++                      ctx = selabel_open(SELABEL_CTX_FILE, NULL, 0);
++                      if (ctx != NULL) {
++                              if (selabel_lookup(ctx, &configuredsc,
++                                                 fullpath, mode) != 0) {
++                                      selabel_close(ctx);
++                                      free(genpath);
++                                      if (previous != NULL) {
++                                              freecon(previous);
++                                      }
++                                      return NULL;
++                              }
++                              selabel_close(ctx);
++                      }
++#else
++                      if (matchpathcon(fullpath, mode, &configuredsc) != 0) {
++                              free(genpath);
++                              if (previous != NULL) {
++                                      freecon(previous);
++                              }
++                              return NULL;
++                      }
++#endif
++                      free(genpath);
++                      if (configuredsc == NULL) {
++                              if (previous != NULL) {
++                                      freecon(previous);
++                              }
++                              return NULL;
++                      }
++                      currentsc = NULL;
++                      getcon(&currentsc);
++                      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);
++                      }
++#ifdef DEBUG
++                      if (isatty(fileno(stderr))) {
++                              fprintf(stderr, "Setting file creation context "
++                                      "to \"%s\".\n", configuredsc);
++                      }
++#endif
++                      if (setfscreatecon(configuredsc) != 0) {
++                              freecon(configuredsc);
++                              if (previous != NULL) {
++                                      freecon(previous);
++                              }
++                              return NULL;
++                      }
++                      freecon(configuredsc);
++#ifdef DEBUG
++              } else {
++                      if (isatty(fileno(stderr))) {
++                              fprintf(stderr, "Unable to determine "
++                                      "current context.\n");
++                      }
++#endif
++              }
++      }
++      return previous;
++}
++
++static void
++pop_fscreatecon(security_context_t previous)
++{
++      if (is_selinux_enabled()) {
++#ifdef DEBUG
++              if (isatty(fileno(stderr))) {
++                      if (previous != NULL) {
++                              fprintf(stderr, "Resetting file creation "
++                                      "context to \"%s\".\n", previous);
++                      } else {
++                              fprintf(stderr, "Resetting file creation "
++                                      "context to default.\n");
++                      }
++              }
++#endif
++              setfscreatecon(previous);
++              if (previous != NULL) {
++                      freecon(previous);
++              }
++      }
++}
++
++void *
++krb5int_push_fscreatecon_for(const char *pathname)
++{
++      struct stat st;
++      void *retval;
++      k5_once(&labeled_once, label_mutex_init);
++      if (k5_mutex_lock(&labeled_mutex) == 0) {
++              if (stat(pathname, &st) != 0) {
++                      st.st_mode = S_IRUSR | S_IWUSR;
++              }
++              retval = push_fscreatecon(pathname, st.st_mode);
++              return retval ? retval : (void *) -1;
++      } else {
++              return NULL;
++      }
++}
++
++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);
++      if (k5_mutex_lock(&labeled_mutex) == 0) {
++              ctx = push_fscreatecon(path, 0);
++              fp = fopen(path, mode);
++              errno_save = errno;
++              pop_fscreatecon(ctx);
++              k5_mutex_unlock(&labeled_mutex);
++              errno = errno_save;
++      } else {
++              fp = fopen(path, mode);
++      }
++
++      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);
++      if (k5_mutex_lock(&labeled_mutex) == 0) {
++              ctx = push_fscreatecon(path, 0);
++              fd = creat(path, mode);
++              errno_save = errno;
++              pop_fscreatecon(ctx);
++              k5_mutex_unlock(&labeled_mutex);
++              errno = errno_save;
++      } else {
++              fd = creat(path, mode);
++      }
++      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);
++      if (k5_mutex_lock(&labeled_mutex) == 0) {
++              ctx = push_fscreatecon(path, mode);
++              ret = mknod(path, mode, dev);
++              errno_save = errno;
++              pop_fscreatecon(ctx);
++              k5_mutex_unlock(&labeled_mutex);
++              errno = errno_save;
++      } else {
++              ret = mknod(path, mode, dev);
++      }
++      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);
++      if (k5_mutex_lock(&labeled_mutex) == 0) {
++              ctx = push_fscreatecon(path, S_IFDIR);
++              ret = mkdir(path, mode);
++              errno_save = errno;
++              pop_fscreatecon(ctx);
++              k5_mutex_unlock(&labeled_mutex);
++              errno = errno_save;
++      } else {
++              ret = mkdir(path, mode);
++      }
++      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);
++      if (k5_mutex_lock(&labeled_mutex) == 0) {
++              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;
++      } else {
++              va_start(ap, flags);
++              mode = va_arg(ap, mode_t);
++              fd = open(path, flags, mode);
++              errno_save = errno;
++              va_end(ap);
++              errno = errno_save;
++      }
++      return fd;
++}
++
++#endif
+--- krb5/src/lib/krb5/rcache/rc_dfl.c
++++ krb5/src/lib/krb5/rcache/rc_dfl.c
+@@ -813,6 +813,9 @@ krb5_rc_dfl_expunge_locked(krb5_context 
+     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;
+@@ -834,7 +837,17 @@ krb5_rc_dfl_expunge_locked(krb5_context 
+     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) {
+--- krb5/src/plugins/kdb/db2/kdb_db2.c
++++ krb5/src/plugins/kdb/db2/kdb_db2.c
+@@ -683,8 +683,8 @@
+     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;
+--- krb5/src/plugins/kdb/db2/libdb2/recno/rec_open.c
++++ krb5/src/plugins/kdb/db2/libdb2/recno/rec_open.c
+@@ -51,6 +51,7 @@
+ #include <stdio.h>
+ #include <unistd.h>
++#include "k5-int.h"
+ #include "db-int.h"
+ #include "recno.h"
+@@ -68,7 +69,8 @@
+       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) {
+--- krb5/src/kdc/main.c
++++ krb5/src/kdc/main.c
+@@ -905,7 +905,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();
+--- krb5/src/lib/kdb/kdb_log.c
++++ krb5/src/lib/kdb/kdb_log.c
+@@ -566,7 +566,7 @@ ulog_map(krb5_context context, const cha
+             return (errno);
+         }
+-        if ((ulogfd = open(logname, O_RDWR+O_CREAT, 0600)) == -1) {
++        if ((ulogfd = THREEPARAMOPEN(logname, O_RDWR | O_CREAT, 0600)) == -1) {
+             return (errno);
+         }
+--- krb5/src/util/gss-kernel-lib/Makefile.in
++++ krb5/src/util/gss-kernel-lib/Makefile.in
+@@ -60,6 +60,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 \
+@@ -166,10 +167,12 @@ gssapi_generic.h: $(GSS_GENERIC)/gssapi_
+       $(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/krb5/patches/krb5-1.3.1-dns.patch b/krb5/patches/krb5-1.3.1-dns.patch
new file mode 100644 (file)
index 0000000..5d27689
--- /dev/null
@@ -0,0 +1,12 @@
+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 @@
+       LIBS="$LIBS $withval"
+       AC_MSG_RESULT("netlib will use \'$withval\'")
+   fi
++  KRB5_AC_ENABLE_DNS
+ ],dnl
+ [AC_LIBRARY_NET]
+ )])dnl
diff --git a/krb5/patches/krb5-1.3.4-send-pr-tempfile.patch b/krb5/patches/krb5-1.3.4-send-pr-tempfile.patch
new file mode 100644 (file)
index 0000000..a9ffa31
--- /dev/null
@@ -0,0 +1,41 @@
+Use mktemp to create our temporary files instead of basing them on our PID.
+Only portable if you assume the presence of a mktemp helper.
+diff -ur krb5-1.3.4/src/util/send-pr/send-pr.sh krb5-1.3.4/src/util/send-pr/send-pr.sh
+--- krb5-1.3.4/src/util/send-pr/send-pr.sh     1997-03-20 01:13:56.000000000 +0100
++++ krb5-1.3.4/src/util/send-pr/send-pr.sh     2004-09-20 11:28:56.000000000 +0200
+@@ -96,9 +96,9 @@
+   fi
+ fi
+-TEMP=$TMPDIR/p$$
+-BAD=$TMPDIR/pbad$$
+-REF=$TMPDIR/pf$$
++TEMP=`mktemp "$TMPDIR"/p.XXXXXX` || exit 1
++BAD=`mktemp "$TMPDIR"/pbad.XXXXXX` || exit 1
++REF=`mktemp "$TMPDIR"/pf.XXXXXX` || exit 1
+ # find a user name
+ if [ "$LOGNAME" = "" ]; then
+@@ -122,9 +122,10 @@
+ else
+   # Must use temp file due to incompatibilities in quoting behavior
+   # and to protect shell metacharacters in the expansion of $LOGNAME
+-  $PASSWD | grep "^$LOGNAME:" | awk -F: '{print $5}' | sed -e 's/,.*//' > $TEMP
+-  ORIGINATOR="`cat $TEMP`"
+-  rm -f $TEMP
++  TEMP2=`mktemp "$TMPDIR"/plogname.XXXXXX` || exit 1
++  $PASSWD | grep "^$LOGNAME:" | awk -F: '{print $5}' | sed -e 's/,.*//' > $TEMP2
++  ORIGINATOR="`cat $TEMP2`"
++  rm -f $TEMP2
+ fi
+ if [ -n "$ORGANIZATION" ]; then
+@@ -280,7 +281,7 @@
+ # Catch some signals. ($xs kludge needed by Sun /bin/sh)
+ xs=0
+ trap 'rm -f $REF $TEMP; exit $xs' 0
+-trap 'echo "$COMMAND: Aborting ..."; rm -f $REF $TEMP; xs=1; exit' 1 2 3 13 15
++trap 'echo "$COMMAND: Aborting ..."; rm -f "$REF" "$BAD" "$TEMP"; xs=1; exit' 1 2 3 13 15
+ # If they told us to use a specific file, then do so.
+ if [ -n "$IN_FILE" ]; then
diff --git a/krb5/patches/krb5-1.6.3-kdc_listen_all.patch0 b/krb5/patches/krb5-1.6.3-kdc_listen_all.patch0
new file mode 100644 (file)
index 0000000..946199e
--- /dev/null
@@ -0,0 +1,247 @@
+Provide an option to make the KDC also listen on loopback interfaces for
+datagram requests.  Adds an internal symbol to libkrb5 which the KDC
+needs if listening on loopback is enabled.
+
+The default might be better changed from FALSE to TRUE so that the
+default matches what we do with stream sockets.
+
+FIXME: doesn't add documentation anywhere.
+
+diff -up src/include/foreachaddr.h src/include/foreachaddr.h
+--- src/include/foreachaddr.h  2004-05-05 18:44:46.000000000 -0400
++++ src/include/foreachaddr.h  2008-04-04 15:39:28.000000000 -0400
+@@ -62,3 +62,18 @@ krb5int_foreach_localaddr (/*@null@*/ vo
+     ;
+ #define foreach_localaddr krb5int_foreach_localaddr
++
++extern int
++krb5int_foreach_localaddr_ext (/*@null@*/ void *data,
++                             int (*pass1fn) (/*@null@*/ void *,
++                                             struct sockaddr *) /*@*/,
++                             /*@null@*/ krb5_boolean (*skipfn) (/*@null@*/ struct sockaddr *, int) /*@*/,
++                             /*@null@*/ int (*betweenfn) (/*@null@*/ void *) /*@*/,
++                             /*@null@*/ int (*pass2fn) (/*@null@*/ void *,
++                                                        struct sockaddr *) /*@*/)
++#if defined(DEBUG) || defined(TEST)
++     /*@modifies fileSystem@*/
++#endif
++    ;
++
++#define foreach_localaddr_ext krb5int_foreach_localaddr_ext
+diff -up src/kdc/kdc_util.h src/kdc/kdc_util.h
+--- src/kdc/kdc_util.h 2008-04-04 16:28:18.000000000 -0400
++++ src/kdc/kdc_util.h 2008-04-04 16:51:27.000000000 -0400
+@@ -126,6 +126,7 @@ krb5_error_code kdc_initialize_rcache (k
+ krb5_error_code setup_server_realm (krb5_principal);
+ /* network.c */
++void process_listen_loopback (krb5_boolean);
+ krb5_error_code listen_and_process (const char *);
+ krb5_error_code setup_network (const char *);
+ krb5_error_code closedown_network (const char *);
+diff -up src/kdc/main.c src/kdc/main.c
+--- src/kdc/main.c     2008-04-04 16:22:43.000000000 -0400
++++ src/kdc/main.c     2008-04-04 16:55:22.000000000 -0400
+@@ -422,6 +422,7 @@ initialize_realms(krb5_context kcontext,
+     krb5_enctype      menctype = ENCTYPE_UNKNOWN;
+     kdc_realm_t               *rdatap;
+     krb5_boolean      manual = FALSE;
++    krb5_boolean      listen_loopback = FALSE;
+     char              *default_udp_ports = 0;
+     char              *default_tcp_ports = 0;
+     krb5_pointer      aprof;
+@@ -448,6 +449,9 @@ initialize_realms(krb5_context kcontext,
+       if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &v4mode))
+           v4mode = 0;
+ #endif
++      hierarchy[1] = "kdc_listen_loopback";
++      if (krb5_aprof_get_boolean(aprof, hierarchy, TRUE, &listen_loopback))
++          listen_loopback = FALSE;
+       /* aprof_init can return 0 with aprof == NULL */
+       if (aprof)
+            krb5_aprof_finish(aprof);
+@@ -587,6 +591,8 @@ initialize_realms(krb5_context kcontext,
+     free(v4mode);
+ #endif
++    process_listen_loopback(listen_loopback);
++
+     /*
+      * Check to see if we processed any realms.
+      */
+diff -up src/kdc/network.c src/kdc/network.c
+--- src/kdc/network.c  2008-04-04 15:39:28.000000000 -0400
++++ src/kdc/network.c  2008-04-04 16:51:44.000000000 -0400
+@@ -221,6 +221,7 @@ static SET(u_short) udp_port_data, tcp_p
+ #include "cm.h"
+ static struct select_state sstate;
++static krb5_boolean listen_loopback;
+ static krb5_error_code add_udp_port(int port)
+ {
+@@ -604,6 +605,12 @@ scan_for_newlines:
+ }
+ #endif
++void
++process_listen_loopback(krb5_boolean listen_loop)
++{
++    listen_loopback = listen_loop;
++}
++
+ /* XXX */
+ extern int krb5int_debug_sendto_kdc;
+ extern void (*krb5int_sendtokdc_debug_handler)(const void*, size_t);
+@@ -662,7 +669,9 @@ setup_network(const char *prog)
+        so we might need only one UDP socket; fall back to binding
+        sockets on each address only if IPV6_PKTINFO isn't
+        supported.  */
+-    if (foreach_localaddr (&setup_data, setup_udp_port, 0, 0)) {
++    if (listen_loopback ?
++      foreach_localaddr_ext (&setup_data, setup_udp_port, 0, 0, 0) :
++      foreach_localaddr (&setup_data, setup_udp_port, 0, 0)) {
+       return setup_data.retval;
+     }
+     setup_tcp_listener_ports(&setup_data);
+diff -up src/lib/krb5/os/localaddr.c src/lib/krb5/os/localaddr.c
+--- src/lib/krb5/os/localaddr.c        2005-04-13 12:55:43.000000000 -0400
++++ src/lib/krb5/os/localaddr.c        2008-04-04 15:39:28.000000000 -0400
+@@ -242,6 +242,17 @@ addr_eq (const struct sockaddr *s1, cons
+ }
+ #endif
++static krb5_boolean
++skip_loopback (struct sockaddr *addr, int flags)
++{
++#ifdef IFF_LOOPBACK
++    if (flags & IFF_LOOPBACK) {
++      return TRUE;
++    }
++#endif
++    return FALSE;
++}
++
+ #ifndef HAVE_IFADDRS_H
+ /*@-usereleased@*/ /* lclint doesn't understand realloc */
+ static /*@null@*/ void *
+@@ -413,14 +424,27 @@ get_linux_ipv6_addrs ()
+    indication, it should do it via some field pointed to by the DATA
+    argument.  */
+-#ifdef HAVE_IFADDRS_H
+-
+ int
+ foreach_localaddr (/*@null@*/ void *data,
+                  int (*pass1fn) (/*@null@*/ void *, struct sockaddr *) /*@*/,
+                  /*@null@*/ int (*betweenfn) (/*@null@*/ void *) /*@*/,
+                  /*@null@*/ int (*pass2fn) (/*@null@*/ void *,
+                                             struct sockaddr *) /*@*/)
++{
++    return foreach_localaddr_ext(data, pass1fn,
++                               &skip_loopback, betweenfn,
++                               pass2fn);
++}
++
++#ifdef HAVE_IFADDRS_H
++
++int
++foreach_localaddr_ext (/*@null@*/ void *data,
++                     int (*pass1fn) (/*@null@*/ void *, struct sockaddr *) /*@*/,
++                     /*@null@*/ krb5_boolean (*skipfn) (/*@null@*/ struct sockaddr *, int) /*@*/,
++                     /*@null@*/ int (*betweenfn) (/*@null@*/ void *) /*@*/,
++                     /*@null@*/ int (*pass2fn) (/*@null@*/ void *,
++                                                struct sockaddr *) /*@*/)
+ #if defined(DEBUG) || defined(TEST)
+      /*@modifies fileSystem@*/
+ #endif
+@@ -436,7 +460,7 @@ foreach_localaddr (/*@null@*/ void *data
+ #endif
+       if ((ifp->ifa_flags & IFF_UP) == 0)
+           continue;
+-      if (ifp->ifa_flags & IFF_LOOPBACK) {
++      if (skipfn && (*skipfn)(ifp->ifa_addr, ifp->ifa_flags)) {
+           /* Pretend it's not up, so the second pass will skip
+              it.  */
+           ifp->ifa_flags &= ~IFF_UP;
+@@ -459,7 +483,7 @@ foreach_localaddr (/*@null@*/ void *data
+       for (ifp2 = ifp_head; ifp2 && ifp2 != ifp; ifp2 = ifp2->ifa_next) {
+           if ((ifp2->ifa_flags & IFF_UP) == 0)
+               continue;
+-          if (ifp2->ifa_flags & IFF_LOOPBACK)
++          if (skipfn && (*skipfn)(ifp2->ifa_addr, ifp2->ifa_flags))
+               continue;
+           if (addr_eq (ifp->ifa_addr, ifp2->ifa_addr)) {
+               match = 1;
+@@ -488,11 +512,12 @@ foreach_localaddr (/*@null@*/ void *data
+ #elif defined (SIOCGLIFNUM) && defined(HAVE_STRUCT_LIFCONF) /* Solaris 8 and later; Sol 7? */
+ int
+-foreach_localaddr (/*@null@*/ void *data,
+-                 int (*pass1fn) (/*@null@*/ void *, struct sockaddr *) /*@*/,
+-                 /*@null@*/ int (*betweenfn) (/*@null@*/ void *) /*@*/,
+-                 /*@null@*/ int (*pass2fn) (/*@null@*/ void *,
+-                                            struct sockaddr *) /*@*/)
++foreach_localaddr_ext (/*@null@*/ void *data,
++                     int (*pass1fn) (/*@null@*/ void *, struct sockaddr *) /*@*/,
++                     /*@null@*/ int (*skipfn) (/*@null@*/ struct sockaddr *, int) /*@*/,
++                     /*@null@*/ int (*betweenfn) (/*@null@*/ void *) /*@*/,
++                     /*@null@*/ int (*pass2fn) (/*@null@*/ void *,
++                                                struct sockaddr *) /*@*/)
+ #if defined(DEBUG) || defined(TEST)
+      /*@modifies fileSystem@*/
+ #endif
+@@ -583,13 +608,12 @@ foreach_localaddr (/*@null@*/ void *data
+           }
+           /*@=moduncon@*/
+-#ifdef IFF_LOOPBACK
+-          /* None of the current callers want loopback addresses.  */
+-          if (lifreq.lifr_flags & IFF_LOOPBACK) {
+-              Tprintf (("  loopback\n"));
++          if (skipfn && (*skipfn)(lifreq.lifr_addr, lifreq.lifr_flags))
++              if (skipfn && (skipfn == &skip_loopback))
++                  Tprintf (("  loopback\n"));
+               goto skip;
+           }
+-#endif
++
+           /* Ignore interfaces that are down.  */
+           if ((lifreq.lifr_flags & IFF_UP) == 0) {
+               Tprintf (("  down\n"));
+@@ -755,13 +779,12 @@ foreach_localaddr (/*@null@*/ void *data
+           }
+           /*@=moduncon@*/
+-#ifdef IFF_LOOPBACK
+           /* None of the current callers want loopback addresses.  */
+-          if (lifreq.iflr_flags & IFF_LOOPBACK) {
+-              Tprintf (("  loopback\n"));
++          if (skipfn && (*skipfn)(ifp2->ifa_addr, lifreq.lifr_flags))
++              if (skipfn && (skipfn == &skip_loopback))
++                  Tprintf (("  loopback\n"));
+               goto skip;
+           }
+-#endif
+           /* Ignore interfaces that are down.  */
+           if ((lifreq.iflr_flags & IFF_UP) == 0) {
+               Tprintf (("  down\n"));
+@@ -971,13 +994,12 @@ foreach_localaddr (/*@null@*/ void *data
+       }
+       /*@=moduncon@*/
+-#ifdef IFF_LOOPBACK
+-      /* None of the current callers want loopback addresses.  */
+-      if (ifreq.ifr_flags & IFF_LOOPBACK) {
+-          Tprintf (("  loopback\n"));
++      if (skipfn && (*skipfn)(NULL, ifreq.ifr_flags))
++          if (skipfn && (skipfn == &skip_loopback))
++              Tprintf (("  loopback\n"));
+           goto skip;
+       }
+-#endif
++
+       /* Ignore interfaces that are down.  */
+       if ((ifreq.ifr_flags & IFF_UP) == 0) {
+           Tprintf (("  down\n"));
diff --git a/krb5/patches/krb5-1.7-ktany.patch b/krb5/patches/krb5-1.7-ktany.patch
new file mode 100644 (file)
index 0000000..902f328
--- /dev/null
@@ -0,0 +1,351 @@
+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.
+
+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
+@@ -0,0 +1,292 @@
++/*
++ * lib/krb5/keytab/kt_any.c
++ *
++ * Copyright 1998, 1999 by the Massachusetts Institute of Technology.
++ * All Rights Reserved.
++ *
++ * Export of this software from the United States of America may
++ *   require a specific license from the United States Government.
++ *   It is the responsibility of any person or organization contemplating
++ *   export to obtain such a license before exporting.
++ * 
++ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
++ * distribute this software and its documentation for any purpose and
++ * without fee is hereby granted, provided that the above copyright
++ * notice appear in all copies and that both that copyright notice and
++ * this permission notice appear in supporting documentation, and that
++ * the name of M.I.T. not be used in advertising or publicity pertaining
++ * to distribution of the software without specific, written prior
++ * permission.  M.I.T. makes no representations about the suitability of
++ * this software for any purpose.  It is provided "as is" without express
++ * or implied warranty.
++ * 
++ *
++ * krb5_kta_ops
++ */
++
++#include "k5-int.h"
++
++typedef struct _krb5_ktany_data {
++    char *name;
++    krb5_keytab *choices;
++    int nchoices;
++} krb5_ktany_data;
++
++typedef struct _krb5_ktany_cursor_data {
++    int which;
++    krb5_kt_cursor cursor;
++} krb5_ktany_cursor_data;
++
++static krb5_error_code krb5_ktany_resolve
++                (krb5_context,
++                 const char *,
++                 krb5_keytab *);
++static krb5_error_code krb5_ktany_get_name
++                (krb5_context context,
++                 krb5_keytab id,
++                 char *name,
++                 unsigned int len);
++static krb5_error_code krb5_ktany_close
++                (krb5_context context,
++                 krb5_keytab id);
++static krb5_error_code krb5_ktany_get_entry
++                (krb5_context context,
++                 krb5_keytab id,
++                 krb5_const_principal principal,
++                 krb5_kvno kvno,
++                 krb5_enctype enctype,
++                 krb5_keytab_entry *entry);
++static krb5_error_code krb5_ktany_start_seq_get
++                (krb5_context context,
++                 krb5_keytab id,
++                 krb5_kt_cursor *cursorp);
++static krb5_error_code krb5_ktany_next_entry
++                (krb5_context context,
++                 krb5_keytab id,
++                 krb5_keytab_entry *entry,
++                 krb5_kt_cursor *cursor);
++static krb5_error_code krb5_ktany_end_seq_get
++                (krb5_context context,
++                 krb5_keytab id,
++                 krb5_kt_cursor *cursor);
++static void cleanup
++                (krb5_context context,
++                 krb5_ktany_data *data,
++                 int nchoices);
++
++struct _krb5_kt_ops krb5_kta_ops = {
++    0,
++    "ANY",    /* Prefix -- this string should not appear anywhere else! */
++    krb5_ktany_resolve,
++    krb5_ktany_get_name,
++    krb5_ktany_close,
++    krb5_ktany_get_entry,
++    krb5_ktany_start_seq_get,
++    krb5_ktany_next_entry,
++    krb5_ktany_end_seq_get,
++    NULL,
++    NULL,
++    NULL,
++};
++
++static krb5_error_code
++krb5_ktany_resolve(context, name, id)
++    krb5_context context;
++    const char *name;
++    krb5_keytab *id;
++{
++    const char *p, *q;
++    char *copy;
++    krb5_error_code kerror;
++    krb5_ktany_data *data;
++    int i;
++
++    /* Allocate space for our data and remember a copy of the name. */
++    if ((data = (krb5_ktany_data *)malloc(sizeof(krb5_ktany_data))) == NULL)
++      return(ENOMEM);
++    if ((data->name = (char *)malloc(strlen(name) + 1)) == NULL) {
++      krb5_xfree(data);
++      return(ENOMEM);
++    }
++    strcpy(data->name, name);
++
++    /* Count the number of choices and allocate memory for them. */
++    data->nchoices = 1;
++    for (p = name; (q = strchr(p, ',')) != NULL; p = q + 1)
++      data->nchoices++;
++    if ((data->choices = (krb5_keytab *)
++       malloc(data->nchoices * sizeof(krb5_keytab))) == NULL) {
++      krb5_xfree(data->name);
++      krb5_xfree(data);
++      return(ENOMEM);
++    }
++
++    /* Resolve each of the choices. */
++    i = 0;
++    for (p = name; (q = strchr(p, ',')) != NULL; p = q + 1) {
++      /* Make a copy of the choice name so we can terminate it. */
++      if ((copy = (char *)malloc(q - p + 1)) == NULL) {
++          cleanup(context, data, i);
++          return(ENOMEM);
++      }
++      memcpy(copy, p, q - p);
++      copy[q - p] = 0;
++
++      /* Try resolving the choice name. */
++      kerror = krb5_kt_resolve(context, copy, &data->choices[i]);
++      krb5_xfree(copy);
++      if (kerror) {
++          cleanup(context, data, i);
++          return(kerror);
++      }
++      i++;
++    }
++    if ((kerror = krb5_kt_resolve(context, p, &data->choices[i]))) {
++      cleanup(context, data, i);
++      return(kerror);
++    }
++
++    /* Allocate and fill in an ID for the caller. */
++    if ((*id = (krb5_keytab)malloc(sizeof(**id))) == NULL) {
++      cleanup(context, data, i);
++      return(ENOMEM);
++    }
++    (*id)->ops = &krb5_kta_ops;
++    (*id)->data = (krb5_pointer)data;
++    (*id)->magic = KV5M_KEYTAB;
++
++    return(0);
++}
++
++static krb5_error_code
++krb5_ktany_get_name(context, id, name, len)
++    krb5_context context;
++    krb5_keytab id;
++    char *name;
++    unsigned int len;
++{
++    krb5_ktany_data *data = (krb5_ktany_data *)id->data;
++
++    if (len < strlen(data->name) + 1)
++      return(KRB5_KT_NAME_TOOLONG);
++    strcpy(name, data->name);
++    return(0);
++}
++
++static krb5_error_code
++krb5_ktany_close(context, id)
++    krb5_context context;
++    krb5_keytab id;
++{
++    krb5_ktany_data *data = (krb5_ktany_data *)id->data;
++
++    cleanup(context, data, data->nchoices);
++    id->ops = 0;
++    krb5_xfree(id);
++    return(0);
++}
++
++static krb5_error_code
++krb5_ktany_get_entry(context, id, principal, kvno, enctype, entry)
++    krb5_context context;
++    krb5_keytab id;
++    krb5_const_principal principal;
++    krb5_kvno kvno;
++    krb5_enctype enctype;
++    krb5_keytab_entry *entry;
++{
++    krb5_ktany_data *data = (krb5_ktany_data *)id->data;
++    krb5_error_code kerror = KRB5_KT_NOTFOUND;
++    int i;
++
++    for (i = 0; i < data->nchoices; i++) {
++      if ((kerror = krb5_kt_get_entry(context, data->choices[i], principal,
++                                      kvno, enctype, entry)) != ENOENT)
++          return kerror;
++    }
++    return kerror;
++}
++
++static krb5_error_code
++krb5_ktany_start_seq_get(context, id, cursorp)
++    krb5_context context;
++    krb5_keytab id;
++    krb5_kt_cursor *cursorp;
++{
++    krb5_ktany_data *data = (krb5_ktany_data *)id->data;
++    krb5_ktany_cursor_data *cdata;
++    krb5_error_code kerror = ENOENT;
++    int i;
++
++    if ((cdata = (krb5_ktany_cursor_data *)
++       malloc(sizeof(krb5_ktany_cursor_data))) == NULL)
++      return(ENOMEM);
++
++    /* Find a choice which can handle the serialization request. */
++    for (i = 0; i < data->nchoices; i++) {
++      if ((kerror = krb5_kt_start_seq_get(context, data->choices[i],
++                                          &cdata->cursor)) == 0)
++          break;
++      else if (kerror != ENOENT) {
++          krb5_xfree(cdata);
++          return(kerror);
++      }
++    }
++
++    if (i == data->nchoices) {
++      /* Everyone returned ENOENT, so no go. */
++      krb5_xfree(cdata);
++      return(kerror);
++    }
++
++    cdata->which = i;
++    *cursorp = (krb5_kt_cursor)cdata;
++    return(0);
++}
++
++static krb5_error_code
++krb5_ktany_next_entry(context, id, entry, cursor)
++    krb5_context context;
++    krb5_keytab id;
++    krb5_keytab_entry *entry;
++    krb5_kt_cursor *cursor;
++{
++    krb5_ktany_data *data = (krb5_ktany_data *)id->data;
++    krb5_ktany_cursor_data *cdata = (krb5_ktany_cursor_data *)*cursor;
++    krb5_keytab choice_id;
++
++    choice_id = data->choices[cdata->which];
++    return(krb5_kt_next_entry(context, choice_id, entry, &cdata->cursor));
++}
++
++static krb5_error_code
++krb5_ktany_end_seq_get(context, id, cursor)
++    krb5_context context;
++    krb5_keytab id;
++    krb5_kt_cursor *cursor;
++{
++    krb5_ktany_data *data = (krb5_ktany_data *)id->data;
++    krb5_ktany_cursor_data *cdata = (krb5_ktany_cursor_data *)*cursor;
++    krb5_keytab choice_id;
++    krb5_error_code kerror;
++
++    choice_id = data->choices[cdata->which];
++    kerror = krb5_kt_end_seq_get(context, choice_id, &cdata->cursor);
++    krb5_xfree(cdata);
++    return(kerror);
++}
++
++static void
++cleanup(context, data, nchoices)
++    krb5_context context;
++    krb5_ktany_data *data;
++    int nchoices;
++{
++    int i;
++
++    krb5_xfree(data->name);
++    for (i = 0; i < nchoices; i++)
++      krb5_kt_close(context, data->choices[i]);
++    krb5_xfree(data->choices);
++    krb5_xfree(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;
+ extern const krb5_kt_ops krb5_ktf_writable_ops;
+ extern const krb5_kt_ops krb5_kts_ops;
+ extern const krb5_kt_ops krb5_mkt_ops;
++extern const krb5_kt_ops krb5_kta_ops;
+ struct krb5_kt_typelist {
+     const krb5_kt_ops *ops;
+     const struct krb5_kt_typelist *next;
+ };
++static struct krb5_kt_typelist krb5_kt_typelist_any = {
++    &krb5_kta_ops,
++    NULL
++};
+ const static struct krb5_kt_typelist krb5_kt_typelist_srvtab = {
+     &krb5_kts_ops,
+-    NULL
++    &krb5_kt_typelist_any
+ };
+ const static struct krb5_kt_typelist krb5_kt_typelist_memory = {
+     &krb5_mkt_ops,
+diff -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/krb5/patches/krb5-1.8-api.patch b/krb5/patches/krb5-1.8-api.patch
new file mode 100644 (file)
index 0000000..9cc9cd2
--- /dev/null
@@ -0,0 +1,30 @@
+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.
+
+diff -up krb5-1.8/src/lib/krb5/krb/princ_comp.c.api krb5-1.8/src/lib/krb5/krb/princ_comp.c
+--- krb5-1.8/src/lib/krb5/krb/princ_comp.c.api 2009-10-30 20:48:38.000000000 -0400
++++ krb5-1.8/src/lib/krb5/krb/princ_comp.c     2010-03-05 11:00:55.000000000 -0500
+@@ -41,6 +41,12 @@ realm_compare_flags(krb5_context context
+     const krb5_data *realm1 = krb5_princ_realm(context, princ1);
+     const krb5_data *realm2 = krb5_princ_realm(context, princ2);
++    if ((princ1 == NULL) || (princ2 == NULL))
++        return FALSE;
++
++    if ((realm1 == NULL) || (realm2 == NULL))
++        return FALSE;
++
+     if (realm1->length != realm2->length)
+         return FALSE;
+@@ -92,6 +98,9 @@ krb5_principal_compare_flags(krb5_contex
+     krb5_principal upn2 = NULL;
+     krb5_boolean ret = FALSE;
++    if ((princ1 == NULL) || (princ2 == NULL))
++        return FALSE;
++
+     if (flags & KRB5_PRINCIPAL_COMPARE_ENTERPRISE) {
+         /* Treat UPNs as if they were real principals */
+         if (krb5_princ_type(context, princ1) == KRB5_NT_ENTERPRISE_PRINCIPAL) {
diff --git a/krb5/patches/krb5-1.9-debuginfo.patch0 b/krb5/patches/krb5-1.9-debuginfo.patch0
new file mode 100644 (file)
index 0000000..ae81f7c
--- /dev/null
@@ -0,0 +1,26 @@
+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.
+
+--- src/kadmin/cli/Makefile.in
++++ src/kadmin/cli/Makefile.in
+@@ -43,3 +43,8 @@ clean-unix::
+ # CC_LINK is not meant for compilation and this use may break in the future.
+ datetest: getdate.c
+       $(CC_LINK) $(ALL_CFLAGS) -DTEST -o datetest getdate.c
++
++%.c: %.y
++      $(RM) y.tab.c $@
++      $(YACC.y) $< 
++      $(CP) y.tab.c $@
+--- 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
+ getdate.c: $(GETDATE)
+       $(RM) getdate.c y.tab.c
+       $(YACC) $(GETDATE)
+-      $(MV) y.tab.c getdate.c
++      $(CP) y.tab.c getdate.c
+ install::
+       $(INSTALL_PROGRAM) $(PROG) ${DESTDIR}$(ADMIN_BINDIR)/$(PROG)
diff --git a/krb5/patches/krb5-1.9-dirsrv-accountlock.patch b/krb5/patches/krb5-1.9-dirsrv-accountlock.patch
new file mode 100644 (file)
index 0000000..8657882
--- /dev/null
@@ -0,0 +1,69 @@
+Treat 'nsAccountLock: true' the same as 'loginDisabled: true'.  Updated from
+original version filed as RT#5891.
+
+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
+@@ -1678,6 +1678,12 @@ AC_ARG_WITH([edirectory],
+     yes | no) ;;
+     *)  AC_MSG_ERROR(Invalid option value --with-edirectory="$withval") ;;
+ esac], with_edirectory=no)dnl
++AC_ARG_WITH([dirsrv],
++[  --with-dirsrv       compile 389/Red Hat/Fedora/Netscape Directory Server database backend module],
++[case "$withval" in
++    yes | no) ;;
++    *)  AC_MSG_ERROR(Invalid option value --with-dirsrv="$withval") ;;
++esac], with_dirsrv=no)dnl
+ if test $with_ldap = yes; then
+   if test $with_edirectory = yes; then
+@@ -1689,6 +1695,10 @@ elif test $with_edirectory = yes; then
+   AC_MSG_NOTICE(enabling eDirectory database backend module support)
+   OPENLDAP_PLUGIN=yes
+   AC_DEFINE(HAVE_EDIRECTORY,1,[Define if LDAP KDB interface should assume eDirectory.])
++elif test $with_dirsrv = yes; then
++  AC_MSG_NOTICE(enabling 389/Red Hat/Fedora/Netscape Directory Server database backend module support)
++  OPENLDAP_PLUGIN=yes
++  AC_DEFINE(HAVE_DIRSRV,1,[Define if LDAP KDB interface should assume RHDS/FDS/NDS.])
+ else
+   : # neither enabled
+ dnl  AC_MSG_NOTICE(disabling ldap backend module support)
+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
+@@ -2101,6 +2101,22 @@ populate_krb5_db_entry(krb5_context cont
+         }
+     }
+ #endif
++#ifdef HAVE_DIRSRV
++    {
++        krb5_timestamp              expiretime=0;
++        char                        *is_login_disabled=NULL;
++
++        /* LOGIN DISABLED */
++        if ((st=krb5_ldap_get_string(ld, ent, "nsaccountlock", &is_login_disabled,
++                    &attr_present)) != 0)
++            goto cleanup;
++        if (attr_present == TRUE) {
++            if (strcasecmp(is_login_disabled, "TRUE")== 0)
++                entry->attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
++            free (is_login_disabled);
++        }
++    }
++#endif
+     if ((st=krb5_read_tkt_policy (context, ldap_context, entry, tktpolname)) !=0)
+         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
+                                      "loginexpirationtime",
+                                      "logindisabled",
+ #endif
++#ifdef HAVE_DIRSRV
++                                     "nsaccountlock",
++#endif
+                                      "krbLastPwdChange",
+                                      "krbLastAdminUnlock",
+                                      "krbExtraData",
diff --git a/krb5/patches/krb5-kvno-230379.patch b/krb5/patches/krb5-kvno-230379.patch
new file mode 100644 (file)
index 0000000..ea9b69f
--- /dev/null
@@ -0,0 +1,53 @@
+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.
+
+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.
+
+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 @@
+     char *princ = NULL;
+     char *enctype = NULL;
+     krb5_kvno kvno = 0;
+-    int use_pass = 0, use_key = 0, i;
++    int use_pass = 0, use_key = 0, use_kvno = 0, i;
+     for (i = 1; i < argc; i++) {
+         if ((strlen(argv[i]) == 2) && !strncmp(argv[i], "-p", 2)) {
+@@ -164,6 +164,7 @@
+         }
+         if ((strlen(argv[i]) == 2) && !strncmp(argv[i], "-k", 2)) {
+             kvno = (krb5_kvno) atoi(argv[++i]);
++            use_kvno++;
+             continue;
+         }
+         if ((strlen(argv[i]) == 2) && !strncmp(argv[i], "-e", 2)) {
+@@ -180,7 +181,7 @@
+         }
+     }
+-    if (argc != 8 || !(princ && kvno && enctype) || (use_pass+use_key != 1)) {
++    if (argc != 8 || !(princ && use_kvno && enctype) || (use_pass+use_key != 1)) {
+         fprintf(stderr, _("usage: %s (-key | -password) -p principal "
+                           "-k kvno -e enctype\n"), argv[0]);
+         return;
+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 @@
+                higher than that.  Short-term workaround: only compare
+                the low 8 bits.  */
+-            if (new_entry.vno == (kvno & 0xff)) {
++            if (new_entry.vno == (kvno & 0xff) || new_entry.vno == IGNORE_VNO) {
+                 krb5_kt_free_entry(context, &cur_entry);
+                 cur_entry = new_entry;
+                 break;
diff --git a/krb5/patches/krb5-tex-pdf.sh b/krb5/patches/krb5-tex-pdf.sh
new file mode 100644 (file)
index 0000000..ed72d2b
--- /dev/null
@@ -0,0 +1,55 @@
+#!/bin/sh
+
+# Based on Enrico's snippet for using pdflatex for building PDFs, except we're
+# switching to pregenerating the docs for the SRPM so that we don't get
+# different contents when we build on multiple build machines and architectures
+# (timestamps and IDs change, and even some of the compressed content looks
+# different).  The filename and checksum are used to verify that the PDF always
+# matches the doc which was used to generate it, and we flag an error if that
+# isn't the case.
+
+create() {
+       pushd "$1" > /dev/null
+       touch "$2".ind
+       pdflatex "$2"
+       test ! -e "$2".idx || makeindex ${3:+-s "$3".ist} "$2".idx
+       pdflatex "$2"
+       pdflatex "$2"
+       sum=`sha1sum "$2".tex | sed 's,[[:blank:]].*,,g'`
+       sed -ri \
+               -e 's|^/ID \[<.{32}> <.{32}>\]|/ID [<'"$1/$2"'> <'"$sum"'>]|g' \
+               "$2".pdf
+       popd > /dev/null
+}
+
+check() {
+       pushd "$1" > /dev/null
+       sum=`sha1sum "$2".tex | sed 's, .*,,g'`
+       id=`sed -rn -e '/^\/ID \[<[^>]*> <[^>]*>\]/p' "$2".pdf`
+       filename=`echo "$id" | sed -r 's|^.*\[<([^>]*)> <([^>]*)>\].*|\1|g'`
+       checksum=`echo "$id" | sed -r 's|^.*\[<([^>]*)> <([^>]*)>\].*|\2|g'`
+       echo $filename
+       echo $checksum $sum
+       popd > /dev/null
+       test "$filename" = "$1/$2" && test "$checksum" = "$sum"
+}
+
+mode=$1
+case $mode in
+       create)
+       while read subdir doc style ; do
+               if ! create $subdir $doc $style ; then
+                       exit 1
+               fi
+       done
+       ;;
+       check)
+       while read subdir doc style ; do
+               if ! check $subdir $doc $style ; then
+                       exit 1
+               fi
+       done
+       ;;
+esac
+
+exit 0
diff --git a/krb5/patches/krb5-trunk-7046.patch b/krb5/patches/krb5-trunk-7046.patch
new file mode 100644 (file)
index 0000000..7db7ef5
--- /dev/null
@@ -0,0 +1,301 @@
+commit 9dc75551cb8cc4c03f7e0fe5e8a705ed678079f4
+Author: ghudson <ghudson@dc483132-0cff-0310-8789-dd5450dbe970>
+Date:   Wed Dec 7 19:38:13 2011 +0000
+
+    ticket: 7046
+    subject: Allow S4U2Proxy delegated credentials to be saved
+    
+    The initial implementation of client-side S4U2Proxy support did not
+    allow delegated proxy credentials to be stored (gss_store_cred would
+    error out, and gss_krb5_copy_ccache would generate a non-working
+    cache).  To make this work, we save the impersonator name in a cache
+    config variable and in a cred structure field (replacing the
+    proxy_cred flag), and make the default principal of the proxy cache
+    the subject principal as the caller would expect for a regular
+    delegated cred.
+    
+    git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25529 dc483132-0cff-0310-8789-dd5450dbe970
+
+diff --git a/src/include/k5-int.h b/src/include/k5-int.h
+index 514e2ea..b25c159 100644
+--- a/src/include/k5-int.h
++++ b/src/include/k5-int.h
+@@ -273,7 +273,10 @@ typedef INT64_TYPE krb5_int64;
+ #define KRB5_CONF_V4_INSTANCE_CONVERT         "v4_instance_convert"
+ #define KRB5_CONF_V4_REALM                    "v4_realm"
+ #define KRB5_CONF_ASTERISK                    "*"
++
++/* Cache configuration variables */
+ #define KRB5_CONF_FAST_AVAIL                  "fast_avail"
++#define KRB5_CONF_PROXY_IMPERSONATOR          "proxy_impersonator"
+ /* Error codes used in KRB_ERROR protocol messages.
+    Return values of library routines are based on a different error table
+diff --git a/src/lib/gssapi/krb5/acquire_cred.c b/src/lib/gssapi/krb5/acquire_cred.c
+index c815b35..c08e059 100644
+--- a/src/lib/gssapi/krb5/acquire_cred.c
++++ b/src/lib/gssapi/krb5/acquire_cred.c
+@@ -417,6 +417,34 @@ prep_ccache(krb5_context context, krb5_gss_cred_id_rec *cred,
+     return 0;
+ }
++/* If an impersonator config entry exists in ccache, set *impersonator_out to
++ * the parsed principal.  Otherwise set *impersonator_out to NULL. */
++static krb5_error_code
++get_impersonator(krb5_context context, krb5_ccache ccache,
++                 krb5_principal *impersonator_out)
++{
++    krb5_error_code code;
++    krb5_data data = empty_data(), data0 = empty_data();
++
++    *impersonator_out = NULL;
++
++    code = krb5_cc_get_config(context, ccache, NULL,
++                              KRB5_CONF_PROXY_IMPERSONATOR, &data);
++    if (code)
++        return (code == KRB5_CC_NOTFOUND) ? 0 : code;
++
++    code = krb5int_copy_data_contents_add0(context, &data, &data0);
++    if (code)
++        goto cleanup;
++
++    code = krb5_parse_name(context, data0.data, impersonator_out);
++
++cleanup:
++    krb5_free_data_contents(context, &data);
++    krb5_free_data_contents(context, &data0);
++    return code;
++}
++
+ /* Check ccache and scan it for its expiry time.  On success, cred takes
+  * ownership of ccache. */
+ static krb5_error_code
+@@ -493,6 +521,10 @@ scan_ccache(krb5_context context, krb5_gss_cred_id_rec *cred,
+         goto cleanup;
+     }
++    code = get_impersonator(context, ccache, &cred->impersonator);
++    if (code)
++        goto cleanup;
++
+     (void)krb5_cc_set_flags(context, ccache, KRB5_TC_OPENCLOSE);
+     cred->ccache = ccache;
+@@ -622,6 +654,7 @@ acquire_cred(OM_uint32 *minor_status,
+     cred->usage = args->cred_usage;
+     cred->name = NULL;
++    cred->impersonator = NULL;
+     cred->iakerb_mech = args->iakerb;
+     cred->default_identity = (name == NULL);
+ #ifndef LEAN_CLIENT
+diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h
+index 016a2e6..6b7d530 100644
+--- a/src/lib/gssapi/krb5/gssapiP_krb5.h
++++ b/src/lib/gssapi/krb5/gssapiP_krb5.h
+@@ -172,7 +172,7 @@ typedef struct _krb5_gss_cred_id_rec {
+     /* name/type of credential */
+     gss_cred_usage_t usage;
+     krb5_gss_name_t name;
+-    unsigned int proxy_cred : 1;
++    krb5_principal impersonator;
+     unsigned int default_identity : 1;
+     unsigned int iakerb_mech : 1;
+     unsigned int destroy_ccache : 1;
+diff --git a/src/lib/gssapi/krb5/init_sec_context.c b/src/lib/gssapi/krb5/init_sec_context.c
+index 1b8120c..d7b9ffa 100644
+--- a/src/lib/gssapi/krb5/init_sec_context.c
++++ b/src/lib/gssapi/krb5/init_sec_context.c
+@@ -129,7 +129,6 @@ static krb5_error_code get_credentials(context, cred, server, now,
+     krb5_error_code     code;
+     krb5_creds          in_creds, evidence_creds, *result_creds = NULL;
+     krb5_flags          flags = 0;
+-    krb5_principal      cc_princ = NULL;
+     *out_creds = NULL;
+@@ -140,16 +139,13 @@ static krb5_error_code get_credentials(context, cred, server, now,
+     assert(cred->name != NULL);
+-    if ((code = krb5_cc_get_principal(context, cred->ccache, &cc_princ)))
+-        goto cleanup;
+-
+     /*
+      * Do constrained delegation if we have proxy credentials and
+      * we're not trying to get a ticket to ourselves (in which case
+      * we can just use the S4U2Self or evidence ticket directly).
+      */
+-    if (cred->proxy_cred &&
+-        !krb5_principal_compare(context, cc_princ, server->princ)) {
++    if (cred->impersonator &&
++        !krb5_principal_compare(context, cred->impersonator, server->princ)) {
+         krb5_creds mcreds;
+         flags |= KRB5_GC_CANONICALIZE |
+@@ -159,20 +155,18 @@ static krb5_error_code get_credentials(context, cred, server, now,
+         memset(&mcreds, 0, sizeof(mcreds));
+         mcreds.magic = KV5M_CREDS;
+-        mcreds.times.endtime = cred->tgt_expire;
+-        mcreds.server = cc_princ;
++        mcreds.server = cred->impersonator;
+         mcreds.client = cred->name->princ;
+         code = krb5_cc_retrieve_cred(context, cred->ccache,
+-                                     KRB5_TC_MATCH_TIMES | KRB5_TC_MATCH_AUTHDATA,
+-                                     &mcreds,
++                                     KRB5_TC_MATCH_AUTHDATA, &mcreds,
+                                      &evidence_creds);
+         if (code)
+             goto cleanup;
+         assert(evidence_creds.ticket_flags & TKT_FLG_FORWARDABLE);
+-        in_creds.client = cc_princ;
++        in_creds.client = cred->impersonator;
+         in_creds.second_ticket = evidence_creds.ticket;
+     } else {
+         in_creds.client = cred->name->princ;
+@@ -255,7 +249,6 @@ static krb5_error_code get_credentials(context, cred, server, now,
+ cleanup:
+     krb5_free_authdata(context, in_creds.authdata);
+-    krb5_free_principal(context, cc_princ);
+     krb5_free_cred_contents(context, &evidence_creds);
+     krb5_free_creds(context, result_creds);
+diff --git a/src/lib/gssapi/krb5/rel_cred.c b/src/lib/gssapi/krb5/rel_cred.c
+index 5b2ea2f..4fd3694 100644
+--- a/src/lib/gssapi/krb5/rel_cred.c
++++ b/src/lib/gssapi/krb5/rel_cred.c
+@@ -71,6 +71,8 @@ krb5_gss_release_cred(minor_status, cred_handle)
+     if (cred->name)
+         kg_release_name(context, &cred->name);
++    krb5_free_principal(context, cred->impersonator);
++
+     if (cred->req_enctypes)
+         free(cred->req_enctypes);
+diff --git a/src/lib/gssapi/krb5/s4u_gss_glue.c b/src/lib/gssapi/krb5/s4u_gss_glue.c
+index 4ac2ce3..4b37c5a 100644
+--- a/src/lib/gssapi/krb5/s4u_gss_glue.c
++++ b/src/lib/gssapi/krb5/s4u_gss_glue.c
+@@ -169,6 +169,39 @@ krb5_gss_acquire_cred_impersonate_name(OM_uint32 *minor_status,
+ }
++/*
++ * Set up cred to be an S4U2Proxy credential by copying in the impersonator's
++ * creds, setting a cache config variable with the impersonator principal name,
++ * and saving the impersonator principal name in the cred structure.
++ */
++static krb5_error_code
++make_proxy_cred(krb5_context context, krb5_gss_cred_id_t cred,
++                krb5_gss_cred_id_t impersonator_cred)
++{
++    krb5_error_code code;
++    krb5_data data;
++    char *str;
++
++    code = krb5_cc_copy_creds(context, impersonator_cred->ccache,
++                              cred->ccache);
++    if (code)
++        return code;
++
++    code = krb5_unparse_name(context, impersonator_cred->name->princ, &str);
++    if (code)
++        return code;
++
++    data = string2data(str);
++    code = krb5_cc_set_config(context, cred->ccache, NULL,
++                              KRB5_CONF_PROXY_IMPERSONATOR, &data);
++    krb5_free_unparsed_name(context, str);
++    if (code)
++        return code;
++
++    return krb5_copy_principal(context, impersonator_cred->name->princ,
++                               &cred->impersonator);
++}
++
+ OM_uint32
+ kg_compose_deleg_cred(OM_uint32 *minor_status,
+                       krb5_gss_cred_id_t impersonator_cred,
+@@ -187,7 +220,7 @@ kg_compose_deleg_cred(OM_uint32 *minor_status,
+     if (!kg_is_initiator_cred(impersonator_cred) ||
+         impersonator_cred->name == NULL ||
+-        impersonator_cred->proxy_cred) {
++        impersonator_cred->impersonator != NULL) {
+         code = G_BAD_USAGE;
+         goto cleanup;
+     }
+@@ -208,14 +241,7 @@ kg_compose_deleg_cred(OM_uint32 *minor_status,
+     if (code != 0)
+         goto cleanup;
+-    /*
+-     * Only return a "proxy" credential for use with constrained
+-     * delegation if the subject credentials are forwardable.
+-     * Submitting non-forwardable credentials to the KDC for use
+-     * with constrained delegation will only return an error.
+-     */
+     cred->usage = GSS_C_INITIATE;
+-    cred->proxy_cred = !!(subject_creds->ticket_flags & TKT_FLG_FORWARDABLE);
+     cred->tgt_expire = subject_creds->times.endtime;
+@@ -229,16 +255,18 @@ kg_compose_deleg_cred(OM_uint32 *minor_status,
+         goto cleanup;
+     cred->destroy_ccache = 1;
+-    code = krb5_cc_initialize(context, cred->ccache,
+-                              cred->proxy_cred ? impersonator_cred->name->princ :
+-                              subject_creds->client);
++    code = krb5_cc_initialize(context, cred->ccache, subject_creds->client);
+     if (code != 0)
+         goto cleanup;
+-    if (cred->proxy_cred) {
+-        /* Impersonator's TGT will be necessary for S4U2Proxy */
+-        code = krb5_cc_copy_creds(context, impersonator_cred->ccache,
+-                                  cred->ccache);
++    /*
++     * Only return a "proxy" credential for use with constrained
++     * delegation if the subject credentials are forwardable.
++     * Submitting non-forwardable credentials to the KDC for use
++     * with constrained delegation will only return an error.
++     */
++    if (subject_creds->ticket_flags & TKT_FLG_FORWARDABLE) {
++        code = make_proxy_cred(context, cred, impersonator_cred);
+         if (code != 0)
+             goto cleanup;
+     }
+diff --git a/src/lib/gssapi/krb5/store_cred.c b/src/lib/gssapi/krb5/store_cred.c
+index bff3cde..d587589 100644
+--- a/src/lib/gssapi/krb5/store_cred.c
++++ b/src/lib/gssapi/krb5/store_cred.c
+@@ -91,7 +91,7 @@ copy_initiator_creds(OM_uint32 *minor_status,
+     kcred = (krb5_gss_cred_id_t)input_cred_handle;
+-    if (kcred->ccache == NULL || kcred->proxy_cred) {
++    if (kcred->ccache == NULL) {
+         *minor_status = KG_CCACHE_NOMATCH;
+         major_status = GSS_S_DEFECTIVE_CREDENTIAL;
+         goto cleanup;
+diff --git a/src/lib/gssapi/krb5/val_cred.c b/src/lib/gssapi/krb5/val_cred.c
+index e87f249..46a9ae1 100644
+--- a/src/lib/gssapi/krb5/val_cred.c
++++ b/src/lib/gssapi/krb5/val_cred.c
+@@ -50,8 +50,7 @@ krb5_gss_validate_cred_1(OM_uint32 *minor_status, gss_cred_id_t cred_handle,
+             *minor_status = code;
+             return(GSS_S_DEFECTIVE_CREDENTIAL);
+         }
+-        if (!cred->proxy_cred &&
+-            !krb5_principal_compare(context, princ, cred->name->princ)) {
++        if (!krb5_principal_compare(context, princ, cred->name->princ)) {
+             k5_mutex_unlock(&cred->lock);
+             *minor_status = KG_CCACHE_NOMATCH;
+             return(GSS_S_DEFECTIVE_CREDENTIAL);
diff --git a/krb5/patches/krb5-trunk-7047.patch b/krb5/patches/krb5-trunk-7047.patch
new file mode 100644 (file)
index 0000000..381449b
--- /dev/null
@@ -0,0 +1,28 @@
+commit 59a8a0861d5aacd4e985ad4dc4d46a11c2ebc136
+Author: ghudson <ghudson@dc483132-0cff-0310-8789-dd5450dbe970>
+Date:   Wed Dec 7 19:38:22 2011 +0000
+
+    ticket: 7047
+    subject: Allow S4U2Proxy service tickets to be cached
+    
+    Previous to this change, the GSS code avoids caching S4U2Proxy results
+    for fear of the memory cache growing without bound, but that seems
+    unlikely to be a serious problem.  Allow these to be cached.
+    
+    git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25530 dc483132-0cff-0310-8789-dd5450dbe970
+
+diff --git a/src/lib/gssapi/krb5/init_sec_context.c b/src/lib/gssapi/krb5/init_sec_context.c
+index d7b9ffa..07baefa 100644
+--- a/src/lib/gssapi/krb5/init_sec_context.c
++++ b/src/lib/gssapi/krb5/init_sec_context.c
+@@ -148,9 +148,7 @@ static krb5_error_code get_credentials(context, cred, server, now,
+         !krb5_principal_compare(context, cred->impersonator, server->princ)) {
+         krb5_creds mcreds;
+-        flags |= KRB5_GC_CANONICALIZE |
+-            KRB5_GC_NO_STORE |
+-            KRB5_GC_CONSTRAINED_DELEGATION;
++        flags |= KRB5_GC_CANONICALIZE | KRB5_GC_CONSTRAINED_DELEGATION;
+         memset(&mcreds, 0, sizeof(mcreds));
diff --git a/krb5/patches/krb5-trunk-7048.patch b/krb5/patches/krb5-trunk-7048.patch
new file mode 100644 (file)
index 0000000..0399565
--- /dev/null
@@ -0,0 +1,78 @@
+commit 1c2f5144de0f15f7d9c8659a71adc10c2755b57e
+Author: ghudson <ghudson@dc483132-0cff-0310-8789-dd5450dbe970>
+Date:   Wed Dec 7 19:38:32 2011 +0000
+
+    ticket: 7048
+    subject: Allow null server key to krb5_pac_verify
+    
+    When the KDC verifies a PAC, it doesn't really need to check the
+    server signature, since it can't trust that anyway.  Allow the caller
+    to pass only a TGT key.
+    
+    git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25532 dc483132-0cff-0310-8789-dd5450dbe970
+
+diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
+index f3d0225..83c2dc7 100644
+--- a/src/include/krb5/krb5.hin
++++ b/src/include/krb5/krb5.hin
+@@ -7506,13 +7506,13 @@ krb5_pac_parse(krb5_context context, const void *ptr, size_t len,
+  * @param [in] pac              PAC handle
+  * @param [in] authtime         Expected timestamp
+  * @param [in] principal        Expected principal name (or NULL)
+- * @param [in] server           Key to validate server checksum
++ * @param [in] server           Key to validate server checksum (or NULL)
+  * @param [in] privsvr          Key to validate KDC checksum (or NULL)
+  *
+  * This function validates @a pac against the supplied @a server, @a privsvr,
+  * @a principal and @a authtime.  If @a principal is NULL, the principal and
+- * authtime are not verified.  If @a privsvr is NULL, the KDC checksum is not
+- * verified.
++ * authtime are not verified.  If @a server or @a privsvr is NULL, the
++ * corresponding checksum is not verified.
+  *
+  * If successful, @a pac is marked as verified.
+  *
+diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c
+index f173b04..23aa930 100644
+--- a/src/lib/krb5/krb/pac.c
++++ b/src/lib/krb5/krb/pac.c
+@@ -637,9 +637,11 @@ krb5_pac_verify(krb5_context context,
+     if (server == NULL)
+         return EINVAL;
+-    ret = k5_pac_verify_server_checksum(context, pac, server);
+-    if (ret != 0)
+-        return ret;
++    if (server != NULL) {
++        ret = k5_pac_verify_server_checksum(context, pac, server);
++        if (ret != 0)
++            return ret;
++    }
+     if (privsvr != NULL) {
+         ret = k5_pac_verify_kdc_checksum(context, pac, privsvr);
+
+commit e31486a84380647e49ba6199a3e10ac739fa1a45
+Author: ghudson <ghudson@dc483132-0cff-0310-8789-dd5450dbe970>
+Date:   Thu Dec 8 04:21:23 2011 +0000
+
+    ticket: 7048
+    
+    Actually allow null server key in krb5_pac_verify
+    
+    git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25534 dc483132-0cff-0310-8789-dd5450dbe970
+
+diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c
+index 23aa930..3262d21 100644
+--- a/src/lib/krb5/krb/pac.c
++++ b/src/lib/krb5/krb/pac.c
+@@ -634,9 +634,6 @@ krb5_pac_verify(krb5_context context,
+ {
+     krb5_error_code ret;
+-    if (server == NULL)
+-        return EINVAL;
+-
+     if (server != NULL) {
+         ret = k5_pac_verify_server_checksum(context, pac, server);
+         if (ret != 0)
diff --git a/krb5/patches/krb5-trunk-pkinit-anchorsign.patch b/krb5/patches/krb5-trunk-pkinit-anchorsign.patch
new file mode 100644 (file)
index 0000000..508bb5b
--- /dev/null
@@ -0,0 +1,40 @@
+commit db83abc7dcfe369bd4467c78eebb7028ba0c0e0d
+Author: Greg Hudson <ghudson@mit.edu>
+Date:   Thu Jun 21 17:20:29 2012 -0400
+
+    Handle PKINIT DH replies with no certs
+    
+    If a PKINIT Diffie-Hellman reply contains no certificates in the
+    SignedData object, that may be because the signer certificate was a
+    trust anchor as transmitted to the KDC.  Heimdal's KDC, for instance,
+    filters client trust anchors out of the returned set of certificates.
+    Match against idctx->trustedCAs and idctx->intermediateCAs to handle
+    this case.  This fix only works with OpenSSL 1.0 or later; when built
+    against OpenSSL 0.9.x, the client will still require a cert in the
+    reply.
+    
+    Code changes suggested by nalin@redhat.com.
+    
+    ticket: 7183
+
+diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+index 0136d4f..7120ecf 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+@@ -1398,8 +1398,15 @@ cms_signeddata_verify(krb5_context context,
+         X509_STORE_set_verify_cb_func(store, openssl_callback_ignore_crls);
+     X509_STORE_set_flags(store, vflags);
+-    /* get the signer's information from the CMS message */
++    /*
++     * Get the signer's information from the CMS message.  Match signer ID
++     * against anchors and intermediate CAs in case no certs are present in the
++     * SignedData.  If we start sending kdcPkId values in requests, we'll need
++     * to match against the source of that information too.
++     */
+     CMS_set1_signers_certs(cms, NULL, 0);
++    CMS_set1_signers_certs(cms, idctx->trustedCAs, CMS_NOINTERN);
++    CMS_set1_signers_certs(cms, idctx->intermediateCAs, CMS_NOINTERN);
+     if (((si_sk = CMS_get0_SignerInfos(cms)) == NULL) ||
+         ((si = sk_CMS_SignerInfo_value(si_sk, 0)) == NULL)) {
+         /* Not actually signed; anonymous case */
diff --git a/krb5/systemd/kadmin.service b/krb5/systemd/kadmin.service
new file mode 100644 (file)
index 0000000..7775ea7
--- /dev/null
@@ -0,0 +1,14 @@
+[Unit]
+Description=Kerberos 5 Password-changing and Administration
+After=syslog.target network.target
+ConditionPathExists=!/var/kerberos/krb5kdc/kpropd.acl
+
+[Service]
+Type=forking
+PIDFile=/var/run/kadmind.pid
+EnvironmentFile=-/etc/sysconfig/kadmin
+ExecStart=/usr/sbin/kadmind -P /var/run/kadmind.pid $KADMIND_ARGS
+ExecReload=/bin/kill -HUP $MAINPID
+
+[Install]
+WantedBy=multi-user.target
diff --git a/krb5/systemd/kprop.service b/krb5/systemd/kprop.service
new file mode 100644 (file)
index 0000000..99ba129
--- /dev/null
@@ -0,0 +1,11 @@
+[Unit]
+Description=Kerberos 5 Propagation
+After=syslog.target network.target
+ConditionPathExists=/var/kerberos/krb5kdc/kpropd.acl
+
+[Service]
+Type=forking
+ExecStart=/usr/sbin/kpropd -S
+
+[Install]
+WantedBy=multi-user.target
diff --git a/krb5/systemd/krb5kdc.service b/krb5/systemd/krb5kdc.service
new file mode 100644 (file)
index 0000000..bc49204
--- /dev/null
@@ -0,0 +1,13 @@
+[Unit]
+Description=Kerberos 5 KDC
+After=syslog.target network.target
+
+[Service]
+Type=forking
+PIDFile=/var/run/krb5kdc.pid
+EnvironmentFile=-/etc/sysconfig/krb5kdc
+ExecStart=/usr/sbin/krb5kdc -P /var/run/krb5kdc.pid $KRB5KDC_ARGS
+ExecReload=/bin/kill -HUP $MAINPID
+
+[Install]
+WantedBy=multi-user.target