import krb5-1.20.1-8.el9

c9 imports/c9/krb5-1.20.1-8.el9
CentOS Sources 2 years ago committed by MSVSphere Packaging Team
parent 411d6909de
commit c05990a433

2
.gitignore vendored

@ -1 +1 @@
SOURCES/krb5-1.19.1.tar.gz
SOURCES/krb5-1.20.1.tar.gz

@ -1 +1 @@
65fcedf85595457652cc0d37df65c9258e783d6b SOURCES/krb5-1.19.1.tar.gz
06278439a6cd5a2aa861d8e877451b794487534b SOURCES/krb5-1.20.1.tar.gz

@ -1,4 +1,4 @@
From 90ba715be48c2e1b6c7ca53cb1d75f3af2c388d6 Mon Sep 17 00:00:00 2001
From 37d69135d0be7f46732c401cdbb3abc075bf4117 Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Tue, 23 Aug 2016 16:29:58 -0400
Subject: [PATCH] [downstream] ksu pam integration
@ -30,10 +30,10 @@ Last-updated: krb5-1.18-beta1
create mode 100644 src/clients/ksu/pam.h
diff --git a/src/aclocal.m4 b/src/aclocal.m4
index 024d6370c..ca9fcf664 100644
index 9920476f91..bf9da35bbc 100644
--- a/src/aclocal.m4
+++ b/src/aclocal.m4
@@ -1677,3 +1677,72 @@ if test "$with_ldap" = yes; then
@@ -1458,3 +1458,72 @@ if test "$with_ldap" = yes; then
OPENLDAP_PLUGIN=yes
fi
])dnl
@ -107,7 +107,7 @@ index 024d6370c..ca9fcf664 100644
+])dnl
+
diff --git a/src/clients/ksu/Makefile.in b/src/clients/ksu/Makefile.in
index 8b4edce4d..9d58f29b5 100644
index 8b4edce4d8..9d58f29b5d 100644
--- a/src/clients/ksu/Makefile.in
+++ b/src/clients/ksu/Makefile.in
@@ -3,12 +3,14 @@ BUILDTOP=$(REL)..$(S)..
@ -145,7 +145,7 @@ index 8b4edce4d..9d58f29b5 100644
clean:
$(RM) ksu
diff --git a/src/clients/ksu/main.c b/src/clients/ksu/main.c
index af1286172..931f05404 100644
index af12861729..931f054041 100644
--- a/src/clients/ksu/main.c
+++ b/src/clients/ksu/main.c
@@ -26,6 +26,7 @@
@ -303,7 +303,7 @@ index af1286172..931f05404 100644
}
diff --git a/src/clients/ksu/pam.c b/src/clients/ksu/pam.c
new file mode 100644
index 000000000..cbfe48704
index 0000000000..cbfe487047
--- /dev/null
+++ b/src/clients/ksu/pam.c
@@ -0,0 +1,389 @@
@ -698,7 +698,7 @@ index 000000000..cbfe48704
+#endif
diff --git a/src/clients/ksu/pam.h b/src/clients/ksu/pam.h
new file mode 100644
index 000000000..0ab76569c
index 0000000000..0ab76569cb
--- /dev/null
+++ b/src/clients/ksu/pam.h
@@ -0,0 +1,57 @@
@ -760,10 +760,10 @@ index 000000000..0ab76569c
+void appl_pam_cleanup(void);
+#endif
diff --git a/src/configure.ac b/src/configure.ac
index 4eb080784..693f76a81 100644
index f03028b5fd..aa970b0447 100644
--- a/src/configure.ac
+++ b/src/configure.ac
@@ -1389,6 +1389,8 @@ AC_SUBST([VERTO_VERSION])
@@ -1400,6 +1400,8 @@ AC_SUBST([VERTO_VERSION])
AC_PATH_PROG(GROFF, groff)
@ -772,3 +772,6 @@ index 4eb080784..693f76a81 100644
# Make localedir work in autoconf 2.5x.
if test "${localedir+set}" != set; then
localedir='$(datadir)/locale'
--
2.38.1

@ -1,4 +1,4 @@
From e787771b618a344d45ac515927e914602f48946f Mon Sep 17 00:00:00 2001
From c6b58ed180ed91b579d322ff5004f68750f1eb4f Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Tue, 23 Aug 2016 16:30:53 -0400
Subject: [PATCH] [downstream] SELinux integration
@ -36,7 +36,9 @@ 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.
Last-updated: krb5-1.18-beta1
Last-updated: krb5-1.20.1
[jrische@redhat.com: Replace deprecated security_context_t by char *:
- src/util/support/selinux.c]
---
src/aclocal.m4 | 48 +++
src/build-tools/krb5-config.in | 3 +-
@ -61,13 +63,13 @@ Last-updated: krb5-1.18-beta1
.../kdb/ldap/ldap_util/kdb5_ldap_services.c | 11 +-
src/util/profile/prof_file.c | 3 +-
src/util/support/Makefile.in | 3 +-
src/util/support/selinux.c | 406 ++++++++++++++++++
24 files changed, 573 insertions(+), 21 deletions(-)
src/util/support/selinux.c | 405 ++++++++++++++++++
24 files changed, 572 insertions(+), 21 deletions(-)
create mode 100644 src/include/k5-label.h
create mode 100644 src/util/support/selinux.c
diff --git a/src/aclocal.m4 b/src/aclocal.m4
index ca9fcf664..5afb96e58 100644
index bf9da35bbc..01283f482e 100644
--- a/src/aclocal.m4
+++ b/src/aclocal.m4
@@ -85,6 +85,7 @@ AC_SUBST_FILE(libnodeps_frag)
@ -78,7 +80,7 @@ index ca9fcf664..5afb96e58 100644
KRB5_LIB_PARAMS
KRB5_AC_INITFINI
KRB5_AC_ENABLE_THREADS
@@ -1745,4 +1746,51 @@ AC_SUBST(PAM_LIBS)
@@ -1526,4 +1527,51 @@ AC_SUBST(PAM_LIBS)
AC_SUBST(PAM_MAN)
AC_SUBST(NON_PAM_MAN)
])dnl
@ -131,7 +133,7 @@ index ca9fcf664..5afb96e58 100644
+AC_SUBST(SELINUX_LIBS)
+])dnl
diff --git a/src/build-tools/krb5-config.in b/src/build-tools/krb5-config.in
index dead0dddc..fef3e054f 100755
index dead0dddce..fef3e054fc 100755
--- a/src/build-tools/krb5-config.in
+++ b/src/build-tools/krb5-config.in
@@ -41,6 +41,7 @@ DL_LIB='@DL_LIB@'
@ -152,7 +154,7 @@ index dead0dddc..fef3e054f 100755
echo $lib_flags
diff --git a/src/config/pre.in b/src/config/pre.in
index 3752174c7..0d2068575 100644
index a0c60c70b3..7eaa2f351c 100644
--- a/src/config/pre.in
+++ b/src/config/pre.in
@@ -177,6 +177,7 @@ LD = $(PURE) @LD@
@ -163,7 +165,7 @@ index 3752174c7..0d2068575 100644
INSTALL=@INSTALL@
INSTALL_STRIP=
@@ -403,7 +404,7 @@ SUPPORT_LIB = -l$(SUPPORT_LIBNAME)
@@ -379,7 +380,7 @@ SUPPORT_LIB = -l$(SUPPORT_LIBNAME)
# HESIOD_LIBS is -lhesiod...
HESIOD_LIBS = @HESIOD_LIBS@
@ -173,10 +175,10 @@ index 3752174c7..0d2068575 100644
GSS_LIBS = $(GSS_KRB5_LIB)
# needs fixing if ever used on macOS!
diff --git a/src/configure.ac b/src/configure.ac
index 693f76a81..dd2cad3ee 100644
index aa970b0447..40545f2bfc 100644
--- a/src/configure.ac
+++ b/src/configure.ac
@@ -1391,6 +1391,8 @@ AC_PATH_PROG(GROFF, groff)
@@ -1402,6 +1402,8 @@ AC_PATH_PROG(GROFF, groff)
KRB5_WITH_PAM
@ -186,7 +188,7 @@ index 693f76a81..dd2cad3ee 100644
if test "${localedir+set}" != set; then
localedir='$(datadir)/locale'
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index cf524252f..efb523689 100644
index 44dc1eeb3f..c3aecba7d4 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -128,6 +128,7 @@ typedef unsigned char u_char;
@ -199,7 +201,7 @@ index cf524252f..efb523689 100644
#define KRB5_KDB_MAX_RLIFE (60*60*24*7) /* one week */
diff --git a/src/include/k5-label.h b/src/include/k5-label.h
new file mode 100644
index 000000000..dfaaa847c
index 0000000000..dfaaa847cb
--- /dev/null
+++ b/src/include/k5-label.h
@@ -0,0 +1,32 @@
@ -236,7 +238,7 @@ index 000000000..dfaaa847c
+#endif
+#endif
diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
index 045334a08..db80063eb 100644
index c0194c3c94..7e1dea2cbf 100644
--- a/src/include/krb5/krb5.hin
+++ b/src/include/krb5/krb5.hin
@@ -87,6 +87,12 @@
@ -253,7 +255,7 @@ index 045334a08..db80063eb 100644
#include <stdlib.h>
diff --git a/src/kadmin/dbutil/dump.c b/src/kadmin/dbutil/dump.c
index 634ba4a8b..cea7939f4 100644
index a89b5144f6..4d6cc0bdf9 100644
--- a/src/kadmin/dbutil/dump.c
+++ b/src/kadmin/dbutil/dump.c
@@ -148,12 +148,21 @@ create_ofile(char *ofile, char **tmpname)
@ -288,10 +290,10 @@ index 634ba4a8b..cea7939f4 100644
com_err(progname, errno, _("while creating 'ok' file, '%s'"), file_ok);
goto cleanup;
diff --git a/src/kdc/main.c b/src/kdc/main.c
index 3be6dcb07..24d441e16 100644
index 38b9299066..085afc9220 100644
--- a/src/kdc/main.c
+++ b/src/kdc/main.c
@@ -872,7 +872,7 @@ write_pid_file(const char *path)
@@ -848,7 +848,7 @@ write_pid_file(const char *path)
FILE *file;
unsigned long pid;
@ -301,10 +303,10 @@ index 3be6dcb07..24d441e16 100644
return errno;
pid = (unsigned long) getpid();
diff --git a/src/kprop/kpropd.c b/src/kprop/kpropd.c
index 498ca599a..c6b8efc28 100644
index f2341d720f..ffdac9f397 100644
--- a/src/kprop/kpropd.c
+++ b/src/kprop/kpropd.c
@@ -487,6 +487,9 @@ doit(int fd)
@@ -488,6 +488,9 @@ doit(int fd)
krb5_enctype etype;
int database_fd;
char host[INET6_ADDRSTRLEN + 1];
@ -314,7 +316,7 @@ index 498ca599a..c6b8efc28 100644
signal_wrapper(SIGALRM, alarm_handler);
alarm(params.iprop_resync_timeout);
@@ -542,9 +545,15 @@ doit(int fd)
@@ -543,9 +546,15 @@ doit(int fd)
free(name);
exit(1);
}
@ -331,7 +333,7 @@ index 498ca599a..c6b8efc28 100644
KRB5_LOCKMODE_EXCLUSIVE | KRB5_LOCKMODE_DONTBLOCK);
if (retval) {
diff --git a/src/lib/kadm5/logger.c b/src/lib/kadm5/logger.c
index c6885edf2..9aec3c05e 100644
index c6885edf2a..9aec3c05e8 100644
--- a/src/lib/kadm5/logger.c
+++ b/src/lib/kadm5/logger.c
@@ -309,7 +309,7 @@ krb5_klog_init(krb5_context kcontext, char *ename, char *whoami, krb5_boolean do
@ -353,7 +355,7 @@ index c6885edf2..9aec3c05e 100644
set_cloexec_file(f);
log_control.log_entries[lindex].lfu_filep = f;
diff --git a/src/lib/kdb/kdb_log.c b/src/lib/kdb/kdb_log.c
index 2659a2501..e9b95fce5 100644
index 2659a25018..e9b95fce59 100644
--- a/src/lib/kdb/kdb_log.c
+++ b/src/lib/kdb/kdb_log.c
@@ -480,7 +480,7 @@ ulog_map(krb5_context context, const char *logname, uint32_t ulogentries)
@ -366,7 +368,7 @@ index 2659a2501..e9b95fce5 100644
retval = errno;
goto cleanup;
diff --git a/src/lib/krb5/ccache/cc_dir.c b/src/lib/krb5/ccache/cc_dir.c
index 7b100a0ec..5683a0433 100644
index 1da40b51d0..f3ab7340a6 100644
--- a/src/lib/krb5/ccache/cc_dir.c
+++ b/src/lib/krb5/ccache/cc_dir.c
@@ -183,10 +183,19 @@ write_primary_file(const char *primary_path, const char *contents)
@ -416,7 +418,7 @@ index 7b100a0ec..5683a0433 100644
_("Credential cache directory %s does not exist"),
dirname);
diff --git a/src/lib/krb5/keytab/kt_file.c b/src/lib/krb5/keytab/kt_file.c
index e510211fc..f3ea28c8e 100644
index e510211fc5..f3ea28c8ec 100644
--- a/src/lib/krb5/keytab/kt_file.c
+++ b/src/lib/krb5/keytab/kt_file.c
@@ -735,14 +735,14 @@ krb5_ktfileint_open(krb5_context context, krb5_keytab id, int mode)
@ -437,10 +439,10 @@ index e510211fc..f3ea28c8e 100644
goto report_errno;
writevno = 1;
diff --git a/src/lib/krb5/os/trace.c b/src/lib/krb5/os/trace.c
index 7073459f0..e9b99f4ca 100644
index 3369fc4ba6..95f82cda03 100644
--- a/src/lib/krb5/os/trace.c
+++ b/src/lib/krb5/os/trace.c
@@ -458,7 +458,7 @@ krb5_set_trace_filename(krb5_context context, const char *filename)
@@ -459,7 +459,7 @@ krb5_set_trace_filename(krb5_context context, const char *filename)
fd = malloc(sizeof(*fd));
if (fd == NULL)
return ENOMEM;
@ -450,7 +452,7 @@ index 7073459f0..e9b99f4ca 100644
free(fd);
return errno;
diff --git a/src/plugins/kdb/db2/adb_openclose.c b/src/plugins/kdb/db2/adb_openclose.c
index 7db30a33b..2b9d01921 100644
index 7db30a33b0..2b9d01921d 100644
--- a/src/plugins/kdb/db2/adb_openclose.c
+++ b/src/plugins/kdb/db2/adb_openclose.c
@@ -152,7 +152,7 @@ osa_adb_init_db(osa_adb_db_t *dbp, char *filename, char *lockfilename,
@ -463,7 +465,7 @@ index 7db30a33b..2b9d01921 100644
* maybe someone took away write permission so we could only
* get shared locks?
diff --git a/src/plugins/kdb/db2/kdb_db2.c b/src/plugins/kdb/db2/kdb_db2.c
index 1a476b586..b40bb2240 100644
index 2c163d91cc..9a344a603e 100644
--- a/src/plugins/kdb/db2/kdb_db2.c
+++ b/src/plugins/kdb/db2/kdb_db2.c
@@ -694,8 +694,8 @@ ctx_create_db(krb5_context context, krb5_db2_context *dbc)
@ -478,7 +480,7 @@ index 1a476b586..b40bb2240 100644
retval = errno;
goto cleanup;
diff --git a/src/plugins/kdb/db2/libdb2/btree/bt_open.c b/src/plugins/kdb/db2/libdb2/btree/bt_open.c
index 2977b17f3..d5809a5a9 100644
index 2977b17f3a..d5809a5a93 100644
--- a/src/plugins/kdb/db2/libdb2/btree/bt_open.c
+++ b/src/plugins/kdb/db2/libdb2/btree/bt_open.c
@@ -60,6 +60,7 @@ static char sccsid[] = "@(#)bt_open.c 8.11 (Berkeley) 11/2/95";
@ -499,7 +501,7 @@ index 2977b17f3..d5809a5a9 100644
} else {
diff --git a/src/plugins/kdb/db2/libdb2/hash/hash.c b/src/plugins/kdb/db2/libdb2/hash/hash.c
index 862dbb164..686a960c9 100644
index 862dbb1640..686a960c96 100644
--- a/src/plugins/kdb/db2/libdb2/hash/hash.c
+++ b/src/plugins/kdb/db2/libdb2/hash/hash.c
@@ -51,6 +51,7 @@ static char sccsid[] = "@(#)hash.c 8.12 (Berkeley) 11/7/95";
@ -520,7 +522,7 @@ index 862dbb164..686a960c9 100644
(void)fcntl(hashp->fp, F_SETFD, 1);
}
diff --git a/src/plugins/kdb/db2/libdb2/recno/rec_open.c b/src/plugins/kdb/db2/libdb2/recno/rec_open.c
index d8b26e701..b0daa7c02 100644
index d8b26e7011..b0daa7c021 100644
--- a/src/plugins/kdb/db2/libdb2/recno/rec_open.c
+++ b/src/plugins/kdb/db2/libdb2/recno/rec_open.c
@@ -51,6 +51,7 @@ static char sccsid[] = "@(#)rec_open.c 8.12 (Berkeley) 11/18/94";
@ -542,7 +544,7 @@ index d8b26e701..b0daa7c02 100644
if (fname != NULL && fcntl(rfd, F_SETFD, 1) == -1) {
diff --git a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
index e87688d66..30f7c00ab 100644
index e87688d666..30f7c00ab5 100644
--- a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
@@ -190,7 +190,7 @@ kdb5_ldap_stash_service_password(int argc, char **argv)
@ -579,7 +581,7 @@ index e87688d66..30f7c00ab 100644
if (newfile == NULL) {
com_err(me, errno, _("Error creating file %s"), tmp_file);
diff --git a/src/util/profile/prof_file.c b/src/util/profile/prof_file.c
index aa951df05..79f9500f6 100644
index aa951df05f..79f9500f69 100644
--- a/src/util/profile/prof_file.c
+++ b/src/util/profile/prof_file.c
@@ -33,6 +33,7 @@
@ -600,7 +602,7 @@ index aa951df05..79f9500f6 100644
retval = errno;
if (retval == 0)
diff --git a/src/util/support/Makefile.in b/src/util/support/Makefile.in
index 86d5a950a..1052d53a1 100644
index 86d5a950a6..1052d53a1e 100644
--- a/src/util/support/Makefile.in
+++ b/src/util/support/Makefile.in
@@ -74,6 +74,7 @@ IPC_SYMS= \
@ -622,10 +624,10 @@ index 86d5a950a..1052d53a1 100644
diff --git a/src/util/support/selinux.c b/src/util/support/selinux.c
new file mode 100644
index 000000000..6d41f3244
index 0000000000..807d039da3
--- /dev/null
+++ b/src/util/support/selinux.c
@@ -0,0 +1,406 @@
@@ -0,0 +1,405 @@
+/*
+ * Copyright 2007,2008,2009,2011,2012,2013,2016 Red Hat, Inc. All Rights Reserved.
+ *
@ -724,17 +726,16 @@ index 000000000..6d41f3244
+ }
+}
+
+static security_context_t
+static char *
+push_fscreatecon(const char *pathname, mode_t mode)
+{
+ security_context_t previous, configuredsc, currentsc, derivedsc;
+ char *previous, *configuredsc, *currentsc, *genpath;
+ const char *derivedsc, *fullpath, *currentuser;
+ context_t current, derived;
+ const char *fullpath, *currentuser;
+ char *genpath;
+
+ previous = configuredsc = currentsc = derivedsc = NULL;
+ previous = configuredsc = currentsc = genpath = NULL;
+ derivedsc = NULL;
+ current = derived = NULL;
+ genpath = NULL;
+
+ fullpath = pathname;
+
@ -862,7 +863,7 @@ index 000000000..6d41f3244
+}
+
+static void
+pop_fscreatecon(security_context_t previous)
+pop_fscreatecon(char *previous)
+{
+ if (!is_selinux_enabled()) {
+ return;
@ -916,7 +917,7 @@ index 000000000..6d41f3244
+{
+ FILE *fp;
+ int errno_save;
+ security_context_t ctx;
+ char *ctx;
+
+ if ((strcmp(mode, "r") == 0) ||
+ (strcmp(mode, "rb") == 0)) {
@ -942,7 +943,7 @@ index 000000000..6d41f3244
+{
+ int fd;
+ int errno_save;
+ security_context_t ctx;
+ char *ctx;
+
+ k5_once(&labeled_once, label_mutex_init);
+ k5_mutex_lock(&labeled_mutex);
@ -963,7 +964,7 @@ index 000000000..6d41f3244
+{
+ int ret;
+ int errno_save;
+ security_context_t ctx;
+ char *ctx;
+
+ k5_once(&labeled_once, label_mutex_init);
+ k5_mutex_lock(&labeled_mutex);
@ -984,7 +985,7 @@ index 000000000..6d41f3244
+{
+ int ret;
+ int errno_save;
+ security_context_t ctx;
+ char *ctx;
+
+ k5_once(&labeled_once, label_mutex_init);
+ k5_mutex_lock(&labeled_mutex);
@ -1005,7 +1006,7 @@ index 000000000..6d41f3244
+{
+ int fd;
+ int errno_save;
+ security_context_t ctx;
+ char *ctx;
+ mode_t mode;
+ va_list ap;
+
@ -1032,3 +1033,6 @@ index 000000000..6d41f3244
+}
+
+#endif /* USE_SELINUX */
--
2.38.1

@ -1,4 +1,4 @@
From d5ea86ef491feb38f12e6aa53b7579ac02675df6 Mon Sep 17 00:00:00 2001
From c7fe7cbd61f7debf052ddcc6cc5f01bb7e4f5385 Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Tue, 23 Aug 2016 16:49:25 -0400
Subject: [PATCH] [downstream] fix debuginfo with y.tab.c
@ -14,7 +14,7 @@ Last-updated: krb5-1.9
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/kadmin/cli/Makefile.in b/src/kadmin/cli/Makefile.in
index adfea6e2b..d1327e400 100644
index adfea6e2b5..d1327e400b 100644
--- a/src/kadmin/cli/Makefile.in
+++ b/src/kadmin/cli/Makefile.in
@@ -37,3 +37,8 @@ clean-unix::
@ -27,7 +27,7 @@ index adfea6e2b..d1327e400 100644
+ $(YACC.y) $<
+ $(CP) y.tab.c $@
diff --git a/src/plugins/kdb/ldap/ldap_util/Makefile.in b/src/plugins/kdb/ldap/ldap_util/Makefile.in
index 8669c2436..a22f23c02 100644
index 8669c2436c..a22f23c02c 100644
--- a/src/plugins/kdb/ldap/ldap_util/Makefile.in
+++ b/src/plugins/kdb/ldap/ldap_util/Makefile.in
@@ -20,7 +20,7 @@ $(PROG): $(OBJS) $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIB) $(GETDATE)
@ -39,3 +39,6 @@ index 8669c2436..a22f23c02 100644
install:
$(INSTALL_PROGRAM) $(PROG) ${DESTDIR}$(ADMIN_BINDIR)/$(PROG)
--
2.38.1

@ -1,6 +1,6 @@
From 4f8cba1780bc167c52de2a791cad6a1817508bbe Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Wed, 23 Feb 2022 17:34:33 +0100
From b8e3a859f8904d395ea0e1a7d6c49a791029711c Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Fri, 9 Nov 2018 15:12:21 -0500
Subject: [PATCH] [downstream] FIPS with PRNG and RADIUS and MD4
NB: Use openssl's PRNG in FIPS mode and taint within krad.
@ -19,38 +19,31 @@ post6 restores MD4 (and therefore keygen-only RC4).
post7 restores MD5 and adds radius_md5_fips_override.
post8 restores MD4/MD5 for OpenSSL 3.0
post8 silences a static analyzer warning.
Use OpenSSL 3.0 library context to access MD4 and MD5 lazily from
legacy provider if RC4 encryption type is enabled, without affecting
global context.
post9 add missing includes for FIPS_mode() macro
Remove EVP_MD_CTX_FLAG_NON_FIPS_ALLOW flag since does not have any
effect anymore.
post9 load both default and legacy provider into library context
Last-updated: krb5-1.19
Last-updated: krb5-1.20.1
---
doc/admin/conf_files/krb5_conf.rst | 6 ++
src/lib/crypto/krb/prng.c | 11 ++-
.../crypto/openssl/enc_provider/camellia.c | 6 ++
src/lib/crypto/openssl/enc_provider/rc4.c | 13 ++-
.../crypto/openssl/hash_provider/hash_evp.c | 93 ++++++++++++++++++-
src/lib/crypto/openssl/hmac.c | 6 +-
src/lib/krad/attr.c | 46 ++++++---
doc/admin/conf_files/krb5_conf.rst | 6 +++
src/lib/crypto/krb/prng.c | 17 ++++++-
.../crypto/openssl/enc_provider/camellia.c | 7 +++
src/lib/crypto/openssl/enc_provider/rc4.c | 17 ++++++-
.../crypto/openssl/hash_provider/hash_evp.c | 12 +++++
src/lib/crypto/openssl/hmac.c | 7 ++-
src/lib/krad/attr.c | 46 ++++++++++++++-----
src/lib/krad/attrset.c | 5 +-
src/lib/krad/internal.h | 28 +++++-
src/lib/krad/packet.c | 22 +++--
src/lib/krad/remote.c | 10 +-
src/lib/krad/internal.h | 32 ++++++++++++-
src/lib/krad/packet.c | 22 +++++----
src/lib/krad/remote.c | 10 +++-
src/lib/krad/t_attr.c | 3 +-
src/lib/krad/t_attrset.c | 4 +-
src/plugins/preauth/spake/spake_client.c | 6 ++
src/plugins/preauth/spake/spake_kdc.c | 6 ++
15 files changed, 230 insertions(+), 35 deletions(-)
src/plugins/preauth/spake/spake_client.c | 10 ++++
src/plugins/preauth/spake/spake_kdc.c | 10 ++++
15 files changed, 175 insertions(+), 33 deletions(-)
diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
index 675175955..adba8238d 100644
index d5d6e06ebb..2a4962069f 100644
--- a/doc/admin/conf_files/krb5_conf.rst
+++ b/doc/admin/conf_files/krb5_conf.rst
@@ -330,6 +330,12 @@ The libdefaults section may contain any of the following relations:
@ -67,22 +60,28 @@ index 675175955..adba8238d 100644
If this flag is true, reverse name lookup will be used in addition
to forward name lookup to canonicalizing hostnames for use in
diff --git a/src/lib/crypto/krb/prng.c b/src/lib/crypto/krb/prng.c
index cb9ca9b98..f0e9984ca 100644
index d6b79e2dea..ae37c77518 100644
--- a/src/lib/crypto/krb/prng.c
+++ b/src/lib/crypto/krb/prng.c
@@ -26,6 +26,8 @@
@@ -26,6 +26,14 @@
#include "crypto_int.h"
+#include <openssl/rand.h>
+
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+#include <openssl/fips.h>
+#else
+#include <openssl/crypto.h>
+#endif
+
krb5_error_code KRB5_CALLCONV
krb5_c_random_seed(krb5_context context, krb5_data *data)
{
@@ -99,9 +101,16 @@ krb5_boolean
k5_get_os_entropy(unsigned char *buf, size_t len, int strong)
@@ -96,9 +104,16 @@ cleanup:
static krb5_boolean
get_os_entropy(unsigned char *buf, size_t len)
{
const char *device;
-#if defined(__linux__) && defined(SYS_getrandom)
int r;
@ -98,10 +97,18 @@ index cb9ca9b98..f0e9984ca 100644
/*
* Pull from the /dev/urandom pool, but require it to have been seeded.
diff --git a/src/lib/crypto/openssl/enc_provider/camellia.c b/src/lib/crypto/openssl/enc_provider/camellia.c
index 2da691329..f79679a0b 100644
index 01920e6ce1..3dd3b0624f 100644
--- a/src/lib/crypto/openssl/enc_provider/camellia.c
+++ b/src/lib/crypto/openssl/enc_provider/camellia.c
@@ -304,6 +304,9 @@ krb5int_camellia_cbc_mac(krb5_key key, const krb5_crypto_iov *data,
@@ -32,6 +32,7 @@
#include <openssl/camellia.h>
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
#include <openssl/core_names.h>
+#include <openssl/fips.h>
#else
#include <openssl/modes.h>
#endif
@@ -387,6 +388,9 @@ krb5int_camellia_cbc_mac(krb5_key key, const krb5_crypto_iov *data,
unsigned char blockY[CAMELLIA_BLOCK_SIZE], blockB[CAMELLIA_BLOCK_SIZE];
struct iov_cursor cursor;
@ -111,7 +118,7 @@ index 2da691329..f79679a0b 100644
if (output->length < CAMELLIA_BLOCK_SIZE)
return KRB5_BAD_MSIZE;
@@ -331,6 +334,9 @@ static krb5_error_code
@@ -418,6 +422,9 @@ static krb5_error_code
krb5int_camellia_init_state (const krb5_keyblock *key, krb5_keyusage usage,
krb5_data *state)
{
@ -122,10 +129,21 @@ index 2da691329..f79679a0b 100644
state->data = (void *) malloc(16);
if (state->data == NULL)
diff --git a/src/lib/crypto/openssl/enc_provider/rc4.c b/src/lib/crypto/openssl/enc_provider/rc4.c
index bc87c6f42..9bf407899 100644
index 448d563348..6a83f10d27 100644
--- a/src/lib/crypto/openssl/enc_provider/rc4.c
+++ b/src/lib/crypto/openssl/enc_provider/rc4.c
@@ -66,6 +66,9 @@ k5_arcfour_docrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data,
@@ -38,6 +38,10 @@
#include <openssl/evp.h>
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+#include <openssl/fips.h>
+#endif
+
/*
* The loopback field is a pointer to the structure. If the application copies
* the state (not a valid operation, but one which happens to works with some
@@ -69,6 +73,9 @@ k5_arcfour_docrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data,
EVP_CIPHER_CTX *ctx = NULL;
struct arcfour_state *arcstate;
@ -135,7 +153,7 @@ index bc87c6f42..9bf407899 100644
arcstate = (state != NULL) ? (void *)state->data : NULL;
if (arcstate != NULL) {
ctx = arcstate->ctx;
@@ -113,7 +116,12 @@ k5_arcfour_docrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data,
@@ -116,7 +123,12 @@ k5_arcfour_docrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data,
static void
k5_arcfour_free_state(krb5_data *state)
{
@ -149,7 +167,7 @@ index bc87c6f42..9bf407899 100644
EVP_CIPHER_CTX_free(arcstate->ctx);
free(arcstate);
@@ -125,6 +133,9 @@ k5_arcfour_init_state(const krb5_keyblock *key,
@@ -128,6 +140,9 @@ k5_arcfour_init_state(const krb5_keyblock *key,
{
struct arcfour_state *arcstate;
@ -160,143 +178,69 @@ index bc87c6f42..9bf407899 100644
* The cipher state here is a saved pointer to a struct arcfour_state
* object, rather than a flat byte array as in most enc providers. The
diff --git a/src/lib/crypto/openssl/hash_provider/hash_evp.c b/src/lib/crypto/openssl/hash_provider/hash_evp.c
index 1e0fb8fc3..57bca3fec 100644
index f2fbffdb29..11659908bb 100644
--- a/src/lib/crypto/openssl/hash_provider/hash_evp.c
+++ b/src/lib/crypto/openssl/hash_provider/hash_evp.c
@@ -32,6 +32,46 @@
@@ -60,6 +60,11 @@ hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data,
if (ctx == NULL)
return ENOMEM;
#include "crypto_int.h"
#include <openssl/evp.h>
+#include <openssl/provider.h>
+#include <threads.h>
+
+typedef struct ossl_lib_md_context {
+ OSSL_LIB_CTX *libctx;
+ OSSL_PROVIDER *default_provider;
+ OSSL_PROVIDER *legacy_provider;
+} ossl_md_context_t;
+
+static thread_local ossl_md_context_t *ossl_md_ctx = NULL;
+
+static krb5_error_code
+init_ossl_md_ctx(ossl_md_context_t *ctx, const char *algo)
+{
+ ctx->libctx = OSSL_LIB_CTX_new();
+ if (!ctx->libctx)
+ return KRB5_CRYPTO_INTERNAL;
+
+ /* Load both legacy and default provider as both may be needed. */
+ ctx->default_provider = OSSL_PROVIDER_load(ctx->libctx, "default");
+ ctx->legacy_provider = OSSL_PROVIDER_load(ctx->libctx, "legacy");
+
+ if (!(ctx->default_provider && ctx->legacy_provider))
+ return KRB5_CRYPTO_INTERNAL;
+
+ return 0;
+}
+
+static void
+deinit_ossl_ctx(ossl_md_context_t *ctx)
+{
+ if (ctx->legacy_provider)
+ OSSL_PROVIDER_unload(ctx->legacy_provider);
+
+ if (ctx->default_provider)
+ OSSL_PROVIDER_unload(ctx->default_provider);
+
+ if (ctx->libctx)
+ OSSL_LIB_CTX_free(ctx->libctx);
+}
static krb5_error_code
hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data,
@@ -61,16 +101,65 @@ hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data,
return ok ? 0 : KRB5_CRYPTO_INTERNAL;
}
+static krb5_error_code
+hash_legacy_evp(const char *algo, const krb5_crypto_iov *data, size_t num_data,
+ krb5_data *output)
+{
+ krb5_error_code err;
+ EVP_MD *md = NULL;
+
+ if (!ossl_md_ctx) {
+ ossl_md_ctx = malloc(sizeof(ossl_md_context_t));
+ if (!ossl_md_ctx) {
+ err = ENOMEM;
+ goto end;
+ }
+
+ err = init_ossl_md_ctx(ossl_md_ctx, algo);
+ if (err) {
+ deinit_ossl_ctx(ossl_md_ctx);
+ free(ossl_md_ctx);
+ ossl_md_ctx = NULL;
+ goto end;
+ }
+ }
+
+ md = EVP_MD_fetch(ossl_md_ctx->libctx, algo, NULL);
+ if (!md) {
+ err = KRB5_CRYPTO_INTERNAL;
+ goto end;
+ if (type == EVP_md4() || type == EVP_md5()) {
+ /* See comments below in hash_md4() and hash_md5(). */
+ EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
+ }
+
+ err = hash_evp(md, data, num_data, output);
+
+end:
+ if (md)
+ EVP_MD_free(md);
+
+ return err;
+}
+
ok = EVP_DigestInit_ex(ctx, type, NULL);
for (i = 0; i < num_data; i++) {
if (!SIGN_IOV(&data[i]))
@@ -78,6 +83,11 @@ hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data,
static krb5_error_code
hash_md4(const krb5_crypto_iov *data, size_t num_data, krb5_data *output)
{
- return hash_evp(EVP_md4(), data, num_data, output);
+ /*
+ * MD4 is needed in FIPS mode to perform key generation for RC4 keys used
+ * by IPA. These keys are only used along a (separately) secured channel
+ * for legacy reasons when performing trusts to Active Directory.
+ */
+ return FIPS_mode() ? hash_legacy_evp("MD4", data, num_data, output)
+ : hash_evp(EVP_md4(), data, num_data, output);
return hash_evp(EVP_md4(), data, num_data, output);
}
@@ -90,6 +100,8 @@ const struct krb5_hash_provider krb5int_hash_md4 = {
static krb5_error_code
hash_md5(const krb5_crypto_iov *data, size_t num_data, krb5_data *output)
{
- return hash_evp(EVP_md5(), data, num_data, output);
+ /*
+ * MD5 is needed in FIPS mode for communication with RADIUS servers. This
+ * is gated in libkrad by libdefaults->radius_md5_fips_override.
+ */
+ return FIPS_mode() ? hash_legacy_evp("MD5", data, num_data, output)
+ : hash_evp(EVP_md5(), data, num_data, output);
+ /* MD5 is needed in FIPS mode for communication with RADIUS servers. This
+ * is gated in libkrad by libdefaults->radius_md5_fips_override. */
return hash_evp(EVP_md5(), data, num_data, output);
}
static krb5_error_code
diff --git a/src/lib/crypto/openssl/hmac.c b/src/lib/crypto/openssl/hmac.c
index 7dc59dcc0..769a50c00 100644
index bf12b8d6a0..25a419d73a 100644
--- a/src/lib/crypto/openssl/hmac.c
+++ b/src/lib/crypto/openssl/hmac.c
@@ -103,7 +103,11 @@ map_digest(const struct krb5_hash_provider *hash)
@@ -59,6 +59,7 @@
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
#include <openssl/params.h>
#include <openssl/core_names.h>
+#include <openssl/fips.h>
#else
#include <openssl/hmac.h>
#endif
@@ -111,7 +112,11 @@ map_digest(const struct krb5_hash_provider *hash)
return EVP_sha256();
else if (!strncmp(hash->hash_name, "SHA-384",7))
else if (hash == &krb5int_hash_sha384)
return EVP_sha384();
- else if (!strncmp(hash->hash_name, "MD5", 3))
- else if (hash == &krb5int_hash_md5)
+
+ if (FIPS_mode())
+ return NULL;
+
+ if (!strncmp(hash->hash_name, "MD5", 3))
+ if (hash == &krb5int_hash_md5)
return EVP_md5();
else if (!strncmp(hash->hash_name, "MD4", 3))
else if (hash == &krb5int_hash_md4)
return EVP_md4();
diff --git a/src/lib/krad/attr.c b/src/lib/krad/attr.c
index 9c13d9d75..42d354a3b 100644
index 9c13d9d755..42d354a3b5 100644
--- a/src/lib/krad/attr.c
+++ b/src/lib/krad/attr.c
@@ -38,7 +38,8 @@
@ -420,7 +364,7 @@ index 9c13d9d75..42d354a3b 100644
krad_attr
diff --git a/src/lib/krad/attrset.c b/src/lib/krad/attrset.c
index 03c613716..d89982a13 100644
index f309f1581c..6ec031e320 100644
--- a/src/lib/krad/attrset.c
+++ b/src/lib/krad/attrset.c
@@ -167,7 +167,8 @@ krad_attrset_copy(const krad_attrset *set, krad_attrset **copy)
@ -443,19 +387,23 @@ index 03c613716..d89982a13 100644
return retval;
diff --git a/src/lib/krad/internal.h b/src/lib/krad/internal.h
index 0143d155a..223ffd730 100644
index 7619563fc5..a17b6f39b1 100644
--- a/src/lib/krad/internal.h
+++ b/src/lib/krad/internal.h
@@ -39,6 +39,8 @@
@@ -39,6 +39,12 @@
#include <sys/socket.h>
#include <netdb.h>
+#include <openssl/crypto.h>
+
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+#include <openssl/fips.h>
+#endif
+
#ifndef UCHAR_MAX
#define UCHAR_MAX 255
#endif
@@ -49,6 +51,13 @@
@@ -49,6 +55,13 @@
typedef struct krad_remote_st krad_remote;
@ -469,7 +417,7 @@ index 0143d155a..223ffd730 100644
/* Validate constraints of an attribute. */
krb5_error_code
kr_attr_valid(krad_attr type, const krb5_data *data);
@@ -57,7 +66,8 @@ kr_attr_valid(krad_attr type, const krb5_data *data);
@@ -57,7 +70,8 @@ kr_attr_valid(krad_attr type, const krb5_data *data);
krb5_error_code
kr_attr_encode(krb5_context ctx, const char *secret, const unsigned char *auth,
krad_attr type, const krb5_data *in,
@ -479,7 +427,7 @@ index 0143d155a..223ffd730 100644
/* Decode an attribute. */
krb5_error_code
@@ -69,7 +79,8 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth,
@@ -69,7 +83,8 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth,
krb5_error_code
kr_attrset_encode(const krad_attrset *set, const char *secret,
const unsigned char *auth,
@ -489,7 +437,7 @@ index 0143d155a..223ffd730 100644
/* Decode attributes from a buffer. */
krb5_error_code
@@ -152,4 +163,17 @@ gai_error_code(int err)
@@ -156,4 +171,17 @@ gai_error_code(int err)
}
}
@ -501,14 +449,14 @@ index 0143d155a..223ffd730 100644
+ if (!FIPS_mode())
+ return 0;
+
+ profile_get_boolean(ctx->profile, "libdefaults",
+ "radius_md5_fips_override", NULL, 0, &val);
+ (void)profile_get_boolean(ctx->profile, "libdefaults",
+ "radius_md5_fips_override", NULL, 0, &val);
+ return !val;
+}
+
#endif /* INTERNAL_H_ */
diff --git a/src/lib/krad/packet.c b/src/lib/krad/packet.c
index c597174b6..fc2d24800 100644
index c597174b65..fc2d248001 100644
--- a/src/lib/krad/packet.c
+++ b/src/lib/krad/packet.c
@@ -53,12 +53,6 @@ typedef unsigned char uchar;
@ -569,7 +517,7 @@ index c597174b6..fc2d24800 100644
}
diff --git a/src/lib/krad/remote.c b/src/lib/krad/remote.c
index c96a9b4ee..eca432424 100644
index 06ae751bc8..929f1cef67 100644
--- a/src/lib/krad/remote.c
+++ b/src/lib/krad/remote.c
@@ -263,7 +263,7 @@ on_io_write(krad_remote *rr)
@ -590,7 +538,7 @@ index c96a9b4ee..eca432424 100644
request_finish(r, 0, rsp);
break;
}
@@ -455,6 +455,12 @@ kr_remote_send(krad_remote *rr, krad_code code, krad_attrset *attrs,
@@ -460,6 +460,12 @@ kr_remote_send(krad_remote *rr, krad_code code, krad_attrset *attrs,
(krad_packet_iter_cb)iterator, &r, &tmp);
if (retval != 0)
goto error;
@ -604,7 +552,7 @@ index c96a9b4ee..eca432424 100644
K5_TAILQ_FOREACH(r, &rr->list, list) {
if (r->request == tmp) {
diff --git a/src/lib/krad/t_attr.c b/src/lib/krad/t_attr.c
index eb2a780c8..4d285ad9d 100644
index eb2a780c89..4d285ad9de 100644
--- a/src/lib/krad/t_attr.c
+++ b/src/lib/krad/t_attr.c
@@ -50,6 +50,7 @@ main()
@ -625,7 +573,7 @@ index eb2a780c8..4d285ad9d 100644
insist(len == sizeof(encoded));
insist(memcmp(outbuf, encoded, len) == 0);
diff --git a/src/lib/krad/t_attrset.c b/src/lib/krad/t_attrset.c
index 7928335ca..0f9576253 100644
index 7928335ca4..0f95762534 100644
--- a/src/lib/krad/t_attrset.c
+++ b/src/lib/krad/t_attrset.c
@@ -49,6 +49,7 @@ main()
@ -647,19 +595,23 @@ index 7928335ca..0f9576253 100644
/* Manually encode User-Name. */
diff --git a/src/plugins/preauth/spake/spake_client.c b/src/plugins/preauth/spake/spake_client.c
index 00734a13b..a3ce22b70 100644
index 00734a13b5..13c699071f 100644
--- a/src/plugins/preauth/spake/spake_client.c
+++ b/src/plugins/preauth/spake/spake_client.c
@@ -38,6 +38,8 @@
@@ -38,6 +38,12 @@
#include "groups.h"
#include <krb5/clpreauth_plugin.h>
+#include <openssl/crypto.h>
+
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+#include <openssl/fips.h>
+#endif
+
typedef struct reqstate_st {
krb5_pa_spake *msg; /* set in prep_questions, used in process */
krb5_keyblock *initial_key;
@@ -375,6 +377,10 @@ clpreauth_spake_initvt(krb5_context context, int maj_ver, int min_ver,
@@ -375,6 +381,10 @@ clpreauth_spake_initvt(krb5_context context, int maj_ver, int min_ver,
if (maj_ver != 1)
return KRB5_PLUGIN_VER_NOTSUPP;
@ -671,19 +623,23 @@ index 00734a13b..a3ce22b70 100644
vt->name = "spake";
vt->pa_type_list = pa_types;
diff --git a/src/plugins/preauth/spake/spake_kdc.c b/src/plugins/preauth/spake/spake_kdc.c
index 88c964ce1..c7df0392f 100644
index 1a772d450f..3394f8a58e 100644
--- a/src/plugins/preauth/spake/spake_kdc.c
+++ b/src/plugins/preauth/spake/spake_kdc.c
@@ -41,6 +41,8 @@
@@ -41,6 +41,12 @@
#include <krb5/kdcpreauth_plugin.h>
+#include <openssl/crypto.h>
+
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+#include <openssl/fips.h>
+#endif
+
/*
* The SPAKE kdcpreauth module uses a secure cookie containing the following
* concatenated fields (all integer fields are big-endian):
@@ -571,6 +573,10 @@ kdcpreauth_spake_initvt(krb5_context context, int maj_ver, int min_ver,
@@ -551,6 +557,10 @@ kdcpreauth_spake_initvt(krb5_context context, int maj_ver, int min_ver,
if (maj_ver != 1)
return KRB5_PLUGIN_VER_NOTSUPP;
@ -695,5 +651,5 @@ index 88c964ce1..c7df0392f 100644
vt->name = "spake";
vt->pa_type_list = pa_types;
--
2.35.1
2.38.1

@ -1,7 +1,8 @@
From 790f485cf57e4de65351c29c41666db6370ef367 Mon Sep 17 00:00:00 2001
From 813f3840c7b9f32c1d96dcd847be91fe545653eb Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Thu, 5 May 2022 17:15:12 +0200
Subject: [PATCH] Allow krad UDP/TCP localhost connection with FIPS
Subject: [PATCH] [downstream] Allow krad UDP/TCP localhost connection
with FIPS
libkrad allows to establish connections only to UNIX socket in FIPS
mode, because MD5 digest is not considered safe enough to be used for
@ -11,13 +12,13 @@ UDP ports.
This commit allows TCP or UDP connections in FIPS mode if destination is
localhost.
Resolves: rhbz#2068458
Resolves: rhbz#2082189
---
src/lib/krad/remote.c | 36 ++++++++++++++++++++++++++++++++++--
1 file changed, 34 insertions(+), 2 deletions(-)
src/lib/krad/remote.c | 35 +++++++++++++++++++++++++++++++++--
1 file changed, 33 insertions(+), 2 deletions(-)
diff --git a/src/lib/krad/remote.c b/src/lib/krad/remote.c
index eca432424..c8912892c 100644
index 929f1cef67..063f17a613 100644
--- a/src/lib/krad/remote.c
+++ b/src/lib/krad/remote.c
@@ -33,6 +33,7 @@
@ -28,7 +29,7 @@ index eca432424..c8912892c 100644
#include <sys/un.h>
@@ -74,6 +75,36 @@ on_io(verto_ctx *ctx, verto_ev *ev);
@@ -74,6 +75,35 @@ on_io(verto_ctx *ctx, verto_ev *ev);
static void
on_timeout(verto_ctx *ctx, verto_ev *ev);
@ -60,12 +61,11 @@ index eca432424..c8912892c 100644
+
+ return true;
+}
+
+
/* Iterate over the set of outstanding packets. */
static const krad_packet *
iterator(request **out)
@@ -455,8 +486,9 @@ kr_remote_send(krad_remote *rr, krad_code code, krad_attrset *attrs,
@@ -460,8 +490,9 @@ kr_remote_send(krad_remote *rr, krad_code code, krad_attrset *attrs,
(krad_packet_iter_cb)iterator, &r, &tmp);
if (retval != 0)
goto error;
@ -78,5 +78,5 @@ index eca432424..c8912892c 100644
retval = ESOCKTNOSUPPORT;
goto error;
--
2.35.1
2.38.1

@ -1,4 +1,4 @@
From 2a6a4568ed1df4ed89604b09fa11785c9ae38c67 Mon Sep 17 00:00:00 2001
From c0a6d66e98e62b94d72bb51b8d6c00130a951215 Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Fri, 22 Apr 2022 14:12:37 +0200
Subject: [PATCH] Add configure variable for default PKCS#11 module
@ -20,10 +20,10 @@ ticket: 9058 (new)
9 files changed, 34 insertions(+), 16 deletions(-)
diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
index adba8238d..3d25c9a12 100644
index 2a4962069f..a33711d918 100644
--- a/doc/admin/conf_files/krb5_conf.rst
+++ b/doc/admin/conf_files/krb5_conf.rst
@@ -1020,7 +1020,7 @@ information for PKINIT is as follows:
@@ -1017,7 +1017,7 @@ information for PKINIT is as follows:
All keyword/values are optional. *modname* specifies the location
of a library implementing PKCS #11. If a value is encountered
with no keyword, it is assumed to be the *modname*. If no
@ -33,10 +33,10 @@ index adba8238d..3d25c9a12 100644
a particular smard card reader or token if there is more than one
available. ``certid=`` and/or ``certlabel=`` may be specified to
diff --git a/doc/build/options2configure.rst b/doc/build/options2configure.rst
index a8959626d..8f8ac911c 100644
index 9e355dc2c5..e879b18bd2 100644
--- a/doc/build/options2configure.rst
+++ b/doc/build/options2configure.rst
@@ -143,6 +143,9 @@ Environment variables
@@ -137,6 +137,9 @@ Environment variables
This option allows one to specify libraries to be passed to the
linker (e.g., ``-l<library>``)
@ -47,10 +47,10 @@ index a8959626d..8f8ac911c 100644
If ``-lss`` is not the correct way to link in your installed ss
library, for example if additional support libraries are needed,
diff --git a/doc/conf.py b/doc/conf.py
index 4fb6aae14..29fd53375 100644
index 12168fa695..0ab5ff9606 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -235,6 +235,7 @@ if 'mansubs' in tags:
@@ -242,6 +242,7 @@ if 'mansubs' in tags:
ccache = '``@CCNAME@``'
keytab = '``@KTNAME@``'
ckeytab = '``@CKTNAME@``'
@ -58,7 +58,7 @@ index 4fb6aae14..29fd53375 100644
elif 'pathsubs' in tags:
# Read configured paths from a file produced by the build system.
exec(open("paths.py").read())
@@ -248,6 +249,7 @@ else:
@@ -255,6 +256,7 @@ else:
ccache = ':ref:`DEFCCNAME <paths>`'
keytab = ':ref:`DEFKTNAME <paths>`'
ckeytab = ':ref:`DEFCKTNAME <paths>`'
@ -66,7 +66,7 @@ index 4fb6aae14..29fd53375 100644
rst_epilog = '\n'
@@ -268,6 +270,7 @@ else:
@@ -275,6 +277,7 @@ else:
rst_epilog += '.. |ccache| replace:: %s\n' % ccache
rst_epilog += '.. |keytab| replace:: %s\n' % keytab
rst_epilog += '.. |ckeytab| replace:: %s\n' % ckeytab
@ -75,7 +75,7 @@ index 4fb6aae14..29fd53375 100644
.. |krb5conf| replace:: ``/etc/krb5.conf``
.. |defkeysalts| replace:: ``aes256-cts-hmac-sha1-96:normal aes128-cts-hmac-sha1-96:normal``
diff --git a/doc/mitK5defaults.rst b/doc/mitK5defaults.rst
index 74e69f4ad..aea7af3db 100644
index 74e69f4ad0..aea7af3dbb 100644
--- a/doc/mitK5defaults.rst
+++ b/doc/mitK5defaults.rst
@@ -59,18 +59,19 @@ subdirectories of ``/usr/local``. When MIT krb5 is integrated into an
@ -111,10 +111,10 @@ index 74e69f4ad..aea7af3db 100644
The default client keytab name (DEFCKTNAME) typically defaults to
``FILE:/usr/local/var/krb5/user/%{euid}/client.keytab`` for a custom
diff --git a/src/configure.ac b/src/configure.ac
index 363d5d62d..3a0633177 100644
index 8dc864718d..9774cb71ae 100644
--- a/src/configure.ac
+++ b/src/configure.ac
@@ -1466,6 +1466,14 @@ AC_DEFINE_UNQUOTED(DEFKTNAME, ["$DEFKTNAME"], [Define to default keytab name])
@@ -1471,6 +1471,14 @@ AC_DEFINE_UNQUOTED(DEFKTNAME, ["$DEFKTNAME"], [Define to default keytab name])
AC_DEFINE_UNQUOTED(DEFCKTNAME, ["$DEFCKTNAME"],
[Define to default client keytab name])
@ -130,7 +130,7 @@ index 363d5d62d..3a0633177 100644
AC_CONFIG_FILES([build-tools/kadm-server.pc
build-tools/kadm-client.pc
diff --git a/src/doc/Makefile.in b/src/doc/Makefile.in
index 379bc3651..a1b0cff0a 100644
index 379bc36511..a1b0cff0a4 100644
--- a/src/doc/Makefile.in
+++ b/src/doc/Makefile.in
@@ -10,6 +10,7 @@ sysconfdir=@sysconfdir@
@ -150,7 +150,7 @@ index 379bc3651..a1b0cff0a 100644
# Dummy rule that man/Makefile can invoke
version.py: $(docsrc)/version.py
diff --git a/src/man/Makefile.in b/src/man/Makefile.in
index 00b1b2de0..85cae0914 100644
index 00b1b2de06..85cae0914e 100644
--- a/src/man/Makefile.in
+++ b/src/man/Makefile.in
@@ -8,6 +8,7 @@ sysconfdir=@sysconfdir@
@ -172,10 +172,10 @@ index 00b1b2de0..85cae0914 100644
all: $(MANSUBS)
diff --git a/src/man/krb5.conf.man b/src/man/krb5.conf.man
index 3a702ca8f..e4202723f 100644
index 51acb38815..fd2c6f2bc4 100644
--- a/src/man/krb5.conf.man
+++ b/src/man/krb5.conf.man
@@ -1151,7 +1151,7 @@ user\(aqs certificate and private key.
@@ -1148,7 +1148,7 @@ user\(aqs certificate and private key.
All keyword/values are optional. \fImodname\fP specifies the location
of a library implementing PKCS #11. If a value is encountered
with no keyword, it is assumed to be the \fImodname\fP\&. If no
@ -185,7 +185,7 @@ index 3a702ca8f..e4202723f 100644
a particular smard card reader or token if there is more than one
available. \fBcertid=\fP and/or \fBcertlabel=\fP may be specified to
diff --git a/src/plugins/preauth/pkinit/pkinit.h b/src/plugins/preauth/pkinit/pkinit.h
index b437fd53f..a2018cb10 100644
index 8135535e2c..66f92d8f03 100644
--- a/src/plugins/preauth/pkinit/pkinit.h
+++ b/src/plugins/preauth/pkinit/pkinit.h
@@ -42,7 +42,6 @@
@ -197,5 +197,5 @@ index b437fd53f..a2018cb10 100644
#define PK_NOSLOT 999999
#endif
--
2.35.1
2.38.1

@ -0,0 +1,159 @@
From 3cc9ef956342f55cc9ae283e30fc3ba080248cf3 Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Wed, 1 Jun 2022 18:02:04 +0200
Subject: [PATCH] Set reasonable supportedCMSTypes in PKINIT
The PKINIT client uses AuthPack.supportedCMSTypes to let the KDC know
the algorithms it supports for verification of the CMS data signature.
(The MIT krb5 KDC currently ignores this list, but other
implementations use it.)
Replace 3DES with sha512WithRSAEncryption and sha256WithRSAEncryption.
[ghudson@mit.edu: simplified code and used appropriate helpers; edited
commit message]
ticket: 9066 (new)
---
src/plugins/preauth/pkinit/pkinit_constants.c | 33 ++++++++++++-
src/plugins/preauth/pkinit/pkinit_crypto.h | 4 ++
.../preauth/pkinit/pkinit_crypto_openssl.c | 49 ++++++++++---------
3 files changed, 60 insertions(+), 26 deletions(-)
diff --git a/src/plugins/preauth/pkinit/pkinit_constants.c b/src/plugins/preauth/pkinit/pkinit_constants.c
index 652897fa14..1da482e0b4 100644
--- a/src/plugins/preauth/pkinit/pkinit_constants.c
+++ b/src/plugins/preauth/pkinit/pkinit_constants.c
@@ -32,9 +32,14 @@
#include "pkinit.h"
-/* statically declare OID constants for all three algorithms */
-static char sha1_oid[8] = { 0x2B, 0x06, 0x01, 0x05, 0x02, 0x03, 0x06, 0x01};
+/* RFC 8636 id-pkinit-kdf-ah-sha1: iso(1) identified-organization(3) dod(6)
+ * internet(1) security(5) kerberosv5(2) pkinit(3) kdf(6) sha1(1) */
+static char sha1_oid[8] = { 0x2B, 0x06, 0x01, 0x05, 0x02, 0x03, 0x06, 0x01 };
+/* RFC 8636 id-pkinit-kdf-ah-sha256: iso(1) identified-organization(3) dod(6)
+ * internet(1) security(5) kerberosv5(2) pkinit(3) kdf(6) sha256(2) */
static char sha256_oid[8] = { 0x2B, 0x06, 0x01, 0x05, 0x02, 0x03, 0x06, 0x02 };
+/* RFC 8636 id-pkinit-kdf-ah-sha512: iso(1) identified-organization(3) dod(6)
+ * internet(1) security(5) kerberosv5(2) pkinit(3) kdf(6) sha512(3) */
static char sha512_oid[8] = { 0x2B, 0x06, 0x01, 0x05, 0x02, 0x03, 0x06, 0x03 };
const krb5_data sha1_id = { KV5M_DATA, sizeof(sha1_oid), sha1_oid };
@@ -48,6 +53,30 @@ krb5_data const * const supported_kdf_alg_ids[] = {
NULL
};
+/* RFC 4055 sha256WithRSAEncryption: iso(1) member-body(2) us(840)
+ * rsadsi(113549) pkcs(1) 1 11 */
+static char sha256WithRSAEncr_oid[9] = {
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b
+};
+/* RFC 4055 sha256WithRSAEncryption: iso(1) member-body(2) us(840)
+ * rsadsi(113549) pkcs(1) 1 13 */
+static char sha512WithRSAEncr_oid[9] = {
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d
+};
+
+const krb5_data sha256WithRSAEncr_id = {
+ KV5M_DATA, sizeof(sha256WithRSAEncr_oid), sha256WithRSAEncr_oid
+};
+const krb5_data sha512WithRSAEncr_id = {
+ KV5M_DATA, sizeof(sha512WithRSAEncr_oid), sha512WithRSAEncr_oid
+};
+
+krb5_data const * const supported_cms_algs[] = {
+ &sha512WithRSAEncr_id,
+ &sha256WithRSAEncr_id,
+ NULL
+};
+
/* RFC 2412 section E.2 (well-known group 2) parameters, DER-encoded as
* DomainParameters (RFC 3279 section 2.3.3). */
static const uint8_t o1024[] = {
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto.h b/src/plugins/preauth/pkinit/pkinit_crypto.h
index 65f6210727..64300da856 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto.h
+++ b/src/plugins/preauth/pkinit/pkinit_crypto.h
@@ -620,6 +620,10 @@ extern const krb5_data oakley_4096;
*/
extern krb5_data const * const supported_kdf_alg_ids[];
+/* CMS signature algorithms supported by this implementation, in order of
+ * decreasing preference. */
+extern krb5_data const * const supported_cms_algs[];
+
krb5_error_code
crypto_encode_der_cert(krb5_context context, pkinit_req_crypto_context reqctx,
uint8_t **der_out, size_t *der_len);
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
index d500455dec..1c2aa02827 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
@@ -5475,37 +5475,38 @@ create_krb5_supportedCMSTypes(krb5_context context,
pkinit_plg_crypto_context plg_cryptoctx,
pkinit_req_crypto_context req_cryptoctx,
pkinit_identity_crypto_context id_cryptoctx,
- krb5_algorithm_identifier ***oids)
+ krb5_algorithm_identifier ***algs_out)
{
+ krb5_error_code ret;
+ krb5_algorithm_identifier **algs = NULL;
+ size_t i, count;
- krb5_error_code retval = ENOMEM;
- krb5_algorithm_identifier **loids = NULL;
- krb5_data des3oid = {0, 8, "\x2A\x86\x48\x86\xF7\x0D\x03\x07" };
+ *algs_out = NULL;
- *oids = NULL;
- loids = malloc(2 * sizeof(krb5_algorithm_identifier *));
- if (loids == NULL)
- goto cleanup;
- loids[1] = NULL;
- loids[0] = malloc(sizeof(krb5_algorithm_identifier));
- if (loids[0] == NULL) {
- free(loids);
- goto cleanup;
- }
- retval = pkinit_copy_krb5_data(&loids[0]->algorithm, &des3oid);
- if (retval) {
- free(loids[0]);
- free(loids);
+ /* Count supported OIDs and allocate list (including null terminator). */
+ for (count = 0; supported_cms_algs[count] != NULL; count++);
+ algs = k5calloc(count + 1, sizeof(*algs), &ret);
+ if (algs == NULL)
goto cleanup;
+
+ /* Add an algorithm identifier for each OID, with no parameters. */
+ for (i = 0; i < count; i++) {
+ algs[i] = k5alloc(sizeof(*algs[i]), &ret);
+ if (algs[i] == NULL)
+ goto cleanup;
+ ret = krb5int_copy_data_contents(context, supported_cms_algs[i],
+ &algs[i]->algorithm);
+ if (ret)
+ goto cleanup;
+ algs[i]->parameters = empty_data();
}
- loids[0]->parameters.length = 0;
- loids[0]->parameters.data = NULL;
- *oids = loids;
- retval = 0;
-cleanup:
+ *algs_out = algs;
+ algs = NULL;
- return retval;
+cleanup:
+ free_krb5_algorithm_identifiers(&algs);
+ return ret;
}
krb5_error_code
--
2.38.1

@ -0,0 +1,622 @@
From 593109802b52e3f89c3a65436bfdba78f8c517c4 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Thu, 23 Jun 2022 16:41:40 -0400
Subject: [PATCH] Simplify plugin loading code
Remove the USE_CFBUNDLE code, which was only used by KfM. Handle
platform conditionals according to current practice. Use
k5_dir_filenames() instead of opendir() and remove the Windows
implementation of opendir().
---
src/util/support/plugins.c | 507 +++++++++++--------------------------
1 file changed, 150 insertions(+), 357 deletions(-)
diff --git a/src/util/support/plugins.c b/src/util/support/plugins.c
index c6a9a21d57..0850565687 100644
--- a/src/util/support/plugins.c
+++ b/src/util/support/plugins.c
@@ -29,16 +29,6 @@
#if USE_DLOPEN
#include <dlfcn.h>
#endif
-#include <sys/types.h>
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
#if USE_DLOPEN
#ifdef RTLD_GROUP
@@ -68,16 +58,6 @@
#endif
#endif
-#if USE_DLOPEN && USE_CFBUNDLE
-#include <CoreFoundation/CoreFoundation.h>
-
-/* Currently CoreFoundation only exists on the Mac so we just use
- * pthreads directly to avoid creating empty function calls on other
- * platforms. If a thread initializer ever gets created in the common
- * plugin code, move this there */
-static pthread_mutex_t krb5int_bundle_mutex = PTHREAD_MUTEX_INITIALIZER;
-#endif
-
#include <stdarg.h>
static void Tprintf (const char *fmt, ...)
{
@@ -90,374 +70,193 @@ static void Tprintf (const char *fmt, ...)
}
struct plugin_file_handle {
-#if USE_DLOPEN
+#if defined(USE_DLOPEN)
void *dlhandle;
-#endif
-#ifdef _WIN32
- HMODULE hinstPlugin;
-#endif
-#if !defined (USE_DLOPEN) && !defined (_WIN32)
+#elif defined(_WIN32)
+ HMODULE module;
+#else
char dummy;
#endif
};
-#ifdef _WIN32
-struct dirent {
- long d_ino; /* inode (always 1 in WIN32) */
- off_t d_off; /* offset to this dirent */
- unsigned short d_reclen; /* length of d_name */
- char d_name[_MAX_FNAME+1]; /* filename (null terminated) */
-};
-
-typedef struct {
- intptr_t handle; /* _findfirst/_findnext handle */
- short offset; /* offset into directory */
- short finished; /* 1 if there are not more files */
- struct _finddata_t fileinfo;/* from _findfirst/_findnext */
- char *dir; /* the dir we are reading */
- struct dirent dent; /* the dirent to return */
-} DIR;
+#if defined(USE_DLOPEN)
-DIR * opendir(const char *dir)
+static long
+open_plugin_dlfcn(struct plugin_file_handle *h, const char *filename,
+ struct errinfo *ep)
{
- DIR *dp;
- char *filespec;
- intptr_t handle;
- int index;
-
- filespec = malloc(strlen(dir) + 2 + 1);
- strcpy(filespec, dir);
- index = strlen(filespec) - 1;
- if (index >= 0 && (filespec[index] == '/' || filespec[index] == '\\'))
- filespec[index] = '\0';
- strcat(filespec, "/*");
-
- dp = (DIR *)malloc(sizeof(DIR));
- dp->offset = 0;
- dp->finished = 0;
- dp->dir = strdup(dir);
-
- if ((handle = _findfirst(filespec, &(dp->fileinfo))) < 0) {
- if (errno == ENOENT)
- dp->finished = 1;
- else {
- free(filespec);
- free(dp->dir);
- free(dp);
- return NULL;
- }
+ const char *e;
+
+ h->dlhandle = dlopen(filename, PLUGIN_DLOPEN_FLAGS);
+ if (h->dlhandle == NULL) {
+ e = dlerror();
+ if (e == NULL)
+ e = _("unknown failure");
+ Tprintf("dlopen(%s): %s\n", filename, e);
+ k5_set_error(ep, ENOENT, _("unable to load plugin [%s]: %s"),
+ filename, e);
+ return ENOENT;
}
-
- dp->handle = handle;
- free(filespec);
-
- return dp;
+ return 0;
}
+#define open_plugin open_plugin_dlfcn
-struct dirent * readdir(DIR *dp)
+static long
+get_sym_dlfcn(struct plugin_file_handle *h, const char *csymname,
+ void **sym_out, struct errinfo *ep)
{
- if (!dp || dp->finished) return NULL;
-
- if (dp->offset != 0) {
- if (_findnext(dp->handle, &(dp->fileinfo)) < 0) {
- dp->finished = 1;
- return NULL;
- }
+ const char *e;
+
+ if (h->dlhandle == NULL)
+ return ENOENT;
+ *sym_out = dlsym(h->dlhandle, csymname);
+ if (*sym_out == NULL) {
+ e = dlerror();
+ if (e == NULL)
+ e = _("unknown failure");
+ Tprintf("dlsym(%s): %s\n", csymname, e);
+ k5_set_error(ep, ENOENT, "%s", e);
+ return ENOENT;
}
- dp->offset++;
-
- strncpy(dp->dent.d_name, dp->fileinfo.name, _MAX_FNAME);
- dp->dent.d_ino = 1;
- dp->dent.d_reclen = (unsigned short)strlen(dp->dent.d_name);
- dp->dent.d_off = dp->offset;
-
- return &(dp->dent);
-}
-
-int closedir(DIR *dp)
-{
- if (!dp) return 0;
- _findclose(dp->handle);
- free(dp->dir);
- free(dp);
-
return 0;
}
-#endif
+#define get_sym get_sym_dlfcn
-long KRB5_CALLCONV
-krb5int_open_plugin (const char *filepath, struct plugin_file_handle **h, struct errinfo *ep)
+static void
+close_plugin_dlfcn(struct plugin_file_handle *h)
{
- long err = 0;
- struct plugin_file_handle *htmp = NULL;
- int got_plugin = 0;
-#if defined(USE_CFBUNDLE) || defined(_WIN32)
- struct stat statbuf;
-
- if (!err) {
- if (stat (filepath, &statbuf) < 0) {
- err = errno;
- Tprintf ("stat(%s): %s\n", filepath, strerror (err));
- k5_set_error(ep, err, _("unable to find plugin [%s]: %s"),
- filepath, strerror(err));
- }
- }
-#endif
-
- if (!err) {
- htmp = calloc (1, sizeof (*htmp)); /* calloc initializes ptrs to NULL */
- if (htmp == NULL) { err = ENOMEM; }
- }
-
-#if USE_DLOPEN
- if (!err
-#if USE_CFBUNDLE
- && ((statbuf.st_mode & S_IFMT) == S_IFREG
- || (statbuf.st_mode & S_IFMT) == S_IFDIR)
-#endif /* USE_CFBUNDLE */
- ) {
- void *handle = NULL;
-
-#if USE_CFBUNDLE
- char executablepath[MAXPATHLEN];
-
- if ((statbuf.st_mode & S_IFMT) == S_IFDIR) {
- int lock_err = 0;
- CFStringRef pluginString = NULL;
- CFURLRef pluginURL = NULL;
- CFBundleRef pluginBundle = NULL;
- CFURLRef executableURL = NULL;
-
- /* Lock around CoreFoundation calls since objects are refcounted
- * and the refcounts are not thread-safe. Using pthreads directly
- * because this code is Mac-specific */
- lock_err = pthread_mutex_lock(&krb5int_bundle_mutex);
- if (lock_err) { err = lock_err; }
-
- if (!err) {
- pluginString = CFStringCreateWithCString (kCFAllocatorDefault,
- filepath,
- kCFStringEncodingASCII);
- if (pluginString == NULL) { err = ENOMEM; }
- }
-
- if (!err) {
- pluginURL = CFURLCreateWithFileSystemPath (kCFAllocatorDefault,
- pluginString,
- kCFURLPOSIXPathStyle,
- true);
- if (pluginURL == NULL) { err = ENOMEM; }
- }
-
- if (!err) {
- pluginBundle = CFBundleCreate (kCFAllocatorDefault, pluginURL);
- if (pluginBundle == NULL) { err = ENOENT; } /* XXX need better error */
- }
-
- if (!err) {
- executableURL = CFBundleCopyExecutableURL (pluginBundle);
- if (executableURL == NULL) { err = ENOMEM; }
- }
-
- if (!err) {
- if (!CFURLGetFileSystemRepresentation (executableURL,
- true, /* absolute */
- (UInt8 *)executablepath,
- sizeof (executablepath))) {
- err = ENOMEM;
- }
- }
-
- if (!err) {
- /* override the path the caller passed in */
- filepath = executablepath;
- }
-
- if (executableURL != NULL) { CFRelease (executableURL); }
- if (pluginBundle != NULL) { CFRelease (pluginBundle); }
- if (pluginURL != NULL) { CFRelease (pluginURL); }
- if (pluginString != NULL) { CFRelease (pluginString); }
-
- /* unlock after CFRelease calls since they modify refcounts */
- if (!lock_err) { pthread_mutex_unlock (&krb5int_bundle_mutex); }
- }
-#endif /* USE_CFBUNDLE */
-
- if (!err) {
- handle = dlopen(filepath, PLUGIN_DLOPEN_FLAGS);
- if (handle == NULL) {
- const char *e = dlerror();
- if (e == NULL)
- e = _("unknown failure");
- Tprintf ("dlopen(%s): %s\n", filepath, e);
- err = ENOENT; /* XXX */
- k5_set_error(ep, err, _("unable to load plugin [%s]: %s"),
- filepath, e);
- }
- }
+ if (h->dlhandle != NULL)
+ dlclose(h->dlhandle);
+}
+#define close_plugin close_plugin_dlfcn
- if (!err) {
- got_plugin = 1;
- htmp->dlhandle = handle;
- handle = NULL;
- }
+#elif defined(_WIN32)
- if (handle != NULL) { dlclose (handle); }
+static long
+open_plugin_win32(struct plugin_file_handle *h, const char *filename,
+ struct errinfo *ep)
+{
+ h->module = LoadLibrary(filename);
+ if (h == NULL) {
+ Tprintf("Unable to load dll: %s\n", filename);
+ k5_set_error(ep, ENOENT, _("unable to load DLL [%s]"), filename);
+ return ENOENT;
}
-#endif /* USE_DLOPEN */
-
-#ifdef _WIN32
- if (!err && (statbuf.st_mode & S_IFMT) == S_IFREG) {
- HMODULE handle = NULL;
+ return 0;
+}
+#define open_plugin open_plugin_win32
- handle = LoadLibrary(filepath);
- if (handle == NULL) {
- Tprintf ("Unable to load dll: %s\n", filepath);
- err = ENOENT; /* XXX */
- k5_set_error(ep, err, _("unable to load DLL [%s]"), filepath);
- }
+static long
+get_sym_win32(struct plugin_file_handle *h, const char *csymname,
+ void **sym_out, struct errinfo *ep)
+{
+ LPVOID lpMsgBuf;
+ DWORD dw;
- if (!err) {
- got_plugin = 1;
- htmp->hinstPlugin = handle;
- handle = NULL;
+ if (h->module == NULL)
+ return ENOENT;
+ *sym_out = GetProcAddress(h->module, csymname);
+ if (*sym_out == NULL) {
+ Tprintf("GetProcAddress(%s): %i\n", csymname, GetLastError());
+ dw = GetLastError();
+ if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR)&lpMsgBuf, 0, NULL)) {
+ k5_set_error(ep, ENOENT, _("unable to get DLL Symbol: %s"),
+ (char *)lpMsgBuf);
+ LocalFree(lpMsgBuf);
}
-
- if (handle != NULL)
- FreeLibrary(handle);
- }
-#endif
-
- if (!err && !got_plugin) {
- err = ENOENT; /* no plugin or no way to load plugins */
- k5_set_error(ep, err, _("plugin unavailable: %s"), strerror(err));
+ return ENOENT;
}
+ return 0;
+}
+#define get_sym get_sym_win32
- if (!err) {
- *h = htmp;
- htmp = NULL; /* h takes ownership */
- }
+static void
+close_plugin_win32(struct plugin_file_handle *h)
+{
+ if (h->module != NULL)
+ FreeLibrary(h->module);
+}
+#define close_plugin close_plugin_win32
- free(htmp);
+#else
- return err;
+static long
+open_plugin_dummy(struct plugin_file_handle *h, const char *filename,
+ struct errinfo *ep)
+{
+ k5_set_error(ep, ENOENT, _("plugin loading unavailable"));
+ return ENOENT;
}
+#define open_plugin open_plugin_dummy
static long
-krb5int_get_plugin_sym (struct plugin_file_handle *h,
- const char *csymname, int isfunc, void **ptr,
- struct errinfo *ep)
+get_sym_dummy(struct plugin_file_handle *h, const char *csymname,
+ void **sym_out, struct errinfo *ep)
{
- long err = 0;
- void *sym = NULL;
+ return ENOENT;
+}
+#define get_sym get_sym_dummy
+
+static void
+close_plugin_dummy(struct plugin_file_handle *h)
+{
+}
+#define close_plugin close_plugin_dummy
-#if USE_DLOPEN
- if (!err && !sym && (h->dlhandle != NULL)) {
- /* XXX Do we need to add a leading "_" to the symbol name on any
- modern platforms? */
- sym = dlsym (h->dlhandle, csymname);
- if (sym == NULL) {
- const char *e = dlerror (); /* XXX copy and save away */
- if (e == NULL)
- e = "unknown failure";
- Tprintf ("dlsym(%s): %s\n", csymname, e);
- err = ENOENT; /* XXX */
- k5_set_error(ep, err, "%s", e);
- }
- }
#endif
-#ifdef _WIN32
- LPVOID lpMsgBuf;
- DWORD dw;
+long KRB5_CALLCONV
+krb5int_open_plugin(const char *filename,
+ struct plugin_file_handle **handle_out, struct errinfo *ep)
+{
+ long ret;
+ struct plugin_file_handle *h;
- if (!err && !sym && (h->hinstPlugin != NULL)) {
- sym = GetProcAddress(h->hinstPlugin, csymname);
- if (sym == NULL) {
- const char *e = "unable to get dll symbol"; /* XXX copy and save away */
- Tprintf ("GetProcAddress(%s): %i\n", csymname, GetLastError());
- err = ENOENT; /* XXX */
- k5_set_error(ep, err, "%s", e);
-
- dw = GetLastError();
- if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM,
- NULL,
- dw,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR) &lpMsgBuf,
- 0, NULL )) {
-
- fprintf (stderr, "unable to get dll symbol, %s\n", (LPCTSTR)lpMsgBuf);
- LocalFree(lpMsgBuf);
- }
- }
- }
-#endif
+ *handle_out = NULL;
- if (!err && (sym == NULL)) {
- err = ENOENT; /* unimplemented */
- }
+ h = calloc(1, sizeof(*h));
+ if (h == NULL)
+ return ENOMEM;
- if (!err) {
- *ptr = sym;
+ ret = open_plugin(h, filename, ep);
+ if (ret) {
+ free(h);
+ return ret;
}
- return err;
+ *handle_out = h;
+ return 0;
}
long KRB5_CALLCONV
-krb5int_get_plugin_data (struct plugin_file_handle *h, const char *csymname,
- void **ptr, struct errinfo *ep)
+krb5int_get_plugin_data(struct plugin_file_handle *h, const char *csymname,
+ void **sym_out, struct errinfo *ep)
{
- return krb5int_get_plugin_sym (h, csymname, 0, ptr, ep);
+ return get_sym(h, csymname, sym_out, ep);
}
long KRB5_CALLCONV
-krb5int_get_plugin_func (struct plugin_file_handle *h, const char *csymname,
- void (**ptr)(), struct errinfo *ep)
+krb5int_get_plugin_func(struct plugin_file_handle *h, const char *csymname,
+ void (**sym_out)(), struct errinfo *ep)
{
void *dptr = NULL;
- long err = krb5int_get_plugin_sym (h, csymname, 1, &dptr, ep);
- if (!err) {
- /* Cast function pointers to avoid code duplication */
- *ptr = (void (*)()) dptr;
- }
- return err;
+ long ret = get_sym(h, csymname, &dptr, ep);
+
+ if (!ret)
+ *sym_out = (void (*)())dptr;
+ return ret;
}
void KRB5_CALLCONV
krb5int_close_plugin (struct plugin_file_handle *h)
{
-#if USE_DLOPEN
- if (h->dlhandle != NULL) { dlclose(h->dlhandle); }
-#endif
-#ifdef _WIN32
- if (h->hinstPlugin != NULL) { FreeLibrary(h->hinstPlugin); }
-#endif
- free (h);
+ close_plugin(h);
+ free(h);
}
-/* autoconf docs suggest using this preference order */
-#if HAVE_DIRENT_H || USE_DIRENT_H
-#include <dirent.h>
-#define NAMELEN(D) strlen((D)->d_name)
-#else
-#ifndef _WIN32
-#define dirent direct
-#define NAMELEN(D) ((D)->d->namlen)
-#else
-#define NAMELEN(D) strlen((D)->d_name)
-#endif
-#if HAVE_SYS_NDIR_H
-# include <sys/ndir.h>
-#elif HAVE_SYS_DIR_H
-# include <sys/dir.h>
-#elif HAVE_NDIR_H
-# include <ndir.h>
-#endif
-#endif
-
static long
krb5int_plugin_file_handle_array_init (struct plugin_file_handle ***harray)
{
@@ -619,42 +418,36 @@ krb5int_open_plugin_dirs (const char * const *dirnames,
if (handle != NULL) { krb5int_close_plugin (handle); }
}
} else {
- /* load all plugins in each directory */
- DIR *dir = opendir (dirnames[i]);
+ char **fnames = NULL;
+ int j;
- while (dir != NULL && !err) {
- struct dirent *d = NULL;
+ err = k5_dir_filenames(dirnames[i], &fnames);
+ for (j = 0; !err && fnames[j] != NULL; j++) {
char *filepath = NULL;
struct plugin_file_handle *handle = NULL;
- d = readdir (dir);
- if (d == NULL) { break; }
-
- if ((strcmp (d->d_name, ".") == 0) ||
- (strcmp (d->d_name, "..") == 0)) {
+ if (strcmp(fnames[j], ".") == 0 ||
+ strcmp(fnames[j], "..") == 0)
continue;
- }
- if (!err) {
- int len = NAMELEN (d);
- if (asprintf(&filepath, "%s/%*s", dirnames[i], len, d->d_name) < 0) {
- filepath = NULL;
- err = ENOMEM;
- }
+ if (asprintf(&filepath, "%s/%s", dirnames[i], fnames[j]) < 0) {
+ filepath = NULL;
+ err = ENOMEM;
}
- if (!err) {
- if (krb5int_open_plugin (filepath, &handle, ep) == 0) {
- err = krb5int_plugin_file_handle_array_add (&h, &count, handle);
- if (!err) { handle = NULL; } /* h takes ownership */
- }
+ if (!err && krb5int_open_plugin(filepath, &handle, ep) == 0) {
+ err = krb5int_plugin_file_handle_array_add(&h, &count,
+ handle);
+ if (!err)
+ handle = NULL; /* h takes ownership */
}
free(filepath);
- if (handle != NULL) { krb5int_close_plugin (handle); }
+ if (handle != NULL)
+ krb5int_close_plugin(handle);
}
- if (dir != NULL) { closedir (dir); }
+ k5_free_filenames(fnames);
}
}
--
2.38.1

@ -0,0 +1,48 @@
From 75f71ace74449a6e5154314229bfa61960cd326c Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Thu, 28 Jul 2022 15:20:12 +0200
Subject: [PATCH] Update error checking for OpenSSL CMS_verify
The code for CMS data verification was initially written for OpenSSL's
PKCS7_verify() function. It now uses CMS_verify(), but error handling
is still done using PKCS7_verify() error identifiers. Update the
recognized error codes so that the KDC generates
KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED errors when appropriate.
Use ERR_peek_last_error() to observe the error generated closest to
the API surface.
[ghudson@mit.edu: edited commit message]
ticket: 9069 (new)
tags: pullup
target_version: 1.20-next
---
src/plugins/preauth/pkinit/pkinit_crypto_openssl.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
index 1c2aa02827..16edf15cb2 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
@@ -2102,12 +2102,15 @@ cms_signeddata_verify(krb5_context context,
goto cleanup;
out = BIO_new(BIO_s_mem());
if (CMS_verify(cms, NULL, store, NULL, out, flags) == 0) {
- unsigned long err = ERR_peek_error();
+ unsigned long err = ERR_peek_last_error();
switch(ERR_GET_REASON(err)) {
- case PKCS7_R_DIGEST_FAILURE:
+ case RSA_R_DIGEST_NOT_ALLOWED:
+ case CMS_R_UNKNOWN_DIGEST_ALGORITHM:
+ case CMS_R_NO_MATCHING_DIGEST:
+ case CMS_R_NO_MATCHING_SIGNATURE:
retval = KRB5KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED;
break;
- case PKCS7_R_SIGNATURE_FAILURE:
+ case CMS_R_VERIFICATION_FAILURE:
default:
retval = KRB5KDC_ERR_INVALID_SIG;
}
--
2.38.1

@ -0,0 +1,28 @@
From 3f8a3b57cf0e057635e570d5038fb52c19ca5744 Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Fri, 19 Aug 2022 10:34:52 +0200
Subject: [PATCH] [downstream] Catch SHA-1 digest disallowed error for
PKINIT
An OpenSSL patch causes EVP_R_INVALID_DIGEST error to be raised if
CMS_verify is called to verify a SHA-1 signature. If this error is
caught, it will now return KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED.
---
src/plugins/preauth/pkinit/pkinit_crypto_openssl.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
index 16edf15cb2..bfa3fe8e91 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
@@ -2104,6 +2104,7 @@ cms_signeddata_verify(krb5_context context,
if (CMS_verify(cms, NULL, store, NULL, out, flags) == 0) {
unsigned long err = ERR_peek_last_error();
switch(ERR_GET_REASON(err)) {
+ case EVP_R_INVALID_DIGEST:
case RSA_R_DIGEST_NOT_ALLOWED:
case CMS_R_UNKNOWN_DIGEST_ALGORITHM:
case CMS_R_NO_MATCHING_DIGEST:
--
2.38.1

@ -0,0 +1,239 @@
From 6ba011d89f9cf4661eb7110bf810cfdb514b69fa Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Mon, 19 Sep 2022 15:18:50 -0400
Subject: [PATCH] Add and use ts_interval() helper
ts_delta() returns a signed result, which cannot hold an interval
larger than 2^31-1 seconds. Intervals like this have been seen when
admins set password expiration dates more than 68 years in the future.
Add a second helper ts_interval() which returns a signed result, and
has the arguments reversed so that the start time is first. Use it in
warn_pw_expiry() to handle the password expiration case, in the GSS
krb5 mech where we return an unsigned context or credential lifetime
to the caller, and in the KEYRING ccache type where we compute an
unsigned keyring timeout.
ticket: 9071 (new)
---
src/include/k5-int.h | 9 +++++++++
src/lib/gssapi/krb5/accept_sec_context.c | 10 ++++++----
src/lib/gssapi/krb5/acquire_cred.c | 3 +--
src/lib/gssapi/krb5/context_time.c | 2 +-
src/lib/gssapi/krb5/init_sec_context.c | 4 ++--
src/lib/gssapi/krb5/inq_context.c | 2 +-
src/lib/gssapi/krb5/inq_cred.c | 2 +-
src/lib/gssapi/krb5/s4u_gss_glue.c | 2 +-
src/lib/krb5/ccache/cc_keyring.c | 4 ++--
src/lib/krb5/krb/get_in_tkt.c | 15 +++++++--------
10 files changed, 31 insertions(+), 22 deletions(-)
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index c3aecba7d4..768110e5ef 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -2325,6 +2325,15 @@ ts_delta(krb5_timestamp a, krb5_timestamp b)
return (krb5_deltat)((uint32_t)a - (uint32_t)b);
}
+/* Return (end - start) as an unsigned 32-bit value, or 0 if start > end. */
+static inline uint32_t
+ts_interval(krb5_timestamp start, krb5_timestamp end)
+{
+ if ((uint32_t)start > (uint32_t)end)
+ return 0;
+ return (uint32_t)end - (uint32_t)start;
+}
+
/* Increment a timestamp by a signed 32-bit interval, without relying on
* undefined behavior. */
static inline krb5_timestamp
diff --git a/src/lib/gssapi/krb5/accept_sec_context.c b/src/lib/gssapi/krb5/accept_sec_context.c
index 1bc807172b..7de2c9fd77 100644
--- a/src/lib/gssapi/krb5/accept_sec_context.c
+++ b/src/lib/gssapi/krb5/accept_sec_context.c
@@ -353,8 +353,8 @@ kg_accept_dce(minor_status, context_handle, verifier_cred_handle,
*mech_type = ctx->mech_used;
if (time_rec) {
- *time_rec = ts_delta(ctx->krb_times.endtime, now) +
- ctx->k5_context->clockskew;
+ *time_rec = ts_interval(now - ctx->k5_context->clockskew,
+ ctx->krb_times.endtime);
}
/* Never return GSS_C_DELEG_FLAG since we don't support DCE credential
@@ -1151,8 +1151,10 @@ kg_accept_krb5(minor_status, context_handle,
/* Add the maximum allowable clock skew as a grace period for context
* expiration, just as we do for the ticket. */
- if (time_rec)
- *time_rec = ts_delta(ctx->krb_times.endtime, now) + context->clockskew;
+ if (time_rec) {
+ *time_rec = ts_interval(now - context->clockskew,
+ ctx->krb_times.endtime);
+ }
if (ret_flags)
*ret_flags = ctx->gss_flags;
diff --git a/src/lib/gssapi/krb5/acquire_cred.c b/src/lib/gssapi/krb5/acquire_cred.c
index e226a02692..006eba114d 100644
--- a/src/lib/gssapi/krb5/acquire_cred.c
+++ b/src/lib/gssapi/krb5/acquire_cred.c
@@ -879,8 +879,7 @@ acquire_cred_context(krb5_context context, OM_uint32 *minor_status,
GSS_C_NO_NAME);
if (GSS_ERROR(ret))
goto error_out;
- *time_rec = ts_after(cred->expire, now) ?
- ts_delta(cred->expire, now) : 0;
+ *time_rec = ts_interval(now, cred->expire);
k5_mutex_unlock(&cred->lock);
}
}
diff --git a/src/lib/gssapi/krb5/context_time.c b/src/lib/gssapi/krb5/context_time.c
index 1fdb5a16f2..5469d8154c 100644
--- a/src/lib/gssapi/krb5/context_time.c
+++ b/src/lib/gssapi/krb5/context_time.c
@@ -51,7 +51,7 @@ krb5_gss_context_time(minor_status, context_handle, time_rec)
return(GSS_S_FAILURE);
}
- lifetime = ts_delta(ctx->krb_times.endtime, now);
+ lifetime = ts_interval(now, ctx->krb_times.endtime);
if (!ctx->initiate)
lifetime += ctx->k5_context->clockskew;
if (lifetime <= 0) {
diff --git a/src/lib/gssapi/krb5/init_sec_context.c b/src/lib/gssapi/krb5/init_sec_context.c
index ea87cf6432..f0f094ccb7 100644
--- a/src/lib/gssapi/krb5/init_sec_context.c
+++ b/src/lib/gssapi/krb5/init_sec_context.c
@@ -664,7 +664,7 @@ kg_new_connection(
if (time_rec) {
if ((code = krb5_timeofday(context, &now)))
goto cleanup;
- *time_rec = ts_delta(ctx->krb_times.endtime, now);
+ *time_rec = ts_interval(now, ctx->krb_times.endtime);
}
/* set the other returns */
@@ -878,7 +878,7 @@ mutual_auth(
if (time_rec) {
if ((code = krb5_timeofday(context, &now)))
goto fail;
- *time_rec = ts_delta(ctx->krb_times.endtime, now);
+ *time_rec = ts_interval(now, ctx->krb_times.endtime);
}
if (ret_flags)
diff --git a/src/lib/gssapi/krb5/inq_context.c b/src/lib/gssapi/krb5/inq_context.c
index cac024da1f..51c484fdfe 100644
--- a/src/lib/gssapi/krb5/inq_context.c
+++ b/src/lib/gssapi/krb5/inq_context.c
@@ -120,7 +120,7 @@ krb5_gss_inquire_context(minor_status, context_handle, initiator_name,
/* Add the maximum allowable clock skew as a grace period for context
* expiration, just as we do for the ticket during authentication. */
- lifetime = ts_delta(ctx->krb_times.endtime, now);
+ lifetime = ts_interval(now, ctx->krb_times.endtime);
if (!ctx->initiate)
lifetime += context->clockskew;
if (lifetime < 0)
diff --git a/src/lib/gssapi/krb5/inq_cred.c b/src/lib/gssapi/krb5/inq_cred.c
index bb63b726c8..0e675959a3 100644
--- a/src/lib/gssapi/krb5/inq_cred.c
+++ b/src/lib/gssapi/krb5/inq_cred.c
@@ -131,7 +131,7 @@ krb5_gss_inquire_cred(minor_status, cred_handle, name, lifetime_ret,
}
if (cred->expire != 0) {
- lifetime = ts_delta(cred->expire, now);
+ lifetime = ts_interval(now, cred->expire);
if (lifetime < 0)
lifetime = 0;
}
diff --git a/src/lib/gssapi/krb5/s4u_gss_glue.c b/src/lib/gssapi/krb5/s4u_gss_glue.c
index 7dcfe4e1eb..fa7f980af7 100644
--- a/src/lib/gssapi/krb5/s4u_gss_glue.c
+++ b/src/lib/gssapi/krb5/s4u_gss_glue.c
@@ -279,7 +279,7 @@ kg_compose_deleg_cred(OM_uint32 *minor_status,
if (code != 0)
goto cleanup;
- *time_rec = ts_delta(cred->expire, now);
+ *time_rec = ts_interval(now, cred->expire);
}
major_status = GSS_S_COMPLETE;
diff --git a/src/lib/krb5/ccache/cc_keyring.c b/src/lib/krb5/ccache/cc_keyring.c
index ebef37d607..1dadeef64f 100644
--- a/src/lib/krb5/ccache/cc_keyring.c
+++ b/src/lib/krb5/ccache/cc_keyring.c
@@ -762,7 +762,7 @@ update_keyring_expiration(krb5_context context, krb5_ccache id)
/* Setting the timeout to zero would reset the timeout, so we set it to one
* second instead if creds are already expired. */
- timeout = ts_after(endtime, now) ? ts_delta(endtime, now) : 1;
+ timeout = ts_after(endtime, now) ? ts_interval(now, endtime) : 1;
(void)keyctl_set_timeout(data->cache_id, timeout);
}
@@ -1343,7 +1343,7 @@ krcc_store(krb5_context context, krb5_ccache id, krb5_creds *creds)
if (ts_after(creds->times.endtime, now)) {
(void)keyctl_set_timeout(cred_key,
- ts_delta(creds->times.endtime, now));
+ ts_interval(now, creds->times.endtime));
}
update_keyring_expiration(context, id);
diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
index 8b5ab595e9..1b420a3ac2 100644
--- a/src/lib/krb5/krb/get_in_tkt.c
+++ b/src/lib/krb5/krb/get_in_tkt.c
@@ -1522,7 +1522,7 @@ warn_pw_expiry(krb5_context context, krb5_get_init_creds_opt *options,
void *expire_data;
krb5_timestamp pw_exp, acct_exp, now;
krb5_boolean is_last_req;
- krb5_deltat delta;
+ uint32_t interval;
char ts[256], banner[1024];
if (as_reply == NULL || as_reply->enc_part2 == NULL)
@@ -1553,8 +1553,8 @@ warn_pw_expiry(krb5_context context, krb5_get_init_creds_opt *options,
ret = krb5_timeofday(context, &now);
if (ret != 0)
return;
- if (!is_last_req &&
- (ts_after(now, pw_exp) || ts_delta(pw_exp, now) > 7 * 24 * 60 * 60))
+ interval = ts_interval(now, pw_exp);
+ if (!is_last_req && (!interval || interval > 7 * 24 * 60 * 60))
return;
if (!prompter)
@@ -1564,19 +1564,18 @@ warn_pw_expiry(krb5_context context, krb5_get_init_creds_opt *options,
if (ret != 0)
return;
- delta = ts_delta(pw_exp, now);
- if (delta < 3600) {
+ if (interval < 3600) {
snprintf(banner, sizeof(banner),
_("Warning: Your password will expire in less than one hour "
"on %s"), ts);
- } else if (delta < 86400 * 2) {
+ } else if (interval < 86400 * 2) {
snprintf(banner, sizeof(banner),
_("Warning: Your password will expire in %d hour%s on %s"),
- delta / 3600, delta < 7200 ? "" : "s", ts);
+ interval / 3600, interval < 7200 ? "" : "s", ts);
} else {
snprintf(banner, sizeof(banner),
_("Warning: Your password will expire in %d days on %s"),
- delta / 86400, ts);
+ interval / 86400, ts);
}
/* PROMPTER_INVOCATION */
--
2.38.1

@ -0,0 +1,41 @@
From 9aa12e932f08651785519890896647069e7a30b1 Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Wed, 7 Dec 2022 13:22:42 +0100
Subject: [PATCH] [downstream] Make tests compatible with
sssd_krb5_locator_plugin.so
The sssd_krb5_locator_plugin.so plugin provided by sssd-client conflicts
with the upstream test t_discover_uri.py. The test has to be modified in
order to avoid false positive.
---
src/lib/krb5/os/t_discover_uri.py | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/src/lib/krb5/os/t_discover_uri.py b/src/lib/krb5/os/t_discover_uri.py
index 87bac17929..26bc95a8dc 100644
--- a/src/lib/krb5/os/t_discover_uri.py
+++ b/src/lib/krb5/os/t_discover_uri.py
@@ -1,3 +1,4 @@
+from os.path import exists
from k5test import *
entries = ('URI _kerberos.TEST krb5srv::kkdcp:https://kdc1 1 1\n',
@@ -37,8 +38,14 @@ realm.env['RESOLV_WRAPPER_HOSTS'] = hosts_filename
out = realm.run(['./t_locate_kdc', 'TEST'], env=realm.env)
l = out.splitlines()
+if (exists('/usr/lib/krb5/plugins/libkrb5/sssd_krb5_locator_plugin.so')
+ or exists('/usr/lib64/krb5/plugins/libkrb5/sssd_krb5_locator_plugin.so')):
+ line_range = range(6, 14)
+else:
+ line_range = range(4, 12)
+
j = 0
-for i in range(4, 12):
+for i in line_range:
if l[i].strip() != expected[j]:
fail('URI answers do not match')
j += 1
--
2.38.1

@ -0,0 +1,31 @@
From fb13766f8fbd78acfcf7a150332a4e5474e4f52a Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Mon, 9 Jan 2023 22:39:52 +0100
Subject: [PATCH] [downstream] Do not set root as ksu file owner
Upstream Makefile uses the install command to set root as owner of the
ksu executable file. However, this is no longer supported on latest
versions of the Mock build environment.
In case of ksu, the owner, group, and mode are already set using %attr()
in the specfile.
---
src/config/pre.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/config/pre.in b/src/config/pre.in
index 7eaa2f351c..e9ae71471e 100644
--- a/src/config/pre.in
+++ b/src/config/pre.in
@@ -185,7 +185,7 @@ INSTALL_PROGRAM=@INSTALL_PROGRAM@ $(INSTALL_STRIP)
INSTALL_SCRIPT=@INSTALL_PROGRAM@
INSTALL_DATA=@INSTALL_DATA@
INSTALL_SHLIB=@INSTALL_SHLIB@
-INSTALL_SETUID=$(INSTALL) $(INSTALL_STRIP) -m 4755 -o root
+INSTALL_SETUID=$(INSTALL)
## This is needed because autoconf will sometimes define @exec_prefix@ to be
## ${prefix}.
prefix=@prefix@
--
2.38.1

@ -0,0 +1,165 @@
From 6aea69170c2064aaea73ad3283b6d7dd0cae47e1 Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Thu, 19 Jan 2023 19:22:27 +0100
Subject: [PATCH] [downstream] Allow KRB5KDF, MD5, and MD4 in FIPS mode
OpenSSL's restrictions to use KRB5KDF, MD5, and MD4 in FIPS mode are
bypassed in case AES SHA-1 HMAC or RC4 encryption types are allowed by
the crypto policy.
---
.../crypto/openssl/hash_provider/hash_evp.c | 97 +++++++++++++++++--
src/lib/crypto/openssl/kdf.c | 2 +-
2 files changed, 89 insertions(+), 10 deletions(-)
diff --git a/src/lib/crypto/openssl/hash_provider/hash_evp.c b/src/lib/crypto/openssl/hash_provider/hash_evp.c
index 11659908bb..eb2e693e9f 100644
--- a/src/lib/crypto/openssl/hash_provider/hash_evp.c
+++ b/src/lib/crypto/openssl/hash_provider/hash_evp.c
@@ -44,6 +44,49 @@
#define EVP_MD_CTX_free EVP_MD_CTX_destroy
#endif
+#include <openssl/provider.h>
+#include <openssl/fips.h>
+#include <threads.h>
+
+typedef struct ossl_lib_md_context {
+ OSSL_LIB_CTX *libctx;
+ OSSL_PROVIDER *default_provider;
+ OSSL_PROVIDER *legacy_provider;
+} ossl_md_context_t;
+
+static thread_local ossl_md_context_t *ossl_md_ctx = NULL;
+
+static krb5_error_code
+init_ossl_md_ctx(ossl_md_context_t *ctx, const char *algo)
+{
+ ctx->libctx = OSSL_LIB_CTX_new();
+ if (!ctx->libctx)
+ return KRB5_CRYPTO_INTERNAL;
+
+ /* Load both legacy and default provider as both may be needed. */
+ ctx->default_provider = OSSL_PROVIDER_load(ctx->libctx, "default");
+ ctx->legacy_provider = OSSL_PROVIDER_load(ctx->libctx, "legacy");
+
+ if (!(ctx->default_provider && ctx->legacy_provider))
+ return KRB5_CRYPTO_INTERNAL;
+
+ return 0;
+}
+
+static void
+deinit_ossl_ctx(ossl_md_context_t *ctx)
+{
+ if (ctx->legacy_provider)
+ OSSL_PROVIDER_unload(ctx->legacy_provider);
+
+ if (ctx->default_provider)
+ OSSL_PROVIDER_unload(ctx->default_provider);
+
+ if (ctx->libctx)
+ OSSL_LIB_CTX_free(ctx->libctx);
+}
+
+
static krb5_error_code
hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data,
krb5_data *output)
@@ -60,11 +103,6 @@ hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data,
if (ctx == NULL)
return ENOMEM;
- if (type == EVP_md4() || type == EVP_md5()) {
- /* See comments below in hash_md4() and hash_md5(). */
- EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
- }
-
ok = EVP_DigestInit_ex(ctx, type, NULL);
for (i = 0; i < num_data; i++) {
if (!SIGN_IOV(&data[i]))
@@ -77,6 +115,43 @@ hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data,
return ok ? 0 : KRB5_CRYPTO_INTERNAL;
}
+static krb5_error_code
+hash_legacy_evp(const char *algo, const krb5_crypto_iov *data, size_t num_data,
+ krb5_data *output)
+{
+ krb5_error_code err;
+ EVP_MD *md = NULL;
+
+ if (!ossl_md_ctx) {
+ ossl_md_ctx = malloc(sizeof(ossl_md_context_t));
+ if (!ossl_md_ctx) {
+ err = ENOMEM;
+ goto end;
+ }
+
+ err = init_ossl_md_ctx(ossl_md_ctx, algo);
+ if (err) {
+ deinit_ossl_ctx(ossl_md_ctx);
+ free(ossl_md_ctx);
+ ossl_md_ctx = NULL;
+ goto end;
+ }
+ }
+
+ md = EVP_MD_fetch(ossl_md_ctx->libctx, algo, NULL);
+ if (!md) {
+ err = KRB5_CRYPTO_INTERNAL;
+ goto end;
+ }
+
+ err = hash_evp(md, data, num_data, output);
+
+end:
+ if (md)
+ EVP_MD_free(md);
+
+ return err;
+}
#endif
#ifdef K5_OPENSSL_MD4
@@ -88,7 +163,8 @@ hash_md4(const krb5_crypto_iov *data, size_t num_data, krb5_data *output)
* by IPA. These keys are only used along a (separately) secured channel
* for legacy reasons when performing trusts to Active Directory.
*/
- return hash_evp(EVP_md4(), data, num_data, output);
+ return FIPS_mode() ? hash_legacy_evp("MD4", data, num_data, output)
+ : hash_evp(EVP_md4(), data, num_data, output);
}
const struct krb5_hash_provider krb5int_hash_md4 = {
@@ -100,9 +176,12 @@ const struct krb5_hash_provider krb5int_hash_md4 = {
static krb5_error_code
hash_md5(const krb5_crypto_iov *data, size_t num_data, krb5_data *output)
{
- /* MD5 is needed in FIPS mode for communication with RADIUS servers. This
- * is gated in libkrad by libdefaults->radius_md5_fips_override. */
- return hash_evp(EVP_md5(), data, num_data, output);
+ /*
+ * MD5 is needed in FIPS mode for communication with RADIUS servers. This
+ * is gated in libkrad by libdefaults->radius_md5_fips_override.
+ */
+ return FIPS_mode() ? hash_legacy_evp("MD5", data, num_data, output)
+ : hash_evp(EVP_md5(), data, num_data, output);
}
const struct krb5_hash_provider krb5int_hash_md5 = {
diff --git a/src/lib/crypto/openssl/kdf.c b/src/lib/crypto/openssl/kdf.c
index 5a43c3d9eb..8528ddc4a9 100644
--- a/src/lib/crypto/openssl/kdf.c
+++ b/src/lib/crypto/openssl/kdf.c
@@ -198,7 +198,7 @@ k5_derive_random_rfc3961(const struct krb5_enc_provider *enc, krb5_key key,
goto done;
}
- kdf = EVP_KDF_fetch(NULL, "KRB5KDF", NULL);
+ kdf = EVP_KDF_fetch(NULL, "KRB5KDF", "-fips");
if (kdf == NULL) {
ret = KRB5_CRYPTO_INTERNAL;
goto done;
--
2.38.1

@ -0,0 +1,672 @@
From f09300d9a9988215263775ac122b7ea2898d04db Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Thu, 22 Dec 2022 03:05:23 -0500
Subject: [PATCH] Add PAC full checksums
A paper by Tom Tervoort noted that computing the PAC privsvr checksum
over only the server checksum is vulnerable to collision attacks
(CVE-2022-37967). In response, Microsoft has added a second KDC
checksum over the full contents of the PAC. Generate and verify full
KDC checksums in PACs for service tickets. Update the t_pac.c ticket
test case to use a ticket issued by a recent version of Active
Directory (provided by Stefan Metzmacher).
ticket: 9084 (new)
---
doc/appdev/refs/macros/index.rst | 1 +
src/include/krb5/krb5.hin | 1 +
src/lib/krb5/krb/pac.c | 92 +++++++++--------
src/lib/krb5/krb/pac_sign.c | 146 +++++++++++++++-----------
src/lib/krb5/krb/t_pac.c | 171 ++++++++++++++++++-------------
src/tests/t_authdata.py | 4 +-
6 files changed, 240 insertions(+), 175 deletions(-)
diff --git a/doc/appdev/refs/macros/index.rst b/doc/appdev/refs/macros/index.rst
index 5f34dea5e8..3eeee25593 100644
--- a/doc/appdev/refs/macros/index.rst
+++ b/doc/appdev/refs/macros/index.rst
@@ -247,6 +247,7 @@ Public
KRB5_PAC_SERVER_CHECKSUM.rst
KRB5_PAC_TICKET_CHECKSUM.rst
KRB5_PAC_UPN_DNS_INFO.rst
+ KRB5_PAC_FULL_CHECKSUM.rst
KRB5_PADATA_AFS3_SALT.rst
KRB5_PADATA_AP_REQ.rst
KRB5_PADATA_AS_CHECKSUM.rst
diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
index fb9f2a366c..2ba4010514 100644
--- a/src/include/krb5/krb5.hin
+++ b/src/include/krb5/krb5.hin
@@ -8164,6 +8164,7 @@ krb5_verify_authdata_kdc_issued(krb5_context context,
#define KRB5_PAC_TICKET_CHECKSUM 16 /**< Ticket checksum */
#define KRB5_PAC_ATTRIBUTES_INFO 17 /**< PAC attributes */
#define KRB5_PAC_REQUESTOR 18 /**< PAC requestor SID */
+#define KRB5_PAC_FULL_CHECKSUM 19 /**< KDC full checksum */
struct krb5_pac_data;
/** PAC data structure to convey authorization information */
diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c
index f6c4373de0..954482e0c7 100644
--- a/src/lib/krb5/krb/pac.c
+++ b/src/lib/krb5/krb/pac.c
@@ -490,7 +490,8 @@ zero_signature(krb5_context context, const krb5_pac pac, krb5_ui_4 type,
size_t i;
assert(type == KRB5_PAC_SERVER_CHECKSUM ||
- type == KRB5_PAC_PRIVSVR_CHECKSUM);
+ type == KRB5_PAC_PRIVSVR_CHECKSUM ||
+ type == KRB5_PAC_FULL_CHECKSUM);
assert(data->length >= pac->data.length);
for (i = 0; i < pac->pac->cBuffers; i++) {
@@ -557,17 +558,17 @@ verify_checksum(krb5_context context, const krb5_pac pac, uint32_t buffer_type,
}
static krb5_error_code
-verify_server_checksum(krb5_context context, const krb5_pac pac,
- const krb5_keyblock *server)
+verify_pac_checksums(krb5_context context, const krb5_pac pac,
+ krb5_boolean expect_full_checksum,
+ const krb5_keyblock *server, const krb5_keyblock *privsvr)
{
krb5_error_code ret;
- krb5_data copy; /* PAC with zeroed checksums */
+ krb5_data copy, server_checksum;
+ /* Make a copy of the PAC with zeroed out server and privsvr checksums. */
ret = krb5int_copy_data_contents(context, &pac->data, &copy);
if (ret)
return ret;
-
- /* Zero out both checksum buffers */
ret = zero_signature(context, pac, KRB5_PAC_SERVER_CHECKSUM, &copy);
if (ret)
goto cleanup;
@@ -575,32 +576,46 @@ verify_server_checksum(krb5_context context, const krb5_pac pac,
if (ret)
goto cleanup;
- ret = verify_checksum(context, pac, KRB5_PAC_SERVER_CHECKSUM, server,
- KRB5_KEYUSAGE_APP_DATA_CKSUM, &copy);
+ if (server != NULL) {
+ /* Verify the server checksum over the PAC copy. */
+ ret = verify_checksum(context, pac, KRB5_PAC_SERVER_CHECKSUM, server,
+ KRB5_KEYUSAGE_APP_DATA_CKSUM, &copy);
+ }
-cleanup:
- free(copy.data);
- return ret;
-}
+ if (privsvr != NULL && expect_full_checksum) {
+ /* Zero the full checksum buffer in the copy and verify the full
+ * checksum over the copy with all three checksums zeroed. */
+ ret = zero_signature(context, pac, KRB5_PAC_FULL_CHECKSUM, &copy);
+ if (ret)
+ goto cleanup;
+ ret = verify_checksum(context, pac, KRB5_PAC_FULL_CHECKSUM, privsvr,
+ KRB5_KEYUSAGE_APP_DATA_CKSUM, &copy);
+ if (ret)
+ goto cleanup;
+ }
-static krb5_error_code
-verify_kdc_checksum(krb5_context context, const krb5_pac pac,
- const krb5_keyblock *privsvr)
-{
- krb5_error_code ret;
- krb5_data server_checksum;
+ if (privsvr != NULL) {
+ /* Verify the privsvr checksum over the server checksum. */
+ ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_SERVER_CHECKSUM,
+ &server_checksum);
+ if (ret)
+ return ret;
+ if (server_checksum.length < PAC_SIGNATURE_DATA_LENGTH)
+ return KRB5_BAD_MSIZE;
+ server_checksum.data += PAC_SIGNATURE_DATA_LENGTH;
+ server_checksum.length -= PAC_SIGNATURE_DATA_LENGTH;
- ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_SERVER_CHECKSUM,
- &server_checksum);
- if (ret)
- return ret;
- if (server_checksum.length < PAC_SIGNATURE_DATA_LENGTH)
- return KRB5_BAD_MSIZE;
- server_checksum.data += PAC_SIGNATURE_DATA_LENGTH;
- server_checksum.length -= PAC_SIGNATURE_DATA_LENGTH;
+ ret = verify_checksum(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM, privsvr,
+ KRB5_KEYUSAGE_APP_DATA_CKSUM, &server_checksum);
+ if (ret)
+ goto cleanup;
+ }
+
+ pac->verified = TRUE;
- return verify_checksum(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM, privsvr,
- KRB5_KEYUSAGE_APP_DATA_CKSUM, &server_checksum);
+cleanup:
+ free(copy.data);
+ return ret;
}
/* Per MS-PAC 2.8.3, tickets encrypted to TGS and password change principals
@@ -628,6 +643,7 @@ krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt,
krb5_authdata **authdata, *orig, **ifrel = NULL, **recoded_ifrel = NULL;
uint8_t z = 0;
krb5_authdata zpac = { KV5M_AUTHDATA, KRB5_AUTHDATA_WIN2K_PAC, 1, &z };
+ krb5_boolean is_service_tkt;
size_t i, j;
*pac_out = NULL;
@@ -669,7 +685,8 @@ krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt,
if (ret)
goto cleanup;
- if (privsvr != NULL && k5_pac_should_have_ticket_signature(server_princ)) {
+ is_service_tkt = k5_pac_should_have_ticket_signature(server_princ);
+ if (privsvr != NULL && is_service_tkt) {
/* To check the PAC ticket signatures, re-encode the ticket with the
* PAC contents replaced by a single zero. */
orig = ifrel[j];
@@ -693,8 +710,9 @@ krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt,
goto cleanup;
}
- ret = krb5_pac_verify_ext(context, pac, enc_tkt->times.authtime, NULL,
- server, privsvr, FALSE);
+ ret = verify_pac_checksums(context, pac, is_service_tkt, server, privsvr);
+ if (ret)
+ goto cleanup;
*pac_out = pac;
pac = NULL;
@@ -730,14 +748,8 @@ krb5_pac_verify_ext(krb5_context context,
{
krb5_error_code ret;
- if (server != NULL) {
- ret = verify_server_checksum(context, pac, server);
- if (ret != 0)
- return ret;
- }
-
- if (privsvr != NULL) {
- ret = verify_kdc_checksum(context, pac, privsvr);
+ if (server != NULL || privsvr != NULL) {
+ ret = verify_pac_checksums(context, pac, FALSE, server, privsvr);
if (ret != 0)
return ret;
}
@@ -749,8 +761,6 @@ krb5_pac_verify_ext(krb5_context context,
return ret;
}
- pac->verified = TRUE;
-
return 0;
}
diff --git a/src/lib/krb5/krb/pac_sign.c b/src/lib/krb5/krb/pac_sign.c
index 0f9581abbb..8ea61ac17b 100644
--- a/src/lib/krb5/krb/pac_sign.c
+++ b/src/lib/krb5/krb/pac_sign.c
@@ -187,26 +187,41 @@ k5_pac_encode_header(krb5_context context, krb5_pac pac)
return 0;
}
-krb5_error_code KRB5_CALLCONV
-krb5_pac_sign(krb5_context context, krb5_pac pac, krb5_timestamp authtime,
- krb5_const_principal principal, const krb5_keyblock *server_key,
- const krb5_keyblock *privsvr_key, krb5_data *data)
+/* Find the buffer of type buftype in pac and write within it a checksum of
+ * type cksumtype over data. Set *cksum_out to the checksum. */
+static krb5_error_code
+compute_pac_checksum(krb5_context context, krb5_pac pac, uint32_t buftype,
+ const krb5_keyblock *key, krb5_cksumtype cksumtype,
+ const krb5_data *data, krb5_data *cksum_out)
{
- return krb5_pac_sign_ext(context, pac, authtime, principal, server_key,
- privsvr_key, FALSE, data);
+ krb5_error_code ret;
+ krb5_data buf;
+ krb5_crypto_iov iov[2];
+
+ ret = k5_pac_locate_buffer(context, pac, buftype, &buf);
+ if (ret)
+ return ret;
+
+ assert(buf.length > PAC_SIGNATURE_DATA_LENGTH);
+ *cksum_out = make_data(buf.data + PAC_SIGNATURE_DATA_LENGTH,
+ buf.length - PAC_SIGNATURE_DATA_LENGTH);
+ iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
+ iov[0].data = *data;
+ iov[1].flags = KRB5_CRYPTO_TYPE_CHECKSUM;
+ iov[1].data = *cksum_out;
+ return krb5_c_make_checksum_iov(context, cksumtype, key,
+ KRB5_KEYUSAGE_APP_DATA_CKSUM, iov, 2);
}
-krb5_error_code KRB5_CALLCONV
-krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime,
- krb5_const_principal principal,
- const krb5_keyblock *server_key,
- const krb5_keyblock *privsvr_key, krb5_boolean with_realm,
- krb5_data *data)
+static krb5_error_code
+sign_pac(krb5_context context, krb5_pac pac, krb5_timestamp authtime,
+ krb5_const_principal principal, const krb5_keyblock *server_key,
+ const krb5_keyblock *privsvr_key, krb5_boolean with_realm,
+ krb5_boolean is_service_tkt, krb5_data *data)
{
krb5_error_code ret;
- krb5_data server_cksum, privsvr_cksum;
+ krb5_data full_cksum, server_cksum, privsvr_cksum;
krb5_cksumtype server_cksumtype, privsvr_cksumtype;
- krb5_crypto_iov iov[2];
data->length = 0;
data->data = NULL;
@@ -214,67 +229,53 @@ krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime,
if (principal != NULL) {
ret = k5_insert_client_info(context, pac, authtime, principal,
with_realm);
- if (ret != 0)
+ if (ret)
return ret;
}
- /* Create zeroed buffers for both checksums */
+ /* Create zeroed buffers for all checksums. */
ret = k5_insert_checksum(context, pac, KRB5_PAC_SERVER_CHECKSUM,
server_key, &server_cksumtype);
- if (ret != 0)
+ if (ret)
return ret;
-
ret = k5_insert_checksum(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM,
privsvr_key, &privsvr_cksumtype);
- if (ret != 0)
+ if (ret)
return ret;
+ if (is_service_tkt) {
+ ret = k5_insert_checksum(context, pac, KRB5_PAC_FULL_CHECKSUM,
+ privsvr_key, &privsvr_cksumtype);
+ if (ret)
+ return ret;
+ }
- /* Now, encode the PAC header so that the checksums will include it */
+ /* Encode the PAC header so that the checksums will include it. */
ret = k5_pac_encode_header(context, pac);
- if (ret != 0)
- return ret;
-
- /* Generate the server checksum over the entire PAC */
- ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_SERVER_CHECKSUM,
- &server_cksum);
- if (ret != 0)
+ if (ret)
return ret;
- assert(server_cksum.length > PAC_SIGNATURE_DATA_LENGTH);
-
- iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
- iov[0].data = pac->data;
-
- iov[1].flags = KRB5_CRYPTO_TYPE_CHECKSUM;
- iov[1].data.data = server_cksum.data + PAC_SIGNATURE_DATA_LENGTH;
- iov[1].data.length = server_cksum.length - PAC_SIGNATURE_DATA_LENGTH;
+ if (is_service_tkt) {
+ /* Generate a full KDC checksum over the whole PAC. */
+ ret = compute_pac_checksum(context, pac, KRB5_PAC_FULL_CHECKSUM,
+ privsvr_key, privsvr_cksumtype,
+ &pac->data, &full_cksum);
+ if (ret)
+ return ret;
+ }
- ret = krb5_c_make_checksum_iov(context, server_cksumtype,
- server_key, KRB5_KEYUSAGE_APP_DATA_CKSUM,
- iov, sizeof(iov)/sizeof(iov[0]));
- if (ret != 0)
+ /* Generate the server checksum over the whole PAC, including the full KDC
+ * checksum if we added one. */
+ ret = compute_pac_checksum(context, pac, KRB5_PAC_SERVER_CHECKSUM,
+ server_key, server_cksumtype, &pac->data,
+ &server_cksum);
+ if (ret)
return ret;
- /* Generate the privsvr checksum over the server checksum buffer */
- ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM,
+ /* Generate the privsvr checksum over the server checksum buffer. */
+ ret = compute_pac_checksum(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM,
+ privsvr_key, privsvr_cksumtype, &server_cksum,
&privsvr_cksum);
- if (ret != 0)
- return ret;
-
- assert(privsvr_cksum.length > PAC_SIGNATURE_DATA_LENGTH);
-
- iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
- iov[0].data.data = server_cksum.data + PAC_SIGNATURE_DATA_LENGTH;
- iov[0].data.length = server_cksum.length - PAC_SIGNATURE_DATA_LENGTH;
-
- iov[1].flags = KRB5_CRYPTO_TYPE_CHECKSUM;
- iov[1].data.data = privsvr_cksum.data + PAC_SIGNATURE_DATA_LENGTH;
- iov[1].data.length = privsvr_cksum.length - PAC_SIGNATURE_DATA_LENGTH;
-
- ret = krb5_c_make_checksum_iov(context, privsvr_cksumtype,
- privsvr_key, KRB5_KEYUSAGE_APP_DATA_CKSUM,
- iov, sizeof(iov)/sizeof(iov[0]));
- if (ret != 0)
+ if (ret)
return ret;
data->data = k5memdup(pac->data.data, pac->data.length, &ret);
@@ -288,6 +289,26 @@ krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime,
return 0;
}
+krb5_error_code KRB5_CALLCONV
+krb5_pac_sign(krb5_context context, krb5_pac pac, krb5_timestamp authtime,
+ krb5_const_principal principal, const krb5_keyblock *server_key,
+ const krb5_keyblock *privsvr_key, krb5_data *data)
+{
+ return sign_pac(context, pac, authtime, principal, server_key,
+ privsvr_key, FALSE, FALSE, data);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime,
+ krb5_const_principal principal,
+ const krb5_keyblock *server_key,
+ const krb5_keyblock *privsvr_key, krb5_boolean with_realm,
+ krb5_data *data)
+{
+ return sign_pac(context, pac, authtime, principal, server_key, privsvr_key,
+ with_realm, FALSE, data);
+}
+
/* Add a signature over der_enc_tkt in privsvr to pac. der_enc_tkt should be
* encoded with a dummy PAC authdata element containing a single zero byte. */
static krb5_error_code
@@ -359,6 +380,7 @@ krb5_kdc_sign_ticket(krb5_context context, krb5_enc_tkt_part *enc_tkt,
krb5_error_code ret;
krb5_data *der_enc_tkt = NULL, pac_data = empty_data();
krb5_authdata **list, *pac_ad;
+ krb5_boolean is_service_tkt;
size_t count;
/* Reallocate space for another authdata element in enc_tkt. */
@@ -377,7 +399,8 @@ krb5_kdc_sign_ticket(krb5_context context, krb5_enc_tkt_part *enc_tkt,
memmove(list + 1, list, (count + 1) * sizeof(*list));
list[0] = pac_ad;
- if (k5_pac_should_have_ticket_signature(server_princ)) {
+ is_service_tkt = k5_pac_should_have_ticket_signature(server_princ);
+ if (is_service_tkt) {
ret = encode_krb5_enc_tkt_part(enc_tkt, &der_enc_tkt);
if (ret)
goto cleanup;
@@ -388,9 +411,8 @@ krb5_kdc_sign_ticket(krb5_context context, krb5_enc_tkt_part *enc_tkt,
goto cleanup;
}
- ret = krb5_pac_sign_ext(context, pac, enc_tkt->times.authtime,
- client_princ, server, privsvr, with_realm,
- &pac_data);
+ ret = sign_pac(context, pac, enc_tkt->times.authtime, client_princ, server,
+ privsvr, with_realm, is_service_tkt, &pac_data);
if (ret)
goto cleanup;
diff --git a/src/lib/krb5/krb/t_pac.c b/src/lib/krb5/krb/t_pac.c
index 173bde7bab..81f1642ab0 100644
--- a/src/lib/krb5/krb/t_pac.c
+++ b/src/lib/krb5/krb/t_pac.c
@@ -607,78 +607,102 @@ check_pac(krb5_context context, int index, const unsigned char *pdata,
static const krb5_keyblock ticket_sig_krbtgt_key = {
0, ENCTYPE_AES256_CTS_HMAC_SHA1_96,
- 32, U("\x7a\x58\x98\xd2\xaf\xa6\xaf\xc0\x6a\xce\x06\x04\x4b\xc2\x70\x84"
- "\x9b\x8e\x0a\x6c\x4c\x07\xdc\x6f\xbb\x48\x43\xe1\xd2\xaa\x97\xf7")
+ 32, U("\x03\x73\x81\xEC\x43\x96\x7B\xC2\xAC\x3D\xF5\x2A\xAE\x95\xA6\x8E"
+ "\xBE\x24\x58\xDB\xCE\x52\x28\x20\xAF\x5E\xB7\x04\xA2\x22\x71\x4F")
};
static const krb5_keyblock ticket_sig_server_key = {
- 0, ENCTYPE_ARCFOUR_HMAC,
- 16, U("\xed\x23\x11\x20\x7a\x21\x44\x20\xbf\xc0\x8d\x36\xf7\xf6\xb2\x3e")
+ 0, ENCTYPE_AES256_CTS_HMAC_SHA1_96,
+ 32, U("\x11\x4A\x84\xE3\x14\x8F\xAA\xB1\xFA\x7B\x53\x51\xB2\x8A\xC2\xF1"
+ "\xFD\x19\x6D\x61\xE0\xF3\xF2\x3E\x1F\xDB\xD3\xC1\x79\x7D\xC1\xEE")
};
+/* A ticket issued by an Active Directory KDC (Windows Server 2022), containing
+ * a PAC with a full checksum. */
static const krb5_data ticket_data = {
- .length = 972, .data =
- "\x61\x82\x03\xC8\x30\x82\x03\xC4\xA0\x03\x02\x01\x05\xA1\x0A\x1B"
- "\x08\x43\x44\x4F\x4D\x2E\x43\x4F\x4D\xA2\x0F\x30\x0D\xA0\x03\x02"
- "\x01\x01\xA1\x06\x30\x04\x1B\x02\x73\x31\xA3\x82\x03\x9E\x30\x82"
- "\x03\x9A\xA0\x03\x02\x01\x17\xA1\x03\x02\x01\x03\xA2\x82\x03\x8C"
- "\x04\x82\x03\x88\x44\x31\x61\x20\x17\xC9\xFE\xBC\xAC\x46\xB5\x77"
- "\xE9\x68\x04\x4C\x9B\x31\x91\x0C\xC1\xD4\xDD\xEF\xC7\x34\x20\x08"
- "\x90\x91\xE8\x79\xE0\xB5\x03\x26\xA4\x65\xDE\xEC\x47\x03\x2A\x8F"
- "\x61\xE7\x4D\x38\x5A\x42\x95\x5A\xF9\x2F\x41\x2C\x2A\x6E\x60\xA1"
- "\xEB\x51\xB3\xBD\x4C\x00\x41\x2A\x44\x76\x08\x37\x1A\x51\xFD\x65"
- "\x67\x7E\xBF\x3D\x90\x86\xE3\x9A\x54\x6B\x67\xA8\x08\x7A\x73\xCC"
- "\xC3\xB7\x4B\xD5\x5C\x3A\x14\x6C\xC1\x5F\x54\x4B\x92\x55\xB4\xB7"
- "\x92\x23\x3F\x53\x89\x47\x8E\x1F\x8B\xB9\xDB\x3B\x93\xE8\x70\xE4"
- "\x24\xB8\x9D\xF0\x0E\x35\x28\xF8\x7A\x27\x5D\xF7\x25\x97\x9C\xF5"
- "\x9F\x9F\x64\x04\xF2\xA3\xAB\x11\x15\xB6\xDA\x18\xD6\x46\xD5\xE6"
- "\xB8\x08\xDE\x0A\x62\xFD\xF8\xAA\x52\x90\xD9\x67\x29\xB2\xCD\x06"
- "\xB6\xB0\x50\x2B\x3F\x0F\xA3\xA5\xBF\xAA\x6E\x40\x03\xD6\x5F\x02"
- "\xBC\xD8\x18\x47\x97\x09\xD7\xE4\x96\x3B\xCB\xEB\x92\x2C\x3C\x49"
- "\xFF\x1F\x71\xE0\x52\x94\x0F\x8B\x9F\xB8\x2A\xBB\x9C\xE2\xA3\xDD"
- "\x38\x89\xE2\xB1\x0B\x9E\x1F\x7A\xB3\xE3\xD2\xB0\x94\xDC\x87\xBE"
- "\x37\xA6\xD3\xB3\x29\x35\x9A\x72\xC3\x7A\xF1\xA9\xE6\xC5\xD1\x26"
- "\x83\x65\x44\x17\xBA\x55\xA8\x5E\x94\x26\xED\xE9\x8A\x93\x11\x5D"
- "\x7E\x20\x1B\x9C\x15\x9E\x13\x37\x03\x4D\xDD\x99\x51\xD8\x66\x29"
- "\x6A\xB9\xFB\x49\xFE\x52\x78\xDA\x86\x85\xA9\xA3\xB9\xEF\xEC\xAD"
- "\x35\xA6\x8D\xAC\x0F\x75\x22\xBB\x0B\x49\x1C\x13\x52\x40\xC9\x52"
- "\x69\x09\x54\xD1\x0F\x94\x3F\x22\x48\x67\xB0\x96\x28\xAA\xE6\x28"
- "\xD9\x0C\x08\xEF\x51\xED\x15\x5E\xA2\x53\x59\xA5\x03\xB4\x06\x20"
- "\x3D\xCC\xB4\xC5\xF8\x8C\x73\x67\xA3\x21\x3D\x19\xCD\xD4\x12\x28"
- "\xD2\x93\xDE\x0D\xF0\x71\x10\x50\xD6\x33\x35\x04\x11\x64\x43\x39"
- "\xC3\xDF\x96\xE3\x66\xE3\x85\xCA\xE7\x67\x14\x3A\xF0\x43\xAA\xBB"
- "\xD4\x1D\xB5\x24\xB5\x74\x90\x25\xA7\x87\x7E\xDB\xD3\x83\x8A\x3A"
- "\x69\xA8\x2D\xAF\xB7\xB8\xF3\xDC\x13\xAF\x45\x61\x3F\x59\x39\x7E"
- "\x69\xDE\x0C\x04\xF1\x10\x6B\xB4\x56\xFA\x21\x9F\x72\x2B\x60\x86"
- "\xE3\x23\x0E\xC4\x51\xF6\xBE\xD8\xE1\x5F\xEE\x73\x4C\x17\x4C\x2C"
- "\x1B\xFB\x9F\x1F\x7A\x3B\x07\x5B\x8E\xF1\x01\xAC\xD6\x30\x94\x8A"
- "\x5D\x22\x6F\x08\xCE\xED\x5E\xB6\xDB\x86\x8C\x87\xEB\x8D\x91\xFF"
- "\x0A\x86\x30\xBD\xC0\xF8\x25\xE7\xAE\x24\x35\xF2\xFC\xE5\xFD\x1B"
- "\xB0\x05\x4A\xA3\xE5\xEB\x2E\x05\xAD\x99\x67\x49\x87\xE6\xB3\x87"
- "\x82\xA4\x59\xA7\x6E\xDD\xF2\xB6\x66\xE8\xF7\x70\xF5\xBD\xC9\x0E"
- "\xFA\x9C\x79\x84\xD4\x9B\x05\x0E\xBB\xF5\xDB\xEF\xFC\xCC\x26\xF2"
- "\x93\xCF\xD2\x04\x3C\xA9\x2C\x65\x42\x97\x86\xD8\x38\x0A\x1E\xF6"
- "\xD6\xCA\x30\xB5\x1A\xEC\xFB\xBA\x3B\x84\x57\xB0\xFD\xFB\xE6\xBC"
- "\xF2\x76\xF6\x4C\xBB\xAB\xB1\x31\xA1\x27\x7C\xE6\xE6\x81\xB6\xCE"
- "\x84\x86\x40\xB6\x40\x33\xC4\xF8\xB4\x15\xCF\xAA\xA5\x51\x78\xB9"
- "\x8B\x50\x25\xB2\x88\x86\x96\x72\x8C\x71\x4D\xB5\x3A\x94\x86\x77"
- "\x0E\x95\x9B\x16\x93\xEF\x3A\x11\x79\xBA\x83\xF7\x74\xD3\x8D\xBA"
- "\x15\xE1\x2C\x04\x57\xA8\x92\x1E\x9D\x00\x8E\x20\xFD\x30\x70\xE7"
- "\xF5\x65\x2F\x19\x0C\x94\xBA\x03\x71\x12\x96\xCD\xC8\xB4\x96\xDB"
- "\xCE\x19\xC2\xDF\x3C\xC2\xF6\x3D\x53\xED\x98\xA5\x41\x72\x2A\x22"
- "\x7B\xF3\x2B\x17\x6C\xE1\x39\x7D\xAE\x9B\x11\xF9\xC1\xA6\x9E\x9F"
- "\x89\x3C\x12\xAA\x94\x74\xA7\x4F\x70\xE8\xB9\xDE\x04\xF0\x9D\x39"
- "\x24\x2D\x92\xE8\x46\x2D\x2E\xF0\x40\x66\x1A\xD9\x27\xF9\x98\xF1"
- "\x81\x1D\x70\x62\x63\x30\x6D\xCD\x84\x04\x5F\xFA\x83\xD3\xEC\x8D"
- "\x86\xFB\x40\x61\xC1\x8A\x45\xFF\x7B\xD9\xD4\x18\x61\x7F\x51\xE3"
- "\xFC\x1E\x18\xF0\xAF\xC6\x18\x2C\xE1\x6D\x5D\xF9\x62\xFC\x20\xA3"
- "\xB2\x8A\x5F\xE5\xBB\x29\x0F\x99\x63\x07\x88\x38\x3A\x3B\x73\x2A"
- "\x6D\xDA\x3D\xA8\x0D\x8F\x56\x41\x89\x82\xE5\xB8\x61\x00\x64\x7D"
- "\x17\x0C\xCE\x03\x55\x8F\xF4\x5B\x0D\x50\xF2\xEB\x05\x67\xBE\xDB"
- "\x7B\x75\xC5\xEA\xA1\xAB\x1D\xB0\x3C\x6D\x42\x08\x0B\x9A\x45\x20"
- "\xA8\x8F\xE5\x67\x47\x30\xDE\x93\x5F\x43\x05\xEB\xA8\x2D\x80\xF5"
- "\x1A\xB8\x4A\x4E\x42\x2D\x0B\x7A\xDC\x46\x20\x2D\x13\x17\xDD\x4B"
- "\x94\x96\xAA\x1F\x06\x0C\x1F\x62\x07\x9C\x40\xA1"
+ .length = 1307, .data =
+ "\x61\x82\x05\x17\x30\x82\x05\x13\xA0\x03\x02\x01\x05\xA1\x0F\x1B"
+ "\x0D\x57\x32\x30\x32\x32\x2D\x4C\x37\x2E\x42\x41\x53\x45\xA2\x2A"
+ "\x30\x28\xA0\x03\x02\x01\x01\xA1\x21\x30\x1F\x1B\x04\x63\x69\x66"
+ "\x73\x1B\x17\x77\x32\x30\x32\x32\x2D\x31\x31\x38\x2E\x77\x32\x30"
+ "\x32\x32\x2D\x6C\x37\x2E\x62\x61\x73\x65\xA3\x82\x04\xCD\x30\x82"
+ "\x04\xC9\xA0\x03\x02\x01\x12\xA1\x03\x02\x01\x05\xA2\x82\x04\xBB"
+ "\x04\x82\x04\xB7\x44\x5C\x7B\x5A\x3F\x2E\xA3\x50\x34\xDE\xB0\x69"
+ "\x23\x2D\x47\x89\x2C\xC0\xA3\xF9\xDD\x70\xAA\xA5\x1E\xFE\x74\xE5"
+ "\x19\xA2\x4F\x65\x6C\x9E\x00\xB4\x60\x00\x7C\x0C\x29\x43\x31\x99"
+ "\x77\x02\x73\xED\xB9\x40\xF5\xD2\xD1\xC9\x20\x0F\xE3\x38\xF9\xCC"
+ "\x5E\x2A\xBD\x1F\x91\x66\x1A\xD8\x2A\x80\x3C\x2C\x00\x3C\x1E\xC9"
+ "\x2A\x29\x19\x19\x96\x18\x54\x03\x97\x8F\x1D\x5F\xDB\xE9\x66\x68"
+ "\xCD\xB1\xD5\x00\x35\x69\x49\x45\xF1\x6A\x78\x7B\x37\x71\x87\x14"
+ "\x1C\x98\x4D\x69\xCB\x1B\xD8\xF5\xA3\xD8\x53\x4A\x75\x76\x62\xBA"
+ "\x6C\x3F\xEA\x8B\x97\x21\xCA\x8A\x46\x4B\x38\xDA\x09\x9F\x5A\xC8"
+ "\x38\xFF\x34\x97\x5B\xA2\xE5\xBA\xC9\x87\x17\xD8\x08\x05\x7A\x83"
+ "\x04\xD6\x02\x8E\x9B\x18\xB6\x40\x1A\xF7\x47\x25\x24\x3E\x37\x1E"
+ "\xF6\xC1\x3A\x1F\xCA\xB3\x43\x5A\xAE\x94\x83\x31\xAF\xFB\xEE\xED"
+ "\x46\x71\xEF\xE2\x37\x37\x15\xFE\x1B\x0B\x9E\xF8\x3E\x0C\x43\x96"
+ "\xB6\x0A\x04\x78\xF8\x5E\xAA\x33\x1F\xE2\x07\x5A\x8D\xC4\x4E\x32"
+ "\x6D\xD6\xA0\xC5\xEA\x3D\x12\x59\xD4\x41\x40\x4E\xA1\xD8\xBE\xED"
+ "\x17\xCB\x68\xCC\x59\xCB\x53\xB2\x0E\x58\x8A\xA9\x33\x7F\x6F\x2B"
+ "\x37\x89\x08\x44\xBA\xC7\x67\x17\xBB\x91\xF7\xC3\x0F\x00\xF8\xAA"
+ "\xA1\x33\xA6\x08\x47\xCA\xFA\xE8\x49\x27\x45\x46\xF1\xC1\xC3\x5F"
+ "\xE2\x45\x0A\x7D\x64\x52\x8C\x2E\xE1\xDE\xFF\xB2\x64\xEC\x69\x98"
+ "\x15\xDF\x9E\xB1\xEB\xD6\x9D\x08\x06\x4E\x73\xC1\x0B\x71\x21\x05"
+ "\x9E\xBC\xA2\x17\xCF\xB3\x70\xF4\xEF\xB8\x69\xA9\x94\x27\xFD\x5E"
+ "\x72\xB1\x2D\xD2\x20\x1B\x57\x80\xAB\x38\x97\xCF\x22\x68\x4F\xB8"
+ "\xB7\x17\x53\x25\x67\x0B\xED\xD1\x58\x20\x0D\x45\xF9\x09\xFA\xE7"
+ "\x61\x3E\xDB\xC2\x59\x7B\x3A\x3B\x59\x81\x51\xAA\xA4\x81\xF4\x96"
+ "\x3B\xE1\x6F\x6F\xF4\x8E\x68\x9E\xBA\x1E\x0F\xF2\x44\x68\x11\xFC"
+ "\x2B\x5F\xBE\xF2\xEA\x07\x80\xB9\xCA\x9E\x41\xBD\x2F\x81\xF5\x11"
+ "\x2A\x12\xF3\x4F\xD6\x12\x16\x0F\x21\x90\xF1\xD3\x1E\xF1\xA4\x94"
+ "\x46\xEA\x30\xF3\x84\x06\xC1\xA4\x51\xFC\x43\x35\xBD\xEF\x4D\x89"
+ "\x1D\xA5\x44\xB2\x69\xC4\x0F\xBF\x86\x01\x08\x44\x77\xD5\xB4\xB7"
+ "\x5C\x3F\xA7\xD4\x2F\x39\x73\x85\x88\xEE\xB1\x64\x1D\x80\x6C\xEE"
+ "\x6E\x31\x90\x92\x0D\xA1\xB7\xC4\x5C\xCC\xEE\x91\xC8\xCB\x11\x2D"
+ "\x4A\x1A\x7D\x43\x8F\xEB\x60\x09\xED\x1B\x07\x58\xBE\xBC\xBD\x29"
+ "\xF3\xB3\xA3\x4F\xC5\x8A\x30\x33\xB9\xA9\x9F\x43\x08\x27\x15\xC4"
+ "\x9C\x5D\x8E\xBD\x5C\x05\xC6\x05\x9C\x87\x60\x08\x1E\xE2\x52\xB8"
+ "\x45\x8D\x28\xB6\x2C\x15\x46\x74\x9F\x0E\xAA\x6B\x70\x3A\x2A\x55"
+ "\x45\x26\xB2\x58\x4D\x35\xA6\xF1\x96\xBE\x60\xB2\x71\x7B\xF8\x54"
+ "\xB9\x90\x21\x8E\xB9\x0F\x35\x98\x5E\x88\xEB\x1A\x53\xB4\x59\x7F"
+ "\xAF\x69\x1C\x61\x67\xF4\xF6\xBD\xAC\x24\xCD\xB7\xA9\x67\xE8\xA1"
+ "\x83\x85\x5F\x11\x74\x1F\xF7\x4C\x78\x36\xEF\x50\x74\x88\x58\x4B"
+ "\x1A\x9F\x84\x9A\x9A\x05\x92\xEC\x1D\xD5\xF3\xC4\x95\x51\x28\xE2"
+ "\x3F\x32\x87\xB2\xFD\x21\x27\x66\xE4\x6B\x85\x2F\xDC\x7B\xC0\x22"
+ "\xEB\x7A\x94\x20\x5A\x7B\xD3\x7A\xB9\x5B\xF8\x1A\x5A\x84\x4E\xA1"
+ "\x73\x41\x53\xD2\x60\xF7\x7C\xEE\x68\x59\x85\x80\xFC\x3D\x70\x4B"
+ "\x04\x32\xE7\xF2\xFD\xBD\xB3\xD9\x21\xE2\x37\x56\xA2\x16\xCC\xDE"
+ "\x8A\xD3\xBC\x71\xEF\x58\x19\x0E\x45\x8A\x5B\x53\xD6\x77\x30\x6A"
+ "\xA7\xF8\x68\x06\x4E\x07\xCA\xCE\x30\xD7\x35\xAB\x1A\xC7\x18\xD4"
+ "\xC6\x2F\x1A\xFF\xE9\x7A\x94\x0B\x76\x5E\x7E\x29\x0C\xE6\xD3\x3B"
+ "\x5B\x44\x96\xA8\xF1\x29\x23\x95\xD9\x79\xB3\x39\xFC\x76\xED\xE1"
+ "\x1E\x67\x4E\xF7\xE8\x7B\x7A\x12\x9E\xD8\x4B\x35\x09\x0A\xF2\xC1"
+ "\x63\x5B\xEE\xFD\x2A\xC2\xA6\x66\x30\x3C\x1F\x95\xAF\x65\x22\x95"
+ "\x14\x1D\xF5\xD5\xDC\x38\x79\x35\x1C\xCD\x24\x47\xE0\xFD\x08\xC8"
+ "\xF4\x15\x55\x9F\xD9\xC7\xAC\x3F\x67\xB3\x4F\xEB\x26\x7C\x8E\xD6"
+ "\x74\xB3\x0A\xCD\xE7\xFA\xBE\x7E\xA3\x3E\xEC\x61\x50\x77\x52\x56"
+ "\xCF\x90\x5D\x48\xFB\xD4\x2C\x6C\x61\x8B\xDD\x2B\xF5\x92\x1F\x30"
+ "\xBF\x3F\x80\x0D\x31\xDB\xB2\x0B\x7D\x84\xE3\xA6\x42\x7F\x00\x38"
+ "\x44\x02\xC5\xB8\xD9\x58\x29\x9D\x68\x5C\x32\x8B\x76\xAE\xED\x15"
+ "\xF9\x7C\xAE\x7B\xB6\x8E\xD6\x54\x24\xFF\xFA\x87\x05\xEF\x15\x08"
+ "\x5E\x4B\x21\xA2\x2F\x49\xE7\x0F\xC3\xD0\xB9\x49\x22\xEF\xD5\xCA"
+ "\xB2\x11\xF2\x17\xB6\x77\x24\x68\x76\xB2\x07\xF8\x0A\x73\xDD\x65"
+ "\x9C\x75\x64\xF7\xA1\xC6\x23\x08\x84\x72\x3E\x54\x2E\xEB\x9B\x40"
+ "\xA6\x83\x87\xEB\xB5\x00\x40\x4F\xE1\x72\x2A\x59\x3A\x06\x60\x29"
+ "\x7E\x25\x2F\xD8\x80\x40\x8C\x59\xCA\xCF\x8E\x44\xE4\x2D\x84\x7E"
+ "\xCB\xFD\x1E\x3B\xD5\xFF\x9A\xB9\x66\x93\x6D\x5E\xC8\xB7\x13\x26"
+ "\xD6\x38\x1B\x2B\xE1\x87\x96\x05\xD5\xF3\xAB\x68\xF7\x12\x62\x2C"
+ "\x58\xC1\xC9\x85\x3C\x72\xF1\x26\xEE\xC0\x09\x5F\x1D\x4B\xAC\x01"
+ "\x41\xC8\x12\xF8\xF3\x93\x43\x41\xFF\xEC\x0B\x80\xE2\xEE\x20\x85"
+ "\x25\xCD\x6C\x30\x8C\x0D\x24\x2E\xBA\x19\xEA\x28\x7F\xCF\xD5\x10"
+ "\x5C\xE9\xB2\x9D\x5F\x16\xE4\xC0\xF3\xCC\xD9\x68\x4A\x05\x08\x70"
+ "\x17\x26\xC8\x5C\x4A\xBF\x94\x6A\x0E\xD5\xDA\x67\x47\x4B\xAF\x44"
+ "\xE3\x94\xAA\x05\xDB\xA2\x49\x74\xFA\x5C\x69\xAB\x44\xB7\xF7\xBA"
+ "\xAE\x7A\x23\x87\xEB\x54\x7E\x80\xF1\x5B\x60\xA5\x93\xE5\xD4\x24"
+ "\x84\xF7\x0A\x16\x10\xBE\xE9\x4D\xD8\x6B\x15\x40\x5D\x74\xDA\x1B"
+ "\xFF\x2E\x4D\x17\x9D\x35\xF7\x0D\xCF\x66\x38\x0D\x8A\xE4\xDD\x6B"
+ "\xE1\x0F\x1F\xBD\xFD\x4F\x30\x37\x3F\x96\xB4\x92\x54\xD3\x9A\x7A"
+ "\xD1\x5B\x5B\xA9\x54\x16\xE6\x24\xAB\xD4\x23\x39\x7D\xD2\xC7\x09"
+ "\xFA\xD4\x86\x55\x4D\x60\xC2\x87\x67\x6B\xE6"
};
static void
@@ -686,7 +710,7 @@ test_pac_ticket_signature(krb5_context context)
{
krb5_error_code ret;
krb5_ticket *ticket;
- krb5_principal sprinc;
+ krb5_principal cprinc, sprinc;
krb5_authdata **authdata1, **authdata2;
krb5_pac pac, pac2, pac3;
uint32_t *list;
@@ -701,7 +725,13 @@ test_pac_ticket_signature(krb5_context context)
if (ret)
err(context, ret, "while decrypting ticket");
- ret = krb5_parse_name(context, "s1@CDOM.COM", &sprinc);
+ ret = krb5_parse_name(context, "administrator@W2022-L7.BASE", &cprinc);
+ if (ret)
+ err(context, ret, "krb5_parse_name");
+
+ ret = krb5_parse_name(context,
+ "cifs/w2022-118.w2022-l7.base@W2022-L7.BASE",
+ &sprinc);
if (ret)
err(context, ret, "krb5_parse_name");
@@ -713,7 +743,7 @@ test_pac_ticket_signature(krb5_context context)
/* In this test, the server is also the client. */
ret = krb5_pac_verify(context, pac, ticket->enc_part2->times.authtime,
- ticket->server, NULL, NULL);
+ cprinc, NULL, NULL);
if (ret)
err(context, ret, "while verifying PAC client info");
@@ -722,7 +752,7 @@ test_pac_ticket_signature(krb5_context context)
ticket->enc_part2->authorization_data = NULL;
ret = krb5_kdc_sign_ticket(context, ticket->enc_part2, pac, sprinc,
- sprinc, &ticket_sig_server_key,
+ cprinc, &ticket_sig_server_key,
&ticket_sig_krbtgt_key, FALSE);
if (ret)
err(context, ret, "while signing ticket");
@@ -781,6 +811,7 @@ test_pac_ticket_signature(krb5_context context)
krb5_pac_free(context, pac);
krb5_pac_free(context, pac2);
krb5_pac_free(context, pac3);
+ krb5_free_principal(context, cprinc);
krb5_free_principal(context, sprinc);
krb5_free_ticket(context, ticket);
}
diff --git a/src/tests/t_authdata.py b/src/tests/t_authdata.py
index 47ea9e4b47..e934799268 100644
--- a/src/tests/t_authdata.py
+++ b/src/tests/t_authdata.py
@@ -11,7 +11,7 @@ realm = K5Realm(krb5_conf=conf)
# container.
mark('baseline authdata')
out = realm.run(['./adata', realm.host_princ])
-if '?128: [6, 7, 10, 16]' not in out or '^-42: Hello' not in out:
+if '?128: [6, 7, 10, 16, 19]' not in out or '^-42: Hello' not in out:
fail('expected authdata not seen for basic request')
# Requested authdata is copied into the ticket, with KDC-only types
@@ -243,7 +243,7 @@ out = realm.run(['./adata', '-p', realm.user_princ, 'service/2'])
if '+97: [indcl]' not in out or '[inds1]' in out:
fail('correct auth-indicator not seen for S4U2Proxy req')
# Make sure a PAC with an S4U_DELEGATION_INFO(11) buffer is included.
-if '?128: [1, 6, 7, 10, 11, 16]' not in out:
+if '?128: [1, 6, 7, 10, 11, 16, 19]' not in out:
fail('PAC with delegation info not seen for S4U2Proxy req')
# Get another S4U2Proxy ticket including request-authdata.
--
2.39.1

@ -0,0 +1,45 @@
From ff9c99b689855a646c371379d30a668dfd7a87a7 Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Wed, 1 Feb 2023 15:57:26 +0100
Subject: [PATCH] Fix possible double-free during KDB creation
In krb5_dbe_def_encrypt_key_data(), when we free
key_data->key_data_contents[0], reset it to null so the caller doesn't
free it as well.
Since commit a06945b4ec267e8b80e5e8c95edd89930ff12103 this bug
manifests as a double-free during KDB creation if master key
encryption fails.
[ghudson@mit.edu: edited commit message]
ticket: 9086 (new)
tags: pullup
target_version: 1.20-next
---
src/lib/kdb/encrypt_key.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/lib/kdb/encrypt_key.c b/src/lib/kdb/encrypt_key.c
index dc612c810e..91debea533 100644
--- a/src/lib/kdb/encrypt_key.c
+++ b/src/lib/kdb/encrypt_key.c
@@ -109,6 +109,7 @@ krb5_dbe_def_encrypt_key_data( krb5_context context,
if ((retval = krb5_c_encrypt(context, mkey, /* XXX */ 0, 0,
&plain, &cipher))) {
free(key_data->key_data_contents[0]);
+ key_data->key_data_contents[0] = NULL;
return retval;
}
@@ -121,6 +122,7 @@ krb5_dbe_def_encrypt_key_data( krb5_context context,
key_data->key_data_contents[1] = malloc(keysalt->data.length);
if (key_data->key_data_contents[1] == NULL) {
free(key_data->key_data_contents[0]);
+ key_data->key_data_contents[0] = NULL;
return ENOMEM;
}
memcpy(key_data->key_data_contents[1], keysalt->data.data,
--
2.39.1

@ -0,0 +1,36 @@
From 604fce63b468d0efce4438df4ba0286f00bfce8d Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Tue, 21 Feb 2023 10:03:35 +0100
Subject: [PATCH] Fix meridian type in kadmin datetime parser
The meridian suffix is typed as "Number" in kadmin YACC file for
datetime parsing, while it should be using the "Meridian" enumeration
one.
This results in invalid Meridian value on 64-bit IBM zSystems (s390x),
causing core dumped errors on most kadmin commands where meridian
suffices are used.
Upstream PR:
https://github.com/krb5/krb5/pull/1290
---
src/kadmin/cli/getdate.y | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/kadmin/cli/getdate.y b/src/kadmin/cli/getdate.y
index b9dceec1ee..d14cf963c5 100644
--- a/src/kadmin/cli/getdate.y
+++ b/src/kadmin/cli/getdate.y
@@ -181,7 +181,8 @@ static time_t yyRelSeconds;
%token tAGO tID tDST tNEVER
%token <Number> tDAY tDAYZONE tMINUTE_UNIT tMONTH tMONTH_UNIT
-%token <Number> tSEC_UNIT tSNUMBER tUNUMBER tZONE tMERIDIAN
+%token <Number> tSEC_UNIT tSNUMBER tUNUMBER tZONE
+%token <Meridian> tMERIDIAN
%type <Meridian> o_merid
%%
--
2.39.1

@ -1,220 +0,0 @@
From 3d11179707923b033fa413387a33296b673ff52d Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Thu, 14 Jan 2021 18:13:09 -0500
Subject: [PATCH] Add APIs for marshalling credentials
Faciliate KCM daemon implementations by providing functions to
deserialize and reserialize credentials in the FILE v4 format.
[ghudson@mit.edu: minor editorial changes]
ticket: 8980 (new)
(cherry picked from commit 18ea3bd2fca55b789b7de9c663624bc11d348fa6)
---
doc/appdev/refs/api/index.rst | 2 ++
src/include/krb5/krb5.hin | 36 ++++++++++++++++++++++
src/lib/krb5/ccache/ccmarshal.c | 53 +++++++++++++++++++++++++++++++++
src/lib/krb5/ccache/t_marshal.c | 15 +++++++++-
src/lib/krb5/libkrb5.exports | 2 ++
src/lib/krb5_32.def | 4 +++
6 files changed, 111 insertions(+), 1 deletion(-)
diff --git a/doc/appdev/refs/api/index.rst b/doc/appdev/refs/api/index.rst
index 727d9b492..9e03fd386 100644
--- a/doc/appdev/refs/api/index.rst
+++ b/doc/appdev/refs/api/index.rst
@@ -232,6 +232,7 @@ Rarely used public interfaces
krb5_kt_remove_entry.rst
krb5_kt_start_seq_get.rst
krb5_make_authdata_kdc_issued.rst
+ krb5_marshal_credentials.rst
krb5_merge_authdata.rst
krb5_mk_1cred.rst
krb5_mk_error.rst
@@ -285,6 +286,7 @@ Rarely used public interfaces
krb5_tkt_creds_get_times.rst
krb5_tkt_creds_init.rst
krb5_tkt_creds_step.rst
+ krb5_unmarshal_credentials.rst
krb5_verify_init_creds.rst
krb5_verify_init_creds_opt_init.rst
krb5_verify_init_creds_opt_set_ap_req_nofail.rst
diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
index 63e67a2ba..c26dde535 100644
--- a/src/include/krb5/krb5.hin
+++ b/src/include/krb5/krb5.hin
@@ -3125,6 +3125,42 @@ krb5_get_credentials(krb5_context context, krb5_flags options,
krb5_ccache ccache, krb5_creds *in_creds,
krb5_creds **out_creds);
+/**
+ * Serialize a @c krb5_creds object.
+ *
+ * @param [in] context Library context
+ * @param [in] creds The credentials object to serialize
+ * @param [out] data_out The serialized credentials
+ *
+ * Serialize @a creds in the format used by the FILE ccache format (vesion 4)
+ * and KCM ccache protocol.
+ *
+ * Use krb5_free_data() to free @a data_out when it is no longer needed.
+ *
+ * @retval 0 Success; otherwise - Kerberos error codes
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_marshal_credentials(krb5_context context, krb5_creds *in_creds,
+ krb5_data **data_out);
+
+/**
+ * Deserialize a @c krb5_creds object.
+ *
+ * @param [in] context Library context
+ * @param [in] data The serialized credentials
+ * @param [out] creds_out The resulting creds object
+ *
+ * Deserialize @a data to credentials in the format used by the FILE ccache
+ * format (vesion 4) and KCM ccache protocol.
+ *
+ * Use krb5_free_creds() to free @a creds_out when it is no longer needed.
+ *
+ * @retval 0 Success; otherwise - Kerberos error codes
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_unmarshal_credentials(krb5_context context, const krb5_data *data,
+ krb5_creds **creds_out);
+
/** @deprecated Replaced by krb5_get_validated_creds. */
krb5_error_code KRB5_CALLCONV
krb5_get_credentials_validate(krb5_context context, krb5_flags options,
diff --git a/src/lib/krb5/ccache/ccmarshal.c b/src/lib/krb5/ccache/ccmarshal.c
index ae634ccab..ab284e721 100644
--- a/src/lib/krb5/ccache/ccmarshal.c
+++ b/src/lib/krb5/ccache/ccmarshal.c
@@ -515,3 +515,56 @@ k5_marshal_mcred(struct k5buf *buf, krb5_creds *mcred)
if (mcred->second_ticket.length > 0)
put_data(buf, version, &mcred->second_ticket);
}
+
+krb5_error_code KRB5_CALLCONV
+krb5_marshal_credentials(krb5_context context, krb5_creds *in_creds,
+ krb5_data **data_out)
+{
+ krb5_error_code ret;
+ krb5_data *data;
+ struct k5buf buf;
+
+ *data_out = NULL;
+
+ data = k5alloc(sizeof(krb5_data), &ret);
+ if (ret)
+ return ret;
+
+ k5_buf_init_dynamic(&buf);
+ k5_marshal_cred(&buf, 4, in_creds);
+
+ ret = k5_buf_status(&buf);
+ if (ret) {
+ free(data);
+ return ret;
+ }
+
+ /* Steal payload from buf. */
+ *data = make_data(buf.data, buf.len);
+ *data_out = data;
+ return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_unmarshal_credentials(krb5_context context, const krb5_data *data,
+ krb5_creds **creds_out)
+{
+ krb5_error_code ret;
+ krb5_creds *creds;
+
+ *creds_out = NULL;
+
+ creds = k5alloc(sizeof(krb5_creds), &ret);
+ if (ret)
+ return ret;
+
+ ret = k5_unmarshal_cred((unsigned char *)data->data, data->length, 4,
+ creds);
+ if (ret) {
+ free(creds);
+ return ret;
+ }
+
+ *creds_out = creds;
+ return 0;
+}
diff --git a/src/lib/krb5/ccache/t_marshal.c b/src/lib/krb5/ccache/t_marshal.c
index bd0284afa..96e0931a2 100644
--- a/src/lib/krb5/ccache/t_marshal.c
+++ b/src/lib/krb5/ccache/t_marshal.c
@@ -268,13 +268,14 @@ main(int argc, char **argv)
krb5_context context;
krb5_ccache cache;
krb5_principal princ;
- krb5_creds cred1, cred2;
+ krb5_creds cred1, cred2, *alloc_cred;
krb5_cc_cursor cursor;
const char *filename;
char *ccname, filebuf[256];
int version, fd;
const struct test *t;
struct k5buf buf;
+ krb5_data ser_data, *alloc_data;
if (argc != 2)
abort();
@@ -285,6 +286,18 @@ main(int argc, char **argv)
if (krb5_init_context(&context) != 0)
abort();
+ /* Test public functions for unmarshalling and marshalling. */
+ ser_data = make_data((char *)tests[3].cred1, tests[3].cred1len);
+ if (krb5_unmarshal_credentials(context, &ser_data, &alloc_cred) != 0)
+ abort();
+ verify_cred1(alloc_cred);
+ if (krb5_marshal_credentials(context, alloc_cred, &alloc_data) != 0)
+ abort();
+ assert(alloc_data->length == tests[3].cred1len);
+ assert(memcmp(tests[3].cred1, alloc_data->data, alloc_data->length) == 0);
+ krb5_free_data(context, alloc_data);
+ krb5_free_creds(context, alloc_cred);
+
for (version = FIRST_VERSION; version <= 4; version++) {
t = &tests[version - 1];
diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports
index 2d9d56530..adbfa332b 100644
--- a/src/lib/krb5/libkrb5.exports
+++ b/src/lib/krb5/libkrb5.exports
@@ -489,6 +489,7 @@ krb5_lock_file
krb5_make_authdata_kdc_issued
krb5_make_full_ipaddr
krb5_make_fulladdr
+krb5_marshal_credentials
krb5_mcc_ops
krb5_merge_authdata
krb5_mk_1cred
@@ -592,6 +593,7 @@ krb5_timeofday
krb5_timestamp_to_sfstring
krb5_timestamp_to_string
krb5_unlock_file
+krb5_unmarshal_credentials
krb5_unpack_full_ipaddr
krb5_unparse_name
krb5_unparse_name_ext
diff --git a/src/lib/krb5_32.def b/src/lib/krb5_32.def
index 4953907aa..60b8dd311 100644
--- a/src/lib/krb5_32.def
+++ b/src/lib/krb5_32.def
@@ -503,3 +503,7 @@ EXPORTS
; new in 1.19
k5_cc_store_primary_cred @470 ; PRIVATE
k5_kt_have_match @471 ; PRIVATE GSSAPI
+
+; new in 1.20
+ krb5_marshal_credentials @472
+ krb5_unmarshal_credentials @473

@ -1,359 +0,0 @@
From 418e64100d1e3f8c8e3f773909347bad270a2921 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Thu, 11 Feb 2021 15:33:10 +0100
Subject: [PATCH] Add KCM_OP_GET_CRED_LIST for faster iteration
For large caches, one IPC operation per credential dominates the cost
of iteration. Instead transfer the whole list of credentials to the
client in one IPC operation.
Add optional support for the new opcode to the test KCM server to
allow testing of the main and fallback code paths.
[ghudson@mit.edu: fixed memory leaks and potential memory errors;
adjusted code style and comments; rewrote commit message; added
kcmserver.py support and tests]
ticket: 8990 (new)
(cherry picked from commit 81bdb47d8ded390263d8ee48f71d5c312b4f1736)
(cherry picked from commit a0ee8b02e56c65e5dcd569caed0e151cef004ef4)
---
src/include/kcm.h | 12 ++-
src/lib/krb5/ccache/cc_kcm.c | 144 ++++++++++++++++++++++++++++++++---
src/tests/kcmserver.py | 28 ++++++-
src/tests/t_ccache.py | 10 ++-
4 files changed, 175 insertions(+), 19 deletions(-)
diff --git a/src/include/kcm.h b/src/include/kcm.h
index 5ea1447cd..e4140c3a0 100644
--- a/src/include/kcm.h
+++ b/src/include/kcm.h
@@ -51,9 +51,9 @@
*
* All replies begin with a 32-bit big-endian reply code.
*
- * Parameters are appended to the request or reply with no delimiters. Flags
- * and time offsets are stored as 32-bit big-endian integers. Names are
- * marshalled as zero-terminated strings. Principals and credentials are
+ * Parameters are appended to the request or reply with no delimiters. Flags,
+ * time offsets, and lengths are stored as 32-bit big-endian integers. Names
+ * are marshalled as zero-terminated strings. Principals and credentials are
* marshalled in the v4 FILE ccache format. UUIDs are 16 bytes. UUID lists
* are not delimited, so nothing can come after them.
*/
@@ -89,7 +89,11 @@ typedef enum kcm_opcode {
KCM_OP_HAVE_NTLM_CRED,
KCM_OP_DEL_NTLM_CRED,
KCM_OP_DO_NTLM_AUTH,
- KCM_OP_GET_NTLM_USER_LIST
+ KCM_OP_GET_NTLM_USER_LIST,
+
+ /* MIT extensions */
+ KCM_OP_MIT_EXTENSION_BASE = 13000,
+ KCM_OP_GET_CRED_LIST, /* (name) -> (count, count*{len, cred}) */
} kcm_opcode;
#endif /* KCM_H */
diff --git a/src/lib/krb5/ccache/cc_kcm.c b/src/lib/krb5/ccache/cc_kcm.c
index 9093f894d..772928e4d 100644
--- a/src/lib/krb5/ccache/cc_kcm.c
+++ b/src/lib/krb5/ccache/cc_kcm.c
@@ -61,6 +61,17 @@ struct uuid_list {
size_t pos;
};
+struct cred_list {
+ krb5_creds *creds;
+ size_t count;
+ size_t pos;
+};
+
+struct kcm_cursor {
+ struct uuid_list *uuids;
+ struct cred_list *creds;
+};
+
struct kcmio {
SOCKET fd;
#ifdef __APPLE__
@@ -489,6 +500,69 @@ free_uuid_list(struct uuid_list *uuids)
free(uuids);
}
+static void
+free_cred_list(struct cred_list *list)
+{
+ size_t i;
+
+ if (list == NULL)
+ return;
+
+ /* Creds are transferred to the caller as list->pos is incremented, so we
+ * can start freeing there. */
+ for (i = list->pos; i < list->count; i++)
+ krb5_free_cred_contents(NULL, &list->creds[i]);
+ free(list->creds);
+ free(list);
+}
+
+/* Fetch a cred list from req->reply. */
+static krb5_error_code
+kcmreq_get_cred_list(struct kcmreq *req, struct cred_list **creds_out)
+{
+ struct cred_list *list;
+ const unsigned char *data;
+ krb5_error_code ret = 0;
+ size_t count, len, i;
+
+ *creds_out = NULL;
+
+ /* Check a rough bound on the count to prevent very large allocations. */
+ count = k5_input_get_uint32_be(&req->reply);
+ if (count > req->reply.len / 4)
+ return KRB5_KCM_MALFORMED_REPLY;
+
+ list = malloc(sizeof(*list));
+ if (list == NULL)
+ return ENOMEM;
+
+ list->creds = NULL;
+ list->count = count;
+ list->pos = 0;
+ list->creds = k5calloc(count, sizeof(*list->creds), &ret);
+ if (list->creds == NULL) {
+ free(list);
+ return ret;
+ }
+
+ for (i = 0; i < count; i++) {
+ len = k5_input_get_uint32_be(&req->reply);
+ data = k5_input_get_bytes(&req->reply, len);
+ if (data == NULL)
+ break;
+ ret = k5_unmarshal_cred(data, len, 4, &list->creds[i]);
+ if (ret)
+ break;
+ }
+ if (i < count) {
+ free_cred_list(list);
+ return (ret == ENOMEM) ? ENOMEM : KRB5_KCM_MALFORMED_REPLY;
+ }
+
+ *creds_out = list;
+ return 0;
+}
+
static void
kcmreq_free(struct kcmreq *req)
{
@@ -753,33 +827,53 @@ kcm_start_seq_get(krb5_context context, krb5_ccache cache,
{
krb5_error_code ret;
struct kcmreq req = EMPTY_KCMREQ;
- struct uuid_list *uuids;
+ struct uuid_list *uuids = NULL;
+ struct cred_list *creds = NULL;
+ struct kcm_cursor *cursor;
*cursor_out = NULL;
get_kdc_offset(context, cache);
- kcmreq_init(&req, KCM_OP_GET_CRED_UUID_LIST, cache);
+ kcmreq_init(&req, KCM_OP_GET_CRED_LIST, cache);
ret = cache_call(context, cache, &req);
- if (ret)
+ if (ret == 0) {
+ /* GET_CRED_LIST is available. */
+ ret = kcmreq_get_cred_list(&req, &creds);
+ if (ret)
+ goto cleanup;
+ } else if (ret == KRB5_FCC_INTERNAL) {
+ /* Fall back to GET_CRED_UUID_LIST. */
+ kcmreq_free(&req);
+ kcmreq_init(&req, KCM_OP_GET_CRED_UUID_LIST, cache);
+ ret = cache_call(context, cache, &req);
+ if (ret)
+ goto cleanup;
+ ret = kcmreq_get_uuid_list(&req, &uuids);
+ if (ret)
+ goto cleanup;
+ } else {
goto cleanup;
- ret = kcmreq_get_uuid_list(&req, &uuids);
- if (ret)
+ }
+
+ cursor = k5alloc(sizeof(*cursor), &ret);
+ if (cursor == NULL)
goto cleanup;
- *cursor_out = (krb5_cc_cursor)uuids;
+ cursor->uuids = uuids;
+ cursor->creds = creds;
+ *cursor_out = (krb5_cc_cursor)cursor;
cleanup:
kcmreq_free(&req);
return ret;
}
-static krb5_error_code KRB5_CALLCONV
-kcm_next_cred(krb5_context context, krb5_ccache cache, krb5_cc_cursor *cursor,
- krb5_creds *cred_out)
+static krb5_error_code
+next_cred_by_uuid(krb5_context context, krb5_ccache cache,
+ struct uuid_list *uuids, krb5_creds *cred_out)
{
krb5_error_code ret;
struct kcmreq req;
- struct uuid_list *uuids = (struct uuid_list *)*cursor;
memset(cred_out, 0, sizeof(*cred_out));
@@ -797,11 +891,39 @@ kcm_next_cred(krb5_context context, krb5_ccache cache, krb5_cc_cursor *cursor,
return map_invalid(ret);
}
+static krb5_error_code KRB5_CALLCONV
+kcm_next_cred(krb5_context context, krb5_ccache cache, krb5_cc_cursor *cursor,
+ krb5_creds *cred_out)
+{
+ struct kcm_cursor *c = (struct kcm_cursor *)*cursor;
+ struct cred_list *list;
+
+ if (c->uuids != NULL)
+ return next_cred_by_uuid(context, cache, c->uuids, cred_out);
+
+ list = c->creds;
+ if (list->pos >= list->count)
+ return KRB5_CC_END;
+
+ /* Transfer memory ownership of one cred to the caller. */
+ *cred_out = list->creds[list->pos];
+ memset(&list->creds[list->pos], 0, sizeof(*list->creds));
+ list->pos++;
+
+ return 0;
+}
+
static krb5_error_code KRB5_CALLCONV
kcm_end_seq_get(krb5_context context, krb5_ccache cache,
krb5_cc_cursor *cursor)
{
- free_uuid_list((struct uuid_list *)*cursor);
+ struct kcm_cursor *c = *cursor;
+
+ if (c == NULL)
+ return 0;
+ free_uuid_list(c->uuids);
+ free_cred_list(c->creds);
+ free(c);
*cursor = NULL;
return 0;
}
diff --git a/src/tests/kcmserver.py b/src/tests/kcmserver.py
index 57432e5a7..8c5e66ff1 100644
--- a/src/tests/kcmserver.py
+++ b/src/tests/kcmserver.py
@@ -23,6 +23,7 @@
# traceback.print_exception(etype, value, tb, file=f)
# sys.excepthook = ehook
+import optparse
import select
import socket
import struct
@@ -49,12 +50,14 @@ class KCMOpcodes(object):
SET_DEFAULT_CACHE = 21
GET_KDC_OFFSET = 22
SET_KDC_OFFSET = 23
+ GET_CRED_LIST = 13001
class KRB5Errors(object):
KRB5_CC_END = -1765328242
KRB5_CC_NOSUPP = -1765328137
KRB5_FCC_NOFILE = -1765328189
+ KRB5_FCC_INTERNAL = -1765328188
def make_uuid():
@@ -183,6 +186,14 @@ def op_set_kdc_offset(argbytes):
return 0, b''
+def op_get_cred_list(argbytes):
+ name, rest = unmarshal_name(argbytes)
+ cache = get_cache(name)
+ creds = [cache.creds[u] for u in cache.cred_uuids]
+ return 0, (struct.pack('>L', len(creds)) +
+ b''.join(struct.pack('>L', len(c)) + c for c in creds))
+
+
ophandlers = {
KCMOpcodes.GEN_NEW : op_gen_new,
KCMOpcodes.INITIALIZE : op_initialize,
@@ -197,7 +208,8 @@ ophandlers = {
KCMOpcodes.GET_DEFAULT_CACHE : op_get_default_cache,
KCMOpcodes.SET_DEFAULT_CACHE : op_set_default_cache,
KCMOpcodes.GET_KDC_OFFSET : op_get_kdc_offset,
- KCMOpcodes.SET_KDC_OFFSET : op_set_kdc_offset
+ KCMOpcodes.SET_KDC_OFFSET : op_set_kdc_offset,
+ KCMOpcodes.GET_CRED_LIST : op_get_cred_list
}
# Read and respond to a request from the socket s.
@@ -215,7 +227,11 @@ def service_request(s):
majver, minver, op = struct.unpack('>BBH', req[:4])
argbytes = req[4:]
- code, payload = ophandlers[op](argbytes)
+
+ if op in ophandlers:
+ code, payload = ophandlers[op](argbytes)
+ else:
+ code, payload = KRB5Errors.KRB5_FCC_INTERNAL, b''
# The KCM response is the code (4 bytes) and the response payload.
# The Heimdal IPC response is the length of the KCM response (4
@@ -226,9 +242,15 @@ def service_request(s):
s.sendall(hipc_response)
return True
+parser = optparse.OptionParser()
+parser.add_option('-c', '--credlist', action='store_true', dest='credlist',
+ default=False, help='Support KCM_OP_GET_CRED_LIST')
+(options, args) = parser.parse_args()
+if not options.credlist:
+ del ophandlers[KCMOpcodes.GET_CRED_LIST]
server = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-server.bind(sys.argv[1])
+server.bind(args[0])
server.listen(5)
select_input = [server,]
sys.stderr.write('starting...\n')
diff --git a/src/tests/t_ccache.py b/src/tests/t_ccache.py
index 66804afa5..90040fb7b 100755
--- a/src/tests/t_ccache.py
+++ b/src/tests/t_ccache.py
@@ -125,10 +125,18 @@ def collection_test(realm, ccname):
collection_test(realm, 'DIR:' + os.path.join(realm.testdir, 'cc'))
+
+# Test KCM without and with GET_CRED_LIST support.
kcmserver_path = os.path.join(srctop, 'tests', 'kcmserver.py')
-realm.start_server([sys.executable, kcmserver_path, kcm_socket_path],
+kcmd = realm.start_server([sys.executable, kcmserver_path, kcm_socket_path],
+ 'starting...')
+collection_test(realm, 'KCM:')
+stop_daemon(kcmd)
+os.remove(kcm_socket_path)
+realm.start_server([sys.executable, kcmserver_path, '-c', kcm_socket_path],
'starting...')
collection_test(realm, 'KCM:')
+
if test_keyring:
def cleanup_keyring(anchor, name):
out = realm.run(['keyctl', 'list', anchor])

@ -1,25 +0,0 @@
From 2f039fc910022c9569fe6941a194f0b26bd6c894 Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Fri, 20 Sep 2019 16:11:29 -0400
Subject: [PATCH] Add buildsystem detection of the OpenSSL-3 KDF interface
(cherry picked from commit a3e03dfd40928c4615bd9b8546eac0c104377850)
---
src/configure.ac | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/configure.ac b/src/configure.ac
index eb6307468..9c2e816fe 100644
--- a/src/configure.ac
+++ b/src/configure.ac
@@ -282,6 +282,10 @@ AC_SUBST(CRYPTO_IMPL)
AC_SUBST(CRYPTO_IMPL_CFLAGS)
AC_SUBST(CRYPTO_IMPL_LIBS)
+if test "$CRYPTO_IMPL" = openssl; then
+ AC_CHECK_FUNCS(EVP_KDF_fetch)
+fi
+
AC_ARG_WITH([prng-alg],
AC_HELP_STRING([--with-prng-alg=ALG], [use specified PRNG algorithm. @<:@fortuna@:>@]),
[PRNG_ALG=$withval

@ -1,84 +0,0 @@
From c76a01279bbbbcfd296d2ead8f6e2a5bee7e8443 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Fri, 15 Jan 2021 14:43:34 -0500
Subject: [PATCH] Add hostname canonicalization helper to k5test.py
To facilitate fallback tests, add a canonicalize_hostname() function
to k5test.py which works similarly to krb5_expand_hostname(). Use it
in t_gssapi.py for the recently-added acceptor name fallback test.
(cherry picked from commit 225fffe4e912772acea3a01d45bafb60bfb80948)
---
src/tests/gssapi/t_gssapi.py | 11 +++--------
src/util/k5test.py | 22 ++++++++++++++++++++++
2 files changed, 25 insertions(+), 8 deletions(-)
diff --git a/src/tests/gssapi/t_gssapi.py b/src/tests/gssapi/t_gssapi.py
index 1af6f31c2..e22cec427 100755
--- a/src/tests/gssapi/t_gssapi.py
+++ b/src/tests/gssapi/t_gssapi.py
@@ -8,7 +8,7 @@ for realm in multipass_realms():
realm.run(['./t_iov', '-s', 'p:' + realm.host_princ])
realm.run(['./t_pcontok', 'p:' + realm.host_princ])
-realm = K5Realm(krb5_conf={'libdefaults': {'rdns': 'false'}})
+realm = K5Realm()
# Test gss_add_cred().
realm.run(['./t_add_cred'])
@@ -62,13 +62,8 @@ realm.run(['./t_accname', 'p:host/-nomatch-',
expected_msg=' not found in keytab')
# If possible, test with an acceptor name requiring fallback to match
-# against a keytab entry. Forward-canonicalize the hostname, relying
-# on the rdns=false realm setting.
-try:
- ai = socket.getaddrinfo(hostname, None, 0, 0, 0, socket.AI_CANONNAME)
- (family, socktype, proto, canonname, sockaddr) = ai[0]
-except socket.gaierror:
- canonname = hostname
+# against a keytab entry.
+canonname = canonicalize_hostname(hostname)
if canonname != hostname:
os.rename(realm.keytab, realm.keytab + '.save')
canonprinc = 'host/' + canonname
diff --git a/src/util/k5test.py b/src/util/k5test.py
index 789b0f4b9..251d11a9d 100644
--- a/src/util/k5test.py
+++ b/src/util/k5test.py
@@ -155,6 +155,10 @@ Scripts may use the following functions and variables:
* password(name): Return a weakly random password based on name. The
password will be consistent across calls with the same name.
+* canonicalize_hostname(name, rdns=True): Return the DNS
+ canonicalization of name, optionally using reverse DNS. On error,
+ return name converted to lowercase.
+
* stop_daemon(proc): Stop a daemon process started with
realm.start_server() or realm.start_in_inetd(). Only necessary if
the port needs to be reused; daemon processes will be stopped
@@ -458,6 +462,24 @@ def password(name):
return name + str(os.getpid())
+def canonicalize_hostname(name, rdns=True):
+ """Canonicalize name using DNS, optionally with reverse DNS."""
+ try:
+ ai = socket.getaddrinfo(name, None, 0, 0, 0, socket.AI_CANONNAME)
+ except socket.gaierror as e:
+ return name.lower()
+ (family, socktype, proto, canonname, sockaddr) = ai[0]
+
+ if not rdns:
+ return canonname.lower()
+
+ try:
+ rname = socket.getnameinfo(sockaddr, socket.NI_NAMEREQD)
+ except socket.gaierror:
+ return canonname.lower()
+ return rname[0].lower()
+
+
# Exit handler which ensures processes are cleaned up and, on failure,
# prints messages to help developers debug the problem.
def _onexit():

@ -1,61 +0,0 @@
From 4c2f596da5ddb8a1687a4f9c969d5a8dcd2cbcc7 Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Thu, 3 Jun 2021 16:03:07 -0400
Subject: [PATCH] Allow kinit with keytab to defer canonicalization
[ghudson@mit.edu: added tests]
ticket: 9012 (new)
(cherry picked from commit 5e6a6efc5df689d9fb8730d0227167ffbb6ece0e)
(cherry picked from commit 090c7319652466339e3e6482bdd1b5a294638dff)
---
src/clients/kinit/kinit.c | 11 -----------
src/tests/t_keytab.py | 13 +++++++++++++
2 files changed, 13 insertions(+), 11 deletions(-)
diff --git a/src/clients/kinit/kinit.c b/src/clients/kinit/kinit.c
index d1f5d74c3..5a6d7237c 100644
--- a/src/clients/kinit/kinit.c
+++ b/src/clients/kinit/kinit.c
@@ -510,17 +510,6 @@ k5_begin(struct k_opts *opts, struct k5_data *k5)
_("when creating default server principal name"));
goto cleanup;
}
- if (k5->me->realm.data[0] == 0) {
- ret = krb5_unparse_name(k5->ctx, k5->me, &k5->name);
- if (ret == 0) {
- com_err(progname, KRB5_ERR_HOST_REALM_UNKNOWN,
- _("(principal %s)"), k5->name);
- } else {
- com_err(progname, KRB5_ERR_HOST_REALM_UNKNOWN,
- _("for local services"));
- }
- goto cleanup;
- }
} else if (k5->out_cc != NULL) {
/* If the output ccache is initialized, use its principal. */
if (krb5_cc_get_principal(k5->ctx, k5->out_cc, &princ) == 0)
diff --git a/src/tests/t_keytab.py b/src/tests/t_keytab.py
index 850375c92..a9adebb26 100755
--- a/src/tests/t_keytab.py
+++ b/src/tests/t_keytab.py
@@ -41,6 +41,19 @@ realm.kinit(realm.user_princ, flags=['-i'],
expected_msg='keytab specified, forcing -k')
realm.klist(realm.user_princ)
+# Test default principal for -k. This operation requires
+# canonicalization against the keytab in krb5_get_init_creds_keytab()
+# as the krb5_sname_to_principal() result won't have a realm. Try
+# with and without without fallback processing since the code paths
+# are different.
+mark('default principal for -k')
+realm.run([kinit, '-k'])
+realm.klist(realm.host_princ)
+no_canon_conf = {'libdefaults': {'dns_canonicalize_hostname': 'false'}}
+no_canon = realm.special_env('no_canon', False, krb5_conf=no_canon_conf)
+realm.run([kinit, '-k'], env=no_canon)
+realm.klist(realm.host_princ)
+
# Test extracting keys with multiple key versions present.
mark('multi-kvno extract')
os.remove(realm.keytab)

@ -1,104 +0,0 @@
From 92a4b760d741494dacbb4d9db4cf2db9e3b01f2c Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Mon, 29 Mar 2021 14:32:56 -0400
Subject: [PATCH] Fix KCM flag transmission for remove_cred
MIT krb5 uses low bits for KRB5_TC flags, while Heimdal uses high bits
so that the same flag word can also hold KRB5_GC flags. Add a mapping
function and send the Heimdal flag values when performing a
remove_cred operation.
ticket: 8995
(cherry picked from commit 11a82cf424f9c905bb73680c64524f087090d4ef)
(cherry picked from commit 04f0de4420508161ce439f262f2761ff51a07ab0)
---
src/include/kcm.h | 19 +++++++++++++++++++
src/lib/krb5/ccache/cc_kcm.c | 36 +++++++++++++++++++++++++++++++++++-
2 files changed, 54 insertions(+), 1 deletion(-)
diff --git a/src/include/kcm.h b/src/include/kcm.h
index e4140c3a0..9b66f1cbd 100644
--- a/src/include/kcm.h
+++ b/src/include/kcm.h
@@ -56,8 +56,27 @@
* are marshalled as zero-terminated strings. Principals and credentials are
* marshalled in the v4 FILE ccache format. UUIDs are 16 bytes. UUID lists
* are not delimited, so nothing can come after them.
+ *
+ * Flag words must use Heimdal flag values, which are not the same as MIT krb5
+ * values for KRB5_GC and KRB5_TC constants. The same flag word may contain
+ * both kinds of flags in Heimdal, but not in MIT krb5. Defines for the
+ * applicable Heimdal flag values are given below using KCM_GC and KCM_TC
+ * prefixes.
*/
+#define KCM_GC_CACHED (1U << 0)
+
+#define KCM_TC_DONT_MATCH_REALM (1U << 31)
+#define KCM_TC_MATCH_KEYTYPE (1U << 30)
+#define KCM_TC_MATCH_SRV_NAMEONLY (1U << 29)
+#define KCM_TC_MATCH_FLAGS_EXACT (1U << 28)
+#define KCM_TC_MATCH_FLAGS (1U << 27)
+#define KCM_TC_MATCH_TIMES_EXACT (1U << 26)
+#define KCM_TC_MATCH_TIMES (1U << 25)
+#define KCM_TC_MATCH_AUTHDATA (1U << 24)
+#define KCM_TC_MATCH_2ND_TKT (1U << 23)
+#define KCM_TC_MATCH_IS_SKEY (1U << 22)
+
/* Opcodes without comments are currently unused in the MIT client
* implementation. */
typedef enum kcm_opcode {
diff --git a/src/lib/krb5/ccache/cc_kcm.c b/src/lib/krb5/ccache/cc_kcm.c
index 772928e4d..1f81a2190 100644
--- a/src/lib/krb5/ccache/cc_kcm.c
+++ b/src/lib/krb5/ccache/cc_kcm.c
@@ -110,6 +110,40 @@ map_invalid(krb5_error_code code)
KRB5_KCM_MALFORMED_REPLY : code;
}
+/*
+ * Map an MIT krb5 KRB5_TC flag word to the equivalent Heimdal flag word. Note
+ * that there is no MIT krb5 equivalent for Heimdal's KRB5_TC_DONT_MATCH_REALM
+ * (which is like KRB5_TC_MATCH_SRV_NAMEONLY but also applies to the client
+ * principal) and no Heimdal equivalent for MIT krb5's KRB5_TC_SUPPORTED_KTYPES
+ * (which matches against enctypes from the krb5_context rather than the
+ * matching cred).
+ */
+static inline krb5_flags
+map_tcflags(krb5_flags mitflags)
+{
+ krb5_flags heimflags = 0;
+
+ if (mitflags & KRB5_TC_MATCH_TIMES)
+ heimflags |= KCM_TC_MATCH_TIMES;
+ if (mitflags & KRB5_TC_MATCH_IS_SKEY)
+ heimflags |= KCM_TC_MATCH_IS_SKEY;
+ if (mitflags & KRB5_TC_MATCH_FLAGS)
+ heimflags |= KCM_TC_MATCH_FLAGS;
+ if (mitflags & KRB5_TC_MATCH_TIMES_EXACT)
+ heimflags |= KCM_TC_MATCH_TIMES_EXACT;
+ if (mitflags & KRB5_TC_MATCH_FLAGS_EXACT)
+ heimflags |= KCM_TC_MATCH_FLAGS_EXACT;
+ if (mitflags & KRB5_TC_MATCH_AUTHDATA)
+ heimflags |= KCM_TC_MATCH_AUTHDATA;
+ if (mitflags & KRB5_TC_MATCH_SRV_NAMEONLY)
+ heimflags |= KCM_TC_MATCH_SRV_NAMEONLY;
+ if (mitflags & KRB5_TC_MATCH_2ND_TKT)
+ heimflags |= KCM_TC_MATCH_2ND_TKT;
+ if (mitflags & KRB5_TC_MATCH_KTYPE)
+ heimflags |= KCM_TC_MATCH_KEYTYPE;
+ return heimflags;
+}
+
/* Begin a request for the given opcode. If cache is non-null, supply the
* cache name as a request parameter. */
static void
@@ -936,7 +970,7 @@ kcm_remove_cred(krb5_context context, krb5_ccache cache, krb5_flags flags,
struct kcmreq req;
kcmreq_init(&req, KCM_OP_REMOVE_CRED, cache);
- k5_buf_add_uint32_be(&req.reqbuf, flags);
+ k5_buf_add_uint32_be(&req.reqbuf, map_tcflags(flags));
k5_marshal_mcred(&req.reqbuf, mcred);
ret = cache_call(context, cache, &req);
kcmreq_free(&req);

@ -1,63 +0,0 @@
From b4f3df953015bf6d2d4c973b458f778f31615c11 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Tue, 11 May 2021 14:04:07 -0400
Subject: [PATCH] Fix KCM retrieval support for sssd
Commit 795ebba8c039be172ab93cd41105c73ffdba0fdb added a retrieval
handler using KCM_OP_RETRIEVE, falling back on the same error codes as
the previous KCM_OP_GET_CRED_LIST support. But sssd (as of 2.4)
returns KRB5_CC_NOSUPP instead of KRB5_CC_IO if it recognizes an
opcode but does not implement it. Add a helper function to recognize
all known unsupported-opcode error codes, and use it in kcm_retrieve()
and kcm_start_seq_get().
ticket: 8997
(cherry picked from commit da103e36e13f3c846bcddbe38dd518a21e5260a0)
(cherry picked from commit a5b2cff51808cd86fe8195e7ac074ecd25c3344d)
---
src/lib/krb5/ccache/cc_kcm.c | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/src/lib/krb5/ccache/cc_kcm.c b/src/lib/krb5/ccache/cc_kcm.c
index 23fcf13ea..18505cd3d 100644
--- a/src/lib/krb5/ccache/cc_kcm.c
+++ b/src/lib/krb5/ccache/cc_kcm.c
@@ -144,6 +144,20 @@ map_tcflags(krb5_flags mitflags)
return heimflags;
}
+/*
+ * Return true if code could indicate an unsupported operation. Heimdal's KCM
+ * returns KRB5_FCC_INTERNAL. sssd's KCM daemon (as of sssd 2.4) returns
+ * KRB5_CC_NO_SUPP if it recognizes the operation but does not implement it,
+ * and KRB5_CC_IO if it doesn't recognize the operation (which is unfortunate
+ * since it could also indicate a communication failure).
+ */
+static krb5_boolean
+unsupported_op_error(krb5_error_code code)
+{
+ return code == KRB5_FCC_INTERNAL || code == KRB5_CC_IO ||
+ code == KRB5_CC_NOSUPP;
+}
+
/* Begin a request for the given opcode. If cache is non-null, supply the
* cache name as a request parameter. */
static void
@@ -841,7 +855,7 @@ kcm_retrieve(krb5_context context, krb5_ccache cache, krb5_flags flags,
ret = cache_call(context, cache, &req);
/* Fall back to iteration if the server does not support retrieval. */
- if (ret == KRB5_FCC_INTERNAL || ret == KRB5_CC_IO) {
+ if (unsupported_op_error(ret)) {
ret = k5_cc_retrieve_cred_default(context, cache, flags, mcred,
cred_out);
goto cleanup;
@@ -922,7 +936,7 @@ kcm_start_seq_get(krb5_context context, krb5_ccache cache,
ret = kcmreq_get_cred_list(&req, &creds);
if (ret)
goto cleanup;
- } else if (ret == KRB5_FCC_INTERNAL || ret == KRB5_CC_IO) {
+ } else if (unsupported_op_error(ret)) {
/* Fall back to GET_CRED_UUID_LIST. */
kcmreq_free(&req);
kcmreq_init(&req, KCM_OP_GET_CRED_UUID_LIST, cache);

@ -1,47 +0,0 @@
From 0a8dfc380fe3b210662ba1b1d452fcec2f84841b Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Tue, 3 Aug 2021 01:15:27 -0400
Subject: [PATCH] Fix KDC null deref on TGS inner body null server
After the KDC decodes a FAST inner body, it does not check for a null
server. Prior to commit 39548a5b17bbda9eeb63625a201cfd19b9de1c5b this
would typically result in an error from krb5_unparse_name(), but with
the addition of get_local_tgt() it results in a null dereference. Add
a null check.
Reported by Joseph Sutton of Catalyst.
CVE-2021-37750:
In MIT krb5 releases 1.14 and later, an authenticated attacker can
cause a null dereference in the KDC by sending a FAST TGS request with
no server field.
ticket: 9008 (new)
tags: pullup
target_version: 1.19-next
target_version: 1.18-next
(cherry picked from commit d775c95af7606a51bf79547a94fa52ddd1cb7f49)
(cherry picked from commit bb8fa495d00ccd931eec87a01b8920636cf7903e)
(cherry picked from commit dfe383f8251d0edc7e5e08ec5e4fdd9b7f902b2a)
---
src/kdc/do_tgs_req.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c
index 463a9c0dd..7c596a111 100644
--- a/src/kdc/do_tgs_req.c
+++ b/src/kdc/do_tgs_req.c
@@ -208,6 +208,11 @@ process_tgs_req(krb5_kdc_req *request, krb5_data *pkt,
status = "FIND_FAST";
goto cleanup;
}
+ if (sprinc == NULL) {
+ status = "NULL_SERVER";
+ errcode = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
+ goto cleanup;
+ }
errcode = get_local_tgt(kdc_context, &sprinc->realm, header_server,
&local_tgt, &local_tgt_storage, &local_tgt_key);

@ -1,114 +0,0 @@
From 3fe94b5854c56da38ba14994b6c371c3e3b9094e Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
Date: Wed, 7 Jul 2021 11:47:44 +1200
Subject: [PATCH] Fix KDC null deref on bad encrypted challenge
The function ec_verify() in src/kdc/kdc_preauth_ec.c contains a check
to avoid further processing if the armor key is NULL. However, this
check is bypassed by a call to k5memdup0() which overwrites retval
with 0 if the allocation succeeds. If the armor key is NULL, a call
to krb5_c_fx_cf2_simple() will then dereference it, resulting in a
crash. Add a check before the k5memdup0() call to avoid overwriting
retval.
CVE-2021-36222:
In MIT krb5 releases 1.16 and later, an unauthenticated attacker can
cause a null dereference in the KDC by sending a request containing a
PA-ENCRYPTED-CHALLENGE padata element without using FAST.
[ghudson@mit.edu: trimmed patch; added test case; edited commit
message]
ticket: 9007 (new)
tags: pullup
target_version: 1.19-next
target_version: 1.18-next
(cherry picked from commit fc98f520caefff2e5ee9a0026fdf5109944b3562)
(cherry picked from commit 791211b00a53b394376d096c881b725ee739a936)
---
src/kdc/kdc_preauth_ec.c | 3 ++-
src/tests/Makefile.in | 1 +
src/tests/t_cve-2021-36222.py | 46 +++++++++++++++++++++++++++++++++++
3 files changed, 49 insertions(+), 1 deletion(-)
create mode 100644 src/tests/t_cve-2021-36222.py
diff --git a/src/kdc/kdc_preauth_ec.c b/src/kdc/kdc_preauth_ec.c
index 7e636b3f9..43a9902cc 100644
--- a/src/kdc/kdc_preauth_ec.c
+++ b/src/kdc/kdc_preauth_ec.c
@@ -87,7 +87,8 @@ ec_verify(krb5_context context, krb5_data *req_pkt, krb5_kdc_req *request,
}
/* Check for a configured FAST ec auth indicator. */
- realmstr = k5memdup0(realm.data, realm.length, &retval);
+ if (retval == 0)
+ realmstr = k5memdup0(realm.data, realm.length, &retval);
if (realmstr != NULL)
retval = profile_get_string(context->profile, KRB5_CONF_REALMS,
realmstr,
diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in
index ab416cc5f..20f27d748 100644
--- a/src/tests/Makefile.in
+++ b/src/tests/Makefile.in
@@ -159,6 +159,7 @@ check-pytests: unlockiter s4u2self
$(RUNPYTEST) $(srcdir)/t_cve-2012-1015.py $(PYTESTFLAGS)
$(RUNPYTEST) $(srcdir)/t_cve-2013-1416.py $(PYTESTFLAGS)
$(RUNPYTEST) $(srcdir)/t_cve-2013-1417.py $(PYTESTFLAGS)
+ $(RUNPYTEST) $(srcdir)/t_cve-2021-36222.py $(PYTESTFLAGS)
$(RM) au.log
$(RUNPYTEST) $(srcdir)/t_audit.py $(PYTESTFLAGS)
$(RUNPYTEST) $(srcdir)/jsonwalker.py -d $(srcdir)/au_dict.json \
diff --git a/src/tests/t_cve-2021-36222.py b/src/tests/t_cve-2021-36222.py
new file mode 100644
index 000000000..57e04993b
--- /dev/null
+++ b/src/tests/t_cve-2021-36222.py
@@ -0,0 +1,46 @@
+import socket
+from k5test import *
+
+realm = K5Realm()
+
+# CVE-2021-36222 KDC null dereference on encrypted challenge preauth
+# without FAST
+
+s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+a = (hostname, realm.portbase)
+
+m = ('6A81A0' '30819D' # [APPLICATION 10] SEQUENCE
+ 'A103' '0201' '05' # [1] pvno = 5
+ 'A203' '0201' '0A' # [2] msg-type = 10
+ 'A30E' '300C' # [3] padata = SEQUENCE OF
+ '300A' # SEQUENCE
+ 'A104' '0202' '008A' # [1] padata-type = PA-ENCRYPTED-CHALLENGE
+ 'A202' '0400' # [2] padata-value = ""
+ 'A48180' '307E' # [4] req-body = SEQUENCE
+ 'A007' '0305' '0000000000' # [0] kdc-options = 0
+ 'A120' '301E' # [1] cname = SEQUENCE
+ 'A003' '0201' '01' # [0] name-type = NT-PRINCIPAL
+ 'A117' '3015' # [1] name-string = SEQUENCE-OF
+ '1B06' '6B7262746774' # krbtgt
+ '1B0B' '4B5242544553542E434F4D'
+ # KRBTEST.COM
+ 'A20D' '1B0B' '4B5242544553542E434F4D'
+ # [2] realm = KRBTEST.COM
+ 'A320' '301E' # [3] sname = SEQUENCE
+ 'A003' '0201' '01' # [0] name-type = NT-PRINCIPAL
+ 'A117' '3015' # [1] name-string = SEQUENCE-OF
+ '1B06' '6B7262746774' # krbtgt
+ '1B0B' '4B5242544553542E434F4D'
+ # KRBTEST.COM
+ 'A511' '180F' '31393934303631303036303331375A'
+ # [5] till = 19940610060317Z
+ 'A703' '0201' '00' # [7] nonce = 0
+ 'A808' '3006' # [8] etype = SEQUENCE OF
+ '020112' '020111') # aes256-cts aes128-cts
+
+s.sendto(bytes.fromhex(m), a)
+
+# Make sure kinit still works.
+realm.kinit(realm.user_princ, password('user'))
+
+success('CVE-2021-36222 regression test')

@ -1,106 +0,0 @@
From 7d68cfc84cd7d0657c01afa52dfe69181b401a4a Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Mon, 17 Oct 2022 20:25:11 -0400
Subject: [PATCH] Fix integer overflows in PAC parsing
In krb5_parse_pac(), check for buffer counts large enough to threaten
integer overflow in the header length and memory length calculations.
Avoid potential integer overflows when checking the length of each
buffer.
CVE-2022-42898:
In MIT krb5 releases 1.8 and later, an authenticated attacker may be
able to cause a KDC or kadmind process to crash by reading beyond the
bounds of allocated memory, creating a denial of service. A
privileged attacker may similarly be able to cause a Kerberos or GSS
application service to crash. On 32-bit platforms, an attacker can
also cause insufficient memory to be allocated for the result,
potentially leading to remote code execution in a KDC, kadmind, or GSS
or Kerberos application server process. An attacker with the
privileges of a cross-realm KDC may be able to extract secrets from
the KDC process's memory by having them copied into the PAC of a new
ticket.
ticket: 9074 (new)
tags: pullup
target_version: 1.20-next
target_version: 1.19-next
---
src/lib/krb5/krb/pac.c | 9 +++++++--
src/lib/krb5/krb/t_pac.c | 18 ++++++++++++++++++
2 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c
index 950beda657..1b9ef12276 100644
--- a/src/lib/krb5/krb/pac.c
+++ b/src/lib/krb5/krb/pac.c
@@ -27,6 +27,8 @@
#include "k5-int.h"
#include "authdata.h"
+#define MAX_BUFFERS 4096
+
/* draft-brezak-win2k-krb-authz-00 */
/*
@@ -316,6 +318,9 @@ krb5_pac_parse(krb5_context context,
if (version != 0)
return EINVAL;
+ if (cbuffers < 1 || cbuffers > MAX_BUFFERS)
+ return ERANGE;
+
header_len = PACTYPE_LENGTH + (cbuffers * PAC_INFO_BUFFER_LENGTH);
if (len < header_len)
return ERANGE;
@@ -348,8 +353,8 @@ krb5_pac_parse(krb5_context context,
krb5_pac_free(context, pac);
return EINVAL;
}
- if (buffer->Offset < header_len ||
- buffer->Offset + buffer->cbBufferSize > len) {
+ if (buffer->Offset < header_len || buffer->Offset > len ||
+ buffer->cbBufferSize > len - buffer->Offset) {
krb5_pac_free(context, pac);
return ERANGE;
}
diff --git a/src/lib/krb5/krb/t_pac.c b/src/lib/krb5/krb/t_pac.c
index ee47152ee4..ccd165380d 100644
--- a/src/lib/krb5/krb/t_pac.c
+++ b/src/lib/krb5/krb/t_pac.c
@@ -431,6 +431,16 @@ static const unsigned char s4u_pac_ent_xrealm[] = {
0x8a, 0x81, 0x9c, 0x9c, 0x00, 0x00, 0x00, 0x00
};
+static const unsigned char fuzz1[] = {
+ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x06, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf5
+};
+
+static const unsigned char fuzz2[] = {
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x20
+};
+
static const char *s4u_principal = "w2k8u@ACME.COM";
static const char *s4u_enterprise = "w2k8u@abc@ACME.COM";
@@ -646,6 +656,14 @@ main(int argc, char **argv)
krb5_free_principal(context, sep);
}
+ /* Check problematic PACs found by fuzzing. */
+ ret = krb5_pac_parse(context, fuzz1, sizeof(fuzz1), &pac);
+ if (!ret)
+ err(context, ret, "krb5_pac_parse should have failed");
+ ret = krb5_pac_parse(context, fuzz2, sizeof(fuzz2), &pac);
+ if (!ret)
+ err(context, ret, "krb5_pac_parse should have failed");
+
/*
* Test empty free
*/
--
2.37.3

@ -1,58 +0,0 @@
From 51938a8b731740299fe47d132b8840edba4141bc Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Sat, 29 May 2021 12:05:49 -0400
Subject: [PATCH] Fix k5tls module for OpenSSL 3
Starting in OpenSSL 3, connection termination without a close_notify
alert causes SSL_read() to return SSL_ERROR_SSL instead of
SSL_ERROR_SYSCALL. OpenSSL 3 also provides a new option
SSL_OP_IGNORE_UNEXPECTED_EOF which allows an application to explicitly
ignore possible truncation attacks and receive SSL_ERROR_ZERO_RETURN
instead.
Remove the call to SSL_CTX_get_options() since SSL_CTX_set_options()
doesn't clear existing options.
[ghudson@mit.edu: edited commit message and comment]
(cherry picked from commit aa9b4a2a64046afd2fab7cb49c346295874a5fb6)
(cherry picked from commit 201e38845e9f70234bcaa9ba7c25b28e38169b0a)
---
src/plugins/tls/k5tls/openssl.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/src/plugins/tls/k5tls/openssl.c b/src/plugins/tls/k5tls/openssl.c
index 76a43b3cd..99fda7ffc 100644
--- a/src/plugins/tls/k5tls/openssl.c
+++ b/src/plugins/tls/k5tls/openssl.c
@@ -433,7 +433,7 @@ setup(krb5_context context, SOCKET fd, const char *servername,
char **anchors, k5_tls_handle *handle_out)
{
int e;
- long options;
+ long options = SSL_OP_NO_SSLv2;
SSL_CTX *ctx = NULL;
SSL *ssl = NULL;
k5_tls_handle handle = NULL;
@@ -448,8 +448,19 @@ setup(krb5_context context, SOCKET fd, const char *servername,
ctx = SSL_CTX_new(SSLv23_client_method());
if (ctx == NULL)
goto error;
- options = SSL_CTX_get_options(ctx);
- SSL_CTX_set_options(ctx, options | SSL_OP_NO_SSLv2);
+
+#ifdef SSL_OP_IGNORE_UNEXPECTED_EOF
+ /*
+ * For OpenSSL 3 and later, mark close_notify alerts as optional. We don't
+ * need to worry about truncation attacks because the protocols this module
+ * is used with (Kerberos and change-password) receive a single
+ * length-delimited message from the server. For prior versions of OpenSSL
+ * we check for SSL_ERROR_SYSCALL when reading instead (this error changes
+ * to SSL_ERROR_SSL in OpenSSL 3).
+ */
+ options |= SSL_OP_IGNORE_UNEXPECTED_EOF;
+#endif
+ SSL_CTX_set_options(ctx, options);
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback);
X509_STORE_set_flags(SSL_CTX_get_cert_store(ctx), 0);

@ -1,65 +0,0 @@
From ddbd548562d951d327a10c9dcb975418427f6fea Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Mon, 7 Jun 2021 15:00:41 -0400
Subject: [PATCH] Fix kadmin -k with fallback or referral realm
kadmin -k produces a client principal name with
krb5_sname_to_principal(), but it gets converted to a string and back
due to the signature of kadm5_init_with_skey(), which loses track of
the name type, so no canonicalization is performed.
In libkadm5clnt initialization, recognize the important subset of this
case--an empty realm indicates either fallback processing or the
referral realm--and restore the host-based name type so that the
client principal can be canonicalized against the keytab.
ticket: 9013 (new)
(cherry picked from commit dcb79089276624d7ddf44e08d35bd6d7d7e557d2)
(cherry picked from commit cd8ff035f5b4720a8fc457355726f7bd0eab5eaa)
---
src/lib/kadm5/clnt/client_init.c | 7 +++++++
src/tests/t_kadmin.py | 12 ++++++++++++
2 files changed, 19 insertions(+)
diff --git a/src/lib/kadm5/clnt/client_init.c b/src/lib/kadm5/clnt/client_init.c
index aa1223bb3..0aaca701f 100644
--- a/src/lib/kadm5/clnt/client_init.c
+++ b/src/lib/kadm5/clnt/client_init.c
@@ -221,9 +221,16 @@ init_any(krb5_context context, char *client_name, enum init_type init_type,
return KADM5_MISSING_KRB5_CONF_PARAMS;
}
+ /*
+ * Parse the client name. If it has an empty realm, it is almost certainly
+ * a host-based principal using DNS fallback processing or the referral
+ * realm, so give it the appropriate name type for canonicalization.
+ */
code = krb5_parse_name(handle->context, client_name, &client);
if (code)
goto error;
+ if (init_type == INIT_SKEY && client->realm.length == 0)
+ client->type = KRB5_NT_SRV_HST;
/*
* Get credentials. Also does some fallbacks in case kadmin/fqdn
diff --git a/src/tests/t_kadmin.py b/src/tests/t_kadmin.py
index fe6a3cc2e..98453d92e 100644
--- a/src/tests/t_kadmin.py
+++ b/src/tests/t_kadmin.py
@@ -51,4 +51,16 @@ for i in range(200):
realm.run_kadmin(['addprinc', '-randkey', 'foo%d' % i])
realm.run_kadmin(['listprincs'], expected_msg='foo199')
+# Test kadmin -k with the default principal, with and without
+# fallback. This operation requires canonicalization against the
+# keytab in krb5_get_init_creds_keytab() as the
+# krb5_sname_to_principal() result won't have a realm. Try with and
+# without without fallback processing since the code paths are
+# different.
+mark('kadmin -k')
+realm.run([kadmin, '-k', 'getprinc', realm.host_princ])
+no_canon_conf = {'libdefaults': {'dns_canonicalize_hostname': 'false'}}
+no_canon = realm.special_env('no_canon', False, krb5_conf=no_canon_conf)
+realm.run([kadmin, '-k', 'getprinc', realm.host_princ], env=no_canon)
+
success('kadmin and kpasswd tests')

@ -1,552 +0,0 @@
From f85a818fe1a7438db7e1ea579818da67e0be017d Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Sat, 15 May 2021 17:35:25 -0400
Subject: [PATCH] Fix softpkcs11 build issues with openssl 3.0
EVP_PKEY_get0_RSA() has been modified to have const return type. Remove
its usages in favor of the EVP_PKEY interface. Also remove calls to
RSA_blinding_off(), which we don't need and would require a non-const
object. Similarly, remove RSA_set_method() calls that set a pre-existing
default.
Since softpkcs11 doesn't link against krb5 and can't use zap(), allocate
buffers with OPENSSL_malloc() so can use OPENSSL_clear_free().
Move several argument validation checks to the top of their functions.
Fix some incorrect/inconsistent log messages.
(cherry picked from commit 00de1aad7b3647b91017c7009b0bc65cd0c8b2e0)
(cherry picked from commit a86b780ef275b35e8dc1e6d1886ec8e8d941f7c4)
---
src/tests/softpkcs11/main.c | 360 ++++++++++++++----------------------
1 file changed, 141 insertions(+), 219 deletions(-)
diff --git a/src/tests/softpkcs11/main.c b/src/tests/softpkcs11/main.c
index 1cccdfb43..caa537b68 100644
--- a/src/tests/softpkcs11/main.c
+++ b/src/tests/softpkcs11/main.c
@@ -375,10 +375,9 @@ add_st_object(void)
return NULL;
soft_token.object.objs = objs;
- o = malloc(sizeof(*o));
+ o = calloc(1, sizeof(*o));
if (o == NULL)
return NULL;
- memset(o, 0, sizeof(*o));
o->attrs = NULL;
o->num_attributes = 0;
o->object_handle = soft_token.object.num_objs;
@@ -424,7 +423,7 @@ add_pubkey_info(struct st_object *o, CK_KEY_TYPE key_type, EVP_PKEY *key)
CK_ULONG modulus_bits = 0;
CK_BYTE *exponent = NULL;
size_t exponent_len = 0;
- RSA *rsa;
+ const RSA *rsa;
const BIGNUM *n, *e;
rsa = EVP_PKEY_get0_RSA(key);
@@ -445,8 +444,6 @@ add_pubkey_info(struct st_object *o, CK_KEY_TYPE key_type, EVP_PKEY *key)
add_object_attribute(o, 0, CKA_PUBLIC_EXPONENT,
exponent, exponent_len);
- RSA_set_method(rsa, RSA_PKCS1_OpenSSL());
-
free(modulus);
free(exponent);
}
@@ -679,10 +676,6 @@ add_certificate(char *label,
} else {
/* XXX verify keytype */
- if (key_type == CKK_RSA)
- RSA_set_method(EVP_PKEY_get0_RSA(o->u.private_key.key),
- RSA_PKCS1_OpenSSL());
-
if (X509_check_private_key(cert, o->u.private_key.key) != 1) {
EVP_PKEY_free(o->u.private_key.key);
o->u.private_key.key = NULL;
@@ -695,7 +688,7 @@ add_certificate(char *label,
}
ret = CKR_OK;
- out:
+out:
if (ret != CKR_OK) {
st_logf("something went wrong when adding cert!\n");
@@ -1224,8 +1217,6 @@ C_Login(CK_SESSION_HANDLE hSession,
}
/* XXX check keytype */
- RSA_set_method(EVP_PKEY_get0_RSA(o->u.private_key.key),
- RSA_PKCS1_OpenSSL());
if (X509_check_private_key(o->u.private_key.cert, o->u.private_key.key) != 1) {
EVP_PKEY_free(o->u.private_key.key);
@@ -1495,8 +1486,9 @@ C_Encrypt(CK_SESSION_HANDLE hSession,
struct st_object *o;
void *buffer = NULL;
CK_RV ret;
- RSA *rsa;
- int padding, len, buffer_len, padding_len;
+ size_t buffer_len = 0;
+ int padding;
+ EVP_PKEY_CTX *ctx = NULL;
st_logf("Encrypt\n");
@@ -1512,70 +1504,58 @@ C_Encrypt(CK_SESSION_HANDLE hSession,
return CKR_ARGUMENTS_BAD;
}
- rsa = EVP_PKEY_get0_RSA(o->u.public_key);
-
- if (rsa == NULL)
- return CKR_ARGUMENTS_BAD;
-
- RSA_blinding_off(rsa); /* XXX RAND is broken while running in mozilla ? */
-
- buffer_len = RSA_size(rsa);
-
- buffer = malloc(buffer_len);
- if (buffer == NULL) {
- ret = CKR_DEVICE_MEMORY;
- goto out;
- }
-
- ret = CKR_OK;
- switch(state->encrypt_mechanism->mechanism) {
- case CKM_RSA_PKCS:
- padding = RSA_PKCS1_PADDING;
- padding_len = RSA_PKCS1_PADDING_SIZE;
- break;
- case CKM_RSA_X_509:
- padding = RSA_NO_PADDING;
- padding_len = 0;
- break;
- default:
- ret = CKR_FUNCTION_NOT_SUPPORTED;
- goto out;
- }
-
- if ((CK_ULONG)buffer_len + padding_len < ulDataLen) {
- ret = CKR_ARGUMENTS_BAD;
- goto out;
- }
-
if (pulEncryptedDataLen == NULL) {
st_logf("pulEncryptedDataLen NULL\n");
ret = CKR_ARGUMENTS_BAD;
goto out;
}
- if (pData == NULL_PTR) {
+ if (pData == NULL) {
st_logf("data NULL\n");
ret = CKR_ARGUMENTS_BAD;
goto out;
}
- len = RSA_public_encrypt(ulDataLen, pData, buffer, rsa, padding);
- if (len <= 0) {
+ switch(state->encrypt_mechanism->mechanism) {
+ case CKM_RSA_PKCS:
+ padding = RSA_PKCS1_PADDING;
+ break;
+ case CKM_RSA_X_509:
+ padding = RSA_NO_PADDING;
+ break;
+ default:
+ ret = CKR_FUNCTION_NOT_SUPPORTED;
+ goto out;
+ }
+
+ ctx = EVP_PKEY_CTX_new(o->u.public_key, NULL);
+ if (ctx == NULL || EVP_PKEY_encrypt_init(ctx) <= 0 ||
+ EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 ||
+ EVP_PKEY_encrypt(ctx, NULL, &buffer_len, pData, ulDataLen) <= 0) {
ret = CKR_DEVICE_ERROR;
goto out;
}
- if (len > buffer_len)
- abort();
- if (pEncryptedData != NULL_PTR)
- memcpy(pEncryptedData, buffer, len);
- *pulEncryptedDataLen = len;
-
- out:
- if (buffer) {
- memset(buffer, 0, buffer_len);
- free(buffer);
+ buffer = OPENSSL_malloc(buffer_len);
+ if (buffer == NULL) {
+ ret = CKR_DEVICE_MEMORY;
+ goto out;
}
+
+ if (EVP_PKEY_encrypt(ctx, buffer, &buffer_len, pData, ulDataLen) <= 0) {
+ ret = CKR_DEVICE_ERROR;
+ goto out;
+ }
+ st_logf("Encrypt done\n");
+
+ if (pEncryptedData != NULL)
+ memcpy(pEncryptedData, buffer, buffer_len);
+ *pulEncryptedDataLen = buffer_len;
+
+ ret = CKR_OK;
+out:
+ OPENSSL_clear_free(buffer, buffer_len);
+ EVP_PKEY_CTX_free(ctx);
return ret;
}
@@ -1646,8 +1626,9 @@ C_Decrypt(CK_SESSION_HANDLE hSession,
struct st_object *o;
void *buffer = NULL;
CK_RV ret;
- RSA *rsa;
- int padding, len, buffer_len, padding_len;
+ size_t buffer_len = 0;
+ int padding;
+ EVP_PKEY_CTX *ctx = NULL;
st_logf("Decrypt\n");
@@ -1663,41 +1644,6 @@ C_Decrypt(CK_SESSION_HANDLE hSession,
return CKR_ARGUMENTS_BAD;
}
- rsa = EVP_PKEY_get0_RSA(o->u.private_key.key);
-
- if (rsa == NULL)
- return CKR_ARGUMENTS_BAD;
-
- RSA_blinding_off(rsa); /* XXX RAND is broken while running in mozilla ? */
-
- buffer_len = RSA_size(rsa);
-
- buffer = malloc(buffer_len);
- if (buffer == NULL) {
- ret = CKR_DEVICE_MEMORY;
- goto out;
- }
-
- ret = CKR_OK;
- switch(state->decrypt_mechanism->mechanism) {
- case CKM_RSA_PKCS:
- padding = RSA_PKCS1_PADDING;
- padding_len = RSA_PKCS1_PADDING_SIZE;
- break;
- case CKM_RSA_X_509:
- padding = RSA_NO_PADDING;
- padding_len = 0;
- break;
- default:
- ret = CKR_FUNCTION_NOT_SUPPORTED;
- goto out;
- }
-
- if ((CK_ULONG)buffer_len + padding_len < ulEncryptedDataLen) {
- ret = CKR_ARGUMENTS_BAD;
- goto out;
- }
-
if (pulDataLen == NULL) {
st_logf("pulDataLen NULL\n");
ret = CKR_ARGUMENTS_BAD;
@@ -1710,24 +1656,48 @@ C_Decrypt(CK_SESSION_HANDLE hSession,
goto out;
}
- len = RSA_private_decrypt(ulEncryptedDataLen, pEncryptedData, buffer,
- rsa, padding);
- if (len <= 0) {
+ switch(state->decrypt_mechanism->mechanism) {
+ case CKM_RSA_PKCS:
+ padding = RSA_PKCS1_PADDING;
+ break;
+ case CKM_RSA_X_509:
+ padding = RSA_NO_PADDING;
+ break;
+ default:
+ ret = CKR_FUNCTION_NOT_SUPPORTED;
+ goto out;
+ }
+
+ ctx = EVP_PKEY_CTX_new(o->u.private_key.key, NULL);
+ if (ctx == NULL || EVP_PKEY_decrypt_init(ctx) <= 0 ||
+ EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 ||
+ EVP_PKEY_decrypt(ctx, NULL, &buffer_len, pEncryptedData,
+ ulEncryptedDataLen) <= 0) {
ret = CKR_DEVICE_ERROR;
goto out;
}
- if (len > buffer_len)
- abort();
+
+ buffer = OPENSSL_malloc(buffer_len);
+ if (buffer == NULL) {
+ ret = CKR_DEVICE_MEMORY;
+ goto out;
+ }
+
+ if (EVP_PKEY_decrypt(ctx, buffer, &buffer_len, pEncryptedData,
+ ulEncryptedDataLen) <= 0) {
+ ret = CKR_DEVICE_ERROR;
+ goto out;
+ }
+ st_logf("Decrypt done\n");
if (pData != NULL_PTR)
- memcpy(pData, buffer, len);
- *pulDataLen = len;
+ memcpy(pData, buffer, buffer_len);
+ *pulDataLen = buffer_len;
- out:
- if (buffer) {
- memset(buffer, 0, buffer_len);
- free(buffer);
- }
+ ret = CKR_OK;
+out:
+ OPENSSL_clear_free(buffer, buffer_len);
+ EVP_PKEY_CTX_free(ctx);
return ret;
}
@@ -1806,8 +1776,9 @@ C_Sign(CK_SESSION_HANDLE hSession,
struct st_object *o;
void *buffer = NULL;
CK_RV ret;
- RSA *rsa;
- int padding, len, buffer_len, padding_len;
+ int padding;
+ size_t buffer_len = 0;
+ EVP_PKEY_CTX *ctx = NULL;
st_logf("Sign\n");
VERIFY_SESSION_HANDLE(hSession, &state);
@@ -1822,40 +1793,6 @@ C_Sign(CK_SESSION_HANDLE hSession,
return CKR_ARGUMENTS_BAD;
}
- rsa = EVP_PKEY_get0_RSA(o->u.private_key.key);
-
- if (rsa == NULL)
- return CKR_ARGUMENTS_BAD;
-
- RSA_blinding_off(rsa); /* XXX RAND is broken while running in mozilla ? */
-
- buffer_len = RSA_size(rsa);
-
- buffer = malloc(buffer_len);
- if (buffer == NULL) {
- ret = CKR_DEVICE_MEMORY;
- goto out;
- }
-
- switch(state->sign_mechanism->mechanism) {
- case CKM_RSA_PKCS:
- padding = RSA_PKCS1_PADDING;
- padding_len = RSA_PKCS1_PADDING_SIZE;
- break;
- case CKM_RSA_X_509:
- padding = RSA_NO_PADDING;
- padding_len = 0;
- break;
- default:
- ret = CKR_FUNCTION_NOT_SUPPORTED;
- goto out;
- }
-
- if ((CK_ULONG)buffer_len < ulDataLen + padding_len) {
- ret = CKR_ARGUMENTS_BAD;
- goto out;
- }
-
if (pulSignatureLen == NULL) {
st_logf("signature len NULL\n");
ret = CKR_ARGUMENTS_BAD;
@@ -1868,26 +1805,46 @@ C_Sign(CK_SESSION_HANDLE hSession,
goto out;
}
- len = RSA_private_encrypt(ulDataLen, pData, buffer, rsa, padding);
- st_logf("private encrypt done\n");
- if (len <= 0) {
+ switch(state->sign_mechanism->mechanism) {
+ case CKM_RSA_PKCS:
+ padding = RSA_PKCS1_PADDING;
+ break;
+ case CKM_RSA_X_509:
+ padding = RSA_NO_PADDING;
+ break;
+ default:
+ ret = CKR_FUNCTION_NOT_SUPPORTED;
+ goto out;
+ }
+
+ ctx = EVP_PKEY_CTX_new(o->u.private_key.key, NULL);
+ if (ctx == NULL || EVP_PKEY_sign_init(ctx) <= 0 ||
+ EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 ||
+ EVP_PKEY_sign(ctx, NULL, &buffer_len, pData, ulDataLen) <= 0) {
ret = CKR_DEVICE_ERROR;
goto out;
}
- if (len > buffer_len)
- abort();
- if (pSignature != NULL_PTR)
- memcpy(pSignature, buffer, len);
- *pulSignatureLen = len;
+ buffer = OPENSSL_malloc(buffer_len);
+ if (buffer == NULL) {
+ ret = CKR_DEVICE_MEMORY;
+ goto out;
+ }
+
+ if (EVP_PKEY_sign(ctx, buffer, &buffer_len, pData, ulDataLen) <= 0) {
+ ret = CKR_DEVICE_ERROR;
+ goto out;
+ }
+ st_logf("Sign done\n");
+
+ if (pSignature != NULL)
+ memcpy(pSignature, buffer, buffer_len);
+ *pulSignatureLen = buffer_len;
ret = CKR_OK;
-
- out:
- if (buffer) {
- memset(buffer, 0, buffer_len);
- free(buffer);
- }
+out:
+ OPENSSL_clear_free(buffer, buffer_len);
+ EVP_PKEY_CTX_free(ctx);
return ret;
}
@@ -1951,10 +1908,9 @@ C_Verify(CK_SESSION_HANDLE hSession,
{
struct session_state *state;
struct st_object *o;
- void *buffer = NULL;
CK_RV ret;
- RSA *rsa;
- int padding, len, buffer_len;
+ int padding;
+ EVP_PKEY_CTX *ctx = NULL;
st_logf("Verify\n");
VERIFY_SESSION_HANDLE(hSession, &state);
@@ -1969,39 +1925,6 @@ C_Verify(CK_SESSION_HANDLE hSession,
return CKR_ARGUMENTS_BAD;
}
- rsa = EVP_PKEY_get0_RSA(o->u.public_key);
-
- if (rsa == NULL)
- return CKR_ARGUMENTS_BAD;
-
- RSA_blinding_off(rsa); /* XXX RAND is broken while running in mozilla ? */
-
- buffer_len = RSA_size(rsa);
-
- buffer = malloc(buffer_len);
- if (buffer == NULL) {
- ret = CKR_DEVICE_MEMORY;
- goto out;
- }
-
- ret = CKR_OK;
- switch(state->verify_mechanism->mechanism) {
- case CKM_RSA_PKCS:
- padding = RSA_PKCS1_PADDING;
- break;
- case CKM_RSA_X_509:
- padding = RSA_NO_PADDING;
- break;
- default:
- ret = CKR_FUNCTION_NOT_SUPPORTED;
- goto out;
- }
-
- if ((CK_ULONG)buffer_len < ulDataLen) {
- ret = CKR_ARGUMENTS_BAD;
- goto out;
- }
-
if (pSignature == NULL) {
st_logf("signature NULL\n");
ret = CKR_ARGUMENTS_BAD;
@@ -2014,34 +1937,34 @@ C_Verify(CK_SESSION_HANDLE hSession,
goto out;
}
- len = RSA_public_decrypt(ulDataLen, pData, buffer, rsa, padding);
- st_logf("private encrypt done\n");
- if (len <= 0) {
+ switch(state->verify_mechanism->mechanism) {
+ case CKM_RSA_PKCS:
+ padding = RSA_PKCS1_PADDING;
+ break;
+ case CKM_RSA_X_509:
+ padding = RSA_NO_PADDING;
+ break;
+ default:
+ ret = CKR_FUNCTION_NOT_SUPPORTED;
+ goto out;
+ }
+
+ ctx = EVP_PKEY_CTX_new(o->u.public_key, NULL);
+ if (ctx == NULL || EVP_PKEY_verify_init(ctx) <= 0 ||
+ EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 ||
+ EVP_PKEY_verify(ctx, pSignature, ulSignatureLen, pData,
+ ulDataLen) <= 0) {
ret = CKR_DEVICE_ERROR;
goto out;
}
- if (len > buffer_len)
- abort();
+ st_logf("Verify done\n");
- if ((CK_ULONG)len != ulSignatureLen) {
- ret = CKR_GENERAL_ERROR;
- goto out;
- }
-
- if (memcmp(pSignature, buffer, len) != 0) {
- ret = CKR_GENERAL_ERROR;
- goto out;
- }
-
- out:
- if (buffer) {
- memset(buffer, 0, buffer_len);
- free(buffer);
- }
+ ret = CKR_OK;
+out:
+ EVP_PKEY_CTX_free(ctx);
return ret;
}
-
CK_RV
C_VerifyUpdate(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pPart,
@@ -2072,7 +1995,6 @@ C_GenerateRandom(CK_SESSION_HANDLE hSession,
return CKR_FUNCTION_NOT_SUPPORTED;
}
-
CK_FUNCTION_LIST funcs = {
{ 2, 11 },
C_Initialize,

@ -1,97 +0,0 @@
From 8f70ad82a645ccb7fb1677d260baa5e4112890d4 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Mon, 7 Jun 2021 13:27:29 -0400
Subject: [PATCH] Fix some principal realm canonicalization cases
The no_hostrealm and subst_defrealm flags in struct canonprinc were
only applied when dns_canonicalize_hostname=fallback; in the other
cases, the initial krb5_sname_to_principal() result is treated as
canonical. For no_hostrealm this limitation doesn't currently matter,
because all uses pass a principal with no realm as input. However,
subst_defrealm is used to convert the referral realm to the default
realm in krb5_get_init_creds_keytab(), krb5_cc_cache_match(), and
gss_acquire_cred() when it needs to check the desired name against a
specified ccache.
In k5_canonprinc(), if the input principal is a
krb5_sname_to_principal() result and fallback isn't in effect, apply
subst_defrealm. Document in os-proto.h that no_hostrealm doesn't
remove an existing realm and that krb5_sname_to_principal() may
already have looked one up.
ticket: 9011 (new)
(cherry picked from commit c077d0c6430c4ac163443aacc03d14d206a4cbb8)
(cherry picked from commit 5ae9bc98f23aeaa2ce17debe5a9b0cf1130e54ed)
---
src/lib/krb5/os/os-proto.h | 13 +++++++++----
src/lib/krb5/os/sn2princ.c | 24 +++++++++++++++++++++---
2 files changed, 30 insertions(+), 7 deletions(-)
diff --git a/src/lib/krb5/os/os-proto.h b/src/lib/krb5/os/os-proto.h
index 7d5e7978f..a985f2aec 100644
--- a/src/lib/krb5/os/os-proto.h
+++ b/src/lib/krb5/os/os-proto.h
@@ -85,10 +85,15 @@ struct sendto_callback_info {
/*
* Initialize with all zeros except for princ. Set no_hostrealm to disable
- * host-to-realm lookup, which ordinarily happens after canonicalizing the host
- * part. Set subst_defrealm to substitute the default realm for the referral
- * realm after realm lookup (this has no effect if no_hostrealm is set). Free
- * with free_canonprinc() when done.
+ * host-to-realm lookup, which ordinarily happens during fallback processing
+ * after canonicalizing the host part. Set subst_defrealm to substitute the
+ * default realm for the referral realm after realm lookup. Do not set both
+ * flags. Free with free_canonprinc() when done.
+ *
+ * no_hostrealm only applies if fallback processing is in use
+ * (dns_canonicalize_hostname = fallback). It will not remove the realm if
+ * krb5_sname_to_principal() already canonicalized the hostname and looked up a
+ * realm. subst_defrealm applies whether or not fallback processing is in use.
*/
struct canonprinc {
krb5_const_principal princ;
diff --git a/src/lib/krb5/os/sn2princ.c b/src/lib/krb5/os/sn2princ.c
index c99b7da17..93c155932 100644
--- a/src/lib/krb5/os/sn2princ.c
+++ b/src/lib/krb5/os/sn2princ.c
@@ -271,18 +271,36 @@ krb5_error_code
k5_canonprinc(krb5_context context, struct canonprinc *iter,
krb5_const_principal *princ_out)
{
+ krb5_error_code ret;
int step = ++iter->step;
*princ_out = NULL;
- /* If we're not doing fallback, the input principal is canonical. */
- if (context->dns_canonicalize_hostname != CANONHOST_FALLBACK ||
- iter->princ->type != KRB5_NT_SRV_HST || iter->princ->length != 2 ||
+ /* If the hostname isn't from krb5_sname_to_principal(), the input
+ * principal is canonical. */
+ if (iter->princ->type != KRB5_NT_SRV_HST || iter->princ->length != 2 ||
iter->princ->data[1].length == 0) {
*princ_out = (step == 1) ? iter->princ : NULL;
return 0;
}
+ /* If we're not doing fallback, the hostname is canonical, but we may need
+ * to substitute the default realm. */
+ if (context->dns_canonicalize_hostname != CANONHOST_FALLBACK) {
+ if (step > 1)
+ return 0;
+ iter->copy = *iter->princ;
+ if (iter->subst_defrealm && iter->copy.realm.length == 0) {
+ ret = krb5_get_default_realm(context, &iter->realm);
+ if (ret)
+ return ret;
+ iter->copy = *iter->princ;
+ iter->copy.realm = string2data(iter->realm);
+ }
+ *princ_out = &iter->copy;
+ return 0;
+ }
+
/* Canonicalize without DNS at step 1, with DNS at step 2. */
if (step > 2)
return 0;

@ -1,301 +0,0 @@
From e3f3d31a3db23f6c8437cd0efe45f67a7f4fc6aa Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Sat, 15 May 2021 21:18:06 -0400
Subject: [PATCH] Handle OpenSSL 3's providers
OpenSSL 3 compartmentalizes what algorithms it uses, which for us means
another hoop to jump through to use dubious cryptography. (Right now,
we need to load "legacy" in order to access MD4 and RC4.)
Use our normal initializer logic to set up providers both in the OpenSSL
provider an the PKINIT plugin. Since DT_FINI is too late, release them
using atexit() as OpenSSL does.
(cherry picked from commit bea5a703a06da1f1ab56821b77a2d3661cb0dda4)
[rharwood@redhat.com: work around des3 removal and rc4 fips changes]
---
src/configure.ac | 1 +
src/lib/crypto/openssl/enc_provider/aes.c | 16 ++++++
.../crypto/openssl/enc_provider/camellia.c | 16 ++++++
src/lib/crypto/openssl/enc_provider/rc4.c | 4 ++
.../crypto/openssl/hash_provider/hash_evp.c | 5 ++
src/lib/crypto/openssl/init.c | 53 +++++++++++++++++++
src/plugins/preauth/pkinit/Makefile.in | 1 +
.../preauth/pkinit/pkinit_crypto_openssl.c | 33 ++++++++++--
8 files changed, 126 insertions(+), 3 deletions(-)
diff --git a/src/configure.ac b/src/configure.ac
index 9c2e816fe..20066918b 100644
--- a/src/configure.ac
+++ b/src/configure.ac
@@ -284,6 +284,7 @@ AC_SUBST(CRYPTO_IMPL_LIBS)
if test "$CRYPTO_IMPL" = openssl; then
AC_CHECK_FUNCS(EVP_KDF_fetch)
+ AC_CHECK_FUNCS(OSSL_PROVIDER_load)
fi
AC_ARG_WITH([prng-alg],
diff --git a/src/lib/crypto/openssl/enc_provider/aes.c b/src/lib/crypto/openssl/enc_provider/aes.c
index 6b4622fe9..31c90a69d 100644
--- a/src/lib/crypto/openssl/enc_provider/aes.c
+++ b/src/lib/crypto/openssl/enc_provider/aes.c
@@ -68,6 +68,10 @@ cbc_enc(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
EVP_CIPHER_CTX *ctx;
struct iov_cursor cursor;
+ ret = krb5int_crypto_init();
+ if (ret)
+ return ret;
+
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL)
return ENOMEM;
@@ -102,6 +106,10 @@ cbc_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
EVP_CIPHER_CTX *ctx;
struct iov_cursor cursor;
+ ret = krb5int_crypto_init();
+ if (ret)
+ return ret;
+
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL)
return ENOMEM;
@@ -137,6 +145,10 @@ cts_encr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
struct iov_cursor cursor;
AES_KEY enck;
+ ret = krb5int_crypto_init();
+ if (ret)
+ return ret;
+
memset(iv_cts,0,sizeof(iv_cts));
if (ivec && ivec->data){
if (ivec->length != sizeof(iv_cts))
@@ -190,6 +202,10 @@ cts_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
struct iov_cursor cursor;
AES_KEY deck;
+ ret = krb5int_crypto_init();
+ if (ret)
+ return ret;
+
memset(iv_cts,0,sizeof(iv_cts));
if (ivec && ivec->data){
if (ivec->length != sizeof(iv_cts))
diff --git a/src/lib/crypto/openssl/enc_provider/camellia.c b/src/lib/crypto/openssl/enc_provider/camellia.c
index f79679a0b..7cc7fc6fb 100644
--- a/src/lib/crypto/openssl/enc_provider/camellia.c
+++ b/src/lib/crypto/openssl/enc_provider/camellia.c
@@ -92,6 +92,10 @@ cbc_enc(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
EVP_CIPHER_CTX *ctx;
struct iov_cursor cursor;
+ ret = krb5int_crypto_init();
+ if (ret)
+ return ret;
+
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL)
return ENOMEM;
@@ -126,6 +130,10 @@ cbc_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
EVP_CIPHER_CTX *ctx;
struct iov_cursor cursor;
+ ret = krb5int_crypto_init();
+ if (ret)
+ return ret;
+
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL)
return ENOMEM;
@@ -161,6 +169,10 @@ cts_encr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
struct iov_cursor cursor;
CAMELLIA_KEY enck;
+ ret = krb5int_crypto_init();
+ if (ret)
+ return ret;
+
memset(iv_cts,0,sizeof(iv_cts));
if (ivec && ivec->data){
if (ivec->length != sizeof(iv_cts))
@@ -214,6 +226,10 @@ cts_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
struct iov_cursor cursor;
CAMELLIA_KEY deck;
+ ret = krb5int_crypto_init();
+ if (ret)
+ return ret;
+
memset(iv_cts,0,sizeof(iv_cts));
if (ivec && ivec->data){
if (ivec->length != sizeof(iv_cts))
diff --git a/src/lib/crypto/openssl/enc_provider/rc4.c b/src/lib/crypto/openssl/enc_provider/rc4.c
index 9bf407899..a10cb5192 100644
--- a/src/lib/crypto/openssl/enc_provider/rc4.c
+++ b/src/lib/crypto/openssl/enc_provider/rc4.c
@@ -66,6 +66,10 @@ k5_arcfour_docrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data,
EVP_CIPHER_CTX *ctx = NULL;
struct arcfour_state *arcstate;
+ ret = krb5int_crypto_init();
+ if (ret)
+ return ret;
+
if (FIPS_mode())
return KRB5_CRYPTO_INTERNAL;
diff --git a/src/lib/crypto/openssl/hash_provider/hash_evp.c b/src/lib/crypto/openssl/hash_provider/hash_evp.c
index 2eb5139c0..09d7b3896 100644
--- a/src/lib/crypto/openssl/hash_provider/hash_evp.c
+++ b/src/lib/crypto/openssl/hash_provider/hash_evp.c
@@ -41,6 +41,11 @@ hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data,
const krb5_data *d;
size_t i;
int ok;
+ krb5_error_code ret;
+
+ ret = krb5int_crypto_init();
+ if (ret)
+ return ret;
if (output->length != (unsigned int)EVP_MD_size(type))
return KRB5_CRYPTO_INTERNAL;
diff --git a/src/lib/crypto/openssl/init.c b/src/lib/crypto/openssl/init.c
index 1139bce53..f72dbfe81 100644
--- a/src/lib/crypto/openssl/init.c
+++ b/src/lib/crypto/openssl/init.c
@@ -26,12 +26,65 @@
#include "crypto_int.h"
+#ifdef HAVE_OSSL_PROVIDER_LOAD
+
+/*
+ * Starting in OpenSSL 3, algorithms are grouped into containers called
+ * "providers", not all of which are loaded by default. At time of writing,
+ * we need MD4 and RC4 from the legacy provider. Oddly, 3DES is not in
+ * legacy.
+ */
+
+#include <openssl/provider.h>
+
+static OSSL_PROVIDER *legacy_provider = NULL;
+static OSSL_PROVIDER *default_provider = NULL;
+
+static void
+unload_providers(void)
+{
+ if (default_provider != NULL)
+ (void)OSSL_PROVIDER_unload(default_provider);
+ if (legacy_provider != NULL)
+ (void)OSSL_PROVIDER_unload(legacy_provider);
+ default_provider = NULL;
+ legacy_provider = NULL;
+}
+
+int
+krb5int_crypto_impl_init(void)
+{
+ legacy_provider = OSSL_PROVIDER_load(NULL, "legacy");
+ default_provider = OSSL_PROVIDER_load(NULL, "default");
+
+ /*
+ * Someone might build openssl without the legacy provider. They will
+ * have a bad time, but some things will still work. I don't know think
+ * this configuration is worth supporting.
+ */
+ if (legacy_provider == NULL || default_provider == NULL)
+ abort();
+
+ /*
+ * If we attempt to do this with our normal LIBFINIFUNC logic (DT_FINI),
+ * OpenSSL will have cleaned itself up by the time we're invoked. OpenSSL
+ * registers its cleanup (OPENSSL_cleanup) with atexit() - do the same and
+ * we'll be higher on the stack.
+ */
+ atexit(unload_providers);
+ return 0;
+}
+
+#else /* !HAVE_OSSL_PROVIDER_LOAD */
+
int
krb5int_crypto_impl_init(void)
{
return 0;
}
+#endif
+
void
krb5int_crypto_impl_cleanup(void)
{
diff --git a/src/plugins/preauth/pkinit/Makefile.in b/src/plugins/preauth/pkinit/Makefile.in
index 15ca0eb48..d20fb18a8 100644
--- a/src/plugins/preauth/pkinit/Makefile.in
+++ b/src/plugins/preauth/pkinit/Makefile.in
@@ -5,6 +5,7 @@ MODULE_INSTALL_DIR = $(KRB5_PA_MODULE_DIR)
LIBBASE=pkinit
LIBMAJOR=0
LIBMINOR=0
+LIBINITFUNC=pkinit_openssl_init
RELDIR=../plugins/preauth/pkinit
# Depends on libk5crypto and libkrb5
SHLIB_EXPDEPS = \
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
index 350c2118a..42e5c581d 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
@@ -44,6 +44,13 @@
#include <openssl/params.h>
#endif
+#ifdef HAVE_OSSL_PROVIDER_LOAD
+#include <openssl/provider.h>
+
+static OSSL_PROVIDER *legacy_provider = NULL;
+static OSSL_PROVIDER *default_provider = NULL;
+#endif
+
static krb5_error_code pkinit_init_pkinit_oids(pkinit_plg_crypto_context );
static void pkinit_fini_pkinit_oids(pkinit_plg_crypto_context );
@@ -2937,12 +2944,32 @@ cleanup:
return retval;
}
+/* pkinit_openssl_init() and unload_providers() are largely duplicated from
+ * lib/crypto/openssl/init.c - see explanations there. */
+static void
+unload_providers(void)
+{
+ if (default_provider != NULL)
+ (void)OSSL_PROVIDER_unload(default_provider);
+ if (legacy_provider != NULL)
+ (void)OSSL_PROVIDER_unload(legacy_provider);
+ default_provider = NULL;
+ legacy_provider = NULL;
+}
+
int
pkinit_openssl_init()
{
- /* Initialize OpenSSL. */
- ERR_load_crypto_strings();
- OpenSSL_add_all_algorithms();
+#ifdef HAVE_OSSL_PROVIDER_LOAD
+ legacy_provider = OSSL_PROVIDER_load(NULL, "legacy");
+ default_provider = OSSL_PROVIDER_load(NULL, "default");
+
+ if (legacy_provider == NULL || default_provider == NULL)
+ abort();
+
+ atexit(unload_providers);
+#endif
+
return 0;
}

@ -1,27 +0,0 @@
From 68a557557ab8a3208fab8a70daf4d970b9fc4787 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Tue, 30 Mar 2021 14:35:28 +0200
Subject: [PATCH] Make KCM iteration fallback work with sssd-kcm
sssd-kcm returns KRB5_CC_IO if the operation code is not known.
ticket: 8990
(cherry picked from commit 06afae820a44c1dc96ad88a0b16c3e50bc938b2a)
(cherry picked from commit 2dbca7e14c945d6394e0e05f285a068dcd541295)
---
src/lib/krb5/ccache/cc_kcm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/lib/krb5/ccache/cc_kcm.c b/src/lib/krb5/ccache/cc_kcm.c
index 1f81a2190..46705f1da 100644
--- a/src/lib/krb5/ccache/cc_kcm.c
+++ b/src/lib/krb5/ccache/cc_kcm.c
@@ -876,7 +876,7 @@ kcm_start_seq_get(krb5_context context, krb5_ccache cache,
ret = kcmreq_get_cred_list(&req, &creds);
if (ret)
goto cleanup;
- } else if (ret == KRB5_FCC_INTERNAL) {
+ } else if (ret == KRB5_FCC_INTERNAL || ret == KRB5_CC_IO) {
/* Fall back to GET_CRED_UUID_LIST. */
kcmreq_free(&req);
kcmreq_init(&req, KCM_OP_GET_CRED_UUID_LIST, cache);

@ -1,365 +0,0 @@
From b778f10e31e566269768cba92a0005f35e134333 Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Wed, 19 Jan 2022 19:46:08 +0100
Subject: [PATCH] Make kprop work for dump files larger than 4GB
If the dump file size does not fit in 32 bits, encode four zero bytes
(forcing an error for unmodified kpropd) followed by the size in the
next 64 bits.
Add a functional test case, but only run it when an environment
variable is set, as processing a 4GB dump file is too
resource-intensive for make check.
[ghudson@mit.edu: edited comments and commit message; eliminated use
of defined constant in some cases; added test case]
ticket: 9053 (new)
---
src/kprop/kprop.c | 37 +++++++++++++++++++++----------------
src/kprop/kprop.h | 12 ++++++++++++
src/kprop/kprop_util.c | 42 ++++++++++++++++++++++++++++++++++++++++++
src/kprop/kpropd.c | 33 +++++++++++++++++++++------------
src/tests/t_kprop.py | 34 ++++++++++++++++++++++++++++++++++
5 files changed, 130 insertions(+), 28 deletions(-)
diff --git a/src/kprop/kprop.c b/src/kprop/kprop.c
index 0b53aae7e..5adb4d31f 100644
--- a/src/kprop/kprop.c
+++ b/src/kprop/kprop.c
@@ -25,6 +25,7 @@
*/
#include "k5-int.h"
+#include <inttypes.h>
#include <locale.h>
#include <sys/file.h>
#include <signal.h>
@@ -71,11 +72,11 @@ static void open_connection(krb5_context context, char *host, int *fd_out);
static void kerberos_authenticate(krb5_context context,
krb5_auth_context *auth_context, int fd,
krb5_principal me, krb5_creds **new_creds);
-static int open_database(krb5_context context, char *data_fn, int *size);
+static int open_database(krb5_context context, char *data_fn, off_t *size);
static void close_database(krb5_context context, int fd);
static void xmit_database(krb5_context context,
krb5_auth_context auth_context, krb5_creds *my_creds,
- int fd, int database_fd, int in_database_size);
+ int fd, int database_fd, off_t in_database_size);
static void send_error(krb5_context context, krb5_creds *my_creds, int fd,
char *err_text, krb5_error_code err_code);
static void update_last_prop_file(char *hostname, char *file_name);
@@ -90,7 +91,8 @@ static void usage()
int
main(int argc, char **argv)
{
- int fd, database_fd, database_size;
+ int fd, database_fd;
+ off_t database_size;
krb5_error_code retval;
krb5_context context;
krb5_creds *my_creds;
@@ -339,7 +341,7 @@ kerberos_authenticate(krb5_context context, krb5_auth_context *auth_context,
* in the size of the database file.
*/
static int
-open_database(krb5_context context, char *data_fn, int *size)
+open_database(krb5_context context, char *data_fn, off_t *size)
{
struct stat stbuf, stbuf_ok;
char *data_ok_fn;
@@ -413,19 +415,18 @@ close_database(krb5_context context, int fd)
static void
xmit_database(krb5_context context, krb5_auth_context auth_context,
krb5_creds *my_creds, int fd, int database_fd,
- int in_database_size)
+ off_t in_database_size)
{
krb5_int32 n;
krb5_data inbuf, outbuf;
- char buf[KPROP_BUFSIZ];
+ char buf[KPROP_BUFSIZ], dbsize_buf[KPROP_DBSIZE_MAX_BUFSIZ];
krb5_error_code retval;
krb5_error *error;
- krb5_ui_4 database_size = in_database_size, send_size, sent_size;
+ uint64_t database_size = in_database_size, send_size, sent_size;
/* Send over the size. */
- send_size = htonl(database_size);
- inbuf.data = (char *)&send_size;
- inbuf.length = sizeof(send_size); /* must be 4, really */
+ inbuf = make_data(dbsize_buf, sizeof(dbsize_buf));
+ encode_database_size(database_size, &inbuf);
/* KPROP_CKSUMTYPE */
retval = krb5_mk_safe(context, auth_context, &inbuf, &outbuf, NULL);
if (retval) {
@@ -460,7 +461,7 @@ xmit_database(krb5_context context, krb5_auth_context auth_context,
retval = krb5_mk_priv(context, auth_context, &inbuf, &outbuf, NULL);
if (retval) {
snprintf(buf, sizeof(buf),
- "while encoding database block starting at %d",
+ "while encoding database block starting at %"PRIu64,
sent_size);
com_err(progname, retval, "%s", buf);
send_error(context, my_creds, fd, buf, retval);
@@ -471,14 +472,14 @@ xmit_database(krb5_context context, krb5_auth_context auth_context,
if (retval) {
krb5_free_data_contents(context, &outbuf);
com_err(progname, retval,
- _("while sending database block starting at %d"),
+ _("while sending database block starting at %"PRIu64),
sent_size);
exit(1);
}
krb5_free_data_contents(context, &outbuf);
sent_size += n;
if (debug)
- printf("%d bytes sent.\n", sent_size);
+ printf("%"PRIu64" bytes sent.\n", sent_size);
}
if (sent_size != database_size) {
com_err(progname, 0, _("Premature EOF found for database file!"));
@@ -533,10 +534,14 @@ xmit_database(krb5_context context, krb5_auth_context auth_context,
exit(1);
}
- memcpy(&send_size, outbuf.data, sizeof(send_size));
- send_size = ntohl(send_size);
+ retval = decode_database_size(&outbuf, &send_size);
+ if (retval) {
+ com_err(progname, retval, _("malformed sent database size message"));
+ exit(1);
+ }
if (send_size != database_size) {
- com_err(progname, 0, _("Kpropd sent database size %d, expecting %d"),
+ com_err(progname, 0, _("Kpropd sent database size %"PRIu64
+ ", expecting %"PRIu64),
send_size, database_size);
exit(1);
}
diff --git a/src/kprop/kprop.h b/src/kprop/kprop.h
index 75331cc8a..3a319b535 100644
--- a/src/kprop/kprop.h
+++ b/src/kprop/kprop.h
@@ -32,6 +32,7 @@
#define KPROP_PROT_VERSION "kprop5_01"
#define KPROP_BUFSIZ 32768
+#define KPROP_DBSIZE_MAX_BUFSIZ 12 /* max length of an encoded DB size */
/* pathnames are in osconf.h, included via k5-int.h */
@@ -41,3 +42,14 @@ int sockaddr2krbaddr(krb5_context context, int family, struct sockaddr *sa,
krb5_error_code
sn2princ_realm(krb5_context context, const char *hostname, const char *sname,
const char *realm, krb5_principal *princ_out);
+
+/*
+ * Encode size in four bytes (for backward compatibility) if it fits; otherwise
+ * use the larger encoding. buf must be allocated with at least
+ * KPROP_DBSIZE_MAX_BUFSIZ bytes.
+ */
+void encode_database_size(uint64_t size, krb5_data *buf);
+
+/* Decode a database size. Return KRB5KRB_ERR_GENERIC if buf has an invalid
+ * length or did not encode a 32-bit size compactly. */
+krb5_error_code decode_database_size(const krb5_data *buf, uint64_t *size_out);
diff --git a/src/kprop/kprop_util.c b/src/kprop/kprop_util.c
index c2b2e8764..c0aa2c89b 100644
--- a/src/kprop/kprop_util.c
+++ b/src/kprop/kprop_util.c
@@ -92,3 +92,45 @@ sn2princ_realm(krb5_context context, const char *hostname, const char *sname,
*princ_out = princ;
return 0;
}
+
+void
+encode_database_size(uint64_t size, krb5_data *buf)
+{
+ assert(buf->length >= 12);
+ if (size > 0 && size <= UINT32_MAX) {
+ /* Encode in 32 bits for backward compatibility. */
+ store_32_be(size, buf->data);
+ buf->length = 4;
+ } else {
+ /* Set the first 32 bits to 0 and encode in the following 64 bits. */
+ store_32_be(0, buf->data);
+ store_64_be(size, buf->data + 4);
+ buf->length = 12;
+ }
+}
+
+krb5_error_code
+decode_database_size(const krb5_data *buf, uint64_t *size_out)
+{
+ uint64_t size;
+
+ if (buf->length == 12) {
+ /* A 12-byte buffer must have the first four bytes zeroed. */
+ if (load_32_be(buf->data) != 0)
+ return KRB5KRB_ERR_GENERIC;
+
+ /* The size is stored in the next 64 bits. Values from 1..2^32-1 must
+ * be encoded in four bytes. */
+ size = load_64_be(buf->data + 4);
+ if (size > 0 && size <= UINT32_MAX)
+ return KRB5KRB_ERR_GENERIC;
+ } else if (buf->length == 4) {
+ size = load_32_be(buf->data);
+ } else {
+ /* Invalid buffer size. */
+ return KRB5KRB_ERR_GENERIC;
+ }
+
+ *size_out = size;
+ return 0;
+}
diff --git a/src/kprop/kpropd.c b/src/kprop/kpropd.c
index c6b8efc28..dd6c697c0 100644
--- a/src/kprop/kpropd.c
+++ b/src/kprop/kpropd.c
@@ -55,6 +55,7 @@
#include "com_err.h"
#include "fake-addrinfo.h"
+#include <inttypes.h>
#include <locale.h>
#include <ctype.h>
#include <sys/file.h>
@@ -1358,9 +1359,10 @@ static void
recv_database(krb5_context context, int fd, int database_fd,
krb5_data *confmsg)
{
- krb5_ui_4 database_size, received_size;
+ uint64_t database_size, received_size;
int n;
char buf[1024];
+ char dbsize_buf[KPROP_DBSIZE_MAX_BUFSIZ];
krb5_data inbuf, outbuf;
krb5_error_code retval;
@@ -1382,10 +1384,17 @@ recv_database(krb5_context context, int fd, int database_fd,
_("while decoding database size from client"));
exit(1);
}
- memcpy(&database_size, outbuf.data, sizeof(database_size));
+
+ retval = decode_database_size(&outbuf, &database_size);
+ if (retval) {
+ send_error(context, fd, retval, "malformed database size message");
+ com_err(progname, retval,
+ _("malformed database size message from client"));
+ exit(1);
+ }
+
krb5_free_data_contents(context, &inbuf);
krb5_free_data_contents(context, &outbuf);
- database_size = ntohl(database_size);
/* Initialize the initial vector. */
retval = krb5_auth_con_initivector(context, auth_context);
@@ -1405,7 +1414,7 @@ recv_database(krb5_context context, int fd, int database_fd,
retval = krb5_read_message(context, &fd, &inbuf);
if (retval) {
snprintf(buf, sizeof(buf),
- "while reading database block starting at offset %d",
+ "while reading database block starting at offset %"PRIu64,
received_size);
com_err(progname, retval, "%s", buf);
send_error(context, fd, retval, buf);
@@ -1416,8 +1425,8 @@ recv_database(krb5_context context, int fd, int database_fd,
retval = krb5_rd_priv(context, auth_context, &inbuf, &outbuf, NULL);
if (retval) {
snprintf(buf, sizeof(buf),
- "while decoding database block starting at offset %d",
- received_size);
+ "while decoding database block starting at offset %"
+ PRIu64, received_size);
com_err(progname, retval, "%s", buf);
send_error(context, fd, retval, buf);
krb5_free_data_contents(context, &inbuf);
@@ -1427,13 +1436,13 @@ recv_database(krb5_context context, int fd, int database_fd,
krb5_free_data_contents(context, &inbuf);
if (n < 0) {
snprintf(buf, sizeof(buf),
- "while writing database block starting at offset %d",
+ "while writing database block starting at offset %"PRIu64,
received_size);
send_error(context, fd, errno, buf);
} else if ((unsigned int)n != outbuf.length) {
snprintf(buf, sizeof(buf),
"incomplete write while writing database block starting "
- "at \noffset %d (%d written, %d expected)",
+ "at \noffset %"PRIu64" (%d written, %d expected)",
received_size, n, outbuf.length);
send_error(context, fd, KRB5KRB_ERR_GENERIC, buf);
}
@@ -1444,7 +1453,8 @@ recv_database(krb5_context context, int fd, int database_fd,
/* OK, we've seen the entire file. Did we get too many bytes? */
if (received_size > database_size) {
snprintf(buf, sizeof(buf),
- "Received %d bytes, expected %d bytes for database file",
+ "Received %"PRIu64" bytes, expected %"PRIu64
+ " bytes for database file",
received_size, database_size);
send_error(context, fd, KRB5KRB_ERR_GENERIC, buf);
}
@@ -1454,9 +1464,8 @@ recv_database(krb5_context context, int fd, int database_fd,
/* Create message acknowledging number of bytes received, but
* don't send it until kdb5_util returns successfully. */
- database_size = htonl(database_size);
- inbuf.data = (char *)&database_size;
- inbuf.length = sizeof(database_size);
+ inbuf = make_data(dbsize_buf, sizeof(dbsize_buf));
+ encode_database_size(database_size, &inbuf);
retval = krb5_mk_safe(context,auth_context,&inbuf,confmsg,NULL);
if (retval) {
com_err(progname, retval, "while encoding # of received bytes");
diff --git a/src/tests/t_kprop.py b/src/tests/t_kprop.py
index d96f7c560..4421a7c35 100755
--- a/src/tests/t_kprop.py
+++ b/src/tests/t_kprop.py
@@ -87,5 +87,39 @@ realm.run([kdb5_util, 'dump', dumpfile])
realm.run([kprop, '-f', dumpfile, '-P', str(realm.kprop_port()), hostname])
check_output(kpropd)
realm.run([kadminl, 'listprincs'], replica3, expected_msg='wakawaka')
+stop_daemon(kpropd)
+
+# This test is too resource-intensive to be included in "make check"
+# by default, but it can be enabled in the environment to test the
+# propagation of databases large enough to require a 12-byte encoding
+# of the database size.
+if 'KPROP_LARGE_DB_TEST' in os.environ:
+ output('Generating >4GB dumpfile\n')
+ with open(dumpfile, 'w') as f:
+ f.write('kdb5_util load_dump version 6\n')
+ f.write('princ\t38\t15\t3\t1\t0\tK/M@KRBTEST.COM\t64\t86400\t0\t0\t0'
+ '\t0\t0\t0\t8\t2\t0100\t9\t8\t0100010000000000\t2\t28'
+ '\tb93e105164625f6372656174696f6e404b5242544553542e434f4d00'
+ '\t1\t1\t18\t62\t2000408c027c250e8cc3b81476414f2214d57c1ce'
+ '38891e29792e87258247c73547df4d5756266931dd6686b62270e6568'
+ '95a31ec66bfe913b4f15226227\t-1;\n')
+ for i in range(1, 20000000):
+ f.write('princ\t38\t21\t1\t1\t0\tp%08d@KRBTEST.COM' % i)
+ f.write('\t0\t86400\t0\t0\t0\t0\t0\t0\t2\t27'
+ '\td73e1051757365722f61646d696e404b5242544553542e434f4d00'
+ '\t1\t1\t17\t46'
+ '\t10009c8ab7b3f89ccf3ca3ad98352a461b7f4f1b0c49'
+ '5605117591d9ad52ba4da0adef7a902126973ed2bdc3ffbf\t-1;\n')
+ assert os.path.getsize(dumpfile) > 4 * 1024 * 1024 * 1024
+ with open(dumpfile + '.dump_ok', 'w') as f:
+ f.write('\0')
+ conf_large = {'dbmodules': {'db': {'database_name': '$testdir/db.large'}},
+ 'realms': {'$realm': {'iprop_resync_timeout': '3600'}}}
+ large = realm.special_env('large', True, kdc_conf=conf_large)
+ kpropd = realm.start_kpropd(large, ['-d'])
+ realm.run([kprop, '-f', dumpfile, '-P', str(realm.kprop_port()), hostname])
+ check_output(kpropd)
+ realm.run([kadminl, 'getprinc', 'p19999999'], env=large,
+ expected_msg='Principal: p19999999')
success('kprop tests')
--
2.37.3

File diff suppressed because it is too large Load Diff

@ -1,150 +0,0 @@
From c99ecf1bb49e2fbd0bf30a7b357cf06407b9588a Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Sat, 15 May 2021 18:04:58 -0400
Subject: [PATCH] Remove deprecated OpenSSL calls from softpkcs11
Rewrite add_pubkey_info() in terms of the EVP_PKEY interface. In this
process, fix its unchecked allocations and fail fast for non-RSA keys.
(cherry picked from commit d6bf42279675100e3e4fe7c6e08eef74d49624cb)
(cherry picked from commit 5072bfdfaddae762680d0f9d97afa6dbf8274760)
---
src/configure.ac | 1 +
src/tests/softpkcs11/main.c | 106 ++++++++++++++++++++++++------------
2 files changed, 72 insertions(+), 35 deletions(-)
diff --git a/src/configure.ac b/src/configure.ac
index 3e1052db7..eb6307468 100644
--- a/src/configure.ac
+++ b/src/configure.ac
@@ -1114,6 +1114,7 @@ int i = 1;
])], k5_cv_openssl_version_okay=yes, k5_cv_openssl_version_okay=no)])
old_LIBS="$LIBS"
AC_CHECK_LIB(crypto, PKCS7_get_signer_info)
+ AC_CHECK_FUNCS(EVP_PKEY_get_bn_param)
LIBS="$old_LIBS"
fi
if test "$k5_cv_openssl_version_okay" = yes && (test "$enable_pkinit" = yes || test "$enable_pkinit" = try); then
diff --git a/src/tests/softpkcs11/main.c b/src/tests/softpkcs11/main.c
index caa537b68..86b4ef711 100644
--- a/src/tests/softpkcs11/main.c
+++ b/src/tests/softpkcs11/main.c
@@ -413,47 +413,83 @@ add_object_attribute(struct st_object *o,
return CKR_OK;
}
+#ifdef HAVE_EVP_PKEY_GET_BN_PARAM
+
+/* Declare owner pointers since EVP_PKEY_get_bn_param() gives us copies. */
+#define DECLARE_BIGNUM(name) BIGNUM *name = NULL
+#define RELEASE_BIGNUM(bn) BN_clear_free(bn)
static CK_RV
-add_pubkey_info(struct st_object *o, CK_KEY_TYPE key_type, EVP_PKEY *key)
+get_bignums(EVP_PKEY *key, BIGNUM **n, BIGNUM **e)
{
- switch (key_type) {
- case CKK_RSA: {
- CK_BYTE *modulus = NULL;
- size_t modulus_len = 0;
- CK_ULONG modulus_bits = 0;
- CK_BYTE *exponent = NULL;
- size_t exponent_len = 0;
- const RSA *rsa;
- const BIGNUM *n, *e;
+ if (EVP_PKEY_get_bn_param(key, "n", n) == 0 ||
+ EVP_PKEY_get_bn_param(key, "e", e) == 0)
+ return CKR_DEVICE_ERROR;
- rsa = EVP_PKEY_get0_RSA(key);
- RSA_get0_key(rsa, &n, &e, NULL);
- modulus_bits = BN_num_bits(n);
-
- modulus_len = BN_num_bytes(n);
- modulus = malloc(modulus_len);
- BN_bn2bin(n, modulus);
-
- exponent_len = BN_num_bytes(e);
- exponent = malloc(exponent_len);
- BN_bn2bin(e, exponent);
-
- add_object_attribute(o, 0, CKA_MODULUS, modulus, modulus_len);
- add_object_attribute(o, 0, CKA_MODULUS_BITS,
- &modulus_bits, sizeof(modulus_bits));
- add_object_attribute(o, 0, CKA_PUBLIC_EXPONENT,
- exponent, exponent_len);
-
- free(modulus);
- free(exponent);
- }
- default:
- /* XXX */
- break;
- }
return CKR_OK;
}
+#else
+
+/* Declare const pointers since the old API gives us aliases. */
+#define DECLARE_BIGNUM(name) const BIGNUM *name
+#define RELEASE_BIGNUM(bn)
+static CK_RV
+get_bignums(EVP_PKEY *key, const BIGNUM **n, const BIGNUM **e)
+{
+ const RSA *rsa;
+
+ rsa = EVP_PKEY_get0_RSA(key);
+ RSA_get0_key(rsa, n, e, NULL);
+
+ return CKR_OK;
+}
+
+#endif
+
+static CK_RV
+add_pubkey_info(struct st_object *o, CK_KEY_TYPE key_type, EVP_PKEY *key)
+{
+ CK_BYTE *modulus = NULL, *exponent = 0;
+ size_t modulus_len = 0, exponent_len = 0;
+ CK_ULONG modulus_bits = 0;
+ CK_RV ret;
+ DECLARE_BIGNUM(n);
+ DECLARE_BIGNUM(e);
+
+ if (key_type != CKK_RSA)
+ abort();
+
+ ret = get_bignums(key, &n, &e);
+ if (ret != CKR_OK)
+ goto done;
+
+ modulus_bits = BN_num_bits(n);
+ modulus_len = BN_num_bytes(n);
+ exponent_len = BN_num_bytes(e);
+
+ modulus = malloc(modulus_len);
+ exponent = malloc(exponent_len);
+ if (modulus == NULL || exponent == NULL) {
+ ret = CKR_DEVICE_MEMORY;
+ goto done;
+ }
+
+ BN_bn2bin(n, modulus);
+ BN_bn2bin(e, exponent);
+
+ add_object_attribute(o, 0, CKA_MODULUS, modulus, modulus_len);
+ add_object_attribute(o, 0, CKA_MODULUS_BITS, &modulus_bits,
+ sizeof(modulus_bits));
+ add_object_attribute(o, 0, CKA_PUBLIC_EXPONENT, exponent, exponent_len);
+
+ ret = CKR_OK;
+done:
+ free(modulus);
+ free(exponent);
+ RELEASE_BIGNUM(n);
+ RELEASE_BIGNUM(e);
+ return ret;
+}
static int
pem_callback(char *buf, int num, int w, void *key)

@ -1,188 +0,0 @@
From dea9421ccdbe5c8f63aae85341a8f091c6019407 Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Wed, 1 Jun 2022 18:02:04 +0200
Subject: [PATCH] Set reasonable supportedCMSTypes in PKINIT
The PKINIT client uses AuthPack.supportedCMSTypes to let the KDC know
the algorithms it supports for verification of the CMS data signature.
(The MIT krb5 KDC currently ignores this list, but other
implementations use it.)
Replace 3DES with sha512WithRSAEncryption and sha256WithRSAEncryption.
[ghudson@mit.edu: simplified code and used appropriate helpers; edited
commit message]
ticket: 9066 (new)
---
src/plugins/preauth/pkinit/Makefile.in | 4 +-
src/plugins/preauth/pkinit/pkinit_clnt.c | 8 ++++
...nit_kdf_constants.c => pkinit_constants.c} | 24 ++++++++++++
src/plugins/preauth/pkinit/pkinit_crypto.h | 16 ++++++++
.../preauth/pkinit/pkinit_crypto_openssl.c | 39 +++++++++++++++++++
5 files changed, 89 insertions(+), 2 deletions(-)
rename src/plugins/preauth/pkinit/{pkinit_kdf_constants.c => pkinit_constants.c} (76%)
diff --git a/src/plugins/preauth/pkinit/Makefile.in b/src/plugins/preauth/pkinit/Makefile.in
index d20fb18a8..97aaded03 100644
--- a/src/plugins/preauth/pkinit/Makefile.in
+++ b/src/plugins/preauth/pkinit/Makefile.in
@@ -18,7 +18,7 @@ STLIBOBJS= \
pkinit_srv.o \
pkinit_lib.o \
pkinit_clnt.o \
- pkinit_kdf_constants.o \
+ pkinit_constants.o \
pkinit_profile.o \
pkinit_identity.o \
pkinit_matching.o \
@@ -29,7 +29,7 @@ SRCS= \
$(srcdir)/pkinit_srv.c \
$(srcdir)/pkinit_lib.c \
$(srcdir)/pkinit_kdf_test.c \
- $(srcdir)/pkinit_kdf_constants.c \
+ $(srcdir)/pkinit_constants.c \
$(srcdir)/pkinit_clnt.c \
$(srcdir)/pkinit_profile.c \
$(srcdir)/pkinit_identity.c \
diff --git a/src/plugins/preauth/pkinit/pkinit_clnt.c b/src/plugins/preauth/pkinit/pkinit_clnt.c
index a385da7c3..2817cc213 100644
--- a/src/plugins/preauth/pkinit/pkinit_clnt.c
+++ b/src/plugins/preauth/pkinit/pkinit_clnt.c
@@ -212,6 +212,14 @@ pkinit_as_req_create(krb5_context context,
auth_pack.clientPublicValue = &info;
auth_pack.supportedKDFs = (krb5_data **)supported_kdf_alg_ids;
+ /* add List of CMS algorithms */
+ retval = create_krb5_supportedCMSTypes(context, plgctx->cryptoctx,
+ reqctx->cryptoctx,
+ reqctx->idctx, &cmstypes);
+ auth_pack.supportedCMSTypes = cmstypes;
+ if (retval)
+ goto cleanup;
+
switch(protocol) {
case DH_PROTOCOL:
TRACE_PKINIT_CLIENT_REQ_DH(context);
diff --git a/src/plugins/preauth/pkinit/pkinit_kdf_constants.c b/src/plugins/preauth/pkinit/pkinit_constants.c
similarity index 76%
rename from src/plugins/preauth/pkinit/pkinit_kdf_constants.c
rename to src/plugins/preauth/pkinit/pkinit_constants.c
index 1604f1670..1832e8f7b 100644
--- a/src/plugins/preauth/pkinit/pkinit_kdf_constants.c
+++ b/src/plugins/preauth/pkinit/pkinit_constants.c
@@ -57,3 +57,27 @@ krb5_data const * const supported_kdf_alg_ids[] = {
&sha512_id,
NULL
};
+
+/* RFC 4055 sha256WithRSAEncryption: iso(1) member-body(2) us(840)
+ * rsadsi(113549) pkcs(1) 1 11 */
+static char sha256WithRSAEncr_oid[9] = {
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b
+};
+/* RFC 4055 sha256WithRSAEncryption: iso(1) member-body(2) us(840)
+ * rsadsi(113549) pkcs(1) 1 13 */
+static char sha512WithRSAEncr_oid[9] = {
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d
+};
+
+const krb5_data sha256WithRSAEncr_id = {
+ KV5M_DATA, sizeof(sha256WithRSAEncr_oid), sha256WithRSAEncr_oid
+};
+const krb5_data sha512WithRSAEncr_id = {
+ KV5M_DATA, sizeof(sha512WithRSAEncr_oid), sha512WithRSAEncr_oid
+};
+
+krb5_data const * const supported_cms_algs[] = {
+ &sha512WithRSAEncr_id,
+ &sha256WithRSAEncr_id,
+ NULL
+};
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto.h b/src/plugins/preauth/pkinit/pkinit_crypto.h
index 1f9868351..f38a77093 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto.h
+++ b/src/plugins/preauth/pkinit/pkinit_crypto.h
@@ -380,6 +380,18 @@ krb5_error_code server_process_dh
unsigned int *server_key_len_out); /* OUT
receives length of DH secret key */
+/*
+ * this functions takes in crypto specific representation of
+ * supportedCMSTypes and creates a list of
+ * krb5_algorithm_identifier
+ */
+krb5_error_code create_krb5_supportedCMSTypes
+ (krb5_context context, /* IN */
+ pkinit_plg_crypto_context plg_cryptoctx, /* IN */
+ pkinit_req_crypto_context req_cryptoctx, /* IN */
+ pkinit_identity_crypto_context id_cryptoctx, /* IN */
+ krb5_algorithm_identifier ***supportedCMSTypes); /* OUT */
+
/*
* this functions takes in crypto specific representation of
* trustedCertifiers and creates a list of
@@ -617,6 +629,10 @@ extern const size_t krb5_pkinit_sha512_oid_len;
*/
extern krb5_data const * const supported_kdf_alg_ids[];
+/* CMS signature algorithms supported by this implementation, in order of
+ * decreasing preference. */
+extern krb5_data const * const supported_cms_algs[];
+
krb5_error_code
crypto_encode_der_cert(krb5_context context, pkinit_req_crypto_context reqctx,
uint8_t **der_out, size_t *der_len);
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
index 2a6ef4aaa..41a7464b5 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
@@ -5582,6 +5582,45 @@ cleanup:
return retval;
}
+krb5_error_code
+create_krb5_supportedCMSTypes(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx,
+ krb5_algorithm_identifier ***algs_out)
+{
+ krb5_error_code ret;
+ krb5_algorithm_identifier **algs = NULL;
+ size_t i, count;
+
+ *algs_out = NULL;
+
+ /* Count supported OIDs and allocate list (including null terminator). */
+ for (count = 0; supported_cms_algs[count] != NULL; count++);
+ algs = k5calloc(count + 1, sizeof(*algs), &ret);
+ if (algs == NULL)
+ goto cleanup;
+
+ /* Add an algorithm identifier for each OID, with no parameters. */
+ for (i = 0; i < count; i++) {
+ algs[i] = k5alloc(sizeof(*algs[i]), &ret);
+ if (algs[i] == NULL)
+ goto cleanup;
+ ret = krb5int_copy_data_contents(context, supported_cms_algs[i],
+ &algs[i]->algorithm);
+ if (ret)
+ goto cleanup;
+ algs[i]->parameters = empty_data();
+ }
+
+ *algs_out = algs;
+ algs = NULL;
+
+cleanup:
+ free_krb5_algorithm_identifiers(&algs);
+ return ret;
+}
+
krb5_error_code
create_krb5_trustedCertifiers(krb5_context context,
pkinit_plg_crypto_context plg_cryptoctx,
--
2.35.3

@ -1,578 +0,0 @@
From e33835c4b6c6ce71757e9f659db03afa4bfd9a9a Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Fri, 15 Jan 2021 13:51:34 -0500
Subject: [PATCH] Support host-based GSS initiator names
When checking if we can get initial credentials in the GSS krb5 mech,
use krb5_kt_have_match() to support fallback iteration. When scanning
the ccache or getting initial credentials, rewrite cred->name->princ
to the canonical client name. When a name check is necessary (such as
when the caller specifies both a name and ccache), use a new internal
API k5_sname_compare() to support fallback iteration. Add fallback
iteration to krb5_cc_cache_match() to allow host-based names to be
canonicalized against the cache collection.
Create and store the matching principal for acceptor names in
acquire_accept_cred() so that it isn't affected by changes in
cred->name->princ during acquire_init_cred().
ticket: 8978 (new)
(cherry picked from commit c374ab40dd059a5938ffc0440d87457ac5da3a46)
---
src/include/k5-int.h | 9 +++
src/include/k5-trace.h | 3 +
src/lib/gssapi/krb5/accept_sec_context.c | 15 +---
src/lib/gssapi/krb5/acquire_cred.c | 89 ++++++++++++++----------
src/lib/gssapi/krb5/gssapiP_krb5.h | 1 +
src/lib/gssapi/krb5/rel_cred.c | 1 +
src/lib/krb5/ccache/cccursor.c | 57 +++++++++++----
src/lib/krb5/libkrb5.exports | 1 +
src/lib/krb5/os/sn2princ.c | 23 +++++-
src/lib/krb5_32.def | 1 +
src/tests/gssapi/t_client_keytab.py | 44 ++++++++++++
src/tests/gssapi/t_credstore.py | 32 +++++++++
12 files changed, 214 insertions(+), 62 deletions(-)
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index efb523689..46f2ce2d3 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -2411,4 +2411,13 @@ void k5_change_error_message_code(krb5_context ctx, krb5_error_code oldcode,
#define k5_prependmsg krb5_prepend_error_message
#define k5_wrapmsg krb5_wrap_error_message
+/*
+ * Like krb5_principal_compare(), but with canonicalization of sname if
+ * fallback is enabled. This function should be avoided if multiple matches
+ * are required, since repeated canonicalization is inefficient.
+ */
+krb5_boolean
+k5_sname_compare(krb5_context context, krb5_const_principal sname,
+ krb5_const_principal princ);
+
#endif /* _KRB5_INT_H */
diff --git a/src/include/k5-trace.h b/src/include/k5-trace.h
index b3e039dc8..79b5a7a85 100644
--- a/src/include/k5-trace.h
+++ b/src/include/k5-trace.h
@@ -105,6 +105,9 @@ void krb5int_trace(krb5_context context, const char *fmt, ...);
#endif /* DISABLE_TRACING */
+#define TRACE_CC_CACHE_MATCH(c, princ, ret) \
+ TRACE(c, "Matching {princ} in collection with result: {kerr}", \
+ princ, ret)
#define TRACE_CC_DESTROY(c, cache) \
TRACE(c, "Destroying ccache {ccache}", cache)
#define TRACE_CC_GEN_NEW(c, cache) \
diff --git a/src/lib/gssapi/krb5/accept_sec_context.c b/src/lib/gssapi/krb5/accept_sec_context.c
index fcf2c2152..a1d7e0d96 100644
--- a/src/lib/gssapi/krb5/accept_sec_context.c
+++ b/src/lib/gssapi/krb5/accept_sec_context.c
@@ -683,7 +683,6 @@ kg_accept_krb5(minor_status, context_handle,
krb5_flags ap_req_options = 0;
krb5_enctype negotiated_etype;
krb5_authdata_context ad_context = NULL;
- krb5_principal accprinc = NULL;
krb5_ap_req *request = NULL;
code = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION);
@@ -849,17 +848,9 @@ kg_accept_krb5(minor_status, context_handle,
}
}
- if (!cred->default_identity) {
- if ((code = kg_acceptor_princ(context, cred->name, &accprinc))) {
- major_status = GSS_S_FAILURE;
- goto fail;
- }
- }
-
- code = krb5_rd_req_decoded(context, &auth_context, request, accprinc,
- cred->keytab, &ap_req_options, NULL);
-
- krb5_free_principal(context, accprinc);
+ code = krb5_rd_req_decoded(context, &auth_context, request,
+ cred->acceptor_mprinc, cred->keytab,
+ &ap_req_options, NULL);
if (code) {
major_status = GSS_S_FAILURE;
goto fail;
diff --git a/src/lib/gssapi/krb5/acquire_cred.c b/src/lib/gssapi/krb5/acquire_cred.c
index 632ee7def..e226a0269 100644
--- a/src/lib/gssapi/krb5/acquire_cred.c
+++ b/src/lib/gssapi/krb5/acquire_cred.c
@@ -123,11 +123,11 @@ gss_krb5int_register_acceptor_identity(OM_uint32 *minor_status,
/* Try to verify that keytab contains at least one entry for name. Return 0 if
* it does, KRB5_KT_NOTFOUND if it doesn't, or another error as appropriate. */
static krb5_error_code
-check_keytab(krb5_context context, krb5_keytab kt, krb5_gss_name_t name)
+check_keytab(krb5_context context, krb5_keytab kt, krb5_gss_name_t name,
+ krb5_principal mprinc)
{
krb5_error_code code;
krb5_keytab_entry ent;
- krb5_principal accprinc = NULL;
char *princname;
if (name->service == NULL) {
@@ -141,21 +141,15 @@ check_keytab(krb5_context context, krb5_keytab kt, krb5_gss_name_t name)
if (kt->ops->start_seq_get == NULL)
return 0;
- /* Get the partial principal for the acceptor name. */
- code = kg_acceptor_princ(context, name, &accprinc);
- if (code)
- return code;
-
- /* Scan the keytab for host-based entries matching accprinc. */
- code = k5_kt_have_match(context, kt, accprinc);
+ /* Scan the keytab for host-based entries matching mprinc. */
+ code = k5_kt_have_match(context, kt, mprinc);
if (code == KRB5_KT_NOTFOUND) {
- if (krb5_unparse_name(context, accprinc, &princname) == 0) {
+ if (krb5_unparse_name(context, mprinc, &princname) == 0) {
k5_setmsg(context, code, _("No key table entry found matching %s"),
princname);
free(princname);
}
}
- krb5_free_principal(context, accprinc);
return code;
}
@@ -202,8 +196,14 @@ acquire_accept_cred(krb5_context context, OM_uint32 *minor_status,
}
if (cred->name != NULL) {
+ code = kg_acceptor_princ(context, cred->name, &cred->acceptor_mprinc);
+ if (code) {
+ major = GSS_S_FAILURE;
+ goto cleanup;
+ }
+
/* Make sure we have keys matching the desired name in the keytab. */
- code = check_keytab(context, kt, cred->name);
+ code = check_keytab(context, kt, cred->name, cred->acceptor_mprinc);
if (code) {
if (code == KRB5_KT_NOTFOUND) {
k5_change_error_message_code(context, code, KG_KEYTAB_NOMATCH);
@@ -324,7 +324,6 @@ static krb5_boolean
can_get_initial_creds(krb5_context context, krb5_gss_cred_id_rec *cred)
{
krb5_error_code code;
- krb5_keytab_entry entry;
if (cred->password != NULL)
return TRUE;
@@ -336,20 +335,21 @@ can_get_initial_creds(krb5_context context, krb5_gss_cred_id_rec *cred)
if (cred->name == NULL)
return !krb5_kt_have_content(context, cred->client_keytab);
- /* Check if we have a keytab key for the client principal. */
- code = krb5_kt_get_entry(context, cred->client_keytab, cred->name->princ,
- 0, 0, &entry);
- if (code) {
- krb5_clear_error_message(context);
- return FALSE;
- }
- krb5_free_keytab_entry_contents(context, &entry);
- return TRUE;
+ /*
+ * Check if we have a keytab key for the client principal. This is a bit
+ * more permissive than we really want because krb5_kt_have_match()
+ * supports wildcarding and obeys ignore_acceptor_hostname, but that should
+ * generally be harmless.
+ */
+ code = k5_kt_have_match(context, cred->client_keytab, cred->name->princ);
+ return code == 0;
}
-/* Scan cred->ccache for name, expiry time, impersonator, refresh time. */
+/* Scan cred->ccache for name, expiry time, impersonator, refresh time. If
+ * check_name is true, verify the cache name against the credential name. */
static krb5_error_code
-scan_ccache(krb5_context context, krb5_gss_cred_id_rec *cred)
+scan_ccache(krb5_context context, krb5_gss_cred_id_rec *cred,
+ krb5_boolean check_name)
{
krb5_error_code code;
krb5_ccache ccache = cred->ccache;
@@ -365,23 +365,31 @@ scan_ccache(krb5_context context, krb5_gss_cred_id_rec *cred)
if (code)
return code;
- /* Credentials cache principal must match the initiator name. */
code = krb5_cc_get_principal(context, ccache, &ccache_princ);
if (code != 0)
goto cleanup;
- if (cred->name != NULL &&
- !krb5_principal_compare(context, ccache_princ, cred->name->princ)) {
- code = KG_CCACHE_NOMATCH;
- goto cleanup;
- }
- /* Save the ccache principal as the credential name if not already set. */
- if (!cred->name) {
+ if (cred->name == NULL) {
+ /* Save the ccache principal as the credential name. */
code = kg_init_name(context, ccache_princ, NULL, NULL, NULL,
KG_INIT_NAME_NO_COPY, &cred->name);
if (code)
goto cleanup;
ccache_princ = NULL;
+ } else {
+ /* Check against the desired name if needed. */
+ if (check_name) {
+ if (!k5_sname_compare(context, cred->name->princ, ccache_princ)) {
+ code = KG_CCACHE_NOMATCH;
+ goto cleanup;
+ }
+ }
+
+ /* Replace the credential name principal with the canonical client
+ * principal, retaining acceptor_mprinc if set. */
+ krb5_free_principal(context, cred->name->princ);
+ cred->name->princ = ccache_princ;
+ ccache_princ = NULL;
}
assert(cred->name->princ != NULL);
@@ -447,7 +455,7 @@ get_cache_for_name(krb5_context context, krb5_gss_cred_id_rec *cred)
assert(cred->name != NULL && cred->ccache == NULL);
#ifdef USE_LEASH
code = get_ccache_leash(context, cred->name->princ, &cred->ccache);
- return code ? code : scan_ccache(context, cred);
+ return code ? code : scan_ccache(context, cred, TRUE);
#else
/* Check first whether we can acquire tickets, to avoid overwriting the
* extended error message from krb5_cc_cache_match. */
@@ -456,7 +464,7 @@ get_cache_for_name(krb5_context context, krb5_gss_cred_id_rec *cred)
/* Look for an existing cache for the client principal. */
code = krb5_cc_cache_match(context, cred->name->princ, &cred->ccache);
if (code == 0)
- return scan_ccache(context, cred);
+ return scan_ccache(context, cred, FALSE);
if (code != KRB5_CC_NOTFOUND || !can_get)
return code;
krb5_clear_error_message(context);
@@ -633,6 +641,13 @@ get_initial_cred(krb5_context context, const struct verify_params *verify,
kg_cred_set_initial_refresh(context, cred, &creds.times);
cred->have_tgt = TRUE;
cred->expire = creds.times.endtime;
+
+ /* Steal the canonical client principal name from creds and save it in the
+ * credential name, retaining acceptor_mprinc if set. */
+ krb5_free_principal(context, cred->name->princ);
+ cred->name->princ = creds.client;
+ creds.client = NULL;
+
krb5_free_cred_contents(context, &creds);
cleanup:
krb5_get_init_creds_opt_free(context, opt);
@@ -721,7 +736,7 @@ acquire_init_cred(krb5_context context, OM_uint32 *minor_status,
if (cred->ccache != NULL) {
/* The caller specified a ccache; check what's in it. */
- code = scan_ccache(context, cred);
+ code = scan_ccache(context, cred, TRUE);
if (code == KRB5_FCC_NOFILE) {
/* See if we can get initial creds. If the caller didn't specify
* a name, pick one from the client keytab. */
@@ -984,7 +999,7 @@ kg_cred_resolve(OM_uint32 *minor_status, krb5_context context,
}
}
if (cred->ccache != NULL) {
- code = scan_ccache(context, cred);
+ code = scan_ccache(context, cred, FALSE);
if (code)
goto kerr;
}
@@ -996,7 +1011,7 @@ kg_cred_resolve(OM_uint32 *minor_status, krb5_context context,
code = krb5int_cc_default(context, &cred->ccache);
if (code)
goto kerr;
- code = scan_ccache(context, cred);
+ code = scan_ccache(context, cred, FALSE);
if (code == KRB5_FCC_NOFILE) {
/* Default ccache doesn't exist; fall through to client keytab. */
krb5_cc_close(context, cred->ccache);
diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h
index 3bacdcd35..fd7abbd77 100644
--- a/src/lib/gssapi/krb5/gssapiP_krb5.h
+++ b/src/lib/gssapi/krb5/gssapiP_krb5.h
@@ -175,6 +175,7 @@ typedef struct _krb5_gss_cred_id_rec {
/* name/type of credential */
gss_cred_usage_t usage;
krb5_gss_name_t name;
+ krb5_principal acceptor_mprinc;
krb5_principal impersonator;
unsigned int default_identity : 1;
unsigned int iakerb_mech : 1;
diff --git a/src/lib/gssapi/krb5/rel_cred.c b/src/lib/gssapi/krb5/rel_cred.c
index a9515daf7..0da6c1b95 100644
--- a/src/lib/gssapi/krb5/rel_cred.c
+++ b/src/lib/gssapi/krb5/rel_cred.c
@@ -72,6 +72,7 @@ krb5_gss_release_cred(minor_status, cred_handle)
if (cred->name)
kg_release_name(context, &cred->name);
+ krb5_free_principal(context, cred->acceptor_mprinc);
krb5_free_principal(context, cred->impersonator);
if (cred->req_enctypes)
diff --git a/src/lib/krb5/ccache/cccursor.c b/src/lib/krb5/ccache/cccursor.c
index 8f5872116..760216d05 100644
--- a/src/lib/krb5/ccache/cccursor.c
+++ b/src/lib/krb5/ccache/cccursor.c
@@ -30,6 +30,7 @@
#include "cc-int.h"
#include "../krb/int-proto.h"
+#include "../os/os-proto.h"
#include <assert.h>
@@ -141,18 +142,18 @@ krb5_cccol_cursor_free(krb5_context context,
return 0;
}
-krb5_error_code KRB5_CALLCONV
-krb5_cc_cache_match(krb5_context context, krb5_principal client,
- krb5_ccache *cache_out)
+static krb5_error_code
+match_caches(krb5_context context, krb5_const_principal client,
+ krb5_ccache *cache_out)
{
krb5_error_code ret;
krb5_cccol_cursor cursor;
krb5_ccache cache = NULL;
krb5_principal princ;
- char *name;
krb5_boolean eq;
*cache_out = NULL;
+
ret = krb5_cccol_cursor_new(context, &cursor);
if (ret)
return ret;
@@ -169,20 +170,52 @@ krb5_cc_cache_match(krb5_context context, krb5_principal client,
krb5_cc_close(context, cache);
}
krb5_cccol_cursor_free(context, &cursor);
+
if (ret)
return ret;
- if (cache == NULL) {
- ret = krb5_unparse_name(context, client, &name);
- if (ret == 0) {
- k5_setmsg(context, KRB5_CC_NOTFOUND,
+ if (cache == NULL)
+ return KRB5_CC_NOTFOUND;
+
+ *cache_out = cache;
+ return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_cache_match(krb5_context context, krb5_principal client,
+ krb5_ccache *cache_out)
+{
+ krb5_error_code ret;
+ struct canonprinc iter = { client, .subst_defrealm = TRUE };
+ krb5_const_principal canonprinc = NULL;
+ krb5_ccache cache = NULL;
+ char *name;
+
+ *cache_out = NULL;
+
+ while ((ret = k5_canonprinc(context, &iter, &canonprinc)) == 0 &&
+ canonprinc != NULL) {
+ ret = match_caches(context, canonprinc, &cache);
+ if (ret != KRB5_CC_NOTFOUND)
+ break;
+ }
+ free_canonprinc(&iter);
+
+ if (ret == 0 && canonprinc == NULL) {
+ ret = KRB5_CC_NOTFOUND;
+ if (krb5_unparse_name(context, client, &name) == 0) {
+ k5_setmsg(context, ret,
_("Can't find client principal %s in cache collection"),
name);
krb5_free_unparsed_name(context, name);
}
- ret = KRB5_CC_NOTFOUND;
- } else
- *cache_out = cache;
- return ret;
+ }
+
+ TRACE_CC_CACHE_MATCH(context, client, ret);
+ if (ret)
+ return ret;
+
+ *cache_out = cache;
+ return 0;
}
/* Store the error state for code from context into errsave, but only if code
diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports
index adbfa332b..df6e2ffbe 100644
--- a/src/lib/krb5/libkrb5.exports
+++ b/src/lib/krb5/libkrb5.exports
@@ -181,6 +181,7 @@ k5_size_authdata_context
k5_size_context
k5_size_keyblock
k5_size_principal
+k5_sname_compare
k5_unmarshal_cred
k5_unmarshal_princ
k5_unwrap_cammac_svc
diff --git a/src/lib/krb5/os/sn2princ.c b/src/lib/krb5/os/sn2princ.c
index 8b7214189..c99b7da17 100644
--- a/src/lib/krb5/os/sn2princ.c
+++ b/src/lib/krb5/os/sn2princ.c
@@ -277,7 +277,8 @@ k5_canonprinc(krb5_context context, struct canonprinc *iter,
/* If we're not doing fallback, the input principal is canonical. */
if (context->dns_canonicalize_hostname != CANONHOST_FALLBACK ||
- iter->princ->type != KRB5_NT_SRV_HST || iter->princ->length != 2) {
+ iter->princ->type != KRB5_NT_SRV_HST || iter->princ->length != 2 ||
+ iter->princ->data[1].length == 0) {
*princ_out = (step == 1) ? iter->princ : NULL;
return 0;
}
@@ -288,6 +289,26 @@ k5_canonprinc(krb5_context context, struct canonprinc *iter,
return canonicalize_princ(context, iter, step == 2, princ_out);
}
+krb5_boolean
+k5_sname_compare(krb5_context context, krb5_const_principal sname,
+ krb5_const_principal princ)
+{
+ krb5_error_code ret;
+ struct canonprinc iter = { sname, .subst_defrealm = TRUE };
+ krb5_const_principal canonprinc = NULL;
+ krb5_boolean match = FALSE;
+
+ while ((ret = k5_canonprinc(context, &iter, &canonprinc)) == 0 &&
+ canonprinc != NULL) {
+ if (krb5_principal_compare(context, canonprinc, princ)) {
+ match = TRUE;
+ break;
+ }
+ }
+ free_canonprinc(&iter);
+ return match;
+}
+
krb5_error_code KRB5_CALLCONV
krb5_sname_to_principal(krb5_context context, const char *hostname,
const char *sname, krb5_int32 type,
diff --git a/src/lib/krb5_32.def b/src/lib/krb5_32.def
index 60b8dd311..cf690dbe4 100644
--- a/src/lib/krb5_32.def
+++ b/src/lib/krb5_32.def
@@ -507,3 +507,4 @@ EXPORTS
; new in 1.20
krb5_marshal_credentials @472
krb5_unmarshal_credentials @473
+ k5_sname_compare @474 ; PRIVATE GSSAPI
diff --git a/src/tests/gssapi/t_client_keytab.py b/src/tests/gssapi/t_client_keytab.py
index 7847b3ecd..9a61d53b8 100755
--- a/src/tests/gssapi/t_client_keytab.py
+++ b/src/tests/gssapi/t_client_keytab.py
@@ -141,5 +141,49 @@ msgs = ('Getting initial credentials for user/admin@KRBTEST.COM',
'/Matching credential not found')
realm.run(['./t_ccselect', phost], expected_code=1,
expected_msg='Ticket expired', expected_trace=msgs)
+realm.run([kdestroy, '-A'])
+
+# Test 19: host-based initiator name
+mark('host-based initiator name')
+hsvc = 'h:svc@' + hostname
+svcprinc = 'svc/%s@%s' % (hostname, realm.realm)
+realm.addprinc(svcprinc)
+realm.extract_keytab(svcprinc, realm.client_keytab)
+# On the first run we match against the keytab while getting tickets,
+# substituting the default realm.
+msgs = ('/Can\'t find client principal svc/%s@ in' % hostname,
+ 'Getting initial credentials for svc/%s@' % hostname,
+ 'Found entries for %s in keytab' % svcprinc,
+ 'Retrieving %s from FILE:%s' % (svcprinc, realm.client_keytab),
+ 'Storing %s -> %s in' % (svcprinc, realm.krbtgt_princ),
+ 'Retrieving %s -> %s from' % (svcprinc, realm.krbtgt_princ),
+ 'authenticator for %s -> %s' % (svcprinc, realm.host_princ))
+realm.run(['./t_ccselect', phost, hsvc], expected_trace=msgs)
+# On the second run we match against the collection.
+msgs = ('Matching svc/%s@ in collection with result: 0' % hostname,
+ 'Getting credentials %s -> %s' % (svcprinc, realm.host_princ),
+ 'authenticator for %s -> %s' % (svcprinc, realm.host_princ))
+realm.run(['./t_ccselect', phost, hsvc], expected_trace=msgs)
+realm.run([kdestroy, '-A'])
+
+# Test 20: host-based initiator name with fallback
+mark('host-based fallback initiator name')
+canonname = canonicalize_hostname(hostname)
+if canonname != hostname:
+ hfsvc = 'h:fsvc@' + hostname
+ canonprinc = 'fsvc/%s@%s' % (canonname, realm.realm)
+ realm.addprinc(canonprinc)
+ realm.extract_keytab(canonprinc, realm.client_keytab)
+ msgs = ('/Can\'t find client principal fsvc/%s@ in' % hostname,
+ 'Found entries for %s in keytab' % canonprinc,
+ 'authenticator for %s -> %s' % (canonprinc, realm.host_princ))
+ realm.run(['./t_ccselect', phost, hfsvc], expected_trace=msgs)
+ msgs = ('Matching fsvc/%s@ in collection with result: 0' % hostname,
+ 'Getting credentials %s -> %s' % (canonprinc, realm.host_princ))
+ realm.run(['./t_ccselect', phost, hfsvc], expected_trace=msgs)
+ realm.run([kdestroy, '-A'])
+else:
+ skipped('GSS initiator name fallback test',
+ '%s does not canonicalize to a different name' % hostname)
success('Client keytab tests')
diff --git a/src/tests/gssapi/t_credstore.py b/src/tests/gssapi/t_credstore.py
index c11975bf5..9be57bb82 100644
--- a/src/tests/gssapi/t_credstore.py
+++ b/src/tests/gssapi/t_credstore.py
@@ -15,6 +15,38 @@ msgs = ('Storing %s -> %s in %s' % (service_cs, realm.krbtgt_princ,
realm.run(['./t_credstore', '-s', 'p:' + service_cs, 'ccache', storagecache,
'keytab', servicekeytab], expected_trace=msgs)
+mark('matching')
+scc = 'FILE:' + os.path.join(realm.testdir, 'service_cache')
+realm.kinit(realm.host_princ, flags=['-k', '-c', scc])
+realm.run(['./t_credstore', '-i', 'p:' + realm.host_princ, 'ccache', scc])
+realm.run(['./t_credstore', '-i', 'h:host', 'ccache', scc])
+realm.run(['./t_credstore', '-i', 'h:host@' + hostname, 'ccache', scc])
+realm.run(['./t_credstore', '-i', 'p:wrong', 'ccache', scc],
+ expected_code=1, expected_msg='does not match desired name')
+realm.run(['./t_credstore', '-i', 'h:host@-nomatch-', 'ccache', scc],
+ expected_code=1, expected_msg='does not match desired name')
+realm.run(['./t_credstore', '-i', 'h:svc', 'ccache', scc],
+ expected_code=1, expected_msg='does not match desired name')
+
+mark('matching (fallback)')
+canonname = canonicalize_hostname(hostname)
+if canonname != hostname:
+ canonprinc = 'host/%s@%s' % (canonname, realm.realm)
+ realm.addprinc(canonprinc)
+ realm.extract_keytab(canonprinc, realm.keytab)
+ realm.kinit(canonprinc, flags=['-k', '-c', scc])
+ realm.run(['./t_credstore', '-i', 'h:host', 'ccache', scc])
+ realm.run(['./t_credstore', '-i', 'h:host@' + hostname, 'ccache', scc])
+ realm.run(['./t_credstore', '-i', 'h:host@' + canonname, 'ccache', scc])
+ realm.run(['./t_credstore', '-i', 'p:' + canonprinc, 'ccache', scc])
+ realm.run(['./t_credstore', '-i', 'p:' + realm.host_princ, 'ccache', scc],
+ expected_code=1, expected_msg='does not match desired name')
+ realm.run(['./t_credstore', '-i', 'h:host@-nomatch-', 'ccache', scc],
+ expected_code=1, expected_msg='does not match desired name')
+else:
+ skipped('fallback matching test',
+ '%s does not canonicalize to a different name' % hostname)
+
mark('rcache')
# t_credstore -r should produce a replay error normally, but not with
# rcache set to "none:".

@ -1,91 +0,0 @@
From ad8e02485791023dcf66ef4612616f03895ceeb3 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Fri, 4 Mar 2022 00:45:00 -0500
Subject: [PATCH] Try harder to avoid password change replay errors
Commit d7b3018d338fc9c989c3fa17505870f23c3759a8 (ticket 7905) changed
change_set_password() to prefer TCP. However, because UDP_LAST falls
back to UDP after one second, we can still get a replay error due to a
dropped packet, before the TCP layer has a chance to retry.
Instead, try k5_sendto() with NO_UDP, and only fall back to UDP after
TCP fails completely without reaching a server. In sendto_kdc.c,
implement an ONLY_UDP transport strategy to allow the UDP fallback.
ticket: 9037
---
src/lib/krb5/os/changepw.c | 9 ++++++++-
src/lib/krb5/os/os-proto.h | 1 +
src/lib/krb5/os/sendto_kdc.c | 12 ++++++++----
3 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/src/lib/krb5/os/changepw.c b/src/lib/krb5/os/changepw.c
index 9f968da7f..c59232586 100644
--- a/src/lib/krb5/os/changepw.c
+++ b/src/lib/krb5/os/changepw.c
@@ -255,9 +255,16 @@ change_set_password(krb5_context context,
callback_info.pfn_cleanup = kpasswd_sendto_msg_cleanup;
krb5_free_data_contents(callback_ctx.context, &chpw_rep);
+ /* UDP retransmits may be seen as replays. Only try UDP after other
+ * transports fail completely. */
code = k5_sendto(callback_ctx.context, NULL, &creds->server->realm,
- &sl, UDP_LAST, &callback_info, &chpw_rep,
+ &sl, NO_UDP, &callback_info, &chpw_rep,
ss2sa(&remote_addr), &addrlen, NULL, NULL, NULL);
+ if (code == KRB5_KDC_UNREACH) {
+ code = k5_sendto(callback_ctx.context, NULL, &creds->server->realm,
+ &sl, ONLY_UDP, &callback_info, &chpw_rep,
+ ss2sa(&remote_addr), &addrlen, NULL, NULL, NULL);
+ }
if (code)
goto cleanup;
diff --git a/src/lib/krb5/os/os-proto.h b/src/lib/krb5/os/os-proto.h
index a985f2aec..91d2791ce 100644
--- a/src/lib/krb5/os/os-proto.h
+++ b/src/lib/krb5/os/os-proto.h
@@ -49,6 +49,7 @@ typedef enum {
UDP_FIRST = 0,
UDP_LAST,
NO_UDP,
+ ONLY_UDP
} k5_transport_strategy;
/* A single server hostname or address. */
diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c
index 0eedec175..c7f5d861a 100644
--- a/src/lib/krb5/os/sendto_kdc.c
+++ b/src/lib/krb5/os/sendto_kdc.c
@@ -802,11 +802,14 @@ resolve_server(krb5_context context, const krb5_data *realm,
int err, result;
char portbuf[PORT_LENGTH];
- /* Skip UDP entries if we don't want UDP. */
+ /* Skip entries excluded by the strategy. */
if (strategy == NO_UDP && entry->transport == UDP)
return 0;
+ if (strategy == ONLY_UDP && entry->transport != UDP &&
+ entry->transport != TCP_OR_UDP)
+ return 0;
- transport = (strategy == UDP_FIRST) ? UDP : TCP;
+ transport = (strategy == UDP_FIRST || strategy == ONLY_UDP) ? UDP : TCP;
if (entry->hostname == NULL) {
/* Added by a module, so transport is either TCP or UDP. */
ai.ai_socktype = socktype_for_transport(entry->transport);
@@ -850,8 +853,9 @@ resolve_server(krb5_context context, const krb5_data *realm,
}
/* For TCP_OR_UDP entries, add each address again with the non-preferred
- * transport, unless we are avoiding UDP. Flag these as deferred. */
- if (retval == 0 && entry->transport == TCP_OR_UDP && strategy != NO_UDP) {
+ * transport, if there is one. Flag these as deferred. */
+ if (retval == 0 && entry->transport == TCP_OR_UDP &&
+ (strategy == UDP_FIRST || strategy == UDP_LAST)) {
transport = (strategy == UDP_FIRST) ? TCP : UDP;
for (a = addrs; a != 0 && retval == 0; a = a->ai_next) {
a->ai_socktype = socktype_for_transport(transport);
--
2.35.1

@ -1,236 +0,0 @@
From 43e3bca2a711de257091454bc5e25a985340d847 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Fri, 26 Mar 2021 23:38:54 -0400
Subject: [PATCH] Use KCM_OP_RETRIEVE in KCM client
In kcm_retrieve(), try KCM_OP_RETRIEVE. Fall back to iteration if the
server doesn't implement it, or if we can an answer incompatible with
KRB5_TC_SUPPORTED_KTYPES.
In kcmserver.py, implement partial decoding for creds and cred tags so
that we can do a basic principal name match.
ticket: 8997 (new)
(cherry picked from commit 795ebba8c039be172ab93cd41105c73ffdba0fdb)
(cherry picked from commit c56d4b87de0f30a38dc61d374ad225d02d581eb3)
---
src/include/kcm.h | 2 +-
src/lib/krb5/ccache/cc_kcm.c | 52 +++++++++++++++++++++++++++++++++---
src/tests/kcmserver.py | 44 +++++++++++++++++++++++++++---
src/tests/t_ccache.py | 11 +++++---
4 files changed, 99 insertions(+), 10 deletions(-)
diff --git a/src/include/kcm.h b/src/include/kcm.h
index 9b66f1cbd..85c20d345 100644
--- a/src/include/kcm.h
+++ b/src/include/kcm.h
@@ -87,7 +87,7 @@ typedef enum kcm_opcode {
KCM_OP_INITIALIZE, /* (name, princ) -> () */
KCM_OP_DESTROY, /* (name) -> () */
KCM_OP_STORE, /* (name, cred) -> () */
- KCM_OP_RETRIEVE,
+ KCM_OP_RETRIEVE, /* (name, flags, credtag) -> (cred) */
KCM_OP_GET_PRINCIPAL, /* (name) -> (princ) */
KCM_OP_GET_CRED_UUID_LIST, /* (name) -> (uuid, ...) */
KCM_OP_GET_CRED_BY_UUID, /* (name, uuid) -> (cred) */
diff --git a/src/lib/krb5/ccache/cc_kcm.c b/src/lib/krb5/ccache/cc_kcm.c
index 46705f1da..23fcf13ea 100644
--- a/src/lib/krb5/ccache/cc_kcm.c
+++ b/src/lib/krb5/ccache/cc_kcm.c
@@ -826,9 +826,55 @@ static krb5_error_code KRB5_CALLCONV
kcm_retrieve(krb5_context context, krb5_ccache cache, krb5_flags flags,
krb5_creds *mcred, krb5_creds *cred_out)
{
- /* There is a KCM opcode for retrieving creds, but Heimdal's client doesn't
- * use it. It causes the KCM daemon to actually make a TGS request. */
- return k5_cc_retrieve_cred_default(context, cache, flags, mcred, cred_out);
+ krb5_error_code ret;
+ struct kcmreq req = EMPTY_KCMREQ;
+ krb5_creds cred;
+ krb5_enctype *enctypes = NULL;
+
+ memset(&cred, 0, sizeof(cred));
+
+ /* Include KCM_GC_CACHED in flags to prevent Heimdal's sssd from making a
+ * TGS request itself. */
+ kcmreq_init(&req, KCM_OP_RETRIEVE, cache);
+ k5_buf_add_uint32_be(&req.reqbuf, map_tcflags(flags) | KCM_GC_CACHED);
+ k5_marshal_mcred(&req.reqbuf, mcred);
+ ret = cache_call(context, cache, &req);
+
+ /* Fall back to iteration if the server does not support retrieval. */
+ if (ret == KRB5_FCC_INTERNAL || ret == KRB5_CC_IO) {
+ ret = k5_cc_retrieve_cred_default(context, cache, flags, mcred,
+ cred_out);
+ goto cleanup;
+ }
+ if (ret)
+ goto cleanup;
+
+ ret = k5_unmarshal_cred(req.reply.ptr, req.reply.len, 4, &cred);
+ if (ret)
+ goto cleanup;
+
+ /* In rare cases we might retrieve a credential with a session key this
+ * context can't support, in which case we must retry using iteration. */
+ if (flags & KRB5_TC_SUPPORTED_KTYPES) {
+ ret = krb5_get_tgs_ktypes(context, cred.server, &enctypes);
+ if (ret)
+ goto cleanup;
+ if (!k5_etypes_contains(enctypes, cred.keyblock.enctype)) {
+ ret = k5_cc_retrieve_cred_default(context, cache, flags, mcred,
+ cred_out);
+ goto cleanup;
+ }
+ }
+
+ *cred_out = cred;
+ memset(&cred, 0, sizeof(cred));
+
+cleanup:
+ kcmreq_free(&req);
+ krb5_free_cred_contents(context, &cred);
+ free(enctypes);
+ /* Heimdal's KCM returns KRB5_CC_END if no cred is found. */
+ return (ret == KRB5_CC_END) ? KRB5_CC_NOTFOUND : map_invalid(ret);
}
static krb5_error_code KRB5_CALLCONV
diff --git a/src/tests/kcmserver.py b/src/tests/kcmserver.py
index 8c5e66ff1..25e6f2bbe 100644
--- a/src/tests/kcmserver.py
+++ b/src/tests/kcmserver.py
@@ -40,6 +40,7 @@ class KCMOpcodes(object):
INITIALIZE = 4
DESTROY = 5
STORE = 6
+ RETRIEVE = 7
GET_PRINCIPAL = 8
GET_CRED_UUID_LIST = 9
GET_CRED_BY_UUID = 10
@@ -54,6 +55,7 @@ class KCMOpcodes(object):
class KRB5Errors(object):
+ KRB5_CC_NOTFOUND = -1765328243
KRB5_CC_END = -1765328242
KRB5_CC_NOSUPP = -1765328137
KRB5_FCC_NOFILE = -1765328189
@@ -86,11 +88,29 @@ def get_cache(name):
return cache
+def unpack_data(argbytes):
+ dlen, = struct.unpack('>L', argbytes[:4])
+ return argbytes[4:dlen+4], argbytes[dlen+4:]
+
+
def unmarshal_name(argbytes):
offset = argbytes.find(b'\0')
return argbytes[0:offset], argbytes[offset+1:]
+def unmarshal_princ(argbytes):
+ # Ignore the type at argbytes[0:4].
+ ncomps, = struct.unpack('>L', argbytes[4:8])
+ realm, rest = unpack_data(argbytes[8:])
+ comps = []
+ for i in range(ncomps):
+ comp, rest = unpack_data(rest)
+ comps.append(comp)
+ # Asssume no quoting is needed.
+ princ = b'/'.join(comps) + b'@' + realm
+ return princ, rest
+
+
def op_gen_new(argbytes):
# Does not actually check for uniqueness.
global next_unique
@@ -126,6 +146,22 @@ def op_store(argbytes):
return 0, b''
+def op_retrieve(argbytes):
+ name, rest = unmarshal_name(argbytes)
+ # Ignore the flags at rest[0:4] and the header at rest[4:8].
+ # Assume there are client and server creds in the tag and match
+ # only against them.
+ cprinc, rest = unmarshal_princ(rest[8:])
+ sprinc, rest = unmarshal_princ(rest)
+ cache = get_cache(name)
+ for cred in (cache.creds[u] for u in cache.cred_uuids):
+ cred_cprinc, rest = unmarshal_princ(cred)
+ cred_sprinc, rest = unmarshal_princ(rest)
+ if cred_cprinc == cprinc and cred_sprinc == sprinc:
+ return 0, cred
+ return KRB5Errors.KRB5_CC_NOTFOUND, b''
+
+
def op_get_principal(argbytes):
name, rest = unmarshal_name(argbytes)
cache = get_cache(name)
@@ -199,6 +235,7 @@ ophandlers = {
KCMOpcodes.INITIALIZE : op_initialize,
KCMOpcodes.DESTROY : op_destroy,
KCMOpcodes.STORE : op_store,
+ KCMOpcodes.RETRIEVE : op_retrieve,
KCMOpcodes.GET_PRINCIPAL : op_get_principal,
KCMOpcodes.GET_CRED_UUID_LIST : op_get_cred_uuid_list,
KCMOpcodes.GET_CRED_BY_UUID : op_get_cred_by_uuid,
@@ -243,10 +280,11 @@ def service_request(s):
return True
parser = optparse.OptionParser()
-parser.add_option('-c', '--credlist', action='store_true', dest='credlist',
- default=False, help='Support KCM_OP_GET_CRED_LIST')
+parser.add_option('-f', '--fallback', action='store_true', dest='fallback',
+ default=False, help='Do not support RETRIEVE/GET_CRED_LIST')
(options, args) = parser.parse_args()
-if not options.credlist:
+if options.fallback:
+ del ophandlers[KCMOpcodes.RETRIEVE]
del ophandlers[KCMOpcodes.GET_CRED_LIST]
server = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
diff --git a/src/tests/t_ccache.py b/src/tests/t_ccache.py
index 90040fb7b..6ea9fb969 100755
--- a/src/tests/t_ccache.py
+++ b/src/tests/t_ccache.py
@@ -25,7 +25,7 @@ from k5test import *
kcm_socket_path = os.path.join(os.getcwd(), 'testdir', 'kcm')
conf = {'libdefaults': {'kcm_socket': kcm_socket_path,
'kcm_mach_service': '-'}}
-realm = K5Realm(create_host=False, krb5_conf=conf)
+realm = K5Realm(krb5_conf=conf)
keyctl = which('keyctl')
out = realm.run([klist, '-c', 'KEYRING:process:abcd'], expected_code=1)
@@ -71,6 +71,11 @@ def collection_test(realm, ccname):
realm.kinit('alice', password('alice'))
realm.run([klist], expected_msg='Default principal: alice@')
realm.run([klist, '-A', '-s'])
+ realm.run([kvno, realm.host_princ], expected_msg = 'kvno = 1')
+ realm.run([kvno, realm.host_princ], expected_msg = 'kvno = 1')
+ out = realm.run([klist])
+ if out.count(realm.host_princ) != 1:
+ fail('Wrong number of service tickets in cache')
realm.run([kdestroy])
output = realm.run([klist], expected_code=1)
if 'No credentials cache' not in output and 'not found' not in output:
@@ -126,14 +131,14 @@ def collection_test(realm, ccname):
collection_test(realm, 'DIR:' + os.path.join(realm.testdir, 'cc'))
-# Test KCM without and with GET_CRED_LIST support.
+# Test KCM with and without RETRIEVE and GET_CRED_LIST support.
kcmserver_path = os.path.join(srctop, 'tests', 'kcmserver.py')
kcmd = realm.start_server([sys.executable, kcmserver_path, kcm_socket_path],
'starting...')
collection_test(realm, 'KCM:')
stop_daemon(kcmd)
os.remove(kcm_socket_path)
-realm.start_server([sys.executable, kcmserver_path, '-c', kcm_socket_path],
+realm.start_server([sys.executable, kcmserver_path, '-f', kcm_socket_path],
'starting...')
collection_test(realm, 'KCM:')

@ -1,485 +0,0 @@
From 21e3b9a4463f1d1aeb71de8a27c298f1307d186b Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Fri, 4 Oct 2019 14:49:29 -0400
Subject: [PATCH] Use OpenSSL's KBKDF and KRB5KDF for deriving long-term keys
If supported, use OpenSSL-provided KBKDF (aes-sha2 and camellia) and
KRB5KDF (3des and aes-sha1). We already use OpenSSL's PBKDF2 where
appropriate. OpenSSL added support for these KDFs in 3.0.
OpenSSL's restrictions to use KRB5KDF in FIPS mode are bypassed in case
AES SHA-1 HMAC encryption types are allowed by the crypto policy.
(cherry picked from commit ef8d11f6fb1232201c9efd2ae2ed567023fb85d2)
[rharwood@redhat.com: 3des removal]
---
src/lib/crypto/krb/derive.c | 409 ++++++++++++++++++++++++++++--------
1 file changed, 324 insertions(+), 85 deletions(-)
diff --git a/src/lib/crypto/krb/derive.c b/src/lib/crypto/krb/derive.c
index 6707a7308..8e474b38e 100644
--- a/src/lib/crypto/krb/derive.c
+++ b/src/lib/crypto/krb/derive.c
@@ -27,6 +27,12 @@
#include "crypto_int.h"
+#ifdef HAVE_EVP_KDF_FETCH
+#include <openssl/core_names.h>
+#include <openssl/evp.h>
+#include <openssl/kdf.h>
+#endif
+
static krb5_key
find_cached_dkey(struct derived_key *list, const krb5_data *constant)
{
@@ -77,55 +83,251 @@ cleanup:
return ENOMEM;
}
+#ifdef HAVE_EVP_KDF_FETCH
static krb5_error_code
-derive_random_rfc3961(const struct krb5_enc_provider *enc,
- krb5_key inkey, krb5_data *outrnd,
- const krb5_data *in_constant)
+openssl_kbdkf_counter_hmac(const struct krb5_hash_provider *hash,
+ krb5_key inkey, krb5_data *outrnd,
+ const krb5_data *label, const krb5_data *context)
{
- size_t blocksize, keybytes, n;
krb5_error_code ret;
- krb5_data block = empty_data();
+ EVP_KDF *kdf = NULL;
+ EVP_KDF_CTX *kctx = NULL;
+ OSSL_PARAM params[6];
+ size_t i = 0;
+ char *digest;
- blocksize = enc->block_size;
- keybytes = enc->keybytes;
+ /* On NULL hash, preserve default behavior for pbkdf2_string_to_key(). */
+ if (hash == NULL || !strcmp(hash->hash_name, "SHA1")) {
+ digest = "SHA1";
+ } else if (!strcmp(hash->hash_name, "SHA-256")) {
+ digest = "SHA256";
+ } else if (!strcmp(hash->hash_name, "SHA-384")) {
+ digest = "SHA384";
+ } else {
+ ret = KRB5_CRYPTO_INTERNAL;
+ goto done;
+ }
- if (blocksize == 1)
- return KRB5_BAD_ENCTYPE;
- if (inkey->keyblock.length != enc->keylength || outrnd->length != keybytes)
+ kdf = EVP_KDF_fetch(NULL, "KBKDF", NULL);
+ if (!kdf) {
+ ret = KRB5_CRYPTO_INTERNAL;
+ goto done;
+ }
+
+ kctx = EVP_KDF_CTX_new(kdf);
+ if (!kctx) {
+ ret = KRB5_CRYPTO_INTERNAL;
+ goto done;
+ }
+
+ params[i++] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
+ digest, 0);
+ params[i++] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MAC,
+ "HMAC", 0);
+ params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
+ inkey->keyblock.contents,
+ inkey->keyblock.length);
+ params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
+ context->data,
+ context->length);
+ params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
+ label->data,
+ label->length);
+ params[i] = OSSL_PARAM_construct_end();
+ if (EVP_KDF_derive(kctx, (unsigned char *)outrnd->data, outrnd->length,
+ params) <= 0) {
+ ret = KRB5_CRYPTO_INTERNAL;
+ goto done;
+ }
+
+ ret = 0;
+done:
+ if (ret)
+ zap(outrnd->data, outrnd->length);
+ EVP_KDF_free(kdf);
+ EVP_KDF_CTX_free(kctx);
+ return ret;
+}
+
+static krb5_error_code
+openssl_kbkdf_feedback_cmac(const struct krb5_enc_provider *enc,
+ krb5_key inkey, krb5_data *outrnd,
+ const krb5_data *in_constant)
+{
+ krb5_error_code ret;
+ EVP_KDF *kdf = NULL;
+ EVP_KDF_CTX *kctx = NULL;
+ OSSL_PARAM params[7];
+ size_t i = 0;
+ char *cipher;
+ static unsigned char zeroes[16];
+
+ memset(zeroes, 0, sizeof(zeroes));
+
+ if (!memcmp(enc, &krb5int_enc_camellia128, sizeof(*enc))) {
+ cipher = "CAMELLIA-128-CBC";
+ } else if (!memcmp(enc, &krb5int_enc_camellia256, sizeof(*enc))) {
+ cipher = "CAMELLIA-256-CBC";
+ } else {
+ ret = KRB5_CRYPTO_INTERNAL;
+ goto done;
+ }
+
+ kdf = EVP_KDF_fetch(NULL, "KBKDF", NULL);
+ if (!kdf) {
+ ret = KRB5_CRYPTO_INTERNAL;
+ goto done;
+ }
+
+ kctx = EVP_KDF_CTX_new(kdf);
+ if (!kctx) {
+ ret = KRB5_CRYPTO_INTERNAL;
+ goto done;
+ }
+
+ params[i++] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MODE,
+ "FEEDBACK", 0);
+ params[i++] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MAC,
+ "CMAC", 0);
+ params[i++] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_CIPHER,
+ cipher, 0);
+ params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
+ inkey->keyblock.contents,
+ inkey->keyblock.length);
+ params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
+ in_constant->data,
+ in_constant->length);
+ params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SEED,
+ zeroes, sizeof(zeroes));
+ params[i] = OSSL_PARAM_construct_end();
+ if (EVP_KDF_derive(kctx, (unsigned char *)outrnd->data, outrnd->length,
+ params) <= 0) {
+ ret = KRB5_CRYPTO_INTERNAL;
+ goto done;
+ }
+
+ ret = 0;
+done:
+ if (ret)
+ zap(outrnd->data, outrnd->length);
+ EVP_KDF_free(kdf);
+ EVP_KDF_CTX_free(kctx);
+ return ret;
+}
+
+static krb5_error_code
+openssl_krb5kdf(const struct krb5_enc_provider *enc, krb5_key inkey,
+ krb5_data *outrnd, const krb5_data *in_constant)
+{
+ krb5_error_code ret;
+ EVP_KDF *kdf = NULL;
+ EVP_KDF_CTX *kctx = NULL;
+ OSSL_PARAM params[4];
+ size_t i = 0;
+ char *cipher;
+
+ if (inkey->keyblock.length != enc->keylength ||
+ outrnd->length != enc->keybytes) {
+ return KRB5_CRYPTO_INTERNAL;
+ }
+
+ if (!memcmp(enc, &krb5int_enc_aes128, sizeof(*enc))) {
+ cipher = "AES-128-CBC";
+ } else if (!memcmp(enc, &krb5int_enc_aes256, sizeof(*enc))) {
+ cipher = "AES-256-CBC";
+ } else {
+ ret = KRB5_CRYPTO_INTERNAL;
+ goto done;
+ }
+
+ kdf = EVP_KDF_fetch(NULL, "KRB5KDF", "-fips");
+ if (kdf == NULL) {
+ ret = KRB5_CRYPTO_INTERNAL;
+ goto done;
+ }
+
+ kctx = EVP_KDF_CTX_new(kdf);
+ if (kctx == NULL) {
+ ret = KRB5_CRYPTO_INTERNAL;
+ goto done;
+ }
+
+ params[i++] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_CIPHER,
+ cipher, 0);
+ params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
+ inkey->keyblock.contents,
+ inkey->keyblock.length);
+ params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_CONSTANT,
+ in_constant->data,
+ in_constant->length);
+ params[i] = OSSL_PARAM_construct_end();
+ if (EVP_KDF_derive(kctx, (unsigned char *)outrnd->data, outrnd->length,
+ params) <= 0) {
+ ret = KRB5_CRYPTO_INTERNAL;
+ goto done;
+ }
+
+ ret = 0;
+done:
+ if (ret)
+ zap(outrnd->data, outrnd->length);
+ EVP_KDF_free(kdf);
+ EVP_KDF_CTX_free(kctx);
+ return ret;
+}
+
+#else /* HAVE_EVP_KDF_FETCH */
+
+/*
+ * NIST SP800-108 KDF in counter mode (section 5.1).
+ * Parameters:
+ * - HMAC (with hash as the hash provider) is the PRF.
+ * - A block counter of four bytes is used.
+ * - Four bytes are used to encode the output length in the PRF input.
+ *
+ * There are no uses requiring more than a single PRF invocation.
+ */
+static krb5_error_code
+builtin_sp800_108_counter_hmac(const struct krb5_hash_provider *hash,
+ krb5_key inkey, krb5_data *outrnd,
+ const krb5_data *label,
+ const krb5_data *context)
+{
+ krb5_crypto_iov iov[5];
+ krb5_error_code ret;
+ krb5_data prf;
+ unsigned char ibuf[4], lbuf[4];
+
+ if (hash == NULL || outrnd->length > hash->hashsize)
return KRB5_CRYPTO_INTERNAL;
/* Allocate encryption data buffer. */
- ret = alloc_data(&block, blocksize);
+ ret = alloc_data(&prf, hash->hashsize);
if (ret)
return ret;
- /* Initialize the input block. */
- if (in_constant->length == blocksize) {
- memcpy(block.data, in_constant->data, blocksize);
- } else {
- krb5int_nfold(in_constant->length * 8,
- (unsigned char *) in_constant->data,
- blocksize * 8, (unsigned char *) block.data);
- }
+ /* [i]2: four-byte big-endian binary string giving the block counter (1) */
+ iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
+ iov[0].data = make_data(ibuf, sizeof(ibuf));
+ store_32_be(1, ibuf);
+ /* Label */
+ iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
+ iov[1].data = *label;
+ /* 0x00: separator byte */
+ iov[2].flags = KRB5_CRYPTO_TYPE_DATA;
+ iov[2].data = make_data("", 1);
+ /* Context */
+ iov[3].flags = KRB5_CRYPTO_TYPE_DATA;
+ iov[3].data = *context;
+ /* [L]2: four-byte big-endian binary string giving the output length */
+ iov[4].flags = KRB5_CRYPTO_TYPE_DATA;
+ iov[4].data = make_data(lbuf, sizeof(lbuf));
+ store_32_be(outrnd->length * 8, lbuf);
- /* Loop encrypting the blocks until enough key bytes are generated. */
- n = 0;
- while (n < keybytes) {
- ret = encrypt_block(enc, inkey, &block);
- if (ret)
- goto cleanup;
-
- if ((keybytes - n) <= blocksize) {
- memcpy(outrnd->data + n, block.data, (keybytes - n));
- break;
- }
-
- memcpy(outrnd->data + n, block.data, blocksize);
- n += blocksize;
- }
-
-cleanup:
- zapfree(block.data, blocksize);
+ ret = krb5int_hmac(hash, inkey, iov, 5, &prf);
+ if (!ret)
+ memcpy(outrnd->data, prf.data, outrnd->length);
+ zapfree(prf.data, prf.length);
return ret;
}
@@ -139,9 +341,9 @@ cleanup:
* - Four bytes are used to encode the output length in the PRF input.
*/
static krb5_error_code
-derive_random_sp800_108_feedback_cmac(const struct krb5_enc_provider *enc,
- krb5_key inkey, krb5_data *outrnd,
- const krb5_data *in_constant)
+builtin_sp800_108_feedback_cmac(const struct krb5_enc_provider *enc,
+ krb5_key inkey, krb5_data *outrnd,
+ const krb5_data *in_constant)
{
size_t blocksize, keybytes, n;
krb5_crypto_iov iov[6];
@@ -204,56 +406,94 @@ cleanup:
return ret;
}
-/*
- * NIST SP800-108 KDF in counter mode (section 5.1).
- * Parameters:
- * - HMAC (with hash as the hash provider) is the PRF.
- * - A block counter of four bytes is used.
- * - Four bytes are used to encode the output length in the PRF input.
- *
- * There are no uses requiring more than a single PRF invocation.
- */
+static krb5_error_code
+builtin_derive_random_rfc3961(const struct krb5_enc_provider *enc,
+ krb5_key inkey, krb5_data *outrnd,
+ const krb5_data *in_constant)
+{
+ size_t blocksize, keybytes, n;
+ krb5_error_code ret;
+ krb5_data block = empty_data();
+
+ blocksize = enc->block_size;
+ keybytes = enc->keybytes;
+
+ if (blocksize == 1)
+ return KRB5_BAD_ENCTYPE;
+ if (inkey->keyblock.length != enc->keylength || outrnd->length != keybytes)
+ return KRB5_CRYPTO_INTERNAL;
+
+ /* Allocate encryption data buffer. */
+ ret = alloc_data(&block, blocksize);
+ if (ret)
+ return ret;
+
+ /* Initialize the input block. */
+ if (in_constant->length == blocksize) {
+ memcpy(block.data, in_constant->data, blocksize);
+ } else {
+ krb5int_nfold(in_constant->length * 8,
+ (unsigned char *) in_constant->data,
+ blocksize * 8, (unsigned char *) block.data);
+ }
+
+ /* Loop encrypting the blocks until enough key bytes are generated. */
+ n = 0;
+ while (n < keybytes) {
+ ret = encrypt_block(enc, inkey, &block);
+ if (ret)
+ goto cleanup;
+
+ if ((keybytes - n) <= blocksize) {
+ memcpy(outrnd->data + n, block.data, (keybytes - n));
+ break;
+ }
+
+ memcpy(outrnd->data + n, block.data, blocksize);
+ n += blocksize;
+ }
+
+cleanup:
+ zapfree(block.data, blocksize);
+ return ret;
+}
+#endif /* HAVE_EVP_KDF_FETCH */
+
krb5_error_code
k5_sp800_108_counter_hmac(const struct krb5_hash_provider *hash,
krb5_key inkey, krb5_data *outrnd,
const krb5_data *label, const krb5_data *context)
{
- krb5_crypto_iov iov[5];
- krb5_error_code ret;
- krb5_data prf;
- unsigned char ibuf[4], lbuf[4];
+#ifdef HAVE_EVP_KDF_FETCH
+ return openssl_kbdkf_counter_hmac(hash, inkey, outrnd, label, context);
+#else
+ return builtin_sp800_108_counter_hmac(hash, inkey, outrnd, label,
+ context);
+#endif
+}
- if (hash == NULL || outrnd->length > hash->hashsize)
- return KRB5_CRYPTO_INTERNAL;
+static krb5_error_code
+sp800_108_feedback_cmac(const struct krb5_enc_provider *enc,
+ krb5_key inkey, krb5_data *outrnd,
+ const krb5_data *in_constant)
+{
+#ifdef HAVE_EVP_KDF_FETCH
+ return openssl_kbkdf_feedback_cmac(enc, inkey, outrnd, in_constant);
+#else
+ return builtin_sp800_108_feedback_cmac(enc, inkey, outrnd, in_constant);
+#endif
+}
- /* Allocate encryption data buffer. */
- ret = alloc_data(&prf, hash->hashsize);
- if (ret)
- return ret;
-
- /* [i]2: four-byte big-endian binary string giving the block counter (1) */
- iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
- iov[0].data = make_data(ibuf, sizeof(ibuf));
- store_32_be(1, ibuf);
- /* Label */
- iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
- iov[1].data = *label;
- /* 0x00: separator byte */
- iov[2].flags = KRB5_CRYPTO_TYPE_DATA;
- iov[2].data = make_data("", 1);
- /* Context */
- iov[3].flags = KRB5_CRYPTO_TYPE_DATA;
- iov[3].data = *context;
- /* [L]2: four-byte big-endian binary string giving the output length */
- iov[4].flags = KRB5_CRYPTO_TYPE_DATA;
- iov[4].data = make_data(lbuf, sizeof(lbuf));
- store_32_be(outrnd->length * 8, lbuf);
-
- ret = krb5int_hmac(hash, inkey, iov, 5, &prf);
- if (!ret)
- memcpy(outrnd->data, prf.data, outrnd->length);
- zapfree(prf.data, prf.length);
- return ret;
+static krb5_error_code
+derive_random_rfc3961(const struct krb5_enc_provider *enc,
+ krb5_key inkey, krb5_data *outrnd,
+ const krb5_data *in_constant)
+{
+#ifdef HAVE_EVP_KDF_FETCH
+ return openssl_krb5kdf(enc, inkey, outrnd, in_constant);
+#else
+ return builtin_derive_random_rfc3961(enc, inkey, outrnd, in_constant);
+#endif
}
krb5_error_code
@@ -268,8 +508,7 @@ krb5int_derive_random(const struct krb5_enc_provider *enc,
case DERIVE_RFC3961:
return derive_random_rfc3961(enc, inkey, outrnd, in_constant);
case DERIVE_SP800_108_CMAC:
- return derive_random_sp800_108_feedback_cmac(enc, inkey, outrnd,
- in_constant);
+ return sp800_108_feedback_cmac(enc, inkey, outrnd, in_constant);
case DERIVE_SP800_108_HMAC:
return k5_sp800_108_counter_hmac(hash, inkey, outrnd, in_constant,
&empty);

@ -1,408 +0,0 @@
From 8bbb492f2be1418e1e4bb2cf197414810dac9589 Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Fri, 20 Sep 2019 17:20:59 -0400
Subject: [PATCH] Use OpenSSL's SSKDF in PKINIT when available
Starting in 3.0, OpenSSL implements SSKDF, which is the basis of our
id-pkinit-kdf (RFC 8636). Factor out common setup code around
other_info. Adjust code to comply to existing style.
(cherry picked from commit 4376a22e41fb639be31daf81275a332d3f930996)
---
.../preauth/pkinit/pkinit_crypto_openssl.c | 294 +++++++++++-------
1 file changed, 181 insertions(+), 113 deletions(-)
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
index e1153344e..350c2118a 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
@@ -38,6 +38,12 @@
#include <dirent.h>
#include <arpa/inet.h>
+#ifdef HAVE_EVP_KDF_FETCH
+#include <openssl/core_names.h>
+#include <openssl/kdf.h>
+#include <openssl/params.h>
+#endif
+
static krb5_error_code pkinit_init_pkinit_oids(pkinit_plg_crypto_context );
static void pkinit_fini_pkinit_oids(pkinit_plg_crypto_context );
@@ -2294,15 +2300,16 @@ cleanup:
}
-/**
+/*
* Given an algorithm_identifier, this function returns the hash length
* and EVP function associated with that algorithm.
+ *
+ * RFC 8636 defines a SHA384 variant, but we don't use it.
*/
static krb5_error_code
-pkinit_alg_values(krb5_context context,
- const krb5_data *alg_id,
- size_t *hash_bytes,
- const EVP_MD *(**func)(void))
+pkinit_alg_values(krb5_context context, const krb5_data *alg_id,
+ size_t *hash_bytes, const EVP_MD *(**func)(void),
+ char **hash_name)
{
*hash_bytes = 0;
*func = NULL;
@@ -2311,18 +2318,21 @@ pkinit_alg_values(krb5_context context,
krb5_pkinit_sha1_oid_len))) {
*hash_bytes = 20;
*func = &EVP_sha1;
+ *hash_name = strdup("SHA1");
return 0;
} else if ((alg_id->length == krb5_pkinit_sha256_oid_len) &&
(0 == memcmp(alg_id->data, krb5_pkinit_sha256_oid,
krb5_pkinit_sha256_oid_len))) {
*hash_bytes = 32;
*func = &EVP_sha256;
+ *hash_name = strdup("SHA256");
return 0;
} else if ((alg_id->length == krb5_pkinit_sha512_oid_len) &&
(0 == memcmp(alg_id->data, krb5_pkinit_sha512_oid,
krb5_pkinit_sha512_oid_len))) {
*hash_bytes = 64;
*func = &EVP_sha512;
+ *hash_name = strdup("SHA512");
return 0;
} else {
krb5_set_error_message(context, KRB5_ERR_BAD_S2K_PARAMS,
@@ -2331,11 +2341,60 @@ pkinit_alg_values(krb5_context context,
}
} /* pkinit_alg_values() */
+#ifdef HAVE_EVP_KDF_FETCH
+static krb5_error_code
+openssl_sskdf(krb5_context context, size_t hash_bytes, krb5_data *key,
+ krb5_data *info, char *out, size_t out_len, char *digest)
+{
+ krb5_error_code ret;
+ EVP_KDF *kdf = NULL;
+ EVP_KDF_CTX *kctx = NULL;
+ OSSL_PARAM params[4];
+ size_t i = 0;
-/* pkinit_alg_agility_kdf() --
- * This function generates a key using the KDF described in
- * draft_ietf_krb_wg_pkinit_alg_agility-04.txt. The algorithm is
- * described as follows:
+ if (digest == NULL) {
+ ret = oerr(context, ENOMEM,
+ _("Failed to allocate space for digest algorithm name"));
+ goto done;
+ }
+
+ kdf = EVP_KDF_fetch(NULL, "SSKDF", NULL);
+ if (kdf == NULL) {
+ ret = oerr(context, KRB5_CRYPTO_INTERNAL, _("Failed to fetch SSKDF"));
+ goto done;
+ }
+
+ kctx = EVP_KDF_CTX_new(kdf);
+ if (!kctx) {
+ ret = oerr(context, KRB5_CRYPTO_INTERNAL,
+ _("Failed to instantiate SSKDF"));
+ goto done;
+ }
+
+ params[i++] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
+ digest, 0);
+ params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
+ key->data, key->length);
+ params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
+ info->data, info->length);
+ params[i] = OSSL_PARAM_construct_end();
+ if (EVP_KDF_derive(kctx, (unsigned char *)out, out_len, params) <= 0) {
+ ret = oerr(context, KRB5_CRYPTO_INTERNAL,
+ _("Failed to derive key using SSKDF"));
+ goto done;
+ }
+
+ ret = 0;
+done:
+ EVP_KDF_free(kdf);
+ EVP_KDF_CTX_free(kctx);
+ return ret;
+}
+#else
+/*
+ * Generate a key using the KDF described in RFC 8636, also known as SSKDF
+ * (single-step kdf). Our caller precomputes `reps`, but otherwise the
+ * algorithm is as follows:
*
* 1. reps = keydatalen (K) / hash length (H)
*
@@ -2349,95 +2408,16 @@ pkinit_alg_values(krb5_context context,
*
* 4. Set key = Hash1 || Hash2 || ... so that length of key is K bytes.
*/
-krb5_error_code
-pkinit_alg_agility_kdf(krb5_context context,
- krb5_data *secret,
- krb5_data *alg_oid,
- krb5_const_principal party_u_info,
- krb5_const_principal party_v_info,
- krb5_enctype enctype,
- krb5_data *as_req,
- krb5_data *pk_as_rep,
- krb5_keyblock *key_block)
+static krb5_error_code
+builtin_sskdf(krb5_context context, unsigned int reps, size_t hash_len,
+ const EVP_MD *(*EVP_func)(void), krb5_data *secret,
+ krb5_data *other_info, char *out, size_t out_len)
{
- krb5_error_code retval = 0;
+ krb5_error_code ret = 0;
- unsigned int reps = 0;
- uint32_t counter = 1; /* Does this type work on Windows? */
+ uint32_t counter = 1;
size_t offset = 0;
- size_t hash_len = 0;
- size_t rand_len = 0;
- size_t key_len = 0;
- krb5_data random_data;
- krb5_sp80056a_other_info other_info_fields;
- krb5_pkinit_supp_pub_info supp_pub_info_fields;
- krb5_data *other_info = NULL;
- krb5_data *supp_pub_info = NULL;
- krb5_algorithm_identifier alg_id;
EVP_MD_CTX *ctx = NULL;
- const EVP_MD *(*EVP_func)(void);
-
- /* initialize random_data here to make clean-up safe */
- random_data.length = 0;
- random_data.data = NULL;
-
- /* allocate and initialize the key block */
- key_block->magic = 0;
- key_block->enctype = enctype;
- if (0 != (retval = krb5_c_keylengths(context, enctype, &rand_len,
- &key_len)))
- goto cleanup;
-
- random_data.length = rand_len;
- key_block->length = key_len;
-
- if (NULL == (key_block->contents = malloc(key_block->length))) {
- retval = ENOMEM;
- goto cleanup;
- }
-
- memset (key_block->contents, 0, key_block->length);
-
- /* If this is anonymous pkinit, use the anonymous principle for party_u_info */
- if (party_u_info && krb5_principal_compare_any_realm(context, party_u_info,
- krb5_anonymous_principal()))
- party_u_info = (krb5_principal)krb5_anonymous_principal();
-
- if (0 != (retval = pkinit_alg_values(context, alg_oid, &hash_len, &EVP_func)))
- goto cleanup;
-
- /* 1. reps = keydatalen (K) / hash length (H) */
- reps = key_block->length/hash_len;
-
- /* ... and round up, if necessary */
- if (key_block->length > (reps * hash_len))
- reps++;
-
- /* Allocate enough space in the random data buffer to hash directly into
- * it, even if the last hash will make it bigger than the key length. */
- if (NULL == (random_data.data = malloc(reps * hash_len))) {
- retval = ENOMEM;
- goto cleanup;
- }
-
- /* Encode the ASN.1 octet string for "SuppPubInfo" */
- supp_pub_info_fields.enctype = enctype;
- supp_pub_info_fields.as_req = *as_req;
- supp_pub_info_fields.pk_as_rep = *pk_as_rep;
- if (0 != ((retval = encode_krb5_pkinit_supp_pub_info(&supp_pub_info_fields,
- &supp_pub_info))))
- goto cleanup;
-
- /* Now encode the ASN.1 octet string for "OtherInfo" */
- memset(&alg_id, 0, sizeof alg_id);
- alg_id.algorithm = *alg_oid; /*alias*/
-
- other_info_fields.algorithm_identifier = alg_id;
- other_info_fields.party_u_info = (krb5_principal) party_u_info;
- other_info_fields.party_v_info = (krb5_principal) party_v_info;
- other_info_fields.supp_pub_info = *supp_pub_info;
- if (0 != (retval = encode_krb5_sp80056a_other_info(&other_info_fields, &other_info)))
- goto cleanup;
/* 2. Initialize a 32-bit, big-endian bit string counter as 1.
* 3. For i = 1 to reps by 1, do the following:
@@ -2450,7 +2430,7 @@ pkinit_alg_agility_kdf(krb5_context context,
ctx = EVP_MD_CTX_new();
if (ctx == NULL) {
- retval = KRB5_CRYPTO_INTERNAL;
+ ret = KRB5_CRYPTO_INTERNAL;
goto cleanup;
}
@@ -2458,7 +2438,7 @@ pkinit_alg_agility_kdf(krb5_context context,
if (!EVP_DigestInit(ctx, EVP_func())) {
krb5_set_error_message(context, KRB5_CRYPTO_INTERNAL,
"Call to OpenSSL EVP_DigestInit() returned an error.");
- retval = KRB5_CRYPTO_INTERNAL;
+ ret = KRB5_CRYPTO_INTERNAL;
goto cleanup;
}
@@ -2467,15 +2447,16 @@ pkinit_alg_agility_kdf(krb5_context context,
!EVP_DigestUpdate(ctx, other_info->data, other_info->length)) {
krb5_set_error_message(context, KRB5_CRYPTO_INTERNAL,
"Call to OpenSSL EVP_DigestUpdate() returned an error.");
- retval = KRB5_CRYPTO_INTERNAL;
+ ret = KRB5_CRYPTO_INTERNAL;
goto cleanup;
}
- /* 4. Set key = Hash1 || Hash2 || ... so that length of key is K bytes. */
- if (!EVP_DigestFinal(ctx, (uint8_t *)random_data.data + offset, &s)) {
+ /* 4. Set key = Hash1 || Hash2 || ... so that length of key is K
+ * bytes. */
+ if (!EVP_DigestFinal(ctx, (unsigned char *)out + offset, &s)) {
krb5_set_error_message(context, KRB5_CRYPTO_INTERNAL,
"Call to OpenSSL EVP_DigestUpdate() returned an error.");
- retval = KRB5_CRYPTO_INTERNAL;
+ ret = KRB5_CRYPTO_INTERNAL;
goto cleanup;
}
offset += s;
@@ -2484,26 +2465,113 @@ pkinit_alg_agility_kdf(krb5_context context,
EVP_MD_CTX_free(ctx);
ctx = NULL;
}
-
- retval = krb5_c_random_to_key(context, enctype, &random_data,
- key_block);
-
cleanup:
EVP_MD_CTX_free(ctx);
+ return ret;
+} /* builtin_sskdf() */
+#endif /* HAVE_EVP_KDF_FETCH */
- /* If this has been an error, free the allocated key_block, if any */
- if (retval) {
- krb5_free_keyblock_contents(context, key_block);
+/* id-pkinit-kdf family, as specified by RFC 8636. */
+krb5_error_code
+pkinit_alg_agility_kdf(krb5_context context, krb5_data *secret,
+ krb5_data *alg_oid, krb5_const_principal party_u_info,
+ krb5_const_principal party_v_info,
+ krb5_enctype enctype, krb5_data *as_req,
+ krb5_data *pk_as_rep, krb5_keyblock *key_block)
+{
+ krb5_error_code ret;
+ size_t hash_len = 0, rand_len = 0, key_len = 0;
+ const EVP_MD *(*EVP_func)(void);
+ krb5_sp80056a_other_info other_info_fields;
+ krb5_pkinit_supp_pub_info supp_pub_info_fields;
+ krb5_data *other_info = NULL, *supp_pub_info = NULL;
+ krb5_data random_data = empty_data();
+ krb5_algorithm_identifier alg_id;
+ unsigned int reps;
+ char *hash_name = NULL;
+
+ /* Allocate and initialize the key block. */
+ key_block->magic = 0;
+ key_block->enctype = enctype;
+
+ /* Use separate variables to avoid alignment restriction problems. */
+ ret = krb5_c_keylengths(context, enctype, &rand_len, &key_len);
+ if (ret)
+ goto cleanup;
+ random_data.length = rand_len;
+ key_block->length = key_len;
+
+ key_block->contents = k5calloc(key_block->length, 1, &ret);
+ if (key_block->contents == NULL)
+ goto cleanup;
+
+ /* If this is anonymous pkinit, use the anonymous principle for
+ * party_u_info. */
+ if (party_u_info &&
+ krb5_principal_compare_any_realm(context, party_u_info,
+ krb5_anonymous_principal())) {
+ party_u_info = (krb5_principal)krb5_anonymous_principal();
}
- /* free other allocated resources, either way */
- if (random_data.data)
- free(random_data.data);
+ ret = pkinit_alg_values(context, alg_oid, &hash_len, &EVP_func,
+ &hash_name);
+ if (ret)
+ goto cleanup;
+
+ /* 1. reps = keydatalen (K) / hash length (H) */
+ reps = key_block->length / hash_len;
+
+ /* ... and round up, if necessary. */
+ if (key_block->length > (reps * hash_len))
+ reps++;
+
+ /* Allocate enough space in the random data buffer to hash directly into
+ * it, even if the last hash will make it bigger than the key length. */
+ random_data.data = k5alloc(reps * hash_len, &ret);
+ if (random_data.data == NULL)
+ goto cleanup;
+
+ /* Encode the ASN.1 octet string for "SuppPubInfo". */
+ supp_pub_info_fields.enctype = enctype;
+ supp_pub_info_fields.as_req = *as_req;
+ supp_pub_info_fields.pk_as_rep = *pk_as_rep;
+ ret = encode_krb5_pkinit_supp_pub_info(&supp_pub_info_fields,
+ &supp_pub_info);
+ if (ret)
+ goto cleanup;
+
+ /* Now encode the ASN.1 octet string for "OtherInfo". */
+ memset(&alg_id, 0, sizeof(alg_id));
+ alg_id.algorithm = *alg_oid;
+ other_info_fields.algorithm_identifier = alg_id;
+ other_info_fields.party_u_info = (krb5_principal)party_u_info;
+ other_info_fields.party_v_info = (krb5_principal)party_v_info;
+ other_info_fields.supp_pub_info = *supp_pub_info;
+ ret = encode_krb5_sp80056a_other_info(&other_info_fields, &other_info);
+ if (ret)
+ goto cleanup;
+
+#ifdef HAVE_EVP_KDF_FETCH
+ ret = openssl_sskdf(context, hash_len, secret, other_info,
+ random_data.data, key_block->length, hash_name);
+#else
+ ret = builtin_sskdf(context, reps, hash_len, EVP_func, secret,
+ other_info, random_data.data, key_block->length);
+#endif
+ if (ret)
+ goto cleanup;
+
+ ret = krb5_c_random_to_key(context, enctype, &random_data, key_block);
+cleanup:
+ if (ret)
+ krb5_free_keyblock_contents(context, key_block);
+
+ free(hash_name);
+ zapfree(random_data.data, random_data.length);
krb5_free_data(context, other_info);
krb5_free_data(context, supp_pub_info);
-
- return retval;
-} /*pkinit_alg_agility_kdf() */
+ return ret;
+}
/* Call DH_compute_key() and ensure that we left-pad short results instead of
* leaving junk bytes at the end of the buffer. */

@ -1,113 +0,0 @@
From f0740c131b69f3346f07e7b7b03ebf27c50c0ccd Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Fri, 11 Mar 2022 11:33:56 +0100
Subject: [PATCH] Use SHA-256 instead of SHA-1 for PKINIT CMS digest
Various organizations including NIST have been strongly recommending to
stop using SHA-1 for digital signatures for some years already. CMS
digest is used to generate such signatures, hence it should be upgraded
to use SHA-256.
---
.../preauth/pkinit/pkinit_crypto_openssl.c | 27 ++++++++++---------
1 file changed, 14 insertions(+), 13 deletions(-)
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
index 42e5c581d..2a6ef4aaa 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
@@ -1240,7 +1240,7 @@ cms_signeddata_create(krb5_context context,
/* will not fill-out EVP_PKEY because it's on the smartcard */
/* Set digest algs */
- p7si->digest_alg->algorithm = OBJ_nid2obj(NID_sha1);
+ p7si->digest_alg->algorithm = OBJ_nid2obj(NID_sha256);
if (p7si->digest_alg->parameter != NULL)
ASN1_TYPE_free(p7si->digest_alg->parameter);
@@ -1251,17 +1251,17 @@ cms_signeddata_create(krb5_context context,
/* Set sig algs */
if (p7si->digest_enc_alg->parameter != NULL)
ASN1_TYPE_free(p7si->digest_enc_alg->parameter);
- p7si->digest_enc_alg->algorithm = OBJ_nid2obj(NID_sha1WithRSAEncryption);
+ p7si->digest_enc_alg->algorithm = OBJ_nid2obj(NID_sha256WithRSAEncryption);
if (!(p7si->digest_enc_alg->parameter = ASN1_TYPE_new()))
goto cleanup;
p7si->digest_enc_alg->parameter->type = V_ASN1_NULL;
/* add signed attributes */
- /* compute sha1 digest over the EncapsulatedContentInfo */
+ /* compute sha256 digest over the EncapsulatedContentInfo */
ctx = EVP_MD_CTX_new();
if (ctx == NULL)
goto cleanup;
- EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
+ EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
EVP_DigestUpdate(ctx, data, data_len);
md_tmp = EVP_MD_CTX_md(ctx);
EVP_DigestFinal_ex(ctx, md_data, &md_len);
@@ -1289,9 +1289,10 @@ cms_signeddata_create(krb5_context context,
goto cleanup2;
#ifndef WITHOUT_PKCS11
- /* Some tokens can only do RSAEncryption without sha1 hash */
- /* to compute sha1WithRSAEncryption, encode the algorithm ID for the hash
- * function and the hash value into an ASN.1 value of type DigestInfo
+ /* Some tokens can only do RSAEncryption without sha256 hash */
+ /* to compute sha256WithRSAEncryption, encode the algorithm ID for the
+ * hash function and the hash value into an ASN.1 value of type
+ * DigestInfo
* DigestInfo::=SEQUENCE {
* digestAlgorithm AlgorithmIdentifier,
* digest OCTET STRING }
@@ -1310,7 +1311,7 @@ cms_signeddata_create(krb5_context context,
alg = X509_ALGOR_new();
if (alg == NULL)
goto cleanup2;
- X509_ALGOR_set0(alg, OBJ_nid2obj(NID_sha1), V_ASN1_NULL, NULL);
+ X509_ALGOR_set0(alg, OBJ_nid2obj(NID_sha256), V_ASN1_NULL, NULL);
alg_len = i2d_X509_ALGOR(alg, NULL);
digest = ASN1_OCTET_STRING_new();
@@ -1339,7 +1340,7 @@ cms_signeddata_create(krb5_context context,
#endif
{
pkiDebug("mech = %s\n",
- id_cryptoctx->pkcs11_method == 1 ? "CKM_SHA1_RSA_PKCS" : "FS");
+ id_cryptoctx->pkcs11_method == 1 ? "CKM_SHA256_RSA_PKCS" : "FS");
retval = pkinit_sign_data(context, id_cryptoctx, abuf, alen,
&sig, &sig_len);
}
@@ -4189,7 +4190,7 @@ create_signature(unsigned char **sig, unsigned int *sig_len,
ctx = EVP_MD_CTX_new();
if (ctx == NULL)
return ENOMEM;
- EVP_SignInit(ctx, EVP_sha1());
+ EVP_SignInit(ctx, EVP_sha256());
EVP_SignUpdate(ctx, data, data_len);
*sig_len = EVP_PKEY_size(pkey);
if ((*sig = malloc(*sig_len)) == NULL)
@@ -4663,10 +4664,10 @@ pkinit_get_certs_pkcs11(krb5_context context,
#ifndef PKINIT_USE_MECH_LIST
/*
- * We'd like to use CKM_SHA1_RSA_PKCS for signing if it's available, but
+ * We'd like to use CKM_SHA256_RSA_PKCS for signing if it's available, but
* many cards seems to be confused about whether they are capable of
* this or not. The safe thing seems to be to ignore the mechanism list,
- * always use CKM_RSA_PKCS and calculate the sha1 digest ourselves.
+ * always use CKM_RSA_PKCS and calculate the sha256 digest ourselves.
*/
id_cryptoctx->mech = CKM_RSA_PKCS;
@@ -4694,7 +4695,7 @@ pkinit_get_certs_pkcs11(krb5_context context,
if (mechp[i] == CKM_RSA_PKCS) {
/* This seems backwards... */
id_cryptoctx->mech =
- (info.flags & CKF_SIGN) ? CKM_SHA1_RSA_PKCS : CKM_RSA_PKCS;
+ (info.flags & CKF_SIGN) ? CKM_SHA256_RSA_PKCS : CKM_RSA_PKCS;
}
}
free(mechp);
--
2.35.1

@ -1,727 +0,0 @@
From 20cbbd0b273af56c6d527c8e6b9d96eef49926f2 Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Thu, 31 Mar 2022 18:24:39 +0200
Subject: [PATCH] Use newly enforced dejagnu path naming convention
Since version 1.6.3, dejagnu started to enforce a naming convention that
was already in place, but not mandatory: dejagnu test directories have
to be named "testsuite". If they don't implicit relative sub-paths
resolution (e.g. "lib", "config") is not forking.
This commit renames kadm5 library's unit tests and global tests
directories to match this requirement.
Resolves: rhbz#2053133
Signed-off-by: Julien Rische <jrische@redhat.com>
---
src/configure.ac | 4 +--
src/lib/kadm5/Makefile.in | 2 +-
.../{unit-test => testsuite}/Makefile.in | 28 +++++++++---------
.../api.2/crte-policy.exp | 0
.../api.2/get-policy.exp | 0
.../api.2/mod-policy.exp | 0
.../api.current/chpass-principal-v2.exp | 0
.../api.current/chpass-principal.exp | 0
.../api.current/crte-policy.exp | 0
.../api.current/crte-principal.exp | 0
.../api.current/destroy.exp | 0
.../api.current/dlte-policy.exp | 0
.../api.current/dlte-principal.exp | 0
.../api.current/get-policy.exp | 0
.../api.current/get-principal-v2.exp | 0
.../api.current/get-principal.exp | 0
.../api.current/init-v2.exp | 0
.../api.current/init.exp | 0
.../api.current/mod-policy.exp | 0
.../api.current/mod-principal-v2.exp | 0
.../api.current/mod-principal.exp | 0
.../api.current/randkey-principal-v2.exp | 0
.../api.current/randkey-principal.exp | 0
.../{unit-test => testsuite}/config/unix.exp | 0
src/lib/kadm5/{unit-test => testsuite}/deps | 0
.../{unit-test => testsuite}/destroy-test.c | 0
.../diff-files/destroy-1 | 0
.../diff-files/no-diffs | 0
.../{unit-test => testsuite}/handle-test.c | 0
.../{unit-test => testsuite}/init-test.c | 0
.../{unit-test => testsuite}/iter-test.c | 0
.../kadm5/{unit-test => testsuite}/lib/lib.t | 2 +-
.../{unit-test => testsuite}/lock-test.c | 0
.../{unit-test => testsuite}/randkey-test.c | 0
.../{unit-test => testsuite}/setkey-test.c | 0
.../kadm5/{unit-test => testsuite}/site.exp | 0
src/tests/Makefile.in | 2 +-
src/tests/t_authdata.py | 2 +-
src/tests/t_certauth.py | 2 +-
src/tests/t_pkinit.py | 2 +-
src/tests/t_proxy.py | 12 ++++----
src/tests/{dejagnu => testsuite}/Makefile.in | 4 +--
.../{dejagnu => testsuite}/config/default.exp | 2 +-
src/tests/{dejagnu => testsuite}/deps | 0
.../krb-standalone/gssapi.exp | 2 +-
.../krb-standalone/kprop.exp | 0
.../krb-standalone/princexpire.exp | 0
.../krb-standalone/sample.exp | 2 +-
.../krb-standalone/simple.exp | 2 +-
.../krb-standalone/standalone.exp | 0
.../krb-standalone/tcp.exp | 0
.../pkinit-certs/ca.pem | 0
.../pkinit-certs/generic.p12 | Bin
.../pkinit-certs/generic.pem | 0
.../pkinit-certs/kdc.pem | 0
.../pkinit-certs/make-certs.sh | 0
.../pkinit-certs/privkey-enc.pem | 0
.../pkinit-certs/privkey.pem | 0
.../pkinit-certs/user-enc.p12 | Bin
.../pkinit-certs/user-upn.p12 | Bin
.../pkinit-certs/user-upn.pem | 0
.../pkinit-certs/user-upn2.p12 | Bin
.../pkinit-certs/user-upn2.pem | 0
.../pkinit-certs/user-upn3.p12 | Bin
.../pkinit-certs/user-upn3.pem | 0
.../pkinit-certs/user.p12 | Bin
.../pkinit-certs/user.pem | 0
.../{dejagnu => testsuite}/proxy-certs/ca.pem | 0
.../proxy-certs/make-certs.sh | 0
.../proxy-certs/proxy-badsig.pem | 0
.../proxy-certs/proxy-ideal.pem | 0
.../proxy-certs/proxy-no-match.pem | 0
.../proxy-certs/proxy-san.pem | 0
.../proxy-certs/proxy-subject.pem | 0
src/tests/{dejagnu => testsuite}/t_inetd.c | 2 +-
src/util/k5test.py | 2 +-
76 files changed, 36 insertions(+), 36 deletions(-)
rename src/lib/kadm5/{unit-test => testsuite}/Makefile.in (86%)
rename src/lib/kadm5/{unit-test => testsuite}/api.2/crte-policy.exp (100%)
rename src/lib/kadm5/{unit-test => testsuite}/api.2/get-policy.exp (100%)
rename src/lib/kadm5/{unit-test => testsuite}/api.2/mod-policy.exp (100%)
rename src/lib/kadm5/{unit-test => testsuite}/api.current/chpass-principal-v2.exp (100%)
rename src/lib/kadm5/{unit-test => testsuite}/api.current/chpass-principal.exp (100%)
rename src/lib/kadm5/{unit-test => testsuite}/api.current/crte-policy.exp (100%)
rename src/lib/kadm5/{unit-test => testsuite}/api.current/crte-principal.exp (100%)
rename src/lib/kadm5/{unit-test => testsuite}/api.current/destroy.exp (100%)
rename src/lib/kadm5/{unit-test => testsuite}/api.current/dlte-policy.exp (100%)
rename src/lib/kadm5/{unit-test => testsuite}/api.current/dlte-principal.exp (100%)
rename src/lib/kadm5/{unit-test => testsuite}/api.current/get-policy.exp (100%)
rename src/lib/kadm5/{unit-test => testsuite}/api.current/get-principal-v2.exp (100%)
rename src/lib/kadm5/{unit-test => testsuite}/api.current/get-principal.exp (100%)
rename src/lib/kadm5/{unit-test => testsuite}/api.current/init-v2.exp (100%)
rename src/lib/kadm5/{unit-test => testsuite}/api.current/init.exp (100%)
rename src/lib/kadm5/{unit-test => testsuite}/api.current/mod-policy.exp (100%)
rename src/lib/kadm5/{unit-test => testsuite}/api.current/mod-principal-v2.exp (100%)
rename src/lib/kadm5/{unit-test => testsuite}/api.current/mod-principal.exp (100%)
rename src/lib/kadm5/{unit-test => testsuite}/api.current/randkey-principal-v2.exp (100%)
rename src/lib/kadm5/{unit-test => testsuite}/api.current/randkey-principal.exp (100%)
rename src/lib/kadm5/{unit-test => testsuite}/config/unix.exp (100%)
rename src/lib/kadm5/{unit-test => testsuite}/deps (100%)
rename src/lib/kadm5/{unit-test => testsuite}/destroy-test.c (100%)
rename src/lib/kadm5/{unit-test => testsuite}/diff-files/destroy-1 (100%)
rename src/lib/kadm5/{unit-test => testsuite}/diff-files/no-diffs (100%)
rename src/lib/kadm5/{unit-test => testsuite}/handle-test.c (100%)
rename src/lib/kadm5/{unit-test => testsuite}/init-test.c (100%)
rename src/lib/kadm5/{unit-test => testsuite}/iter-test.c (100%)
rename src/lib/kadm5/{unit-test => testsuite}/lib/lib.t (99%)
rename src/lib/kadm5/{unit-test => testsuite}/lock-test.c (100%)
rename src/lib/kadm5/{unit-test => testsuite}/randkey-test.c (100%)
rename src/lib/kadm5/{unit-test => testsuite}/setkey-test.c (100%)
rename src/lib/kadm5/{unit-test => testsuite}/site.exp (100%)
rename src/tests/{dejagnu => testsuite}/Makefile.in (92%)
rename src/tests/{dejagnu => testsuite}/config/default.exp (99%)
rename src/tests/{dejagnu => testsuite}/deps (100%)
rename src/tests/{dejagnu => testsuite}/krb-standalone/gssapi.exp (98%)
rename src/tests/{dejagnu => testsuite}/krb-standalone/kprop.exp (100%)
rename src/tests/{dejagnu => testsuite}/krb-standalone/princexpire.exp (100%)
rename src/tests/{dejagnu => testsuite}/krb-standalone/sample.exp (98%)
rename src/tests/{dejagnu => testsuite}/krb-standalone/simple.exp (98%)
rename src/tests/{dejagnu => testsuite}/krb-standalone/standalone.exp (100%)
rename src/tests/{dejagnu => testsuite}/krb-standalone/tcp.exp (100%)
rename src/tests/{dejagnu => testsuite}/pkinit-certs/ca.pem (100%)
rename src/tests/{dejagnu => testsuite}/pkinit-certs/generic.p12 (100%)
rename src/tests/{dejagnu => testsuite}/pkinit-certs/generic.pem (100%)
rename src/tests/{dejagnu => testsuite}/pkinit-certs/kdc.pem (100%)
rename src/tests/{dejagnu => testsuite}/pkinit-certs/make-certs.sh (100%)
rename src/tests/{dejagnu => testsuite}/pkinit-certs/privkey-enc.pem (100%)
rename src/tests/{dejagnu => testsuite}/pkinit-certs/privkey.pem (100%)
rename src/tests/{dejagnu => testsuite}/pkinit-certs/user-enc.p12 (100%)
rename src/tests/{dejagnu => testsuite}/pkinit-certs/user-upn.p12 (100%)
rename src/tests/{dejagnu => testsuite}/pkinit-certs/user-upn.pem (100%)
rename src/tests/{dejagnu => testsuite}/pkinit-certs/user-upn2.p12 (100%)
rename src/tests/{dejagnu => testsuite}/pkinit-certs/user-upn2.pem (100%)
rename src/tests/{dejagnu => testsuite}/pkinit-certs/user-upn3.p12 (100%)
rename src/tests/{dejagnu => testsuite}/pkinit-certs/user-upn3.pem (100%)
rename src/tests/{dejagnu => testsuite}/pkinit-certs/user.p12 (100%)
rename src/tests/{dejagnu => testsuite}/pkinit-certs/user.pem (100%)
rename src/tests/{dejagnu => testsuite}/proxy-certs/ca.pem (100%)
rename src/tests/{dejagnu => testsuite}/proxy-certs/make-certs.sh (100%)
rename src/tests/{dejagnu => testsuite}/proxy-certs/proxy-badsig.pem (100%)
rename src/tests/{dejagnu => testsuite}/proxy-certs/proxy-ideal.pem (100%)
rename src/tests/{dejagnu => testsuite}/proxy-certs/proxy-no-match.pem (100%)
rename src/tests/{dejagnu => testsuite}/proxy-certs/proxy-san.pem (100%)
rename src/tests/{dejagnu => testsuite}/proxy-certs/proxy-subject.pem (100%)
rename src/tests/{dejagnu => testsuite}/t_inetd.c (99%)
diff --git a/src/configure.ac b/src/configure.ac
index 20066918b..363d5d62d 100644
--- a/src/configure.ac
+++ b/src/configure.ac
@@ -1500,7 +1500,7 @@ V5_AC_OUTPUT_MAKEFILE(.
lib/rpc lib/rpc/unit-test
- lib/kadm5 lib/kadm5/clnt lib/kadm5/srv lib/kadm5/unit-test
+ lib/kadm5 lib/kadm5/clnt lib/kadm5/srv lib/kadm5/testsuite
lib/krad
lib/apputils
@@ -1544,5 +1544,5 @@ V5_AC_OUTPUT_MAKEFILE(.
appl/gss-sample appl/user_user
tests tests/asn.1 tests/create tests/hammer tests/verify tests/gssapi
- tests/dejagnu tests/threads tests/shlib tests/gss-threads tests/misc
+ tests/testsuite tests/threads tests/shlib tests/gss-threads tests/misc
)
diff --git a/src/lib/kadm5/Makefile.in b/src/lib/kadm5/Makefile.in
index c4eaad38d..76fc4b548 100644
--- a/src/lib/kadm5/Makefile.in
+++ b/src/lib/kadm5/Makefile.in
@@ -1,6 +1,6 @@
mydir=lib$(S)kadm5
BUILDTOP=$(REL)..$(S)..
-SUBDIRS = clnt srv unit-test
+SUBDIRS = clnt srv testsuite
##DOSBUILDTOP = ..\..
diff --git a/src/lib/kadm5/unit-test/Makefile.in b/src/lib/kadm5/testsuite/Makefile.in
similarity index 86%
rename from src/lib/kadm5/unit-test/Makefile.in
rename to src/lib/kadm5/testsuite/Makefile.in
index 68fa097ff..5a55b786b 100644
--- a/src/lib/kadm5/unit-test/Makefile.in
+++ b/src/lib/kadm5/testsuite/Makefile.in
@@ -1,4 +1,4 @@
-mydir=lib$(S)kadm5$(S)unit-test
+mydir=lib$(S)kadm5$(S)testsuite
BUILDTOP=$(REL)..$(S)..$(S)..
KDB_DEP_LIB=$(DL_LIB) $(THREAD_LINKOPTS)
@@ -61,7 +61,7 @@ runenv.exp: Makefile
eval echo "set env\($$i\) \$$$$i"; done > runenv.exp
#
-# The unit-test targets
+# The testsuite targets
#
check: check-@DO_TEST@
@@ -72,13 +72,13 @@ check-:
@echo "+++ Either tcl, runtest, or Perl is unavailable."
@echo "+++"
-check-ok unit-test: unit-test-client unit-test-server
+check-ok testsuite: testsuite-client testsuite-server
-unit-test-client: unit-test-client-setup unit-test-client-body \
- unit-test-client-cleanup
+testsuite-client: testsuite-client-setup testsuite-client-body \
+ testsuite-client-cleanup
-unit-test-server: unit-test-server-setup unit-test-server-body \
- unit-test-server-cleanup
+testsuite-server: testsuite-server-setup testsuite-server-body \
+ testsuite-server-cleanup
test-randkey: randkey-test
$(ENV_SETUP) $(VALGRIND) ./randkey-test
@@ -98,19 +98,19 @@ test-destroy: destroy-test
test-setkey-client: client-setkey-test
$(ENV_SETUP) $(VALGRIND) ./client-setkey-test testkeys admin admin
-unit-test-client-setup: runenv.sh
+testsuite-client-setup: runenv.sh
$(ENV_SETUP) $(VALGRIND) $(START_SERVERS)
-unit-test-client-cleanup:
+testsuite-client-cleanup:
$(ENV_SETUP) $(STOP_SERVERS)
-unit-test-server-setup: runenv.sh
+testsuite-server-setup: runenv.sh
$(ENV_SETUP) $(VALGRIND) $(START_SERVERS_LOCAL)
-unit-test-server-cleanup:
+testsuite-server-cleanup:
$(ENV_SETUP) $(STOP_SERVERS_LOCAL)
-unit-test-client-body: site.exp test-noauth test-destroy test-handle-client \
+testsuite-client-body: site.exp test-noauth test-destroy test-handle-client \
test-setkey-client runenv.exp
$(ENV_SETUP) $(RUNTEST) --tool api RPC=1 API=$(CLNTTCL) \
KINIT=$(BUILDTOP)/clients/kinit/kinit \
@@ -121,7 +121,7 @@ unit-test-client-body: site.exp test-noauth test-destroy test-handle-client \
-mv api.log capi.log
-mv api.sum capi.sum
-unit-test-server-body: site.exp test-handle-server lock-test
+testsuite-server-body: site.exp test-handle-server lock-test
$(ENV_SETUP) $(RUNTEST) --tool api RPC=0 API=$(SRVTCL) \
LOCKTEST=./lock-test \
KADMIN_LOCAL=$(BUILDTOP)/kadmin/cli/kadmin.local \
@@ -140,4 +140,4 @@ clean:
$(RM) lock-test lock-test.o
$(RM) server-iter-test iter-test.o
$(RM) server-setkey-test client-setkey-test setkey-test.o
- $(RM) *.log *.plog *.sum *.psum unit-test-log.* runenv.exp
+ $(RM) *.log *.plog *.sum *.psum testsuite-log.* runenv.exp
diff --git a/src/lib/kadm5/unit-test/api.2/crte-policy.exp b/src/lib/kadm5/testsuite/api.2/crte-policy.exp
similarity index 100%
rename from src/lib/kadm5/unit-test/api.2/crte-policy.exp
rename to src/lib/kadm5/testsuite/api.2/crte-policy.exp
diff --git a/src/lib/kadm5/unit-test/api.2/get-policy.exp b/src/lib/kadm5/testsuite/api.2/get-policy.exp
similarity index 100%
rename from src/lib/kadm5/unit-test/api.2/get-policy.exp
rename to src/lib/kadm5/testsuite/api.2/get-policy.exp
diff --git a/src/lib/kadm5/unit-test/api.2/mod-policy.exp b/src/lib/kadm5/testsuite/api.2/mod-policy.exp
similarity index 100%
rename from src/lib/kadm5/unit-test/api.2/mod-policy.exp
rename to src/lib/kadm5/testsuite/api.2/mod-policy.exp
diff --git a/src/lib/kadm5/unit-test/api.current/chpass-principal-v2.exp b/src/lib/kadm5/testsuite/api.current/chpass-principal-v2.exp
similarity index 100%
rename from src/lib/kadm5/unit-test/api.current/chpass-principal-v2.exp
rename to src/lib/kadm5/testsuite/api.current/chpass-principal-v2.exp
diff --git a/src/lib/kadm5/unit-test/api.current/chpass-principal.exp b/src/lib/kadm5/testsuite/api.current/chpass-principal.exp
similarity index 100%
rename from src/lib/kadm5/unit-test/api.current/chpass-principal.exp
rename to src/lib/kadm5/testsuite/api.current/chpass-principal.exp
diff --git a/src/lib/kadm5/unit-test/api.current/crte-policy.exp b/src/lib/kadm5/testsuite/api.current/crte-policy.exp
similarity index 100%
rename from src/lib/kadm5/unit-test/api.current/crte-policy.exp
rename to src/lib/kadm5/testsuite/api.current/crte-policy.exp
diff --git a/src/lib/kadm5/unit-test/api.current/crte-principal.exp b/src/lib/kadm5/testsuite/api.current/crte-principal.exp
similarity index 100%
rename from src/lib/kadm5/unit-test/api.current/crte-principal.exp
rename to src/lib/kadm5/testsuite/api.current/crte-principal.exp
diff --git a/src/lib/kadm5/unit-test/api.current/destroy.exp b/src/lib/kadm5/testsuite/api.current/destroy.exp
similarity index 100%
rename from src/lib/kadm5/unit-test/api.current/destroy.exp
rename to src/lib/kadm5/testsuite/api.current/destroy.exp
diff --git a/src/lib/kadm5/unit-test/api.current/dlte-policy.exp b/src/lib/kadm5/testsuite/api.current/dlte-policy.exp
similarity index 100%
rename from src/lib/kadm5/unit-test/api.current/dlte-policy.exp
rename to src/lib/kadm5/testsuite/api.current/dlte-policy.exp
diff --git a/src/lib/kadm5/unit-test/api.current/dlte-principal.exp b/src/lib/kadm5/testsuite/api.current/dlte-principal.exp
similarity index 100%
rename from src/lib/kadm5/unit-test/api.current/dlte-principal.exp
rename to src/lib/kadm5/testsuite/api.current/dlte-principal.exp
diff --git a/src/lib/kadm5/unit-test/api.current/get-policy.exp b/src/lib/kadm5/testsuite/api.current/get-policy.exp
similarity index 100%
rename from src/lib/kadm5/unit-test/api.current/get-policy.exp
rename to src/lib/kadm5/testsuite/api.current/get-policy.exp
diff --git a/src/lib/kadm5/unit-test/api.current/get-principal-v2.exp b/src/lib/kadm5/testsuite/api.current/get-principal-v2.exp
similarity index 100%
rename from src/lib/kadm5/unit-test/api.current/get-principal-v2.exp
rename to src/lib/kadm5/testsuite/api.current/get-principal-v2.exp
diff --git a/src/lib/kadm5/unit-test/api.current/get-principal.exp b/src/lib/kadm5/testsuite/api.current/get-principal.exp
similarity index 100%
rename from src/lib/kadm5/unit-test/api.current/get-principal.exp
rename to src/lib/kadm5/testsuite/api.current/get-principal.exp
diff --git a/src/lib/kadm5/unit-test/api.current/init-v2.exp b/src/lib/kadm5/testsuite/api.current/init-v2.exp
similarity index 100%
rename from src/lib/kadm5/unit-test/api.current/init-v2.exp
rename to src/lib/kadm5/testsuite/api.current/init-v2.exp
diff --git a/src/lib/kadm5/unit-test/api.current/init.exp b/src/lib/kadm5/testsuite/api.current/init.exp
similarity index 100%
rename from src/lib/kadm5/unit-test/api.current/init.exp
rename to src/lib/kadm5/testsuite/api.current/init.exp
diff --git a/src/lib/kadm5/unit-test/api.current/mod-policy.exp b/src/lib/kadm5/testsuite/api.current/mod-policy.exp
similarity index 100%
rename from src/lib/kadm5/unit-test/api.current/mod-policy.exp
rename to src/lib/kadm5/testsuite/api.current/mod-policy.exp
diff --git a/src/lib/kadm5/unit-test/api.current/mod-principal-v2.exp b/src/lib/kadm5/testsuite/api.current/mod-principal-v2.exp
similarity index 100%
rename from src/lib/kadm5/unit-test/api.current/mod-principal-v2.exp
rename to src/lib/kadm5/testsuite/api.current/mod-principal-v2.exp
diff --git a/src/lib/kadm5/unit-test/api.current/mod-principal.exp b/src/lib/kadm5/testsuite/api.current/mod-principal.exp
similarity index 100%
rename from src/lib/kadm5/unit-test/api.current/mod-principal.exp
rename to src/lib/kadm5/testsuite/api.current/mod-principal.exp
diff --git a/src/lib/kadm5/unit-test/api.current/randkey-principal-v2.exp b/src/lib/kadm5/testsuite/api.current/randkey-principal-v2.exp
similarity index 100%
rename from src/lib/kadm5/unit-test/api.current/randkey-principal-v2.exp
rename to src/lib/kadm5/testsuite/api.current/randkey-principal-v2.exp
diff --git a/src/lib/kadm5/unit-test/api.current/randkey-principal.exp b/src/lib/kadm5/testsuite/api.current/randkey-principal.exp
similarity index 100%
rename from src/lib/kadm5/unit-test/api.current/randkey-principal.exp
rename to src/lib/kadm5/testsuite/api.current/randkey-principal.exp
diff --git a/src/lib/kadm5/unit-test/config/unix.exp b/src/lib/kadm5/testsuite/config/unix.exp
similarity index 100%
rename from src/lib/kadm5/unit-test/config/unix.exp
rename to src/lib/kadm5/testsuite/config/unix.exp
diff --git a/src/lib/kadm5/unit-test/deps b/src/lib/kadm5/testsuite/deps
similarity index 100%
rename from src/lib/kadm5/unit-test/deps
rename to src/lib/kadm5/testsuite/deps
diff --git a/src/lib/kadm5/unit-test/destroy-test.c b/src/lib/kadm5/testsuite/destroy-test.c
similarity index 100%
rename from src/lib/kadm5/unit-test/destroy-test.c
rename to src/lib/kadm5/testsuite/destroy-test.c
diff --git a/src/lib/kadm5/unit-test/diff-files/destroy-1 b/src/lib/kadm5/testsuite/diff-files/destroy-1
similarity index 100%
rename from src/lib/kadm5/unit-test/diff-files/destroy-1
rename to src/lib/kadm5/testsuite/diff-files/destroy-1
diff --git a/src/lib/kadm5/unit-test/diff-files/no-diffs b/src/lib/kadm5/testsuite/diff-files/no-diffs
similarity index 100%
rename from src/lib/kadm5/unit-test/diff-files/no-diffs
rename to src/lib/kadm5/testsuite/diff-files/no-diffs
diff --git a/src/lib/kadm5/unit-test/handle-test.c b/src/lib/kadm5/testsuite/handle-test.c
similarity index 100%
rename from src/lib/kadm5/unit-test/handle-test.c
rename to src/lib/kadm5/testsuite/handle-test.c
diff --git a/src/lib/kadm5/unit-test/init-test.c b/src/lib/kadm5/testsuite/init-test.c
similarity index 100%
rename from src/lib/kadm5/unit-test/init-test.c
rename to src/lib/kadm5/testsuite/init-test.c
diff --git a/src/lib/kadm5/unit-test/iter-test.c b/src/lib/kadm5/testsuite/iter-test.c
similarity index 100%
rename from src/lib/kadm5/unit-test/iter-test.c
rename to src/lib/kadm5/testsuite/iter-test.c
diff --git a/src/lib/kadm5/unit-test/lib/lib.t b/src/lib/kadm5/testsuite/lib/lib.t
similarity index 99%
rename from src/lib/kadm5/unit-test/lib/lib.t
rename to src/lib/kadm5/testsuite/lib/lib.t
index 3444775cf..327946849 100644
--- a/src/lib/kadm5/unit-test/lib/lib.t
+++ b/src/lib/kadm5/testsuite/lib/lib.t
@@ -226,7 +226,7 @@ proc end_dump_compare {name} {
global RPC
if { ! $RPC } {
-# set file $TOP/admin/lib/unit-test/diff-files/$name
+# set file $TOP/admin/lib/testsuite/diff-files/$name
# exec $env(SIMPLE_DUMP) > /tmp/dump.after
# exec $env(COMPARE_DUMP) /tmp/dump.before /tmp/dump.after $file
}
diff --git a/src/lib/kadm5/unit-test/lock-test.c b/src/lib/kadm5/testsuite/lock-test.c
similarity index 100%
rename from src/lib/kadm5/unit-test/lock-test.c
rename to src/lib/kadm5/testsuite/lock-test.c
diff --git a/src/lib/kadm5/unit-test/randkey-test.c b/src/lib/kadm5/testsuite/randkey-test.c
similarity index 100%
rename from src/lib/kadm5/unit-test/randkey-test.c
rename to src/lib/kadm5/testsuite/randkey-test.c
diff --git a/src/lib/kadm5/unit-test/setkey-test.c b/src/lib/kadm5/testsuite/setkey-test.c
similarity index 100%
rename from src/lib/kadm5/unit-test/setkey-test.c
rename to src/lib/kadm5/testsuite/setkey-test.c
diff --git a/src/lib/kadm5/unit-test/site.exp b/src/lib/kadm5/testsuite/site.exp
similarity index 100%
rename from src/lib/kadm5/unit-test/site.exp
rename to src/lib/kadm5/testsuite/site.exp
diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in
index 20f27d748..1198dca0c 100644
--- a/src/tests/Makefile.in
+++ b/src/tests/Makefile.in
@@ -1,6 +1,6 @@
mydir=tests
BUILDTOP=$(REL)..
-SUBDIRS = asn.1 create hammer verify gssapi dejagnu shlib gss-threads misc \
+SUBDIRS = asn.1 create hammer verify gssapi testsuite shlib gss-threads misc \
threads softpkcs11
RUN_DB_TEST = $(RUN_SETUP) KRB5_KDC_PROFILE=kdc.conf KRB5_CONFIG=krb5.conf \
diff --git a/src/tests/t_authdata.py b/src/tests/t_authdata.py
index 2e01f46bc..e5135f435 100644
--- a/src/tests/t_authdata.py
+++ b/src/tests/t_authdata.py
@@ -57,7 +57,7 @@ if not os.path.exists(os.path.join(plugins, 'preauth', 'pkinit.so')):
skipped('anonymous ticket authdata tests', 'PKINIT not built')
else:
# Set up a realm with PKINIT support and get anonymous tickets.
- certs = os.path.join(srctop, 'tests', 'dejagnu', 'pkinit-certs')
+ certs = os.path.join(srctop, 'tests', 'testsuite', 'pkinit-certs')
ca_pem = os.path.join(certs, 'ca.pem')
kdc_pem = os.path.join(certs, 'kdc.pem')
privkey_pem = os.path.join(certs, 'privkey.pem')
diff --git a/src/tests/t_certauth.py b/src/tests/t_certauth.py
index 0fe0fdb4a..bfa5bfc96 100644
--- a/src/tests/t_certauth.py
+++ b/src/tests/t_certauth.py
@@ -4,7 +4,7 @@ from k5test import *
if not os.path.exists(os.path.join(plugins, 'preauth', 'pkinit.so')):
skip_rest('certauth tests', 'PKINIT module not built')
-certs = os.path.join(srctop, 'tests', 'dejagnu', 'pkinit-certs')
+certs = os.path.join(srctop, 'tests', 'testsuite', 'pkinit-certs')
ca_pem = os.path.join(certs, 'ca.pem')
kdc_pem = os.path.join(certs, 'kdc.pem')
privkey_pem = os.path.join(certs, 'privkey.pem')
diff --git a/src/tests/t_pkinit.py b/src/tests/t_pkinit.py
index aee4da2b1..8763ce484 100755
--- a/src/tests/t_pkinit.py
+++ b/src/tests/t_pkinit.py
@@ -7,7 +7,7 @@ if not os.path.exists(os.path.join(plugins, 'preauth', 'pkinit.so')):
soft_pkcs11 = os.path.join(buildtop, 'tests', 'softpkcs11', 'softpkcs11.so')
# Construct a krb5.conf fragment configuring pkinit.
-certs = os.path.join(srctop, 'tests', 'dejagnu', 'pkinit-certs')
+certs = os.path.join(srctop, 'tests', 'testsuite', 'pkinit-certs')
ca_pem = os.path.join(certs, 'ca.pem')
kdc_pem = os.path.join(certs, 'kdc.pem')
user_pem = os.path.join(certs, 'user.pem')
diff --git a/src/tests/t_proxy.py b/src/tests/t_proxy.py
index 3069eaa8f..6ae5c8c8e 100755
--- a/src/tests/t_proxy.py
+++ b/src/tests/t_proxy.py
@@ -10,17 +10,17 @@ except:
# Construct a krb5.conf fragment configuring the client to use a local proxy
# server.
-proxysubjectpem = os.path.join(srctop, 'tests', 'dejagnu', 'proxy-certs',
+proxysubjectpem = os.path.join(srctop, 'tests', 'testsuite', 'proxy-certs',
'proxy-subject.pem')
-proxysanpem = os.path.join(srctop, 'tests', 'dejagnu', 'proxy-certs',
+proxysanpem = os.path.join(srctop, 'tests', 'testsuite', 'proxy-certs',
'proxy-san.pem')
-proxyidealpem = os.path.join(srctop, 'tests', 'dejagnu', 'proxy-certs',
+proxyidealpem = os.path.join(srctop, 'tests', 'testsuite', 'proxy-certs',
'proxy-ideal.pem')
-proxywrongpem = os.path.join(srctop, 'tests', 'dejagnu', 'proxy-certs',
+proxywrongpem = os.path.join(srctop, 'tests', 'testsuite', 'proxy-certs',
'proxy-no-match.pem')
-proxybadpem = os.path.join(srctop, 'tests', 'dejagnu', 'proxy-certs',
+proxybadpem = os.path.join(srctop, 'tests', 'testsuite', 'proxy-certs',
'proxy-badsig.pem')
-proxyca = os.path.join(srctop, 'tests', 'dejagnu', 'proxy-certs', 'ca.pem')
+proxyca = os.path.join(srctop, 'tests', 'testsuite', 'proxy-certs', 'ca.pem')
proxyurl = 'https://localhost:$port5/KdcProxy'
proxyurlupcase = 'https://LocalHost:$port5/KdcProxy'
proxyurl4 = 'https://127.0.0.1:$port5/KdcProxy'
diff --git a/src/tests/dejagnu/Makefile.in b/src/tests/testsuite/Makefile.in
similarity index 92%
rename from src/tests/dejagnu/Makefile.in
rename to src/tests/testsuite/Makefile.in
index e78e270ed..d3efe3606 100644
--- a/src/tests/dejagnu/Makefile.in
+++ b/src/tests/testsuite/Makefile.in
@@ -1,4 +1,4 @@
-mydir=tests$(S)dejagnu
+mydir=tests$(S)testsuite
BUILDTOP=$(REL)..$(S)..
RUNTEST = @RUNTEST@ $(DEJAFLAGS)
RUNTESTFLAGS =
@@ -13,7 +13,7 @@ check: check-runtest-@HAVE_RUNTEST@
check-runtest-no:
@echo "+++"
- @echo "+++ WARNING: tests/dejagnu tests not run."
+ @echo "+++ WARNING: tests/testsuite tests not run."
@echo "+++ runtest is unavailable."
@echo "+++"
@echo 'Skipped dejagnu tests: runtest not found' >> $(SKIPTESTS)
diff --git a/src/tests/dejagnu/config/default.exp b/src/tests/testsuite/config/default.exp
similarity index 99%
rename from src/tests/dejagnu/config/default.exp
rename to src/tests/testsuite/config/default.exp
index 302dee74c..1492fac32 100644
--- a/src/tests/dejagnu/config/default.exp
+++ b/src/tests/testsuite/config/default.exp
@@ -256,7 +256,7 @@ verbose "Test realm is $REALMNAME"
# Find some programs we need. We use the binaries from the build tree
# if they exist. If they do not, then they must be in PATH. We
-# expect $objdir to be ...tests/dejagnu.
+# expect $objdir to be ...tests/testsuite.
foreach i {
{KDB5_UTIL $objdir/../../kadmin/dbutil/kdb5_util}
diff --git a/src/tests/dejagnu/deps b/src/tests/testsuite/deps
similarity index 100%
rename from src/tests/dejagnu/deps
rename to src/tests/testsuite/deps
diff --git a/src/tests/dejagnu/krb-standalone/gssapi.exp b/src/tests/testsuite/krb-standalone/gssapi.exp
similarity index 98%
rename from src/tests/dejagnu/krb-standalone/gssapi.exp
rename to src/tests/testsuite/krb-standalone/gssapi.exp
index e3357e769..d176e210c 100644
--- a/src/tests/dejagnu/krb-standalone/gssapi.exp
+++ b/src/tests/testsuite/krb-standalone/gssapi.exp
@@ -2,7 +2,7 @@
# This is a DejaGnu test script.
# This script tests that the GSS-API tester functions correctly.
-# This mostly just calls procedures in test/dejagnu/config/default.exp.
+# This mostly just calls procedures in test/testsuite/config/default.exp.
if ![info exists KDESTROY] {
set KDESTROY [findfile $objdir/../../clients/kdestroy/kdestroy]
diff --git a/src/tests/dejagnu/krb-standalone/kprop.exp b/src/tests/testsuite/krb-standalone/kprop.exp
similarity index 100%
rename from src/tests/dejagnu/krb-standalone/kprop.exp
rename to src/tests/testsuite/krb-standalone/kprop.exp
diff --git a/src/tests/dejagnu/krb-standalone/princexpire.exp b/src/tests/testsuite/krb-standalone/princexpire.exp
similarity index 100%
rename from src/tests/dejagnu/krb-standalone/princexpire.exp
rename to src/tests/testsuite/krb-standalone/princexpire.exp
diff --git a/src/tests/dejagnu/krb-standalone/sample.exp b/src/tests/testsuite/krb-standalone/sample.exp
similarity index 98%
rename from src/tests/dejagnu/krb-standalone/sample.exp
rename to src/tests/testsuite/krb-standalone/sample.exp
index 93a75f1d0..009de5ddb 100644
--- a/src/tests/dejagnu/krb-standalone/sample.exp
+++ b/src/tests/testsuite/krb-standalone/sample.exp
@@ -2,7 +2,7 @@
# This is a DejaGnu test script.
# This script tests that sample user-user communication works.
-# This mostly just calls procedures in test/dejagnu/config/default.exp.
+# This mostly just calls procedures in test/testsuite/config/default.exp.
if ![info exists KLIST] {
set KLIST [findfile $objdir/../../clients/klist/klist]
diff --git a/src/tests/dejagnu/krb-standalone/simple.exp b/src/tests/testsuite/krb-standalone/simple.exp
similarity index 98%
rename from src/tests/dejagnu/krb-standalone/simple.exp
rename to src/tests/testsuite/krb-standalone/simple.exp
index d8b218248..92b33066e 100644
--- a/src/tests/dejagnu/krb-standalone/simple.exp
+++ b/src/tests/testsuite/krb-standalone/simple.exp
@@ -2,7 +2,7 @@
# This is a DejaGnu test script.
# This script tests that krb-safe and krb-priv messages work.
-# This mostly just calls procedures in test/dejagnu/config/default.exp.
+# This mostly just calls procedures in test/testsuite/config/default.exp.
if ![info exists KLIST] {
set KLIST [findfile $objdir/../../clients/klist/klist]
diff --git a/src/tests/dejagnu/krb-standalone/standalone.exp b/src/tests/testsuite/krb-standalone/standalone.exp
similarity index 100%
rename from src/tests/dejagnu/krb-standalone/standalone.exp
rename to src/tests/testsuite/krb-standalone/standalone.exp
diff --git a/src/tests/dejagnu/krb-standalone/tcp.exp b/src/tests/testsuite/krb-standalone/tcp.exp
similarity index 100%
rename from src/tests/dejagnu/krb-standalone/tcp.exp
rename to src/tests/testsuite/krb-standalone/tcp.exp
diff --git a/src/tests/dejagnu/pkinit-certs/ca.pem b/src/tests/testsuite/pkinit-certs/ca.pem
similarity index 100%
rename from src/tests/dejagnu/pkinit-certs/ca.pem
rename to src/tests/testsuite/pkinit-certs/ca.pem
diff --git a/src/tests/dejagnu/pkinit-certs/generic.p12 b/src/tests/testsuite/pkinit-certs/generic.p12
similarity index 100%
rename from src/tests/dejagnu/pkinit-certs/generic.p12
rename to src/tests/testsuite/pkinit-certs/generic.p12
diff --git a/src/tests/dejagnu/pkinit-certs/generic.pem b/src/tests/testsuite/pkinit-certs/generic.pem
similarity index 100%
rename from src/tests/dejagnu/pkinit-certs/generic.pem
rename to src/tests/testsuite/pkinit-certs/generic.pem
diff --git a/src/tests/dejagnu/pkinit-certs/kdc.pem b/src/tests/testsuite/pkinit-certs/kdc.pem
similarity index 100%
rename from src/tests/dejagnu/pkinit-certs/kdc.pem
rename to src/tests/testsuite/pkinit-certs/kdc.pem
diff --git a/src/tests/dejagnu/pkinit-certs/make-certs.sh b/src/tests/testsuite/pkinit-certs/make-certs.sh
similarity index 100%
rename from src/tests/dejagnu/pkinit-certs/make-certs.sh
rename to src/tests/testsuite/pkinit-certs/make-certs.sh
diff --git a/src/tests/dejagnu/pkinit-certs/privkey-enc.pem b/src/tests/testsuite/pkinit-certs/privkey-enc.pem
similarity index 100%
rename from src/tests/dejagnu/pkinit-certs/privkey-enc.pem
rename to src/tests/testsuite/pkinit-certs/privkey-enc.pem
diff --git a/src/tests/dejagnu/pkinit-certs/privkey.pem b/src/tests/testsuite/pkinit-certs/privkey.pem
similarity index 100%
rename from src/tests/dejagnu/pkinit-certs/privkey.pem
rename to src/tests/testsuite/pkinit-certs/privkey.pem
diff --git a/src/tests/dejagnu/pkinit-certs/user-enc.p12 b/src/tests/testsuite/pkinit-certs/user-enc.p12
similarity index 100%
rename from src/tests/dejagnu/pkinit-certs/user-enc.p12
rename to src/tests/testsuite/pkinit-certs/user-enc.p12
diff --git a/src/tests/dejagnu/pkinit-certs/user-upn.p12 b/src/tests/testsuite/pkinit-certs/user-upn.p12
similarity index 100%
rename from src/tests/dejagnu/pkinit-certs/user-upn.p12
rename to src/tests/testsuite/pkinit-certs/user-upn.p12
diff --git a/src/tests/dejagnu/pkinit-certs/user-upn.pem b/src/tests/testsuite/pkinit-certs/user-upn.pem
similarity index 100%
rename from src/tests/dejagnu/pkinit-certs/user-upn.pem
rename to src/tests/testsuite/pkinit-certs/user-upn.pem
diff --git a/src/tests/dejagnu/pkinit-certs/user-upn2.p12 b/src/tests/testsuite/pkinit-certs/user-upn2.p12
similarity index 100%
rename from src/tests/dejagnu/pkinit-certs/user-upn2.p12
rename to src/tests/testsuite/pkinit-certs/user-upn2.p12
diff --git a/src/tests/dejagnu/pkinit-certs/user-upn2.pem b/src/tests/testsuite/pkinit-certs/user-upn2.pem
similarity index 100%
rename from src/tests/dejagnu/pkinit-certs/user-upn2.pem
rename to src/tests/testsuite/pkinit-certs/user-upn2.pem
diff --git a/src/tests/dejagnu/pkinit-certs/user-upn3.p12 b/src/tests/testsuite/pkinit-certs/user-upn3.p12
similarity index 100%
rename from src/tests/dejagnu/pkinit-certs/user-upn3.p12
rename to src/tests/testsuite/pkinit-certs/user-upn3.p12
diff --git a/src/tests/dejagnu/pkinit-certs/user-upn3.pem b/src/tests/testsuite/pkinit-certs/user-upn3.pem
similarity index 100%
rename from src/tests/dejagnu/pkinit-certs/user-upn3.pem
rename to src/tests/testsuite/pkinit-certs/user-upn3.pem
diff --git a/src/tests/dejagnu/pkinit-certs/user.p12 b/src/tests/testsuite/pkinit-certs/user.p12
similarity index 100%
rename from src/tests/dejagnu/pkinit-certs/user.p12
rename to src/tests/testsuite/pkinit-certs/user.p12
diff --git a/src/tests/dejagnu/pkinit-certs/user.pem b/src/tests/testsuite/pkinit-certs/user.pem
similarity index 100%
rename from src/tests/dejagnu/pkinit-certs/user.pem
rename to src/tests/testsuite/pkinit-certs/user.pem
diff --git a/src/tests/dejagnu/proxy-certs/ca.pem b/src/tests/testsuite/proxy-certs/ca.pem
similarity index 100%
rename from src/tests/dejagnu/proxy-certs/ca.pem
rename to src/tests/testsuite/proxy-certs/ca.pem
diff --git a/src/tests/dejagnu/proxy-certs/make-certs.sh b/src/tests/testsuite/proxy-certs/make-certs.sh
similarity index 100%
rename from src/tests/dejagnu/proxy-certs/make-certs.sh
rename to src/tests/testsuite/proxy-certs/make-certs.sh
diff --git a/src/tests/dejagnu/proxy-certs/proxy-badsig.pem b/src/tests/testsuite/proxy-certs/proxy-badsig.pem
similarity index 100%
rename from src/tests/dejagnu/proxy-certs/proxy-badsig.pem
rename to src/tests/testsuite/proxy-certs/proxy-badsig.pem
diff --git a/src/tests/dejagnu/proxy-certs/proxy-ideal.pem b/src/tests/testsuite/proxy-certs/proxy-ideal.pem
similarity index 100%
rename from src/tests/dejagnu/proxy-certs/proxy-ideal.pem
rename to src/tests/testsuite/proxy-certs/proxy-ideal.pem
diff --git a/src/tests/dejagnu/proxy-certs/proxy-no-match.pem b/src/tests/testsuite/proxy-certs/proxy-no-match.pem
similarity index 100%
rename from src/tests/dejagnu/proxy-certs/proxy-no-match.pem
rename to src/tests/testsuite/proxy-certs/proxy-no-match.pem
diff --git a/src/tests/dejagnu/proxy-certs/proxy-san.pem b/src/tests/testsuite/proxy-certs/proxy-san.pem
similarity index 100%
rename from src/tests/dejagnu/proxy-certs/proxy-san.pem
rename to src/tests/testsuite/proxy-certs/proxy-san.pem
diff --git a/src/tests/dejagnu/proxy-certs/proxy-subject.pem b/src/tests/testsuite/proxy-certs/proxy-subject.pem
similarity index 100%
rename from src/tests/dejagnu/proxy-certs/proxy-subject.pem
rename to src/tests/testsuite/proxy-certs/proxy-subject.pem
diff --git a/src/tests/dejagnu/t_inetd.c b/src/tests/testsuite/t_inetd.c
similarity index 99%
rename from src/tests/dejagnu/t_inetd.c
rename to src/tests/testsuite/t_inetd.c
index abcde50fa..2bad2cf65 100644
--- a/src/tests/dejagnu/t_inetd.c
+++ b/src/tests/testsuite/t_inetd.c
@@ -1,5 +1,5 @@
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/* tests/dejagnu/t_inetd.c */
+/* tests/testsuite/t_inetd.c */
/*
* Copyright 1991 by the Massachusetts Institute of Technology.
* All Rights Reserved.
diff --git a/src/util/k5test.py b/src/util/k5test.py
index 251d11a9d..908a1495c 100644
--- a/src/util/k5test.py
+++ b/src/util/k5test.py
@@ -1383,7 +1383,7 @@ kswitch = os.path.join(buildtop, 'clients', 'kswitch', 'kswitch')
kvno = os.path.join(buildtop, 'clients', 'kvno', 'kvno')
kdestroy = os.path.join(buildtop, 'clients', 'kdestroy', 'kdestroy')
kpasswd = os.path.join(buildtop, 'clients', 'kpasswd', 'kpasswd')
-t_inetd = os.path.join(buildtop, 'tests', 'dejagnu', 't_inetd')
+t_inetd = os.path.join(buildtop, 'tests', 'testsuite', 't_inetd')
kproplog = os.path.join(buildtop, 'kprop', 'kproplog')
kpropd = os.path.join(buildtop, 'kprop', 'kpropd')
kprop = os.path.join(buildtop, 'kprop', 'kprop')
--
2.35.1

@ -1,24 +0,0 @@
From ad123366e5fb2694cf6d9f4f292a001a761b78fa Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Tue, 23 Aug 2016 16:46:21 -0400
Subject: [PATCH] [downstream] netlib and dns
We want to be able to use --with-netlib and --enable-dns at the same time.
Last-updated: krb5-1.3.1
---
src/aclocal.m4 | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/aclocal.m4 b/src/aclocal.m4
index 5afb96e58..4a4d460e3 100644
--- a/src/aclocal.m4
+++ b/src/aclocal.m4
@@ -718,6 +718,7 @@ AC_HELP_STRING([--with-netlib=LIBS], use user defined resolver library),
LIBS="$LIBS $withval"
AC_MSG_RESULT("netlib will use \'$withval\'")
fi
+ KRB5_AC_ENABLE_DNS
],dnl
[AC_LIBRARY_NET]
)])dnl

@ -5,10 +5,12 @@
[realms]
EXAMPLE.COM = {
#master_key_type = aes256-cts
master_key_type = aes256-cts-hmac-sha384-192
acl_file = /var/kerberos/krb5kdc/kadm5.acl
dict_file = /usr/share/dict/words
default_principal_flags = +preauth
admin_keytab = /var/kerberos/krb5kdc/kadm5.keytab
supported_enctypes = aes256-cts:normal aes128-cts:normal arcfour-hmac:normal camellia256-cts:normal camellia128-cts:normal
supported_enctypes = aes256-cts-hmac-sha384-192:normal aes128-cts-hmac-sha256-128:normal aes256-cts-hmac-sha1-96:normal aes128-cts-hmac-sha1-96:normal camellia256-cts-cmac:normal camellia128-cts-cmac:normal arcfour-hmac-md5:normal
# Supported encryption types for FIPS mode:
#supported_enctypes = aes256-cts-hmac-sha384-192:normal aes128-cts-hmac-sha256-128:normal
}

@ -1,16 +0,0 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEExEk8tzn0qJ+YUsvCDLoIV1+Dct8FAmAuntAACgkQDLoIV1+D
ct8TIhAArFittFBcz4ZfMxqhHVGdK6kOeQXrrV27d3FW6y28BvS7yHJ8CkyK+I3g
4rsaaf7srkH8jaiCjmjHC2rWJIuceOwkD4GRqXtb2CiqKxXI9eZ+g9ipB7DGKixg
+1nki7mOhd3oaeUkCRFXgyiOqSE/ird7/itLYzEoAroLpTazNp6Kk4gXmhJIENlq
dj1God+JxhuwzzWZRdsy2SyvMQPQMOTIilsXRboObZFvPrhZKkJmgNm+RzU/YRSg
/1Po7takBXq8qhgnwPHTnTPb+BYRdrqQc/a2WcmEdgbzeMpijNmkFsgAFeKDijSz
1nmFO4SQd/rAfgUovkDd+GMAYZ6DCLFqoI/WeKOgCrRMxJMMRbLlr48bTvMwjuIl
xE5gy8h2Iju/UP1lxz8KheCm/FyNzNw4pe74zbGgK5fdiEQ8xNlKZOs9LRrtvyfL
j1G+IX6cK+5yTo/NceYjnHVAatbuW6C6xJmsIQ1GYdMPvto7Wctq/4/BmwxqgFAJ
HCPuQgAGi875JpPYvi/c3tioRiIPwOz54CXCrcFyKELvgHi6lGN6MRNSzAP4QdA0
HlXZQ4/4NFOJxjLGu9ZXKUbYPaGizhI+ayzg5/RJLHPIgW7yLvwFqkBIa1xs26bA
xiP5JKuDC4mqDPwVjwpufkUBH6SoBFnbiIWEYSKVPLJFw+Dbhv0=
=PP6r
-----END PGP SIGNATURE-----

@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEExEk8tzn0qJ+YUsvCDLoIV1+Dct8FAmNvED8ACgkQDLoIV1+D
ct9uKw/8C5GS8mdh335lB+bkfjYYCZLD+oQToDAAbdCddrIcuLftvnTfXJ8cMtMc
UT2hsp8u7ZupjJRevdhaH7fFwomc0V8iSES5J2cQHTNd9aK93j/W6NaMoqWLrQWg
jx99oqLn7orvp8N5RufEQcNMNWhFIX4XSfrA3vPfHbbffA2vkjJzOGno4UHi8zUn
6nye7jbrBpiQIeFIJSS3VPsvGrKdRgb9BqGTUsqPIuFvr3Qvo42lKr5X8CWYSXjK
0aKlOpfbWdkteEe2o84/wyMpuGvmYkmOgaMB5xQ3jfEuvPNAWX2CWHNDamiqwBT/
YxwhZimNa1B9r3P1yDHvpUu8cJaRzw2UDRi2f3Kztrmn2jlqzmoZ31WBALJA7lmL
SrVFdXi7AcWwppMp1kbe9SvurCXID8/Q4n+qAdzSvqrXbeWerVUkdYFvtxQ1bMJR
jnqN11iZFYaoCaaR2lFEhjoMdR80jUa2m6vdF7a7xhH1UvuPHDnzLT9X/TiPvx0R
Itrp5MMIrUQHcZUL9hM5hrg3nxEsGsSCnjB0zWDmgXdLGwd4CvcOF4HPQR3BBlEH
CLtAa27bBXMJTYVvmmKt06hw+U3ALDfUlFrV6ZNLr9ug69l29n7JoChAbZ97Hx1m
twPwJpKd8AiUz+j3KCfgGU21qMbHNP3jEn3q9tkq0qcs/z7RCmU=
=1WIq
-----END PGP SIGNATURE-----

@ -1,69 +0,0 @@
From 0ac0fd2d349e4d5ef7379182f4d7ce480edd8d2b Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Mon, 8 Nov 2021 17:48:50 +0100
Subject: [PATCH 2/2] Support larger RADIUS attributes in libkrad
In kr_attrset_decode(), explicitly treat the length byte as unsigned.
Otherwise attributes longer than 125 characters will be rejected with
EBADMSG.
Add a 253-character-long NAS-Identifier attribute to the tests to make
sure that attributes with the maximal number of characters are working
as expected.
[ghudson@mit.edu: used uint8_t cast per current practices; edited
commit message]
ticket: 9036 (new)
---
src/lib/krad/attrset.c | 2 +-
src/lib/krad/t_packet.c | 13 +++++++++++++
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/src/lib/krad/attrset.c b/src/lib/krad/attrset.c
index d89982a13..6ec031e32 100644
--- a/src/lib/krad/attrset.c
+++ b/src/lib/krad/attrset.c
@@ -218,7 +218,7 @@ kr_attrset_decode(krb5_context ctx, const krb5_data *in, const char *secret,
for (i = 0; i + 2 < in->length; ) {
type = in->data[i++];
- tmp = make_data(&in->data[i + 1], in->data[i] - 2);
+ tmp = make_data(&in->data[i + 1], (uint8_t)in->data[i] - 2);
i += tmp.length + 1;
retval = (in->length < i) ? EBADMSG : 0;
diff --git a/src/lib/krad/t_packet.c b/src/lib/krad/t_packet.c
index 0a92e9cc2..c22489144 100644
--- a/src/lib/krad/t_packet.c
+++ b/src/lib/krad/t_packet.c
@@ -57,6 +57,14 @@ make_packet(krb5_context ctx, const krb5_data *username,
krb5_error_code retval;
const krb5_data *data;
int i = 0;
+ krb5_data nas_id;
+
+ nas_id = string2data("12345678901234567890123456789012345678901234567890"
+ "12345678901234567890123456789012345678901234567890"
+ "12345678901234567890123456789012345678901234567890"
+ "12345678901234567890123456789012345678901234567890"
+ "12345678901234567890123456789012345678901234567890"
+ "123");
retval = krad_attrset_new(ctx, &set);
if (retval != 0)
@@ -71,6 +79,11 @@ make_packet(krb5_context ctx, const krb5_data *username,
if (retval != 0)
goto out;
+ retval = krad_attrset_add(set, krad_attr_name2num("NAS-Identifier"),
+ &nas_id);
+ if (retval != 0)
+ goto out;
+
retval = krad_packet_new_request(ctx, "foo",
krad_code_name2num("Access-Request"),
set, iterator, &i, &tmp);
--
2.35.3

@ -1,171 +0,0 @@
From a8551b609fd50458ca3c06a9dd345b6cdf18689b Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Tue, 9 Nov 2021 13:00:43 -0500
Subject: [PATCH 1/2] Avoid use after free during libkrad cleanup
libkrad client requests contain a list of references to remotes, with
no back-references or reference counts. To prevent accesses to
dangling references during cleanup, cancel all requests on all remotes
before freeing any remotes.
Remove the code for aging out unused servers. This code was fairly
safe as all requests referencing a remote should have completed or
timed out during an hour of disuse, but in the current design we have
no way to guarantee or check that. The set of addresses we send
RADIUS requests to will generally be small, so aging out servers is
unnecessary.
ticket: 9035 (new)
---
src/lib/krad/client.c | 42 ++++++++++++++---------------------------
src/lib/krad/internal.h | 4 ++++
src/lib/krad/remote.c | 11 ++++++++---
3 files changed, 26 insertions(+), 31 deletions(-)
diff --git a/src/lib/krad/client.c b/src/lib/krad/client.c
index 6365dd1c6..810940afc 100644
--- a/src/lib/krad/client.c
+++ b/src/lib/krad/client.c
@@ -64,7 +64,6 @@ struct request_st {
struct server_st {
krad_remote *serv;
- time_t last;
K5_LIST_ENTRY(server_st) list;
};
@@ -81,15 +80,10 @@ get_server(krad_client *rc, const struct addrinfo *ai, const char *secret,
krad_remote **out)
{
krb5_error_code retval;
- time_t currtime;
server *srv;
- if (time(&currtime) == (time_t)-1)
- return errno;
-
K5_LIST_FOREACH(srv, &rc->servers, list) {
if (kr_remote_equals(srv->serv, ai, secret)) {
- srv->last = currtime;
*out = srv->serv;
return 0;
}
@@ -98,7 +92,6 @@ get_server(krad_client *rc, const struct addrinfo *ai, const char *secret,
srv = calloc(1, sizeof(server));
if (srv == NULL)
return ENOMEM;
- srv->last = currtime;
retval = kr_remote_new(rc->kctx, rc->vctx, ai, secret, &srv->serv);
if (retval != 0) {
@@ -173,28 +166,12 @@ request_new(krad_client *rc, krad_code code, const krad_attrset *attrs,
return 0;
}
-/* Close remotes that haven't been used in a while. */
-static void
-age(struct server_head *head, time_t currtime)
-{
- server *srv, *tmp;
-
- K5_LIST_FOREACH_SAFE(srv, head, list, tmp) {
- if (currtime == (time_t)-1 || currtime - srv->last > 60 * 60) {
- K5_LIST_REMOVE(srv, list);
- kr_remote_free(srv->serv);
- free(srv);
- }
- }
-}
-
/* Handle a response from a server (or related errors). */
static void
on_response(krb5_error_code retval, const krad_packet *reqp,
const krad_packet *rspp, void *data)
{
request *req = data;
- time_t currtime;
size_t i;
/* Do nothing if we are already completed. */
@@ -221,10 +198,6 @@ on_response(krb5_error_code retval, const krad_packet *reqp,
for (i = 0; req->remotes[i].remote != NULL; i++)
kr_remote_cancel(req->remotes[i].remote, req->remotes[i].packet);
- /* Age out servers that haven't been used in a while. */
- if (time(&currtime) != (time_t)-1)
- age(&req->rc->servers, currtime);
-
request_free(req);
}
@@ -247,10 +220,23 @@ krad_client_new(krb5_context kctx, verto_ctx *vctx, krad_client **out)
void
krad_client_free(krad_client *rc)
{
+ server *srv;
+
if (rc == NULL)
return;
- age(&rc->servers, -1);
+ /* Cancel all requests before freeing any remotes, since each request's
+ * callback data may contain references to multiple remotes. */
+ K5_LIST_FOREACH(srv, &rc->servers, list)
+ kr_remote_cancel_all(srv->serv);
+
+ while (!K5_LIST_EMPTY(&rc->servers)) {
+ srv = K5_LIST_FIRST(&rc->servers);
+ K5_LIST_REMOVE(srv, list);
+ kr_remote_free(srv->serv);
+ free(srv);
+ }
+
free(rc);
}
diff --git a/src/lib/krad/internal.h b/src/lib/krad/internal.h
index 223ffd730..fa012db78 100644
--- a/src/lib/krad/internal.h
+++ b/src/lib/krad/internal.h
@@ -120,6 +120,10 @@ kr_remote_send(krad_remote *rr, krad_code code, krad_attrset *attrs,
void
kr_remote_cancel(krad_remote *rr, const krad_packet *pkt);
+/* Cancel all requests awaiting responses. */
+void
+kr_remote_cancel_all(krad_remote *rr);
+
/* Determine if this remote object refers to the remote resource identified
* by the addrinfo struct and the secret. */
krb5_boolean
diff --git a/src/lib/krad/remote.c b/src/lib/krad/remote.c
index c8912892c..01a5fd2a4 100644
--- a/src/lib/krad/remote.c
+++ b/src/lib/krad/remote.c
@@ -452,15 +452,20 @@ error:
return retval;
}
+void
+kr_remote_cancel_all(krad_remote *rr)
+{
+ while (!K5_TAILQ_EMPTY(&rr->list))
+ request_finish(K5_TAILQ_FIRST(&rr->list), ECANCELED, NULL);
+}
+
void
kr_remote_free(krad_remote *rr)
{
if (rr == NULL)
return;
- while (!K5_TAILQ_EMPTY(&rr->list))
- request_finish(K5_TAILQ_FIRST(&rr->list), ECANCELED, NULL);
-
+ kr_remote_cancel_all(rr);
free(rr->secret);
if (rr->info != NULL)
free(rr->info->ai_addr);
--
2.35.3

@ -30,76 +30,77 @@
%global configure_default_ccache_name 1
%global configured_default_ccache_name KEYRING:persistent:%%{uid}
# for prereleases, % global prerelease beta1
%if %{defined prerelease}
%global dashpre -%{prerelease}
%global zdpd 0.%{prerelease}.
# Use baserelease to set the release number!
#
# baserelease is what we have standardized across Fedora and what
# rpmdev-bumpspec knows how to handle.
%global baserelease 8
# This should be e.g. beta1 or %%nil
%global pre_release %nil
%global krb5_release %{baserelease}
%if "x%{?pre_release}" != "x"
%global krb5_release 0.%{baserelease}.%{pre_release}
%global krb5_pre_release -%{pre_release}
%endif
%global krb5_version_major 1
%global krb5_version_minor 20
# For a release without a patch number set to %%nil
%global krb5_version_patch 1
%global krb5_version_major_minor %{krb5_version_major}.%{krb5_version_minor}
%global krb5_version %{krb5_version_major_minor}
%if "x%{?krb5_version_patch}" != "x"
%global krb5_version %{krb5_version_major_minor}.%{krb5_version_patch}
%endif
# Should be in form 5.0, 6.1, etc.
%global kdbversion 8.0
%global kdbversion 9.0
Summary: The Kerberos network authentication system
Name: krb5
Version: 1.19.1
Release: %{?zdpd}24%{?dist}
Version: %{krb5_version}
Release: %{krb5_release}%{?dist}
# rharwood has trust path to signing key and verifies on check-in
Source0: https://web.mit.edu/kerberos/dist/krb5/%{version}/krb5-%{version}%{?dashpre}.tar.gz
Source1: https://web.mit.edu/kerberos/dist/krb5/%{version}/krb5-%{version}%{?dashpre}.tar.gz.asc
Source0: https://web.mit.edu/kerberos/dist/krb5/%{krb5_version_major_minor}/krb5-%{krb5_version}%{?krb5_pre_release}.tar.gz
Source1: https://web.mit.edu/kerberos/dist/krb5/%{krb5_version_major_minor}/krb5-%{krb5_version}%{?krb5_pre_release}.tar.gz.asc
# Numbering is a relic of old init systems etc. It's easiest to just leave.
Source2: kprop.service
Source4: kadmin.service
Source5: krb5kdc.service
Source6: krb5.conf
Source10: kdc.conf
Source11: kadm5.acl
Source19: krb5kdc.sysconfig
Source20: kadmin.sysconfig
Source21: kprop.sysconfig
Source29: ksu.pamd
Source33: krb5kdc.logrotate
Source34: kadmind.logrotate
Source39: krb5-krb5kdc.conf
Patch0: downstream-ksu-pam-integration.patch
Patch1: downstream-SELinux-integration.patch
Patch3: downstream-netlib-and-dns.patch
Patch4: downstream-fix-debuginfo-with-y.tab.c.patch
Patch5: downstream-Remove-3des-support.patch
Patch7: downstream-FIPS-with-PRNG-and-RADIUS-and-MD4.patch
Patch8: Add-APIs-for-marshalling-credentials.patch
Patch9: Add-hostname-canonicalization-helper-to-k5test.py.patch
Patch10: Support-host-based-GSS-initiator-names.patch
Patch11: Fix-softpkcs11-build-issues-with-openssl-3.0.patch
Patch12: Remove-deprecated-OpenSSL-calls-from-softpkcs11.patch
Patch13: Fix-k5tls-module-for-OpenSSL-3.patch
Patch14: Add-buildsystem-detection-of-the-OpenSSL-3-KDF-inter.patch
Patch15: Use-OpenSSL-s-SSKDF-in-PKINIT-when-available.patch
Patch16: Use-OpenSSL-s-KBKDF-and-KRB5KDF-for-deriving-long-te.patch
Patch17: Handle-OpenSSL-3-s-providers.patch
Patch18: Add-KCM_OP_GET_CRED_LIST-for-faster-iteration.patch
Patch19: Fix-KCM-flag-transmission-for-remove_cred.patch
Patch20: Make-KCM-iteration-fallback-work-with-sssd-kcm.patch
Patch21: Use-KCM_OP_RETRIEVE-in-KCM-client.patch
Patch22: Fix-KCM-retrieval-support-for-sssd.patch
Patch23: Move-some-dejagnu-kadmin-tests-to-Python-tests.patch
Patch24: Fix-some-principal-realm-canonicalization-cases.patch
Patch25: Allow-kinit-with-keytab-to-defer-canonicalization.patch
Patch26: Fix-kadmin-k-with-fallback-or-referral-realm.patch
Patch27: Fix-KDC-null-deref-on-bad-encrypted-challenge.patch
Patch28: Fix-KDC-null-deref-on-TGS-inner-body-null-server.patch
Patch29: Use-SHA256-instead-of-SHA1-for-PKINIT-CMS-digest.patch
Patch30: downstream-Use-newly-enforced-dejagnu-path-naming-convention.patch
Patch31: Try-harder-to-avoid-password-change-replay-errors.patch
Patch32: Add-configure-variable-for-default-PKCS-11-module.patch
Patch33: downstream-Allow-krad-UDP-TCP-localhost-connection-with-FIPS.patch
Patch34: krb5-krad-remote.patch
Patch35: krb5-krad-larger-attrs.patch
Patch36: Set-reasonable-supportedCMSTypes-in-PKINIT.patch
Patch37: Make-kprop-work-for-dump-files-larger-than-4GB.patch
Patch38: Fix-integer-overflows-in-PAC-parsing.patch
Source3: kadmin.service
Source4: krb5kdc.service
Source5: krb5.conf
Source6: kdc.conf
Source7: kadm5.acl
Source8: krb5kdc.sysconfig
Source9: kadmin.sysconfig
Source10: kprop.sysconfig
Source11: ksu.pamd
Source12: krb5kdc.logrotate
Source13: kadmind.logrotate
Source14: krb5-krb5kdc.conf
Patch01: 0001-downstream-ksu-pam-integration.patch
Patch02: 0002-downstream-SELinux-integration.patch
Patch03: 0003-downstream-fix-debuginfo-with-y.tab.c.patch
Patch04: 0004-downstream-Remove-3des-support.patch
Patch05: 0005-downstream-FIPS-with-PRNG-and-RADIUS-and-MD4.patch
Patch06: 0006-downstream-Allow-krad-UDP-TCP-localhost-connection-w.patch
Patch07: 0007-Add-configure-variable-for-default-PKCS-11-module.patch
Patch08: 0008-Set-reasonable-supportedCMSTypes-in-PKINIT.patch
Patch09: 0009-Simplify-plugin-loading-code.patch
Patch10: 0010-Update-error-checking-for-OpenSSL-CMS_verify.patch
Patch11: 0011-downstream-Catch-SHA-1-digest-disallowed-error-for-P.patch
Patch12: 0012-Add-and-use-ts_interval-helper.patch
Patch13: 0013-downstream-Make-tests-compatible-with-sssd_krb5_loca.patch
Patch14: 0014-downstream-Do-not-set-root-as-ksu-file-owner.patch
Patch15: 0015-downstream-Allow-KRB5KDF-MD5-and-MD4-in-FIPS-mode.patch
Patch16: 0016-Add-PAC-full-checksums.patch
Patch17: 0017-Fix-possible-double-free-during-KDB-creation.patch
Patch18: 0018-Fix-meridian-type-in-kadmin-datetime-parser.patch
License: MIT
URL: https://web.mit.edu/kerberos/www/
@ -257,10 +258,7 @@ popd
# Mess with some of the default ports that we use for testing, so that multiple
# builds going on the same host don't step on each other.
cfg="src/kadmin/testing/proto/kdc.conf.proto \
src/kadmin/testing/proto/krb5.conf.proto \
src/lib/kadm5/testsuite/api.current/init-v2.exp \
src/util/k5test.py"
cfg="src/util/k5test.py"
LONG_BIT=`getconf LONG_BIT`
PORT=`expr 61000 + $LONG_BIT - 48`
sed -i -e s,61000,`expr "$PORT" + 0`,g $cfg
@ -276,6 +274,12 @@ PORT=`expr 7777 + $LONG_BIT - 48`
sed -i -e s,7777,`expr "$PORT" + 0`,g $cfg
sed -i -e s,7778,`expr "$PORT" + 1`,g $cfg
# Fix kadmind port hard-coded in tests
PORT=`expr 61000 + $LONG_BIT - 48`
sed -i -e \
"s,params.kadmind_port = 61001;,params.kadmind_port = $((PORT + 1));," \
src/lib/kadm5/t_kadm5.c
%build
# Go ahead and supply tcl info, because configure doesn't know how to find it.
source %{_libdir}/tclConfig.sh
@ -301,7 +305,6 @@ CPPFLAGS="`echo $DEFINES $INCLUDES`"
--without-krb5-config \
--with-system-et \
--with-system-ss \
--with-netlib=-lresolv \
--with-tcl \
--enable-dns-for-realm \
--with-ldap \
@ -316,6 +319,11 @@ CPPFLAGS="`echo $DEFINES $INCLUDES`"
--with-lmdb \
|| (cat config.log; exit 1)
# Check we have required features enabled
for x in DNS_LOOKUP DNS_LOOKUP_REALM; do
grep -q "#define KRB5_${x} 1" include/autoconf.h
done
# Sanity check the KDC_RUN_DIR.
pushd include
make osconf.h
@ -355,15 +363,15 @@ popd
# Sample KDC config files (bundled kdc.conf and kadm5.acl).
mkdir -p $RPM_BUILD_ROOT%{_var}/kerberos/krb5kdc
install -pm 600 %{SOURCE10} $RPM_BUILD_ROOT%{_var}/kerberos/krb5kdc/
install -pm 600 %{SOURCE11} $RPM_BUILD_ROOT%{_var}/kerberos/krb5kdc/
install -pm 600 %{SOURCE6} $RPM_BUILD_ROOT%{_var}/kerberos/krb5kdc/
install -pm 600 %{SOURCE7} $RPM_BUILD_ROOT%{_var}/kerberos/krb5kdc/
# Where per-user keytabs live by default.
mkdir -p $RPM_BUILD_ROOT%{_var}/kerberos/krb5/user
# Default configuration file for everything.
mkdir -p $RPM_BUILD_ROOT/etc
install -pm 644 %{SOURCE6} $RPM_BUILD_ROOT/etc/krb5.conf
install -pm 644 %{SOURCE5} $RPM_BUILD_ROOT/etc/krb5.conf
# Default include on this directory
mkdir -p $RPM_BUILD_ROOT/etc/krb5.conf.d
@ -383,16 +391,16 @@ mkdir -m 755 -p $RPM_BUILD_ROOT/etc/gss/mech.d
export DEFCCNAME="%{configured_default_ccache_name}"
awk '{print}
/^# default_realm/{print " default_ccache_name =", ENVIRON["DEFCCNAME"]}' \
%{SOURCE6} > $RPM_BUILD_ROOT/etc/krb5.conf
touch -r %{SOURCE6} $RPM_BUILD_ROOT/etc/krb5.conf
%{SOURCE5} > $RPM_BUILD_ROOT/etc/krb5.conf
touch -r %{SOURCE5} $RPM_BUILD_ROOT/etc/krb5.conf
grep default_ccache_name $RPM_BUILD_ROOT/etc/krb5.conf
%endif
# Server init scripts (krb5kdc,kadmind,kpropd) and their sysconfig files.
mkdir -p $RPM_BUILD_ROOT%{_unitdir}
for unit in \
%{SOURCE5}\
%{SOURCE4} \
%{SOURCE4}\
%{SOURCE3} \
%{SOURCE2} ; do
# In the past, the init script was supposed to be named after the service
# that the started daemon provided. Changing their names is an
@ -400,11 +408,11 @@ for unit in \
install -pm 644 ${unit} $RPM_BUILD_ROOT%{_unitdir}
done
mkdir -p $RPM_BUILD_ROOT/%{_tmpfilesdir}
install -pm 644 %{SOURCE39} $RPM_BUILD_ROOT/%{_tmpfilesdir}/
install -pm 644 %{SOURCE14} $RPM_BUILD_ROOT/%{_tmpfilesdir}/
mkdir -p $RPM_BUILD_ROOT/%{_localstatedir}/run/krb5kdc
mkdir -p $RPM_BUILD_ROOT/etc/sysconfig
for sysconfig in %{SOURCE19} %{SOURCE20} %{SOURCE21} ; do
for sysconfig in %{SOURCE8} %{SOURCE9} %{SOURCE10} ; do
install -pm 644 ${sysconfig} \
$RPM_BUILD_ROOT/etc/sysconfig/`basename ${sysconfig} .sysconfig`
done
@ -412,15 +420,15 @@ done
# logrotate configuration files
mkdir -p $RPM_BUILD_ROOT/etc/logrotate.d/
for logrotate in \
%{SOURCE33} \
%{SOURCE34} ; do
%{SOURCE12} \
%{SOURCE13} ; do
install -pm 644 ${logrotate} \
$RPM_BUILD_ROOT/etc/logrotate.d/`basename ${logrotate} .logrotate`
done
# PAM configuration files.
mkdir -p $RPM_BUILD_ROOT/etc/pam.d/
for pam in %{SOURCE29} ; do
for pam in %{SOURCE11} ; do
install -pm 644 ${pam} \
$RPM_BUILD_ROOT/etc/pam.d/`basename ${pam} .pamd`
done
@ -657,9 +665,43 @@ exit 0
%{_libdir}/libkadm5srv_mit.so.*
%changelog
* Tue Nov 08 2022 Julien Rische <jrische@redhat.com> - 1.19.1-24
* Wed Feb 22 2023 Julien Rische <jrische@redhat.com> - 1.20.1-8
- Fix datetime parsing in kadmin on s390x
- Resolves: rhbz#2169985
* Tue Feb 14 2023 Julien Rische <jrische@redhat.com> - 1.20.1-7
- Fix double free on kdb5_util key creation failure
- Resolves: rhbz#2166603
* Tue Jan 31 2023 Julien Rische <jrische@redhat.com> - 1.20.1-6
- Add support for MS-PAC extended KDC signature (CVE-2022-37967)
- Resolves: rhbz#2165827
* Thu Jan 19 2023 Julien Rische <jrische@redhat.com> - 1.20.1-5
- Bypass FIPS restrictions to use KRB5KDF in case AES SHA-1 HMAC is enabled
- Lazily load MD4/5 from OpenSSL if using RADIUS or RC4 enctype in FIPS mode
- Resolves: rhbz#2162461
* Thu Jan 12 2023 Julien Rische <jrische@redhat.com> - 1.20.1-4
- Set aes256-cts-hmac-sha384-192 as EXAMLE.COM master key in kdc.conf
- Add AES SHA-2 HMAC family as EXAMPLE.COM supported etypes in kdc.conf
- Resolves: rhbz#2068535
* Tue Jan 10 2023 Julien Rische <jrische@redhat.com> - 1.20.1-2
- Strip debugging data from ksu executable file
- Resolves: rhbz#2159643
* Wed Dec 07 2022 Julien Rische <jrische@redhat.com> - 1.20.1-1
- Make tests compatible with sssd-client
- Resolves: rhbz#2151513
- Remove invalid password expiry warning
- Resolves: rhbz#2121099
- Update error checking for OpenSSL CMS_verify
- Resolves: rhbz#2063838
- New upstream version (1.20.1)
- Resolves: rhbz#2016312
- Fix integer overflows in PAC parsing (CVE-2022-42898)
- Resolves: rhbz#2140970
- Resolves: rhbz#2140971
* Tue Oct 18 2022 Julien Rische <jrische@redhat.com> - 1.19.1-23
- Fix kprop for propagating dump files larger than 4GB

Loading…
Cancel
Save