New upstream version (1.20.1)

Also set "supportedCMSTypes" to SHA-512/256 with RSA encryption

Resolves: rhbz#2124463
Resolves: rhbz#2114766
Signed-off-by: Julien Rische <jrische@redhat.com>
This commit is contained in:
Julien Rische 2022-11-23 18:27:49 +01:00
parent c13bf943d8
commit 56cee506e7
44 changed files with 1453 additions and 27035 deletions

95
.gitignore vendored
View File

@ -1,49 +1,50 @@
krb5-1.3.4.tar.gz
krb5-1.3.5.tar.gz
krb5-1.3.5.tar.gz.asc
krb5-1.3.6.tar.gz
krb5-1.3.6.tar.gz.asc
krb5-1.4.tar.gz
krb5-1.4.tar.gz.asc
krb5-1.4.1.tar.gz
krb5-1.4.1.tar.gz.asc
krb5-1.4.2.tar.gz
krb5-1.4.2.tar.gz.asc
krb5-1.4.3.tar.gz
krb5-1.4.3.tar.gz.asc
krb5-1.5.tar.gz
krb5-1.5.tar.gz.asc
krb5-1.6.tar.gz
krb5-1.6.tar.gz.asc
krb5-1.6-pdf.tar.gz
krb5-1.6.1.tar.gz
krb5-1.6.1.tar.gz.asc
krb5-1.6.1-pdf.tar.gz
krb5-1.6.2.tar.gz
krb5-1.6.2.tar.gz.asc
krb5-1.6.2-pdf.tar.gz
krb5-1.6.3.tar.gz
krb5-1.6.3.tar.gz.asc
krb5-1.6.3-pdf.tar.gz
krb5-1.7.tar.gz
krb5-1.7.tar.gz.asc
krb5-1.7-pdf.tar.gz
krb5-1.7.1.tar.gz
krb5-1.7.1.tar.gz.asc
krb5-1.7.1-pdf.tar.gz
krb5-1.8.tar.gz
krb5-1.8.tar.gz.asc
krb5-appl-1.0.tar.gz
krb5-appl-1.0.tar.gz.asc
krb5-1.8-pdf.tar.gz
krb5-1.8.1.tar.gz
krb5-1.8.1.tar.gz.asc
krb5-1.8.1-pdf.tar.gz
krb5-1.8.2.tar.gz.asc
krb5-1.8.2-pdf.tar.gz
krb5-1.8.3.tar.gz
krb5-1.8.3.tar.gz.asc
krb5-1.8.3-pdf.tar.gz
/results_krb5
/krb5-1.3.4.tar.gz
/krb5-1.3.5.tar.gz
/krb5-1.3.5.tar.gz.asc
/krb5-1.3.6.tar.gz
/krb5-1.3.6.tar.gz.asc
/krb5-1.4.tar.gz
/krb5-1.4.tar.gz.asc
/krb5-1.4.1.tar.gz
/krb5-1.4.1.tar.gz.asc
/krb5-1.4.2.tar.gz
/krb5-1.4.2.tar.gz.asc
/krb5-1.4.3.tar.gz
/krb5-1.4.3.tar.gz.asc
/krb5-1.5.tar.gz
/krb5-1.5.tar.gz.asc
/krb5-1.6.tar.gz
/krb5-1.6.tar.gz.asc
/krb5-1.6-pdf.tar.gz
/krb5-1.6.1.tar.gz
/krb5-1.6.1.tar.gz.asc
/krb5-1.6.1-pdf.tar.gz
/krb5-1.6.2.tar.gz
/krb5-1.6.2.tar.gz.asc
/krb5-1.6.2-pdf.tar.gz
/krb5-1.6.3.tar.gz
/krb5-1.6.3.tar.gz.asc
/krb5-1.6.3-pdf.tar.gz
/krb5-1.7.tar.gz
/krb5-1.7.tar.gz.asc
/krb5-1.7-pdf.tar.gz
/krb5-1.7.1.tar.gz
/krb5-1.7.1.tar.gz.asc
/krb5-1.7.1-pdf.tar.gz
/krb5-1.8.tar.gz
/krb5-1.8.tar.gz.asc
/krb5-appl-1.0.tar.gz
/krb5-appl-1.0.tar.gz.asc
/krb5-1.8-pdf.tar.gz
/krb5-1.8.1.tar.gz
/krb5-1.8.1.tar.gz.asc
/krb5-1.8.1-pdf.tar.gz
/krb5-1.8.2.tar.gz.asc
/krb5-1.8.2-pdf.tar.gz
/krb5-1.8.3.tar.gz
/krb5-1.8.3.tar.gz.asc
/krb5-1.8.3-pdf.tar.gz
/krb5-1.9-beta2.tar.gz
/krb5-1.9-beta2.tar.gz.asc
/krb5-1.9-beta2-pdf.tar.bz2
@ -199,3 +200,5 @@ krb5-1.8.3-pdf.tar.gz
/krb5-1.19.1.tar.gz.asc
/krb5-1.19.2.tar.gz
/krb5-1.19.2.tar.gz.asc
/krb5-1.20.1.tar.gz
/krb5-1.20.1.tar.gz.asc

View File

@ -1,4 +1,4 @@
From 659b3b4a654b879ce84ad8fb4621dde5ae693385 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

View File

@ -1,4 +1,4 @@
From 97966ffaac6bf9f2e09ac33a16b15794b31d51de 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

View File

@ -1,4 +1,4 @@
From 98b50683165089bf7bd9d91f953abbd79a8b1b08 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

View File

@ -1,4 +1,4 @@
From 91e1d43858d90f59f5d9f45987cfca02c3175feb Mon Sep 17 00:00:00 2001
From 239cd24624b801d4fc4bb4686bef8526e7675d77 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
@ -21,10 +21,10 @@ post7 restores MD5 and adds radius_md5_fips_override.
post8 silences a static analyzer warning.
Last-updated: krb5-1.17
Last-updated: krb5-1.20
---
doc/admin/conf_files/krb5_conf.rst | 6 +++
src/lib/crypto/krb/prng.c | 11 ++++-
src/lib/crypto/krb/prng.c | 15 +++++-
.../crypto/openssl/enc_provider/camellia.c | 6 +++
src/lib/crypto/openssl/enc_provider/rc4.c | 13 +++++-
.../crypto/openssl/hash_provider/hash_evp.c | 12 +++++
@ -38,10 +38,10 @@ Last-updated: krb5-1.17
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, 151 insertions(+), 33 deletions(-)
15 files changed, 155 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:
@ -58,22 +58,26 @@ 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..9e80a03d21 100644
--- a/src/lib/crypto/krb/prng.c
+++ b/src/lib/crypto/krb/prng.c
@@ -26,6 +26,8 @@
@@ -26,6 +26,12 @@
#include "crypto_int.h"
+#include <openssl/rand.h>
+
+#if OPENSSL_VERSION_NUMBER < 0x30000000L
+#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 +102,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;
@ -89,10 +93,10 @@ 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..d9f327add6 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,
@@ -387,6 +387,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;
@ -102,7 +106,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 +421,9 @@ static krb5_error_code
krb5int_camellia_init_state (const krb5_keyblock *key, krb5_keyusage usage,
krb5_data *state)
{
@ -113,10 +117,10 @@ 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..ce63cb5f1b 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,
@@ -69,6 +69,9 @@ k5_arcfour_docrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data,
EVP_CIPHER_CTX *ctx = NULL;
struct arcfour_state *arcstate;
@ -126,7 +130,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 +119,12 @@ k5_arcfour_docrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data,
static void
k5_arcfour_free_state(krb5_data *state)
{
@ -140,7 +144,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 +136,9 @@ k5_arcfour_init_state(const krb5_keyblock *key,
{
struct arcfour_state *arcstate;
@ -151,10 +155,10 @@ 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..2eb5139c0 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
@@ -49,6 +49,11 @@ hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data,
@@ -60,6 +60,11 @@ hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data,
if (ctx == NULL)
return ENOMEM;
@ -166,7 +170,7 @@ index 1e0fb8fc3..2eb5139c0 100644
ok = EVP_DigestInit_ex(ctx, type, NULL);
for (i = 0; i < num_data; i++) {
if (!SIGN_IOV(&data[i]))
@@ -64,12 +69,19 @@ hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data,
@@ -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)
{
@ -178,6 +182,7 @@ index 1e0fb8fc3..2eb5139c0 100644
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)
{
@ -187,24 +192,24 @@ index 1e0fb8fc3..2eb5139c0 100644
}
diff --git a/src/lib/crypto/openssl/hmac.c b/src/lib/crypto/openssl/hmac.c
index 7dc59dcc0..769a50c00 100644
index bf12b8d6a0..f21e268f7f 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)
@@ -111,7 +111,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 @@
@ -328,7 +333,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)
@ -351,7 +356,7 @@ index 03c613716..d89982a13 100644
return retval;
diff --git a/src/lib/krad/internal.h b/src/lib/krad/internal.h
index 0143d155a..57672982f 100644
index 7619563fc5..e123763954 100644
--- a/src/lib/krad/internal.h
+++ b/src/lib/krad/internal.h
@@ -39,6 +39,8 @@
@ -397,7 +402,7 @@ index 0143d155a..57672982f 100644
/* Decode attributes from a buffer. */
krb5_error_code
@@ -152,4 +163,17 @@ gai_error_code(int err)
@@ -156,4 +167,17 @@ gai_error_code(int err)
}
}
@ -416,7 +421,7 @@ index 0143d155a..57672982f 100644
+
#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;
@ -477,7 +482,7 @@ index c597174b6..fc2d24800 100644
}
diff --git a/src/lib/krad/remote.c b/src/lib/krad/remote.c
index a938665f6..7b5804b1d 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)
@ -498,7 +503,7 @@ index a938665f6..7b5804b1d 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;
@ -512,7 +517,7 @@ index a938665f6..7b5804b1d 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()
@ -533,7 +538,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()
@ -555,7 +560,7 @@ 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..a3ce22b70f 100644
--- a/src/plugins/preauth/spake/spake_client.c
+++ b/src/plugins/preauth/spake/spake_client.c
@@ -38,6 +38,8 @@
@ -579,7 +584,7 @@ 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..232e78bc05 100644
--- a/src/plugins/preauth/spake/spake_kdc.c
+++ b/src/plugins/preauth/spake/spake_kdc.c
@@ -41,6 +41,8 @@
@ -591,7 +596,7 @@ index 88c964ce1..c7df0392f 100644
/*
* 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 +553,10 @@ kdcpreauth_spake_initvt(krb5_context context, int maj_ver, int min_ver,
if (maj_ver != 1)
return KRB5_PLUGIN_VER_NOTSUPP;
@ -602,3 +607,6 @@ index 88c964ce1..c7df0392f 100644
vt = (krb5_kdcpreauth_vtable)vtable;
vt->name = "spake";
vt->pa_type_list = pa_types;
--
2.38.1

View File

@ -1,7 +1,8 @@
From a43d621ae83c89abb74764f0fd9d90a8e9992333 Mon Sep 17 00:00:00 2001
From 5587c755b6ca82bde093523e2d17b255158cd90e 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
@ -17,7 +18,7 @@ Resolves: rhbz#2082189
1 file changed, 33 insertions(+), 2 deletions(-)
diff --git a/src/lib/krad/remote.c b/src/lib/krad/remote.c
index 7b5804b1d..e671bc5c2 100644
index 929f1cef67..063f17a613 100644
--- a/src/lib/krad/remote.c
+++ b/src/lib/krad/remote.c
@@ -33,6 +33,7 @@
@ -64,7 +65,7 @@ index 7b5804b1d..e671bc5c2 100644
/* Iterate over the set of outstanding packets. */
static const krad_packet *
iterator(request **out)
@@ -455,8 +485,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;
@ -77,5 +78,5 @@ index 7b5804b1d..e671bc5c2 100644
retval = ESOCKTNOSUPPORT;
goto error;
--
2.35.1
2.38.1

View File

@ -1,4 +1,4 @@
From 2a91dabd9752825b96faf3b25ea643d5282c5957 Mon Sep 17 00:00:00 2001
From 842b4c3b5695e2518e6f1a1545db78865c04b59c 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,7 +47,7 @@ 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 a876fd633..252ab891a 100644
index 12168fa695..0ab5ff9606 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -242,6 +242,7 @@ if 'mansubs' in tags:
@ -75,7 +75,7 @@ index a876fd633..252ab891a 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 82b049af9..52e6563da 100644
index 8dc864718d..9774cb71ae 100644
--- a/src/configure.ac
+++ b/src/configure.ac
@@ -1442,6 +1442,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 82b049af9..52e6563da 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 e993d5c09..42f5ea4f9 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 e993d5c09..42f5ea4f9 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

View File

@ -0,0 +1,159 @@
From 3fb8c4c68274d2ff4addb44b7b95b4698c2c4f34 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

View File

@ -0,0 +1,622 @@
From ffb47e4120d68aef015453350a3a50a9bab1ec58 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

View File

@ -1,220 +0,0 @@
From 3a99832252755cf7e5fef2bd824459cea3eb823e 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

View File

@ -1,358 +0,0 @@
From 8772d8f47b7460a0eef48366881483fd9b3acfd3 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)
---
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])

View File

@ -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

View File

@ -1,84 +0,0 @@
From e88f0319427cee7245fb05c97a25473297c9d2d6 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():

View File

@ -1,60 +0,0 @@
From fb4d9fa851b1d0d3375556d1cdc1fce72176df1e 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)
---
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)

View File

@ -1,35 +0,0 @@
From 95547c12b39e62df55cef05cae890302834b7f98 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Wed, 23 Jun 2021 16:57:39 -0400
Subject: [PATCH] Clean up context after failed open in libkdb5
If krb5_db_open() or krb5_db_create() fails, release the dal_handle,
as the caller is unlikely to call krb5_db_close() after a failure.
(cherry picked from commit 849b7056e703bd3724d909263769ce190db59acc)
---
src/lib/kdb/kdb5.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/lib/kdb/kdb5.c b/src/lib/kdb/kdb5.c
index 47e9b31a7..11e2430c4 100644
--- a/src/lib/kdb/kdb5.c
+++ b/src/lib/kdb/kdb5.c
@@ -675,6 +675,8 @@ krb5_db_open(krb5_context kcontext, char **db_args, int mode)
return status;
status = v->init_module(kcontext, section, db_args, mode);
free(section);
+ if (status)
+ (void)krb5_db_fini(kcontext);
return status;
}
@@ -702,6 +704,8 @@ krb5_db_create(krb5_context kcontext, char **db_args)
return status;
status = v->create(kcontext, section, db_args);
free(section);
+ if (status)
+ (void)krb5_db_fini(kcontext);
return status;
}

View File

@ -1,193 +0,0 @@
From 5e5ea8e8345c8b2f3254b0d346b8e0de0df3a696 Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Wed, 26 May 2021 18:22:10 -0400
Subject: [PATCH] Clean up gssapi_krb5 ccache name functions
Modernize kg_get_ccache_name() and kg_get_ccache_name(). Drop
unnecessary use of const in kg_get_ccache_name() so that its return
value can be properly freed. Fixes some static analyzer false
positives.
(cherry picked from commit f573f7f8ee5269103a0492d6521a3242c5ffb63b)
---
src/lib/gssapi/krb5/gssapiP_krb5.h | 3 +-
src/lib/gssapi/krb5/gssapi_krb5.c | 47 ++++++++--------------
src/lib/gssapi/krb5/set_ccache.c | 64 ++++++++++++------------------
3 files changed, 42 insertions(+), 72 deletions(-)
diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h
index fd7abbd77..88d41130a 100644
--- a/src/lib/gssapi/krb5/gssapiP_krb5.h
+++ b/src/lib/gssapi/krb5/gssapiP_krb5.h
@@ -380,8 +380,7 @@ OM_uint32 kg_sync_ccache_name (krb5_context context, OM_uint32 *minor_status);
OM_uint32 kg_caller_provided_ccache_name (OM_uint32 *minor_status,
int *out_caller_provided_name);
-OM_uint32 kg_get_ccache_name (OM_uint32 *minor_status,
- const char **out_name);
+OM_uint32 kg_get_ccache_name (OM_uint32 *minor_status, char **out_name);
OM_uint32 kg_set_ccache_name (OM_uint32 *minor_status,
const char *name);
diff --git a/src/lib/gssapi/krb5/gssapi_krb5.c b/src/lib/gssapi/krb5/gssapi_krb5.c
index 46aa9b7a5..9915a8bb5 100644
--- a/src/lib/gssapi/krb5/gssapi_krb5.c
+++ b/src/lib/gssapi/krb5/gssapi_krb5.c
@@ -253,46 +253,31 @@ kg_caller_provided_ccache_name (OM_uint32 *minor_status,
}
OM_uint32
-kg_get_ccache_name (OM_uint32 *minor_status, const char **out_name)
+kg_get_ccache_name(OM_uint32 *minor_status, char **out_name)
{
- const char *name = NULL;
- OM_uint32 err = 0;
char *kg_ccache_name;
+ const char *def_name;
+ OM_uint32 err;
+ krb5_context context;
+
+ *out_name = NULL;
kg_ccache_name = k5_getspecific(K5_KEY_GSS_KRB5_CCACHE_NAME);
-
if (kg_ccache_name != NULL) {
- name = strdup(kg_ccache_name);
- if (name == NULL)
- err = ENOMEM;
+ *out_name = strdup(kg_ccache_name);
+ err = (*out_name == NULL) ? ENOMEM : 0;
} else {
- krb5_context context = NULL;
-
- /* Reset the context default ccache (see text above), and then
- retrieve it. */
+ /* Use the default ccache name. */
err = krb5_gss_init_context(&context);
- if (!err)
- err = krb5_cc_set_default_name (context, NULL);
- if (!err) {
- name = krb5_cc_default_name(context);
- if (name) {
- name = strdup(name);
- if (name == NULL)
- err = ENOMEM;
- }
- }
- if (err && context)
- save_error_info(err, context);
- if (context)
- krb5_free_context(context);
- }
-
- if (!err) {
- if (out_name) {
- *out_name = name;
- }
+ if (err)
+ goto cleanup;
+ def_name = krb5_cc_default_name(context);
+ *out_name = (def_name != NULL) ? strdup(def_name) : NULL;
+ err = (*out_name == NULL) ? ENOMEM : 0;
+ krb5_free_context(context);
}
+cleanup:
*minor_status = err;
return (*minor_status == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE;
}
diff --git a/src/lib/gssapi/krb5/set_ccache.c b/src/lib/gssapi/krb5/set_ccache.c
index 8acf3ec90..91c3462be 100644
--- a/src/lib/gssapi/krb5/set_ccache.c
+++ b/src/lib/gssapi/krb5/set_ccache.c
@@ -26,7 +26,7 @@
/*
* Set ccache name used by gssapi, and optionally obtain old ccache
- * name. Caller should not free returned name.
+ * name. Caller must not free returned name.
*/
#include <string.h>
@@ -38,11 +38,9 @@ gss_krb5int_ccache_name(OM_uint32 *minor_status,
const gss_OID desired_object,
const gss_buffer_t value)
{
- char *old_name = NULL;
OM_uint32 err = 0;
- OM_uint32 minor = 0;
- char *gss_out_name;
struct krb5_gss_ccache_name_req *req;
+ char *old_name, *cur_name = NULL;
err = gss_krb5int_initialize_library();
if (err) {
@@ -57,45 +55,33 @@ gss_krb5int_ccache_name(OM_uint32 *minor_status,
req = (struct krb5_gss_ccache_name_req *)value->value;
- gss_out_name = k5_getspecific(K5_KEY_GSS_KRB5_SET_CCACHE_OLD_NAME);
+ /* Our job is simple if the caller doesn't want the current name. */
+ if (req->out_name == NULL)
+ return kg_set_ccache_name(minor_status, req->name);
- if (req->out_name) {
- const char *tmp_name = NULL;
+ /* Fetch the current name and change it. */
+ kg_get_ccache_name(&err, &cur_name);
+ if (err)
+ goto cleanup;
+ kg_set_ccache_name(&err, req->name);
+ if (err)
+ goto cleanup;
- if (!err) {
- kg_get_ccache_name (&err, &tmp_name);
- }
- if (!err) {
- old_name = gss_out_name;
- gss_out_name = (char *)tmp_name;
- }
- }
- /* If out_name was NULL, we keep the same gss_out_name value, and
- don't free up any storage (leave old_name NULL). */
+ /* Store the current name in a thread-specific variable. Free that
+ * variable's previous contents. */
+ old_name = k5_getspecific(K5_KEY_GSS_KRB5_SET_CCACHE_OLD_NAME);
+ err = k5_setspecific(K5_KEY_GSS_KRB5_SET_CCACHE_OLD_NAME, cur_name);
+ if (err)
+ goto cleanup;
+ free(old_name);
- if (!err)
- kg_set_ccache_name (&err, req->name);
-
- minor = k5_setspecific(K5_KEY_GSS_KRB5_SET_CCACHE_OLD_NAME, gss_out_name);
- if (minor) {
- /* Um. Now what? */
- if (err == 0) {
- err = minor;
- }
- free(gss_out_name);
- gss_out_name = NULL;
- }
-
- if (!err) {
- if (req->out_name) {
- *(req->out_name) = gss_out_name;
- }
- }
-
- if (old_name != NULL) {
- free (old_name);
- }
+ /* Give the caller an alias to the stored value. */
+ *req->out_name = cur_name;
+ cur_name = NULL;
+ err = 0;
+cleanup:
+ free(cur_name);
*minor_status = err;
return (*minor_status == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE;
}

View File

@ -1,103 +0,0 @@
From 1528c264d0e1eebff34132c01f4f770f01f1d1c2 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)
---
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);

View File

@ -1,62 +0,0 @@
From 43be8fba5301d08fc4d5ddef14f8ae3d9655b0ba 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)
---
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);

View File

@ -1,45 +0,0 @@
From bb8fa495d00ccd931eec87a01b8920636cf7903e 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)
---
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 6d244ffd4..39a504ca1 100644
--- a/src/kdc/do_tgs_req.c
+++ b/src/kdc/do_tgs_req.c
@@ -207,6 +207,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);

View File

@ -1,106 +0,0 @@
From 06d30f43a41029d83248bbac1a9b65fc09987597 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

View File

@ -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);

View File

@ -1,64 +0,0 @@
From 2d2bb9a14613b3283dabdd40c3ee28e5b680cf93 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)
---
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')

View File

@ -1,664 +0,0 @@
From a14e0fd3c1d00ba625e6d9eb72829f31527c6ad8 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Wed, 23 Jun 2021 16:53:16 -0400
Subject: [PATCH] Fix leaks on error in kadm5 init functions
In the GENERIC_CHECK_HANDLE function, separate out the
version-checking logic so we can call it in the init functions before
allocating resources.
In the client and server library initialization functions, use a
single exit path after argument validation, and share the destruction
code with kadm5_destroy() via a helper.
(cherry picked from commit 552d7b7626450f963b8e37345c472420c842402c)
---
src/lib/kadm5/admin_internal.h | 39 ++++---
src/lib/kadm5/clnt/client_init.c | 174 +++++++++++-----------------
src/lib/kadm5/srv/server_init.c | 191 ++++++++++---------------------
3 files changed, 145 insertions(+), 259 deletions(-)
diff --git a/src/lib/kadm5/admin_internal.h b/src/lib/kadm5/admin_internal.h
index faf8e9c36..9be53883a 100644
--- a/src/lib/kadm5/admin_internal.h
+++ b/src/lib/kadm5/admin_internal.h
@@ -11,29 +11,32 @@
#define KADM5_SERVER_HANDLE_MAGIC 0x12345800
-#define GENERIC_CHECK_HANDLE(handle, old_api_version, new_api_version) \
+#define CHECK_VERSIONS(struct_version, api_version, old_api_err, new_api_err) \
{ \
- kadm5_server_handle_t srvr = \
- (kadm5_server_handle_t) handle; \
- \
- if (! srvr) \
- return KADM5_BAD_SERVER_HANDLE; \
- if (srvr->magic_number != KADM5_SERVER_HANDLE_MAGIC) \
- return KADM5_BAD_SERVER_HANDLE; \
- if ((srvr->struct_version & KADM5_MASK_BITS) != \
- KADM5_STRUCT_VERSION_MASK) \
+ if ((struct_version & KADM5_MASK_BITS) != KADM5_STRUCT_VERSION_MASK) \
return KADM5_BAD_STRUCT_VERSION; \
- if (srvr->struct_version < KADM5_STRUCT_VERSION_1) \
+ if (struct_version < KADM5_STRUCT_VERSION_1) \
return KADM5_OLD_STRUCT_VERSION; \
- if (srvr->struct_version > KADM5_STRUCT_VERSION_1) \
+ if (struct_version > KADM5_STRUCT_VERSION_1) \
return KADM5_NEW_STRUCT_VERSION; \
- if ((srvr->api_version & KADM5_MASK_BITS) != \
- KADM5_API_VERSION_MASK) \
+ if ((api_version & KADM5_MASK_BITS) != KADM5_API_VERSION_MASK) \
return KADM5_BAD_API_VERSION; \
- if (srvr->api_version < KADM5_API_VERSION_2) \
- return old_api_version; \
- if (srvr->api_version > KADM5_API_VERSION_4) \
- return new_api_version; \
+ if (api_version < KADM5_API_VERSION_2) \
+ return old_api_err; \
+ if (api_version > KADM5_API_VERSION_4) \
+ return new_api_err; \
+ }
+
+#define GENERIC_CHECK_HANDLE(handle, old_api_err, new_api_err) \
+ { \
+ kadm5_server_handle_t srvr = handle; \
+ \
+ if (srvr == NULL) \
+ return KADM5_BAD_SERVER_HANDLE; \
+ if (srvr->magic_number != KADM5_SERVER_HANDLE_MAGIC) \
+ return KADM5_BAD_SERVER_HANDLE; \
+ CHECK_VERSIONS(srvr->struct_version, srvr->api_version, \
+ old_api_err, new_api_err); \
}
/*
diff --git a/src/lib/kadm5/clnt/client_init.c b/src/lib/kadm5/clnt/client_init.c
index 0aaca701f..75614bb19 100644
--- a/src/lib/kadm5/clnt/client_init.c
+++ b/src/lib/kadm5/clnt/client_init.c
@@ -138,6 +138,36 @@ kadm5_init_with_skey(krb5_context context, char *client_name,
server_handle);
}
+static kadm5_ret_t
+free_handle(kadm5_server_handle_t handle)
+{
+ kadm5_ret_t ret = 0;
+ OM_uint32 minor_stat;
+ krb5_ccache ccache;
+
+ if (handle == NULL)
+ return 0;
+
+ if (handle->destroy_cache && handle->cache_name != NULL) {
+ ret = krb5_cc_resolve(handle->context, handle->cache_name, &ccache);
+ if (!ret)
+ ret = krb5_cc_destroy(handle->context, ccache);
+ }
+ free(handle->cache_name);
+ (void)gss_release_cred(&minor_stat, &handle->cred);
+ if (handle->clnt != NULL && handle->clnt->cl_auth != NULL)
+ AUTH_DESTROY(handle->clnt->cl_auth);
+ if (handle->clnt != NULL)
+ clnt_destroy(handle->clnt);
+ if (handle->client_socket != -1)
+ close(handle->client_socket);
+ free(handle->lhandle);
+ kadm5_free_config_params(handle->context, &handle->params);
+ free(handle);
+
+ return ret;
+}
+
static kadm5_ret_t
init_any(krb5_context context, char *client_name, enum init_type init_type,
char *pass, krb5_ccache ccache_in, char *service_name,
@@ -145,36 +175,34 @@ init_any(krb5_context context, char *client_name, enum init_type init_type,
krb5_ui_4 api_version, char **db_args, void **server_handle)
{
int fd = -1;
- OM_uint32 minor_stat;
krb5_boolean iprop_enable;
int port;
rpcprog_t rpc_prog;
rpcvers_t rpc_vers;
- krb5_ccache ccache;
krb5_principal client = NULL, server = NULL;
struct timeval timeout;
- kadm5_server_handle_t handle;
+ kadm5_server_handle_t handle = NULL;
kadm5_config_params params_local;
- int code = 0;
+ krb5_error_code code;
generic_ret r = { 0, 0 };
initialize_ovk_error_table();
initialize_ovku_error_table();
- if (! server_handle) {
+ if (server_handle == NULL || client_name == NULL)
return EINVAL;
- }
- if (! (handle = malloc(sizeof(*handle)))) {
- return ENOMEM;
- }
- memset(handle, 0, sizeof(*handle));
- if (! (handle->lhandle = malloc(sizeof(*handle)))) {
- free(handle);
- return ENOMEM;
- }
+ CHECK_VERSIONS(struct_version, api_version, KADM5_OLD_LIB_API_VERSION,
+ KADM5_NEW_LIB_API_VERSION);
+
+ handle = k5alloc(sizeof(*handle), &code);
+ if (handle == NULL)
+ goto cleanup;
+ handle->lhandle = k5alloc(sizeof(*handle), &code);
+ if (handle->lhandle == NULL)
+ goto cleanup;
handle->magic_number = KADM5_SERVER_HANDLE_MAGIC;
handle->struct_version = struct_version;
@@ -192,33 +220,20 @@ init_any(krb5_context context, char *client_name, enum init_type init_type,
handle->context = context;
- if(client_name == NULL) {
- free(handle);
- return EINVAL;
- }
-
- /*
- * Verify the version numbers before proceeding; we can't use
- * CHECK_HANDLE because not all fields are set yet.
- */
- GENERIC_CHECK_HANDLE(handle, KADM5_OLD_LIB_API_VERSION,
- KADM5_NEW_LIB_API_VERSION);
-
memset(&params_local, 0, sizeof(params_local));
- if ((code = kadm5_get_config_params(handle->context, 0,
- params_in, &handle->params))) {
- free(handle);
- return(code);
- }
+ code = kadm5_get_config_params(handle->context, 0, params_in,
+ &handle->params);
+ if (code)
+ goto cleanup;
#define REQUIRED_PARAMS (KADM5_CONFIG_REALM | \
KADM5_CONFIG_ADMIN_SERVER | \
KADM5_CONFIG_KADMIND_PORT)
if ((handle->params.mask & REQUIRED_PARAMS) != REQUIRED_PARAMS) {
- free(handle);
- return KADM5_MISSING_KRB5_CONF_PARAMS;
+ code = KADM5_MISSING_KRB5_CONF_PARAMS;
+ goto cleanup;
}
/*
@@ -228,7 +243,7 @@ init_any(krb5_context context, char *client_name, enum init_type init_type,
*/
code = krb5_parse_name(handle->context, client_name, &client);
if (code)
- goto error;
+ goto cleanup;
if (init_type == INIT_SKEY && client->realm.length == 0)
client->type = KRB5_NT_SRV_HST;
@@ -239,7 +254,7 @@ init_any(krb5_context context, char *client_name, enum init_type init_type,
code = get_init_creds(handle, client, init_type, pass, ccache_in,
service_name, handle->params.realm, &server);
if (code)
- goto error;
+ goto cleanup;
/* If the service_name and client_name are iprop-centric, use the iprop
* port and RPC identifiers. */
@@ -258,7 +273,7 @@ init_any(krb5_context context, char *client_name, enum init_type init_type,
code = connect_to_server(handle->params.admin_server, port, &fd);
if (code)
- goto error;
+ goto cleanup;
handle->clnt = clnttcp_create(NULL, rpc_prog, rpc_vers, &fd, 0, 0);
if (handle->clnt == NULL) {
@@ -266,7 +281,7 @@ init_any(krb5_context context, char *client_name, enum init_type init_type,
#ifdef DEBUG
clnt_pcreateerror("clnttcp_create");
#endif
- goto error;
+ goto cleanup;
}
/* Set a one-hour timeout. */
@@ -278,10 +293,6 @@ init_any(krb5_context context, char *client_name, enum init_type init_type,
handle->lhandle->clnt = handle->clnt;
handle->lhandle->client_socket = fd;
- /* now that handle->clnt is set, we can check the handle */
- if ((code = _kadm5_check_handle((void *) handle)))
- goto error;
-
/*
* The RPC connection is open; establish the GSS-API
* authentication context.
@@ -289,7 +300,7 @@ init_any(krb5_context context, char *client_name, enum init_type init_type,
code = setup_gss(handle, params_in,
(init_type == INIT_CREDS) ? client : NULL, server);
if (code)
- goto error;
+ goto cleanup;
/*
* Bypass the remainder of the code and return straight away
@@ -297,7 +308,8 @@ init_any(krb5_context context, char *client_name, enum init_type init_type,
*/
if (iprop_enable) {
code = 0;
- *server_handle = (void *) handle;
+ *server_handle = handle;
+ handle = NULL;
goto cleanup;
}
@@ -306,7 +318,7 @@ init_any(krb5_context context, char *client_name, enum init_type init_type,
#ifdef DEBUG
clnt_perror(handle->clnt, "init_2 null resp");
#endif
- goto error;
+ goto cleanup;
}
/* Drop down to v3 wire protocol if server does not support v4 */
if (r.code == KADM5_NEW_SERVER_API_VERSION &&
@@ -315,7 +327,7 @@ init_any(krb5_context context, char *client_name, enum init_type init_type,
memset(&r, 0, sizeof(generic_ret));
if (init_2(&handle->api_version, &r, handle->clnt)) {
code = KADM5_RPC_ERROR;
- goto error;
+ goto cleanup;
}
}
/* Drop down to v2 wire protocol if server does not support v3 */
@@ -325,47 +337,21 @@ init_any(krb5_context context, char *client_name, enum init_type init_type,
memset(&r, 0, sizeof(generic_ret));
if (init_2(&handle->api_version, &r, handle->clnt)) {
code = KADM5_RPC_ERROR;
- goto error;
+ goto cleanup;
}
}
if (r.code) {
code = r.code;
- goto error;
+ goto cleanup;
}
- *server_handle = (void *) handle;
-
- goto cleanup;
-
-error:
- /*
- * Note that it is illegal for this code to execute if "handle"
- * has not been allocated and initialized. I.e., don't use "goto
- * error" before the block of code at the top of the function
- * that allocates and initializes "handle".
- */
- if (handle->destroy_cache && handle->cache_name) {
- if (krb5_cc_resolve(handle->context,
- handle->cache_name, &ccache) == 0)
- (void) krb5_cc_destroy (handle->context, ccache);
- }
- if (handle->cache_name)
- free(handle->cache_name);
- (void)gss_release_cred(&minor_stat, &handle->cred);
- if(handle->clnt && handle->clnt->cl_auth)
- AUTH_DESTROY(handle->clnt->cl_auth);
- if(handle->clnt)
- clnt_destroy(handle->clnt);
- if (fd != -1)
- close(fd);
- free(handle->lhandle);
- kadm5_free_config_params(handle->context, &handle->params);
+ *server_handle = handle;
+ handle = NULL;
cleanup:
- krb5_free_principal(handle->context, client);
- krb5_free_principal(handle->context, server);
- if (code)
- free(handle);
+ krb5_free_principal(context, client);
+ krb5_free_principal(context, server);
+ (void)free_handle(handle);
return code;
}
@@ -695,38 +681,8 @@ rpc_auth(kadm5_server_handle_t handle, kadm5_config_params *params_in,
kadm5_ret_t
kadm5_destroy(void *server_handle)
{
- OM_uint32 minor_stat;
- krb5_ccache ccache = NULL;
- int code = KADM5_OK;
- kadm5_server_handle_t handle =
- (kadm5_server_handle_t) server_handle;
-
CHECK_HANDLE(server_handle);
-
- if (handle->destroy_cache && handle->cache_name) {
- if ((code = krb5_cc_resolve(handle->context,
- handle->cache_name, &ccache)) == 0)
- code = krb5_cc_destroy (handle->context, ccache);
- }
- if (handle->cache_name)
- free(handle->cache_name);
- if (handle->cred)
- (void)gss_release_cred(&minor_stat, &handle->cred);
- if (handle->clnt && handle->clnt->cl_auth)
- AUTH_DESTROY(handle->clnt->cl_auth);
- if (handle->clnt)
- clnt_destroy(handle->clnt);
- if (handle->client_socket != -1)
- close(handle->client_socket);
- if (handle->lhandle)
- free (handle->lhandle);
-
- kadm5_free_config_params(handle->context, &handle->params);
-
- handle->magic_number = 0;
- free(handle);
-
- return code;
+ return free_handle(server_handle);
}
/* not supported on client */
kadm5_ret_t kadm5_lock(void *server_handle)
diff --git a/src/lib/kadm5/srv/server_init.c b/src/lib/kadm5/srv/server_init.c
index 3adc4b57d..2c0d51efd 100644
--- a/src/lib/kadm5/srv/server_init.c
+++ b/src/lib/kadm5/srv/server_init.c
@@ -19,23 +19,6 @@
#include "osconf.h"
#include "iprop_hdr.h"
-/*
- * Function check_handle
- *
- * Purpose: Check a server handle and return a com_err code if it is
- * invalid or 0 if it is valid.
- *
- * Arguments:
- *
- * handle The server handle.
- */
-
-static int check_handle(void *handle)
-{
- CHECK_HANDLE(handle);
- return 0;
-}
-
static int dup_db_args(kadm5_server_handle_t handle, char **db_args)
{
int count = 0;
@@ -84,6 +67,23 @@ static void free_db_args(kadm5_server_handle_t handle)
}
}
+static void
+free_handle(kadm5_server_handle_t handle)
+{
+ if (handle == NULL)
+ return;
+
+ destroy_pwqual(handle);
+ k5_kadm5_hook_free_handles(handle->context, handle->hook_handles);
+ ulog_fini(handle->context);
+ krb5_db_fini(handle->context);
+ krb5_free_principal(handle->context, handle->current_caller);
+ kadm5_free_config_params(handle->context, &handle->params);
+ free(handle->lhandle);
+ free_db_args(handle);
+ free(handle);
+}
+
kadm5_ret_t kadm5_init_with_password(krb5_context context, char *client_name,
char *pass, char *service_name,
kadm5_config_params *params,
@@ -163,8 +163,8 @@ kadm5_ret_t kadm5_init(krb5_context context, char *client_name, char *pass,
char **db_args,
void **server_handle)
{
- int ret;
- kadm5_server_handle_t handle;
+ krb5_error_code ret;
+ kadm5_server_handle_t handle = NULL;
kadm5_config_params params_local; /* for v1 compat */
if (! server_handle)
@@ -173,17 +173,17 @@ kadm5_ret_t kadm5_init(krb5_context context, char *client_name, char *pass,
if (! client_name)
return EINVAL;
- if (! (handle = (kadm5_server_handle_t) malloc(sizeof *handle)))
- return ENOMEM;
- memset(handle, 0, sizeof(*handle));
+ CHECK_VERSIONS(struct_version, api_version, KADM5_OLD_SERVER_API_VERSION,
+ KADM5_NEW_SERVER_API_VERSION);
+
+ handle = k5alloc(sizeof(*handle), &ret);
+ if (handle == NULL)
+ goto cleanup;
+ handle->context = context;
ret = dup_db_args(handle, db_args);
- if (ret) {
- free(handle);
- return ret;
- }
-
- handle->context = context;
+ if (ret)
+ goto cleanup;
initialize_ovk_error_table();
initialize_ovku_error_table();
@@ -192,13 +192,6 @@ kadm5_ret_t kadm5_init(krb5_context context, char *client_name, char *pass,
handle->struct_version = struct_version;
handle->api_version = api_version;
- /*
- * Verify the version numbers before proceeding; we can't use
- * CHECK_HANDLE because not all fields are set yet.
- */
- GENERIC_CHECK_HANDLE(handle, KADM5_OLD_SERVER_API_VERSION,
- KADM5_NEW_SERVER_API_VERSION);
-
/*
* Acquire relevant profile entries. Merge values
* in params_in with values from profile, based on
@@ -208,11 +201,8 @@ kadm5_ret_t kadm5_init(krb5_context context, char *client_name, char *pass,
ret = kadm5_get_config_params(handle->context, 1, params_in,
&handle->params);
- if (ret) {
- free_db_args(handle);
- free(handle);
- return(ret);
- }
+ if (ret)
+ goto cleanup;
#define REQUIRED_PARAMS (KADM5_CONFIG_REALM | KADM5_CONFIG_DBNAME | \
KADM5_CONFIG_ENCTYPE | \
@@ -226,132 +216,69 @@ kadm5_ret_t kadm5_init(krb5_context context, char *client_name, char *pass,
KADM5_CONFIG_IPROP_PORT)
if ((handle->params.mask & REQUIRED_PARAMS) != REQUIRED_PARAMS) {
- kadm5_free_config_params(handle->context, &handle->params);
- free_db_args(handle);
- free(handle);
- return KADM5_MISSING_CONF_PARAMS;
+ ret = KADM5_MISSING_CONF_PARAMS;
+ goto cleanup;
}
if ((handle->params.mask & KADM5_CONFIG_IPROP_ENABLED) == KADM5_CONFIG_IPROP_ENABLED
&& handle->params.iprop_enabled) {
if ((handle->params.mask & IPROP_REQUIRED_PARAMS) != IPROP_REQUIRED_PARAMS) {
- kadm5_free_config_params(handle->context, &handle->params);
- free_db_args(handle);
- free(handle);
- return KADM5_MISSING_CONF_PARAMS;
+ ret = KADM5_MISSING_CONF_PARAMS;
+ goto cleanup;
}
}
ret = krb5_set_default_realm(handle->context, handle->params.realm);
- if (ret) {
- kadm5_free_config_params(handle->context, &handle->params);
- free_db_args(handle);
- free(handle);
- return ret;
- }
+ if (ret)
+ goto cleanup;
ret = krb5_db_open(handle->context, db_args,
KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN);
- if (ret) {
- kadm5_free_config_params(handle->context, &handle->params);
- free_db_args(handle);
- free(handle);
- return(ret);
- }
+ if (ret)
+ goto cleanup;
- if ((ret = krb5_parse_name(handle->context, client_name,
- &handle->current_caller))) {
- kadm5_free_config_params(handle->context, &handle->params);
- krb5_db_fini(handle->context);
- free_db_args(handle);
- free(handle);
- return ret;
- }
+ ret = krb5_parse_name(handle->context, client_name,
+ &handle->current_caller);
+ if (ret)
+ goto cleanup;
- if (! (handle->lhandle = malloc(sizeof(*handle)))) {
- kadm5_free_config_params(handle->context, &handle->params);
- krb5_db_fini(handle->context);
- free_db_args(handle);
- free(handle);
- return ENOMEM;
- }
+ handle->lhandle = k5alloc(sizeof(*handle), &ret);
+ if (handle->lhandle == NULL)
+ goto cleanup;
*handle->lhandle = *handle;
handle->lhandle->api_version = KADM5_API_VERSION_4;
handle->lhandle->struct_version = KADM5_STRUCT_VERSION;
handle->lhandle->lhandle = handle->lhandle;
- /* can't check the handle until current_caller is set */
- ret = check_handle((void *) handle);
- if (ret) {
- kadm5_free_config_params(handle->context, &handle->params);
- free_db_args(handle);
- free(handle);
- return ret;
- }
-
ret = kdb_init_master(handle, handle->params.realm,
(handle->params.mask & KADM5_CONFIG_MKEY_FROM_KBD)
&& handle->params.mkey_from_kbd);
- if (ret) {
- kadm5_free_config_params(handle->context, &handle->params);
- krb5_db_fini(handle->context);
- free_db_args(handle);
- free(handle);
- return ret;
- }
+ if (ret)
+ goto cleanup;
ret = kdb_init_hist(handle, handle->params.realm);
- if (ret) {
- kadm5_free_config_params(handle->context, &handle->params);
- krb5_db_fini(handle->context);
- free_db_args(handle);
- free(handle);
- return ret;
- }
+ if (ret)
+ goto cleanup;
ret = k5_kadm5_hook_load(context,&handle->hook_handles);
- if (ret) {
- kadm5_free_config_params(handle->context, &handle->params);
- krb5_db_fini(handle->context);
- krb5_free_principal(handle->context, handle->current_caller);
- free_db_args(handle);
- free(handle);
- return ret;
- }
+ if (ret)
+ goto cleanup;
ret = init_pwqual(handle);
- if (ret) {
- kadm5_free_config_params(handle->context, &handle->params);
- k5_kadm5_hook_free_handles(context, handle->hook_handles);
- krb5_db_fini(handle->context);
- krb5_free_principal(handle->context, handle->current_caller);
- free_db_args(handle);
- free(handle);
- return ret;
- }
+ if (ret)
+ goto cleanup;
- *server_handle = (void *) handle;
+ *server_handle = handle;
+ handle = NULL;
- return KADM5_OK;
+cleanup:
+ free_handle(handle);
+ return ret;
}
kadm5_ret_t kadm5_destroy(void *server_handle)
{
- kadm5_server_handle_t handle = server_handle;
-
CHECK_HANDLE(server_handle);
-
- destroy_pwqual(handle);
-
- k5_kadm5_hook_free_handles(handle->context, handle->hook_handles);
- ulog_fini(handle->context);
- krb5_db_fini(handle->context);
- krb5_free_principal(handle->context, handle->current_caller);
- kadm5_free_config_params(handle->context, &handle->params);
- handle->magic_number = 0;
- free(handle->lhandle);
- free_db_args(handle);
- free(handle);
-
+ free_handle(server_handle);
return KADM5_OK;
}

View File

@ -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,

View File

@ -1,96 +0,0 @@
From 0779309f52f4c05bb1f01f638261ef1b8ca82488 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)
---
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;

View File

@ -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;
}

View File

@ -1,26 +0,0 @@
From 32ee800fa31d3bbda660bb9270f9aa20718ab202 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)
---
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);

File diff suppressed because it is too large Load Diff

View File

@ -1,71 +0,0 @@
From f8747c22fd159ad3556fdf6ec4f269c754c1eadb Mon Sep 17 00:00:00 2001
From: Simo Sorce <simo@redhat.com>
Date: Thu, 19 May 2022 12:27:40 -0400
Subject: [PATCH] Read GSS configuration files with mtime 0
There is at least one case (with flatpaks) where configuration files
in the special read-only /etc all have an mtime of 0. Using an
initial last modified time of 0 in g_initialize.c causes these files
to never be read.
Change the initial high value to the be the "invalid" value
(time_t)-1. Since the C and POSIX standards do not require time_t to
be signed, special-case the checks in load_if_changed() and
updateMechList() to treat all mod times as newer than -1.
[ghudson@mit.edu: edited commit message; slightly modified approach]
ticket: 9060 (new)
target_version: 1.20
tags: pullup
---
src/lib/gssapi/mechglue/g_initialize.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/src/lib/gssapi/mechglue/g_initialize.c b/src/lib/gssapi/mechglue/g_initialize.c
index 6d49700a5..857d4a4f2 100644
--- a/src/lib/gssapi/mechglue/g_initialize.c
+++ b/src/lib/gssapi/mechglue/g_initialize.c
@@ -93,7 +93,7 @@ static void free_mechSet(void);
static gss_mech_info g_mechList = NULL;
static gss_mech_info g_mechListTail = NULL;
static k5_mutex_t g_mechListLock = K5_MUTEX_PARTIAL_INITIALIZER;
-static time_t g_confFileModTime = (time_t)0;
+static time_t g_confFileModTime = (time_t)-1;
static time_t g_confLastCall = (time_t)0;
static gss_OID_set_desc g_mechSet = { 0, NULL };
@@ -469,9 +469,9 @@ load_if_changed(const char *pathname, time_t last, time_t *highest)
mtime = check_link_mtime(pathname, &mtime);
if (mtime == (time_t)-1)
return;
- if (mtime > *highest)
+ if (mtime > *highest || *highest == (time_t)-1)
*highest = mtime;
- if (mtime > last)
+ if (mtime > last || last == (time_t)-1)
loadConfigFile(pathname);
}
@@ -482,7 +482,7 @@ static void
loadConfigFiles()
{
glob_t globbuf;
- time_t highest = 0, now;
+ time_t highest = (time_t)-1, now;
char **path;
const char *val;
@@ -522,7 +522,8 @@ updateMechList(void)
#if defined(_WIN32)
time_t lastConfModTime = getRegConfigModTime(MECH_KEY);
- if (g_confFileModTime >= lastConfModTime)
+ if (g_confFileModTime >= lastConfModTime &&
+ g_confFileModTime != (time_t)-1)
return;
g_confFileModTime = lastConfModTime;
loadConfigFromRegistry(HKEY_CURRENT_USER, MECH_KEY);
--
2.35.3

File diff suppressed because it is too large Load Diff

View File

@ -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)

View File

@ -1,578 +0,0 @@
From 818a777822658d44ce647fe975011a5ea25e8250 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:".

View File

@ -1,91 +0,0 @@
From 1f706852ee759160e763c355a3053ad5e045fa06 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

View File

@ -1,235 +0,0 @@
From 336f744403baa5dfaffcc5bd226fdd8f14a0200b 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)
---
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:')

View File

@ -1,482 +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.
(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", NULL);
+ 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);

View File

@ -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. */

View File

@ -1,113 +0,0 @@
From 538be893707e2306e89f5e5ca92c0db0ee305e3e 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

View File

@ -1,22 +0,0 @@
From 37e1fe755c6e976253a7f40ec7a9e740e4329789 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Mon, 21 Jun 2021 19:15:26 -0400
Subject: [PATCH] Use asan in one of the CI builds
(cherry picked from commit 7368354bcd0b58480a88b1fb81e63bd6aae7edf2)
---
.github/workflows/build.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 8d1042b7b..06a35b7b9 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -17,6 +17,7 @@ jobs:
os: ubuntu-18.04
compiler: clang
makevars: CPPFLAGS=-Werror
+ configureopts: --enable-asan
- name: linux-clang-openssl
os: ubuntu-18.04
compiler: clang

View File

@ -1,752 +0,0 @@
From 86d606e33439fd0511c5154be7f32b0df2c72e54 Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Fri, 15 Nov 2019 20:05:16 +0000
Subject: [PATCH] [downstream] Use backported version of OpenSSL-3 KDF
interface
Last-updated: krb5-1.17
---
src/configure.ac | 4 +
src/lib/crypto/krb/derive.c | 356 +++++++++++++-----
.../preauth/pkinit/pkinit_crypto_openssl.c | 257 ++++++++-----
3 files changed, 428 insertions(+), 189 deletions(-)
diff --git a/src/configure.ac b/src/configure.ac
index 3e1052db7..ea708491b 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)
+AC_CHECK_FUNCS(EVP_KDF_CTX_new_id EVP_KDF_ctrl EVP_KDF_derive,
+ AC_DEFINE(OSSL_KDFS, 1, [Define if using OpenSSL KDFs]),
+ AC_MSG_ERROR([backported OpenSSL KDFs not found]))
+
AC_ARG_WITH([prng-alg],
AC_HELP_STRING([--with-prng-alg=ALG], [use specified PRNG algorithm. @<:@fortuna@:>@]),
[PRNG_ALG=$withval
diff --git a/src/lib/crypto/krb/derive.c b/src/lib/crypto/krb/derive.c
index 6707a7308..915a173dd 100644
--- a/src/lib/crypto/krb/derive.c
+++ b/src/lib/crypto/krb/derive.c
@@ -27,6 +27,13 @@
#include "crypto_int.h"
+#ifdef OSSL_KDFS
+#include <openssl/evp.h>
+#include <openssl/kdf.h>
+#else
+#error "Refusing to build without OpenSSL KDFs!"
+#endif
+
static krb5_key
find_cached_dkey(struct derived_key *list, const krb5_data *constant)
{
@@ -77,55 +84,193 @@ cleanup:
return ENOMEM;
}
+#ifdef OSSL_KDFS
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_CRYPTO_INTERNAL;
+ EVP_KDF_CTX *ctx = NULL;
+ const EVP_MD *digest;
+
+ if (!strcmp(hash->hash_name, "SHA1"))
+ digest = EVP_sha1();
+ else if (!strcmp(hash->hash_name, "SHA-256"))
+ digest = EVP_sha256();
+ else if (!strcmp(hash->hash_name, "SHA-384"))
+ digest = EVP_sha384();
+ else
+ goto done;
+
+ ctx = EVP_KDF_CTX_new_id(EVP_KDF_KB);
+ if (!ctx)
+ goto done;
+
+ if (EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_MD, digest) != 1 ||
+ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KB_MAC_TYPE,
+ EVP_KDF_KB_MAC_TYPE_HMAC) != 1 ||
+ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY, inkey->keyblock.contents,
+ inkey->keyblock.length) != 1 ||
+ (context->length > 0 &&
+ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KB_INFO, context->data,
+ context->length) != 1) ||
+ (label->length > 0 &&
+ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SALT, label->data,
+ label->length) != 1) ||
+ EVP_KDF_derive(ctx, (unsigned char *)outrnd->data,
+ outrnd->length) != 1)
+ goto done;
+
+ ret = 0;
+done:
+ if (ret)
+ zap(outrnd->data, outrnd->length);
+ EVP_KDF_CTX_free(ctx);
+ 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 = KRB5_CRYPTO_INTERNAL;
+ EVP_KDF_CTX *ctx = NULL;
+ const EVP_CIPHER *cipher;
+ static unsigned char zeroes[16];
+
+ memset(zeroes, 0, sizeof(zeroes));
+
+ if (enc->keylength == 16)
+ cipher = EVP_camellia_128_cbc();
+ else if (enc->keylength == 32)
+ cipher = EVP_camellia_256_cbc();
+ else
+ goto done;
+
+ ctx = EVP_KDF_CTX_new_id(EVP_KDF_KB);
+ if (!ctx)
+ goto done;
+
+ if (EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KB_MODE,
+ EVP_KDF_KB_MODE_FEEDBACK) != 1 ||
+ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KB_MAC_TYPE,
+ EVP_KDF_KB_MAC_TYPE_CMAC) != 1 ||
+ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_CIPHER, cipher) != 1 ||
+ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY, inkey->keyblock.contents,
+ inkey->keyblock.length) != 1 ||
+ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SALT, in_constant->data,
+ in_constant->length) != 1 ||
+ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KB_SEED, zeroes,
+ sizeof(zeroes)) != 1 ||
+ EVP_KDF_derive(ctx, (unsigned char *)outrnd->data,
+ outrnd->length) != 1)
+ goto done;
+
+ ret = 0;
+done:
+ if (ret)
+ zap(outrnd->data, outrnd->length);
+ EVP_KDF_CTX_free(ctx);
+ 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 = KRB5_CRYPTO_INTERNAL;
+ EVP_KDF_CTX *ctx = NULL;
+ const EVP_CIPHER *cipher;
+
+ if (inkey->keyblock.length != enc->keylength ||
+ outrnd->length != enc->keybytes) {
+ return KRB5_CRYPTO_INTERNAL;
+ }
+
+ if (enc->encrypt == krb5int_aes_encrypt && enc->keylength == 16)
+ cipher = EVP_aes_128_cbc();
+ else if (enc->encrypt == krb5int_aes_encrypt && enc->keylength == 32)
+ cipher = EVP_aes_256_cbc();
+ else if (enc->keylength == 24)
+ cipher = EVP_des_ede3_cbc();
+ else
+ goto done;
+
+ ctx = EVP_KDF_CTX_new_id(EVP_KDF_KRB5KDF);
+ if (ctx == NULL)
+ goto done;
+
+ if (EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_CIPHER, cipher) != 1 ||
+ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY, inkey->keyblock.contents,
+ inkey->keyblock.length) != 1 ||
+ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KRB5KDF_CONSTANT,
+ in_constant->data, in_constant->length) != 1 ||
+ EVP_KDF_derive(ctx, (unsigned char *)outrnd->data,
+ outrnd->length) != 1)
+ goto done;
+
+ ret = 0;
+done:
+ if (ret)
+ zap(outrnd->data, outrnd->length);
+ EVP_KDF_CTX_free(ctx);
+ return ret;
+}
+
+#else /* OSSL_KDFS */
+
+/*
+ * 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 block = empty_data();
+ krb5_data prf;
+ unsigned char ibuf[4], lbuf[4];
- blocksize = enc->block_size;
- keybytes = enc->keybytes;
-
- if (blocksize == 1)
- return KRB5_BAD_ENCTYPE;
- if (inkey->keyblock.length != enc->keylength || outrnd->length != keybytes)
+ 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 +284,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 +349,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 /* OSSL_KDFS */
+
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 OSSL_KDFS
+ 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
+k5_sp800_108_feedback_cmac(const struct krb5_enc_provider *enc,
+ krb5_key inkey, krb5_data *outrnd,
+ const krb5_data *in_constant)
+{
+#ifdef OSSL_KDFS
+ 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
+k5_derive_random_rfc3961(const struct krb5_enc_provider *enc,
+ krb5_key inkey, krb5_data *outrnd,
+ const krb5_data *in_constant)
+{
+#ifdef OSSL_KDFS
+ return openssl_krb5kdf(enc, inkey, outrnd, in_constant);
+#else
+ return builtin_derive_random_rfc3961(enc, inkey, outrnd, in_constant);
+#endif
}
krb5_error_code
@@ -266,10 +449,9 @@ krb5int_derive_random(const struct krb5_enc_provider *enc,
switch (alg) {
case DERIVE_RFC3961:
- return derive_random_rfc3961(enc, inkey, outrnd, in_constant);
+ return k5_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 k5_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);
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
index e1153344e..911e74fd9 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
@@ -38,6 +38,13 @@
#include <dirent.h>
#include <arpa/inet.h>
+#ifdef OSSL_KDFS
+#include <openssl/evp.h>
+#include <openssl/kdf.h>
+#else
+#error "Refusing to build without OpenSSL KDFs!"
+#endif
+
static krb5_error_code pkinit_init_pkinit_oids(pkinit_plg_crypto_context );
static void pkinit_fini_pkinit_oids(pkinit_plg_crypto_context );
@@ -2331,11 +2338,51 @@ pkinit_alg_values(krb5_context context,
}
} /* pkinit_alg_values() */
+#ifdef OSSL_KDFS
+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)
+{
+ krb5_error_code ret = KRB5_CRYPTO_INTERNAL;
+ EVP_KDF_CTX *ctx = NULL;
+ const EVP_MD *digest;
-/* 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:
+ /* RFC 8636 defines a SHA384 variant, but we don't use it. */
+ if (hash_bytes == 20) {
+ digest = EVP_sha1();
+ } else if (hash_bytes == 32) {
+ digest = EVP_sha256();
+ } else if (hash_bytes == 64) {
+ digest = EVP_sha512();
+ } else {
+ krb5_set_error_message(context, ret, "Bad hash type for SSKDF");
+ goto done;
+ }
+
+ ctx = EVP_KDF_CTX_new_id(EVP_KDF_SS);
+ if (!ctx) {
+ oerr(context, ret, _("Failed to instantiate SSKDF"));
+ goto done;
+ }
+
+ if (EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_MD, digest) != 1 ||
+ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY, key->data,
+ key->length) != 1 ||
+ EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSKDF_INFO, info->data,
+ info->length) != 1 ||
+ EVP_KDF_derive(ctx, (unsigned char *)out, out_len) != 1)
+ goto done;
+
+ ret = 0;
+done:
+ EVP_KDF_CTX_free(ctx);
+ 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 +2396,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;
- 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:
@@ -2471,8 +2439,9 @@ pkinit_alg_agility_kdf(krb5_context context,
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;
@@ -2484,26 +2453,110 @@ 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 retval;
+} /* builtin_sskdf() */
+#endif /* OSSL_KDFS */
- /* 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 retval;
+ 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;
+
+ /* Allocate and initialize the key block. */
+ key_block->magic = 0;
+ key_block->enctype = enctype;
+
+ /* Use separate variables to avoid alignment restriction problems. */
+ retval = krb5_c_keylengths(context, enctype, &rand_len, &key_len);
+ if (retval)
+ goto cleanup;
+ random_data.length = rand_len;
+ key_block->length = key_len;
+
+ key_block->contents = k5calloc(key_block->length, 1, &retval);
+ 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);
+ retval = pkinit_alg_values(context, alg_oid, &hash_len, &EVP_func);
+ if (retval)
+ 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, &retval);
+ 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;
+ retval = encode_krb5_pkinit_supp_pub_info(&supp_pub_info_fields,
+ &supp_pub_info);
+ if (retval)
+ 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;
+ retval = encode_krb5_sp80056a_other_info(&other_info_fields, &other_info);
+ if (retval)
+ goto cleanup;
+
+#ifdef OSSL_KDFS
+ retval = openssl_sskdf(context, hash_len, secret, other_info,
+ random_data.data, key_block->length);
+#else
+ retval = builtin_sskdf(context, reps, hash_len, EVP_func, secret,
+ other_info, random_data.data, key_block->length);
+#endif
+ if (retval)
+ goto cleanup;
+
+ retval = krb5_c_random_to_key(context, enctype, &random_data, key_block);
+cleanup:
+ if (retval)
+ krb5_free_keyblock_contents(context, key_block);
+
+ 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() */
+}
/* Call DH_compute_key() and ensure that we left-pad short results instead of
* leaving junk bytes at the end of the buffer. */

View File

@ -1,69 +0,0 @@
From f35077bfc570205092eca2a9d44e50ce265622f4 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Mon, 8 Nov 2021 17:48:50 +0100
Subject: [PATCH] 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 03c613716..f309f1581 100644
--- a/src/lib/krad/attrset.c
+++ b/src/lib/krad/attrset.c
@@ -217,7 +217,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.1

View File

@ -1,209 +0,0 @@
From ce160f8826bae223876a6527a731c36b6912db15 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 0143d155a..7619563fc 100644
--- a/src/lib/krad/internal.h
+++ b/src/lib/krad/internal.h
@@ -109,6 +109,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 7e491e994..06ae751bc 100644
--- a/src/lib/krad/remote.c
+++ b/src/lib/krad/remote.c
@@ -421,15 +421,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.1
From e0084425df784952e76b3bcc8ae9d08300234733 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Mon, 8 Nov 2021 17:47:17 +0100
Subject: [PATCH 2/2] More python3 fixes for t_daemon.py
[ghudson@mit.edu: use a list comprehension instead of map()]
---
src/lib/krad/t_daemon.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/lib/krad/t_daemon.py b/src/lib/krad/t_daemon.py
index 7668cd7f8..4a3de079c 100755
--- a/src/lib/krad/t_daemon.py
+++ b/src/lib/krad/t_daemon.py
@@ -50,7 +50,7 @@ class TestServer(server.Server):
for key in pkt.keys():
if key == "User-Password":
- passwd = map(pkt.PwDecrypt, pkt[key])
+ passwd = [pkt.PwDecrypt(x) for x in pkt[key]]
reply = self.CreateReplyPacket(pkt)
if passwd == ['accept']:
@@ -61,8 +61,8 @@ class TestServer(server.Server):
srv = TestServer(addresses=["localhost"],
hosts={"127.0.0.1":
- server.RemoteHost("127.0.0.1", "foo", "localhost")},
- dict=dictionary.Dictionary(StringIO.StringIO(DICTIONARY)))
+ server.RemoteHost("127.0.0.1", b"foo", "localhost")},
+ dict=dictionary.Dictionary(StringIO(DICTIONARY)))
# Write a sentinel character to let the parent process know we're listening.
sys.stdout.write("~")
--
2.35.1

125
krb5.spec
View File

@ -34,7 +34,7 @@
#
# baserelease is what we have standardized across Fedora and what
# rpmdev-bumpspec knows how to handle.
%global baserelease 13
%global baserelease 0.1
# This should be e.g. beta1 or %%nil
%global pre_release %nil
@ -46,9 +46,9 @@
%endif
%global krb5_version_major 1
%global krb5_version_minor 19
%global krb5_version_minor 20
# For a release without a patch number set to %%nil
%global krb5_version_patch 2
%global krb5_version_patch 1
%global krb5_version_major_minor %{krb5_version_major}.%{krb5_version_minor}
%global krb5_version %{krb5_version_major_minor}
@ -68,59 +68,29 @@ Release: %{krb5_release}%{?dist}
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
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
Patch0: downstream-ksu-pam-integration.patch
Patch1: downstream-SELinux-integration.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: Add-KCM_OP_GET_CRED_LIST-for-faster-iteration.patch
Patch12: Fix-KCM-flag-transmission-for-remove_cred.patch
Patch13: Make-KCM-iteration-fallback-work-with-sssd-kcm.patch
Patch14: Use-KCM_OP_RETRIEVE-in-KCM-client.patch
Patch15: Fix-KCM-retrieval-support-for-sssd.patch
Patch17: Move-some-dejagnu-kadmin-tests-to-Python-tests.patch
Patch18: Fix-some-principal-realm-canonicalization-cases.patch
Patch19: Allow-kinit-with-keytab-to-defer-canonicalization.patch
Patch20: Fix-kadmin-k-with-fallback-or-referral-realm.patch
Patch21: Fix-softpkcs11-build-issues-with-openssl-3.0.patch
Patch22: Remove-deprecated-OpenSSL-calls-from-softpkcs11.patch
Patch23: Fix-k5tls-module-for-OpenSSL-3.patch
Patch24: Fix-leaks-on-error-in-kadm5-init-functions.patch
Patch25: Clean-up-context-after-failed-open-in-libkdb5.patch
Patch26: Use-asan-in-one-of-the-CI-builds.patch
Patch29: Clean-up-gssapi_krb5-ccache-name-functions.patch
Patch30: Fix-KDC-null-deref-on-TGS-inner-body-null-server.patch
Patch32: Add-buildsystem-detection-of-the-OpenSSL-3-KDF-inter.patch
Patch33: Use-OpenSSL-s-SSKDF-in-PKINIT-when-available.patch
Patch34: Use-OpenSSL-s-KBKDF-and-KRB5KDF-for-deriving-long-te.patch
Patch35: Handle-OpenSSL-3-s-providers.patch
Patch36: Remove-TCL-based-libkadm5-API-tests.patch
Patch37: Use-SHA256-instead-of-SHA1-for-PKINIT-CMS-digest.patch
Patch38: krb5-krad-remote.patch
Patch39: krb5-krad-larger-attrs.patch
Patch40: Try-harder-to-avoid-password-change-replay-errors.patch
Patch41: Add-configure-variable-for-default-PKCS-11-module.patch
Patch42: downstream-Allow-krad-UDP-TCP-localhost-connection-with-FIPS.patch
Patch43: Read-GSS-configuration-files-with-mtime-0.patch
Patch44: Fix-integer-overflows-in-PAC-parsing.patch
Patch1: 0001-downstream-ksu-pam-integration.patch
Patch2: 0002-downstream-SELinux-integration.patch
Patch3: 0003-downstream-fix-debuginfo-with-y.tab.c.patch
Patch4: 0004-downstream-Remove-3des-support.patch
Patch5: 0005-downstream-FIPS-with-PRNG-and-RADIUS-and-MD4.patch
Patch6: 0006-downstream-Allow-krad-UDP-TCP-localhost-connection-w.patch
Patch7: 0007-Add-configure-variable-for-default-PKCS-11-module.patch
Patch8: 0008-Set-reasonable-supportedCMSTypes-in-PKINIT.patch
Patch9: 0009-Simplify-plugin-loading-code.patch
License: MIT
URL: https://web.mit.edu/kerberos/www/
@ -153,8 +123,14 @@ BuildRequires: procps-ng
BuildRequires: resolv_wrapper
%endif
%if 0%{?fedora} > 35
# Need KDFs. This is the "real" version
BuildRequires: openssl-devel => 1:3.0.0
%else
# Need KDFs. This is the backported version
BuildRequires: openssl-devel >= 1:1.1.1d-4
BuildRequires: openssl-devel < 1:3.0.0
%endif
%description
Kerberos V5 is a trusted-third-party network authentication system,
@ -180,7 +156,12 @@ to install this package.
%package libs
Summary: The non-admin shared libraries used by Kerberos 5
%if 0%{?fedora} > 35
Requires: openssl-libs >= 1:3.0.0
%else
Requires: openssl-libs >= 1:1.1.1d-4
Requires: openssl-libs < 1:3.0.0
%endif
Requires: coreutils, gawk, sed
Requires: keyutils-libs >= 1.5.8
Requires: /etc/crypto-policies/back-ends/krb5.config
@ -296,6 +277,13 @@ 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
@ -379,15 +367,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
@ -407,16 +395,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}\
%{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
@ -424,11 +412,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
@ -436,15 +424,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
@ -676,6 +664,13 @@ exit 0
%{_libdir}/libkadm5srv_mit.so.*
%changelog
* Tue Nov 22 2022 Julien Rische <jrische@redhat.com> - 1.20.1-0.1
- New upstream version (1.20.1)
- Resolves: rhbz#2124463
- Restore "supportedCMSTypes" attribute in PKINIT preauth requests
- Set SHA-512 or SHA-256 with RSA as preferred CMS signature algorithms
- Resolves: rhbz#2114766
* Wed Nov 09 2022 Julien Rische <jrische@redhat.com> - 1.19.2-13
- Fix integer overflows in PAC parsing (CVE-2022-42898)
- Resolves: rhbz#2143011

View File

@ -1,2 +1,2 @@
SHA512 (krb5-1.19.2.tar.gz) = b90d6ed0e1e8a87eb5cb2c36d88b823a6a6caabf85e5d419adb8a930f7eea09a5f8491464e7e454cca7ba88be09d19415962fe0036ad2e31fc584f9fc0bbd470
SHA512 (krb5-1.19.2.tar.gz.asc) = 87c4d096dbb6821401125b8f8a315ce1aac029744ba9670a4f8a2a680e6dd5798e1c6d5d2b68b17fd9a4b3b9c6ff111cd1dcac42f934d48fb20381b3765e0f64
SHA512 (krb5-1.20.1.tar.gz) = 6f57479f13f107cd84f30de5c758eb6b9fc59171329c13e5da6073b806755f8d163eb7bd84767ea861ad6458ea0c9eeb00ee044d3bcad01ef136e9888564b6a2
SHA512 (krb5-1.20.1.tar.gz.asc) = 1d3312bd67581e07adfdadf2c5fe394179631d8add8bd075efefe982a0de22369004e60a14422d426382c8c591e4181b9897088afe9d4e86f0b5a97e5954c67a