commit
c43cb49715
@ -0,0 +1 @@
|
||||
SOURCES/krb5-1.21.3.tar.gz
|
@ -0,0 +1 @@
|
||||
3e383bbe88cbed56bdad4ba655c40abf0e961cf7 SOURCES/krb5-1.21.3.tar.gz
|
@ -0,0 +1,310 @@
|
||||
From 6f7fd964539dfe4a885068f43a91db9738661870 Mon Sep 17 00:00:00 2001
|
||||
From: Julien Rische <jrische@redhat.com>
|
||||
Date: Tue, 9 Jul 2024 11:15:33 +0200
|
||||
Subject: [PATCH] [downstream] Revert "Don't issue session keys with
|
||||
deprecated enctypes"
|
||||
|
||||
This reverts commit 1b57a4d134bbd0e7c52d5885a92eccc815726463.
|
||||
---
|
||||
doc/admin/conf_files/krb5_conf.rst | 12 ------------
|
||||
doc/admin/enctypes.rst | 23 +++-------------------
|
||||
src/include/k5-int.h | 4 ----
|
||||
src/kdc/kdc_util.c | 10 ----------
|
||||
src/lib/krb5/krb/get_in_tkt.c | 31 +++++++++++-------------------
|
||||
src/lib/krb5/krb/init_ctx.c | 10 ----------
|
||||
src/tests/gssapi/t_enctypes.py | 3 +--
|
||||
src/tests/t_etype_info.py | 2 +-
|
||||
src/tests/t_sesskeynego.py | 28 ++-------------------------
|
||||
src/util/k5test.py | 4 ++--
|
||||
10 files changed, 20 insertions(+), 107 deletions(-)
|
||||
|
||||
diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
|
||||
index ecdf917501..f22d5db11b 100644
|
||||
--- a/doc/admin/conf_files/krb5_conf.rst
|
||||
+++ b/doc/admin/conf_files/krb5_conf.rst
|
||||
@@ -95,18 +95,6 @@ Additionally, krb5.conf may include any of the relations described in
|
||||
|
||||
The libdefaults section may contain any of the following relations:
|
||||
|
||||
-**allow_des3**
|
||||
- Permit the KDC to issue tickets with des3-cbc-sha1 session keys.
|
||||
- In future releases, this flag will allow des3-cbc-sha1 to be used
|
||||
- at all. The default value for this tag is false. (Added in
|
||||
- release 1.21.)
|
||||
-
|
||||
-**allow_rc4**
|
||||
- Permit the KDC to issue tickets with arcfour-hmac session keys.
|
||||
- In future releases, this flag will allow arcfour-hmac to be used
|
||||
- at all. The default value for this tag is false. (Added in
|
||||
- release 1.21.)
|
||||
-
|
||||
**allow_weak_crypto**
|
||||
If this flag is set to false, then weak encryption types (as noted
|
||||
in :ref:`Encryption_types` in :ref:`kdc.conf(5)`) will be filtered
|
||||
diff --git a/doc/admin/enctypes.rst b/doc/admin/enctypes.rst
|
||||
index dce19ad43e..694922c0d9 100644
|
||||
--- a/doc/admin/enctypes.rst
|
||||
+++ b/doc/admin/enctypes.rst
|
||||
@@ -48,15 +48,12 @@ Session key selection
|
||||
The KDC chooses the session key enctype by taking the intersection of
|
||||
its **permitted_enctypes** list, the list of long-term keys for the
|
||||
most recent kvno of the service, and the client's requested list of
|
||||
-enctypes. Starting in krb5-1.21, all services are assumed to support
|
||||
-aes256-cts-hmac-sha1-96; also, des3-cbc-sha1 and arcfour-hmac session
|
||||
-keys will not be issued by default.
|
||||
+enctypes.
|
||||
|
||||
Starting in krb5-1.11, it is possible to set a string attribute on a
|
||||
service principal to control what session key enctypes the KDC may
|
||||
-issue for service tickets for that principal, overriding the service's
|
||||
-long-term keys and the assumption of aes256-cts-hmac-sha1-96 support.
|
||||
-See :ref:`set_string` in :ref:`kadmin(1)` for details.
|
||||
+issue for service tickets for that principal. See :ref:`set_string`
|
||||
+in :ref:`kadmin(1)` for details.
|
||||
|
||||
|
||||
Choosing enctypes for a service
|
||||
@@ -90,20 +87,6 @@ affect how enctypes are chosen.
|
||||
acceptable risk for your environment and the weak enctypes are
|
||||
required for backward compatibility.
|
||||
|
||||
-**allow_des3**
|
||||
- was added in release 1.21 and defaults to *false*. Unless this
|
||||
- flag is set to *true*, the KDC will not issue tickets with
|
||||
- des3-cbc-sha1 session keys. In a future release, this flag will
|
||||
- control whether des3-cbc-sha1 is permitted in similar fashion to
|
||||
- weak enctypes.
|
||||
-
|
||||
-**allow_rc4**
|
||||
- was added in release 1.21 and defaults to *false*. Unless this
|
||||
- flag is set to *true*, the KDC will not issue tickets with
|
||||
- arcfour-hmac session keys. In a future release, this flag will
|
||||
- control whether arcfour-hmac is permitted in similar fashion to
|
||||
- weak enctypes.
|
||||
-
|
||||
**permitted_enctypes**
|
||||
controls the set of enctypes that a service will permit for
|
||||
session keys and for ticket and authenticator encryption. The KDC
|
||||
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
|
||||
index 2f7791b775..1d1c8293f4 100644
|
||||
--- a/src/include/k5-int.h
|
||||
+++ b/src/include/k5-int.h
|
||||
@@ -180,8 +180,6 @@ typedef unsigned char u_char;
|
||||
* matches the variable name. Keep these alphabetized. */
|
||||
#define KRB5_CONF_ACL_FILE "acl_file"
|
||||
#define KRB5_CONF_ADMIN_SERVER "admin_server"
|
||||
-#define KRB5_CONF_ALLOW_DES3 "allow_des3"
|
||||
-#define KRB5_CONF_ALLOW_RC4 "allow_rc4"
|
||||
#define KRB5_CONF_ALLOW_WEAK_CRYPTO "allow_weak_crypto"
|
||||
#define KRB5_CONF_AUTH_TO_LOCAL "auth_to_local"
|
||||
#define KRB5_CONF_AUTH_TO_LOCAL_NAMES "auth_to_local_names"
|
||||
@@ -1240,8 +1238,6 @@ struct _krb5_context {
|
||||
struct _kdb_log_context *kdblog_context;
|
||||
|
||||
krb5_boolean allow_weak_crypto;
|
||||
- krb5_boolean allow_des3;
|
||||
- krb5_boolean allow_rc4;
|
||||
krb5_boolean ignore_acceptor_hostname;
|
||||
krb5_boolean enforce_ok_as_delegate;
|
||||
enum dns_canonhost dns_canonicalize_hostname;
|
||||
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
|
||||
index e54cc751f9..75e04b73db 100644
|
||||
--- a/src/kdc/kdc_util.c
|
||||
+++ b/src/kdc/kdc_util.c
|
||||
@@ -1088,16 +1088,6 @@ select_session_keytype(krb5_context context, krb5_db_entry *server,
|
||||
if (!krb5_is_permitted_enctype(context, ktype[i]))
|
||||
continue;
|
||||
|
||||
- /*
|
||||
- * Prevent these deprecated enctypes from being used as session keys
|
||||
- * unless they are explicitly allowed. In the future they will be more
|
||||
- * comprehensively disabled and eventually removed.
|
||||
- */
|
||||
- if (ktype[i] == ENCTYPE_DES3_CBC_SHA1 && !context->allow_des3)
|
||||
- continue;
|
||||
- if (ktype[i] == ENCTYPE_ARCFOUR_HMAC && !context->allow_rc4)
|
||||
- continue;
|
||||
-
|
||||
if (dbentry_supports_enctype(context, server, ktype[i]))
|
||||
return ktype[i];
|
||||
}
|
||||
diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
|
||||
index ea089f0fcc..1b420a3ac2 100644
|
||||
--- a/src/lib/krb5/krb/get_in_tkt.c
|
||||
+++ b/src/lib/krb5/krb/get_in_tkt.c
|
||||
@@ -1582,31 +1582,22 @@ warn_pw_expiry(krb5_context context, krb5_get_init_creds_opt *options,
|
||||
(*prompter)(context, data, 0, banner, 0, 0);
|
||||
}
|
||||
|
||||
-/* Display a warning via the prompter if a deprecated enctype was used for
|
||||
- * either the reply key or the session key. */
|
||||
+/* Display a warning via the prompter if des3-cbc-sha1 was used for either the
|
||||
+ * reply key or the session key. */
|
||||
static void
|
||||
-warn_deprecated(krb5_context context, krb5_init_creds_context ctx,
|
||||
- krb5_enctype as_key_enctype)
|
||||
+warn_des3(krb5_context context, krb5_init_creds_context ctx,
|
||||
+ krb5_enctype as_key_enctype)
|
||||
{
|
||||
- krb5_enctype etype;
|
||||
- char encbuf[128], banner[256];
|
||||
+ const char *banner;
|
||||
|
||||
- if (ctx->prompter == NULL)
|
||||
- return;
|
||||
-
|
||||
- if (krb5int_c_deprecated_enctype(as_key_enctype))
|
||||
- etype = as_key_enctype;
|
||||
- else if (krb5int_c_deprecated_enctype(ctx->cred.keyblock.enctype))
|
||||
- etype = ctx->cred.keyblock.enctype;
|
||||
- else
|
||||
+ if (as_key_enctype != ENCTYPE_DES3_CBC_SHA1 &&
|
||||
+ ctx->cred.keyblock.enctype != ENCTYPE_DES3_CBC_SHA1)
|
||||
return;
|
||||
-
|
||||
- if (krb5_enctype_to_name(etype, FALSE, encbuf, sizeof(encbuf)) != 0)
|
||||
+ if (ctx->prompter == NULL)
|
||||
return;
|
||||
- snprintf(banner, sizeof(banner),
|
||||
- _("Warning: encryption type %s used for authentication is "
|
||||
- "deprecated and will be disabled"), encbuf);
|
||||
|
||||
+ banner = _("Warning: encryption type des3-cbc-sha1 used for "
|
||||
+ "authentication is weak and will be disabled");
|
||||
/* PROMPTER_INVOCATION */
|
||||
(*ctx->prompter)(context, ctx->prompter_data, NULL, banner, 0, NULL);
|
||||
}
|
||||
@@ -1857,7 +1848,7 @@ init_creds_step_reply(krb5_context context,
|
||||
ctx->complete = TRUE;
|
||||
warn_pw_expiry(context, ctx->opt, ctx->prompter, ctx->prompter_data,
|
||||
ctx->in_tkt_service, ctx->reply);
|
||||
- warn_deprecated(context, ctx, encrypting_key.enctype);
|
||||
+ warn_des3(context, ctx, encrypting_key.enctype);
|
||||
|
||||
cleanup:
|
||||
krb5_free_pa_data(context, kdc_padata);
|
||||
diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c
|
||||
index a6c2bbeb54..87b486c53f 100644
|
||||
--- a/src/lib/krb5/krb/init_ctx.c
|
||||
+++ b/src/lib/krb5/krb/init_ctx.c
|
||||
@@ -221,16 +221,6 @@ krb5_init_context_profile(profile_t profile, krb5_flags flags,
|
||||
goto cleanup;
|
||||
ctx->allow_weak_crypto = tmp;
|
||||
|
||||
- retval = get_boolean(ctx, KRB5_CONF_ALLOW_DES3, 0, &tmp);
|
||||
- if (retval)
|
||||
- goto cleanup;
|
||||
- ctx->allow_des3 = tmp;
|
||||
-
|
||||
- retval = get_boolean(ctx, KRB5_CONF_ALLOW_RC4, 0, &tmp);
|
||||
- if (retval)
|
||||
- goto cleanup;
|
||||
- ctx->allow_rc4 = tmp;
|
||||
-
|
||||
retval = get_boolean(ctx, KRB5_CONF_IGNORE_ACCEPTOR_HOSTNAME, 0, &tmp);
|
||||
if (retval)
|
||||
goto cleanup;
|
||||
diff --git a/src/tests/gssapi/t_enctypes.py b/src/tests/gssapi/t_enctypes.py
|
||||
index f5f11842e2..7494d7fcdb 100755
|
||||
--- a/src/tests/gssapi/t_enctypes.py
|
||||
+++ b/src/tests/gssapi/t_enctypes.py
|
||||
@@ -18,8 +18,7 @@ d_rc4 = 'DEPRECATED:arcfour-hmac'
|
||||
# These tests make assumptions about the default enctype lists, so set
|
||||
# them explicitly rather than relying on the library defaults.
|
||||
supp='aes256-cts:normal aes128-cts:normal des3-cbc-sha1:normal rc4-hmac:normal'
|
||||
-conf = {'libdefaults': {'permitted_enctypes': 'aes des3 rc4',
|
||||
- 'allow_des3': 'true', 'allow_rc4': 'true'},
|
||||
+conf = {'libdefaults': {'permitted_enctypes': 'aes des3 rc4'},
|
||||
'realms': {'$realm': {'supported_enctypes': supp}}}
|
||||
realm = K5Realm(krb5_conf=conf)
|
||||
shutil.copyfile(realm.ccache, os.path.join(realm.testdir, 'save'))
|
||||
diff --git a/src/tests/t_etype_info.py b/src/tests/t_etype_info.py
|
||||
index 38cf96ca8f..c982508d8b 100644
|
||||
--- a/src/tests/t_etype_info.py
|
||||
+++ b/src/tests/t_etype_info.py
|
||||
@@ -1,7 +1,7 @@
|
||||
from k5test import *
|
||||
|
||||
supported_enctypes = 'aes128-cts des3-cbc-sha1 rc4-hmac'
|
||||
-conf = {'libdefaults': {'allow_des3': 'true', 'allow_rc4': 'true'},
|
||||
+conf = {'libdefaults': {'allow_weak_crypto': 'true'},
|
||||
'realms': {'$realm': {'supported_enctypes': supported_enctypes}}}
|
||||
realm = K5Realm(create_host=False, get_creds=False, krb5_conf=conf)
|
||||
|
||||
diff --git a/src/tests/t_sesskeynego.py b/src/tests/t_sesskeynego.py
|
||||
index 5a213617b5..9024aee838 100755
|
||||
--- a/src/tests/t_sesskeynego.py
|
||||
+++ b/src/tests/t_sesskeynego.py
|
||||
@@ -25,8 +25,6 @@ conf3 = {'libdefaults': {
|
||||
'default_tkt_enctypes': 'aes128-cts',
|
||||
'default_tgs_enctypes': 'rc4-hmac,aes128-cts'}}
|
||||
conf4 = {'libdefaults': {'permitted_enctypes': 'aes256-cts'}}
|
||||
-conf5 = {'libdefaults': {'allow_rc4': 'true'}}
|
||||
-conf6 = {'libdefaults': {'allow_des3': 'true'}}
|
||||
# Test with client request and session_enctypes preferring aes128, but
|
||||
# aes256 long-term key.
|
||||
realm = K5Realm(krb5_conf=conf1, create_host=False, get_creds=False)
|
||||
@@ -56,12 +54,10 @@ realm.run([kadminl, 'setstr', 'server', 'session_enctypes',
|
||||
'aes128-cts,aes256-cts'])
|
||||
test_kvno(realm, 'aes128-cts-hmac-sha1-96', 'aes256-cts-hmac-sha1-96')
|
||||
|
||||
-# 3b: Skip RC4 (as the KDC does not allow it for session keys by
|
||||
-# default) and negotiate aes128-cts session key, with only an aes256
|
||||
-# long-term service key.
|
||||
+# 3b: Negotiate rc4-hmac session key when principal only has aes256 long-term.
|
||||
realm.run([kadminl, 'setstr', 'server', 'session_enctypes',
|
||||
'rc4-hmac,aes128-cts,aes256-cts'])
|
||||
-test_kvno(realm, 'aes128-cts-hmac-sha1-96', 'aes256-cts-hmac-sha1-96')
|
||||
+test_kvno(realm, 'DEPRECATED:arcfour-hmac', 'aes256-cts-hmac-sha1-96')
|
||||
realm.stop()
|
||||
|
||||
# 4: Check that permitted_enctypes is a default for session key enctypes.
|
||||
@@ -71,24 +67,4 @@ realm.run([kvno, 'user'],
|
||||
expected_trace=('etypes requested in TGS request: aes256-cts',))
|
||||
realm.stop()
|
||||
|
||||
-# 5: allow_rc4 permits negotiation of rc4-hmac session key.
|
||||
-realm = K5Realm(krb5_conf=conf5, create_host=False, get_creds=False)
|
||||
-realm.run([kadminl, 'addprinc', '-randkey', '-e', 'aes256-cts', 'server'])
|
||||
-realm.run([kadminl, 'setstr', 'server', 'session_enctypes', 'rc4-hmac'])
|
||||
-test_kvno(realm, 'DEPRECATED:arcfour-hmac', 'aes256-cts-hmac-sha1-96')
|
||||
-realm.stop()
|
||||
-
|
||||
-# 6: allow_des3 permits negotiation of des3-cbc-sha1 session key.
|
||||
-realm = K5Realm(krb5_conf=conf6, create_host=False, get_creds=False)
|
||||
-realm.run([kadminl, 'addprinc', '-randkey', '-e', 'aes256-cts', 'server'])
|
||||
-realm.run([kadminl, 'setstr', 'server', 'session_enctypes', 'des3-cbc-sha1'])
|
||||
-test_kvno(realm, 'DEPRECATED:des3-cbc-sha1', 'aes256-cts-hmac-sha1-96')
|
||||
-realm.stop()
|
||||
-
|
||||
-# 7: default config negotiates aes256-sha1 session key for RC4-only service.
|
||||
-realm = K5Realm(create_host=False, get_creds=False)
|
||||
-realm.run([kadminl, 'addprinc', '-randkey', '-e', 'rc4-hmac', 'server'])
|
||||
-test_kvno(realm, 'aes256-cts-hmac-sha1-96', 'DEPRECATED:arcfour-hmac')
|
||||
-realm.stop()
|
||||
-
|
||||
success('sesskeynego')
|
||||
diff --git a/src/util/k5test.py b/src/util/k5test.py
|
||||
index 8e5f5ba8e9..2a86c5cdfc 100644
|
||||
--- a/src/util/k5test.py
|
||||
+++ b/src/util/k5test.py
|
||||
@@ -1340,14 +1340,14 @@ _passes = [
|
||||
|
||||
# Exercise the DES3 enctype.
|
||||
('des3', None,
|
||||
- {'libdefaults': {'permitted_enctypes': 'des3 aes256-sha1'}},
|
||||
+ {'libdefaults': {'permitted_enctypes': 'des3'}},
|
||||
{'realms': {'$realm': {
|
||||
'supported_enctypes': 'des3-cbc-sha1:normal',
|
||||
'master_key_type': 'des3-cbc-sha1'}}}),
|
||||
|
||||
# Exercise the arcfour enctype.
|
||||
('arcfour', None,
|
||||
- {'libdefaults': {'permitted_enctypes': 'rc4 aes256-sha1'}},
|
||||
+ {'libdefaults': {'permitted_enctypes': 'rc4'}},
|
||||
{'realms': {'$realm': {
|
||||
'supported_enctypes': 'arcfour-hmac:normal',
|
||||
'master_key_type': 'arcfour-hmac'}}}),
|
||||
--
|
||||
2.45.1
|
||||
|
@ -0,0 +1,777 @@
|
||||
From de4205c45e310ceaaa7cd7958af7293322fa43a6 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
|
||||
|
||||
Modify ksu so that it performs account and session management on behalf of
|
||||
the target user account, mimicking the action of regular su. The default
|
||||
service name is "ksu", because on Fedora at least the configuration used
|
||||
is determined by whether or not a login shell is being opened, and so
|
||||
this may need to vary, too. At run-time, ksu's behavior can be reset to
|
||||
the earlier, non-PAM behavior by setting "use_pam" to false in the [ksu]
|
||||
section of /etc/krb5.conf.
|
||||
|
||||
When enabled, ksu gains a dependency on libpam.
|
||||
|
||||
Originally RT#5939, though it's changed since then to perform the account
|
||||
and session management before dropping privileges, and to apply on top of
|
||||
changes we're proposing for how it handles cache collections.
|
||||
|
||||
Last-updated: krb5-1.18-beta1
|
||||
---
|
||||
src/aclocal.m4 | 69 +++++++
|
||||
src/clients/ksu/Makefile.in | 8 +-
|
||||
src/clients/ksu/main.c | 88 +++++++-
|
||||
src/clients/ksu/pam.c | 389 ++++++++++++++++++++++++++++++++++++
|
||||
src/clients/ksu/pam.h | 57 ++++++
|
||||
src/configure.ac | 2 +
|
||||
6 files changed, 610 insertions(+), 3 deletions(-)
|
||||
create mode 100644 src/clients/ksu/pam.c
|
||||
create mode 100644 src/clients/ksu/pam.h
|
||||
|
||||
diff --git a/src/aclocal.m4 b/src/aclocal.m4
|
||||
index 3d66a876b3..ce3c5a9bac 100644
|
||||
--- a/src/aclocal.m4
|
||||
+++ b/src/aclocal.m4
|
||||
@@ -1458,3 +1458,72 @@ if test "$with_ldap" = yes; then
|
||||
OPENLDAP_PLUGIN=yes
|
||||
fi
|
||||
])dnl
|
||||
+dnl
|
||||
+dnl
|
||||
+dnl Use PAM instead of local crypt() compare for checking local passwords,
|
||||
+dnl and perform PAM account, session management, and password-changing where
|
||||
+dnl appropriate.
|
||||
+dnl
|
||||
+AC_DEFUN(KRB5_WITH_PAM,[
|
||||
+AC_ARG_WITH(pam,[AC_HELP_STRING(--with-pam,[compile with PAM support])],
|
||||
+ withpam="$withval",withpam=auto)
|
||||
+AC_ARG_WITH(pam-ksu-service,[AC_HELP_STRING(--with-ksu-service,[PAM service name for ksu ["ksu"]])],
|
||||
+ withksupamservice="$withval",withksupamservice=ksu)
|
||||
+old_LIBS="$LIBS"
|
||||
+if test "$withpam" != no ; then
|
||||
+ AC_MSG_RESULT([checking for PAM...])
|
||||
+ PAM_LIBS=
|
||||
+
|
||||
+ AC_CHECK_HEADERS(security/pam_appl.h)
|
||||
+ if test "x$ac_cv_header_security_pam_appl_h" != xyes ; then
|
||||
+ if test "$withpam" = auto ; then
|
||||
+ AC_MSG_RESULT([Unable to locate security/pam_appl.h.])
|
||||
+ withpam=no
|
||||
+ else
|
||||
+ AC_MSG_ERROR([Unable to locate security/pam_appl.h.])
|
||||
+ fi
|
||||
+ fi
|
||||
+
|
||||
+ LIBS=
|
||||
+ unset ac_cv_func_pam_start
|
||||
+ AC_CHECK_FUNCS(putenv pam_start)
|
||||
+ if test "x$ac_cv_func_pam_start" = xno ; then
|
||||
+ unset ac_cv_func_pam_start
|
||||
+ AC_CHECK_LIB(dl,dlopen)
|
||||
+ AC_CHECK_FUNCS(pam_start)
|
||||
+ if test "x$ac_cv_func_pam_start" = xno ; then
|
||||
+ AC_CHECK_LIB(pam,pam_start)
|
||||
+ unset ac_cv_func_pam_start
|
||||
+ unset ac_cv_func_pam_getenvlist
|
||||
+ AC_CHECK_FUNCS(pam_start pam_getenvlist)
|
||||
+ if test "x$ac_cv_func_pam_start" = xyes ; then
|
||||
+ PAM_LIBS="$LIBS"
|
||||
+ else
|
||||
+ if test "$withpam" = auto ; then
|
||||
+ AC_MSG_RESULT([Unable to locate libpam.])
|
||||
+ withpam=no
|
||||
+ else
|
||||
+ AC_MSG_ERROR([Unable to locate libpam.])
|
||||
+ fi
|
||||
+ fi
|
||||
+ fi
|
||||
+ fi
|
||||
+ if test "$withpam" != no ; then
|
||||
+ AC_MSG_NOTICE([building with PAM support])
|
||||
+ AC_DEFINE(USE_PAM,1,[Define if Kerberos-aware tools should support PAM])
|
||||
+ AC_DEFINE_UNQUOTED(KSU_PAM_SERVICE,"$withksupamservice",
|
||||
+ [Define to the name of the PAM service name to be used by ksu.])
|
||||
+ PAM_LIBS="$LIBS"
|
||||
+ NON_PAM_MAN=".\\\" "
|
||||
+ PAM_MAN=
|
||||
+ else
|
||||
+ PAM_MAN=".\\\" "
|
||||
+ NON_PAM_MAN=
|
||||
+ fi
|
||||
+fi
|
||||
+LIBS="$old_LIBS"
|
||||
+AC_SUBST(PAM_LIBS)
|
||||
+AC_SUBST(PAM_MAN)
|
||||
+AC_SUBST(NON_PAM_MAN)
|
||||
+])dnl
|
||||
+
|
||||
diff --git a/src/clients/ksu/Makefile.in b/src/clients/ksu/Makefile.in
|
||||
index 8b4edce4d8..9d58f29b5d 100644
|
||||
--- a/src/clients/ksu/Makefile.in
|
||||
+++ b/src/clients/ksu/Makefile.in
|
||||
@@ -3,12 +3,14 @@ BUILDTOP=$(REL)..$(S)..
|
||||
DEFINES = -DGET_TGT_VIA_PASSWD -DPRINC_LOOK_AHEAD -DCMD_PATH='"/usr/local/sbin /usr/local/bin /sbin /bin /usr/sbin /usr/bin"'
|
||||
|
||||
KSU_LIBS=@KSU_LIBS@
|
||||
+PAM_LIBS=@PAM_LIBS@
|
||||
|
||||
SRCS = \
|
||||
$(srcdir)/krb_auth_su.c \
|
||||
$(srcdir)/ccache.c \
|
||||
$(srcdir)/authorization.c \
|
||||
$(srcdir)/main.c \
|
||||
+ $(srcdir)/pam.c \
|
||||
$(srcdir)/heuristic.c \
|
||||
$(srcdir)/xmalloc.c \
|
||||
$(srcdir)/setenv.c
|
||||
@@ -17,13 +19,17 @@ OBJS = \
|
||||
ccache.o \
|
||||
authorization.o \
|
||||
main.o \
|
||||
+ pam.o \
|
||||
heuristic.o \
|
||||
xmalloc.o @SETENVOBJ@
|
||||
|
||||
all: ksu
|
||||
|
||||
ksu: $(OBJS) $(KRB5_BASE_DEPLIBS)
|
||||
- $(CC_LINK) -o $@ $(OBJS) $(KRB5_BASE_LIBS) $(KSU_LIBS)
|
||||
+ $(CC_LINK) -o $@ $(OBJS) $(KRB5_BASE_LIBS) $(KSU_LIBS) $(PAM_LIBS)
|
||||
+
|
||||
+pam.o: pam.c
|
||||
+ $(CC) $(ALL_CFLAGS) -c $<
|
||||
|
||||
clean:
|
||||
$(RM) ksu
|
||||
diff --git a/src/clients/ksu/main.c b/src/clients/ksu/main.c
|
||||
index af12861729..931f054041 100644
|
||||
--- a/src/clients/ksu/main.c
|
||||
+++ b/src/clients/ksu/main.c
|
||||
@@ -26,6 +26,7 @@
|
||||
* KSU was written by: Ari Medvinsky, ari@isi.edu
|
||||
*/
|
||||
|
||||
+#include "autoconf.h"
|
||||
#include "ksu.h"
|
||||
#include "adm_proto.h"
|
||||
#include <sys/types.h>
|
||||
@@ -33,6 +34,10 @@
|
||||
#include <signal.h>
|
||||
#include <grp.h>
|
||||
|
||||
+#ifdef USE_PAM
|
||||
+#include "pam.h"
|
||||
+#endif
|
||||
+
|
||||
/* globals */
|
||||
char * prog_name;
|
||||
int auth_debug =0;
|
||||
@@ -40,6 +45,7 @@ char k5login_path[MAXPATHLEN];
|
||||
char k5users_path[MAXPATHLEN];
|
||||
char * gb_err = NULL;
|
||||
int quiet = 0;
|
||||
+int force_fork = 0;
|
||||
/***********/
|
||||
|
||||
#define KS_TEMPORARY_CACHE "MEMORY:_ksu"
|
||||
@@ -536,6 +542,23 @@ main (argc, argv)
|
||||
prog_name,target_user,client_name,
|
||||
source_user,ontty());
|
||||
|
||||
+#ifdef USE_PAM
|
||||
+ if (appl_pam_enabled(ksu_context, "ksu")) {
|
||||
+ if (appl_pam_acct_mgmt(KSU_PAM_SERVICE, 1, target_user, NULL,
|
||||
+ NULL, source_user,
|
||||
+ ttyname(STDERR_FILENO)) != 0) {
|
||||
+ fprintf(stderr, "Access denied for %s.\n", target_user);
|
||||
+ exit(1);
|
||||
+ }
|
||||
+ if (appl_pam_requires_chauthtok()) {
|
||||
+ fprintf(stderr, "Password change required for %s.\n",
|
||||
+ target_user);
|
||||
+ exit(1);
|
||||
+ }
|
||||
+ force_fork++;
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
/* Run authorization as target.*/
|
||||
if (krb5_seteuid(target_uid)) {
|
||||
com_err(prog_name, errno, _("while switching to target for "
|
||||
@@ -596,6 +619,24 @@ main (argc, argv)
|
||||
|
||||
exit(1);
|
||||
}
|
||||
+#ifdef USE_PAM
|
||||
+ } else {
|
||||
+ /* we always do PAM account management, even for root */
|
||||
+ if (appl_pam_enabled(ksu_context, "ksu")) {
|
||||
+ if (appl_pam_acct_mgmt(KSU_PAM_SERVICE, 1, target_user, NULL,
|
||||
+ NULL, source_user,
|
||||
+ ttyname(STDERR_FILENO)) != 0) {
|
||||
+ fprintf(stderr, "Access denied for %s.\n", target_user);
|
||||
+ exit(1);
|
||||
+ }
|
||||
+ if (appl_pam_requires_chauthtok()) {
|
||||
+ fprintf(stderr, "Password change required for %s.\n",
|
||||
+ target_user);
|
||||
+ exit(1);
|
||||
+ }
|
||||
+ force_fork++;
|
||||
+ }
|
||||
+#endif
|
||||
}
|
||||
|
||||
if( some_rest_copy){
|
||||
@@ -653,6 +694,30 @@ main (argc, argv)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
+#ifdef USE_PAM
|
||||
+ if (appl_pam_enabled(ksu_context, "ksu")) {
|
||||
+ if (appl_pam_session_open() != 0) {
|
||||
+ fprintf(stderr, "Error opening session for %s.\n", target_user);
|
||||
+ exit(1);
|
||||
+ }
|
||||
+#ifdef DEBUG
|
||||
+ if (auth_debug){
|
||||
+ printf(" Opened PAM session.\n");
|
||||
+ }
|
||||
+#endif
|
||||
+ if (appl_pam_cred_init()) {
|
||||
+ fprintf(stderr, "Error initializing credentials for %s.\n",
|
||||
+ target_user);
|
||||
+ exit(1);
|
||||
+ }
|
||||
+#ifdef DEBUG
|
||||
+ if (auth_debug){
|
||||
+ printf(" Initialized PAM credentials.\n");
|
||||
+ }
|
||||
+#endif
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
/* set permissions */
|
||||
if (setgid(target_pwd->pw_gid) < 0) {
|
||||
perror("ksu: setgid");
|
||||
@@ -750,7 +815,7 @@ main (argc, argv)
|
||||
fprintf(stderr, "program to be execed %s\n",params[0]);
|
||||
}
|
||||
|
||||
- if( keep_target_cache ) {
|
||||
+ if( keep_target_cache && !force_fork ) {
|
||||
execv(params[0], params);
|
||||
com_err(prog_name, errno, _("while trying to execv %s"), params[0]);
|
||||
sweep_up(ksu_context, cc_target);
|
||||
@@ -780,16 +845,35 @@ main (argc, argv)
|
||||
if (ret_pid == -1) {
|
||||
com_err(prog_name, errno, _("while calling waitpid"));
|
||||
}
|
||||
- sweep_up(ksu_context, cc_target);
|
||||
+ if( !keep_target_cache ) {
|
||||
+ sweep_up(ksu_context, cc_target);
|
||||
+ }
|
||||
exit (statusp);
|
||||
case -1:
|
||||
com_err(prog_name, errno, _("while trying to fork."));
|
||||
sweep_up(ksu_context, cc_target);
|
||||
exit (1);
|
||||
case 0:
|
||||
+#ifdef USE_PAM
|
||||
+ if (appl_pam_enabled(ksu_context, "ksu")) {
|
||||
+ if (appl_pam_setenv() != 0) {
|
||||
+ fprintf(stderr, "Error setting up environment for %s.\n",
|
||||
+ target_user);
|
||||
+ exit (1);
|
||||
+ }
|
||||
+#ifdef DEBUG
|
||||
+ if (auth_debug){
|
||||
+ printf(" Set up PAM environment.\n");
|
||||
+ }
|
||||
+#endif
|
||||
+ }
|
||||
+#endif
|
||||
execv(params[0], params);
|
||||
com_err(prog_name, errno, _("while trying to execv %s"),
|
||||
params[0]);
|
||||
+ if( keep_target_cache ) {
|
||||
+ sweep_up(ksu_context, cc_target);
|
||||
+ }
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
diff --git a/src/clients/ksu/pam.c b/src/clients/ksu/pam.c
|
||||
new file mode 100644
|
||||
index 0000000000..cbfe487047
|
||||
--- /dev/null
|
||||
+++ b/src/clients/ksu/pam.c
|
||||
@@ -0,0 +1,389 @@
|
||||
+/*
|
||||
+ * src/clients/ksu/pam.c
|
||||
+ *
|
||||
+ * Copyright 2007,2009,2010 Red Hat, Inc.
|
||||
+ *
|
||||
+ * All Rights Reserved.
|
||||
+ *
|
||||
+ * Redistribution and use in source and binary forms, with or without
|
||||
+ * modification, are permitted provided that the following conditions are met:
|
||||
+ *
|
||||
+ * Redistributions of source code must retain the above copyright notice, this
|
||||
+ * list of conditions and the following disclaimer.
|
||||
+ *
|
||||
+ * Redistributions in binary form must reproduce the above copyright notice,
|
||||
+ * this list of conditions and the following disclaimer in the documentation
|
||||
+ * and/or other materials provided with the distribution.
|
||||
+ *
|
||||
+ * Neither the name of Red Hat, Inc. nor the names of its contributors may be
|
||||
+ * used to endorse or promote products derived from this software without
|
||||
+ * specific prior written permission.
|
||||
+ *
|
||||
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
+ * POSSIBILITY OF SUCH DAMAGE.
|
||||
+ *
|
||||
+ * Convenience wrappers for using PAM.
|
||||
+ */
|
||||
+
|
||||
+#include "autoconf.h"
|
||||
+#ifdef USE_PAM
|
||||
+#include <sys/types.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <unistd.h>
|
||||
+#include "k5-int.h"
|
||||
+#include "pam.h"
|
||||
+
|
||||
+#ifndef MAXPWSIZE
|
||||
+#define MAXPWSIZE 128
|
||||
+#endif
|
||||
+
|
||||
+static int appl_pam_started;
|
||||
+static pid_t appl_pam_starter = -1;
|
||||
+static int appl_pam_session_opened;
|
||||
+static int appl_pam_creds_initialized;
|
||||
+static int appl_pam_pwchange_required;
|
||||
+static pam_handle_t *appl_pamh;
|
||||
+static struct pam_conv appl_pam_conv;
|
||||
+static char *appl_pam_user;
|
||||
+struct appl_pam_non_interactive_args {
|
||||
+ const char *user;
|
||||
+ const char *password;
|
||||
+};
|
||||
+
|
||||
+int
|
||||
+appl_pam_enabled(krb5_context context, const char *section)
|
||||
+{
|
||||
+ int enabled = 1;
|
||||
+ if ((context != NULL) && (context->profile != NULL)) {
|
||||
+ if (profile_get_boolean(context->profile,
|
||||
+ section,
|
||||
+ USE_PAM_CONFIGURATION_KEYWORD,
|
||||
+ NULL,
|
||||
+ enabled, &enabled) != 0) {
|
||||
+ enabled = 1;
|
||||
+ }
|
||||
+ }
|
||||
+ return enabled;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+appl_pam_cleanup(void)
|
||||
+{
|
||||
+ if (getpid() != appl_pam_starter) {
|
||||
+ return;
|
||||
+ }
|
||||
+#ifdef DEBUG
|
||||
+ printf("Called to clean up PAM.\n");
|
||||
+#endif
|
||||
+ if (appl_pam_creds_initialized) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("Deleting PAM credentials.\n");
|
||||
+#endif
|
||||
+ pam_setcred(appl_pamh, PAM_DELETE_CRED);
|
||||
+ appl_pam_creds_initialized = 0;
|
||||
+ }
|
||||
+ if (appl_pam_session_opened) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("Closing PAM session.\n");
|
||||
+#endif
|
||||
+ pam_close_session(appl_pamh, 0);
|
||||
+ appl_pam_session_opened = 0;
|
||||
+ }
|
||||
+ appl_pam_pwchange_required = 0;
|
||||
+ if (appl_pam_started) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("Shutting down PAM.\n");
|
||||
+#endif
|
||||
+ pam_end(appl_pamh, 0);
|
||||
+ appl_pam_started = 0;
|
||||
+ appl_pam_starter = -1;
|
||||
+ free(appl_pam_user);
|
||||
+ appl_pam_user = NULL;
|
||||
+ }
|
||||
+}
|
||||
+static int
|
||||
+appl_pam_interactive_converse(int num_msg, const struct pam_message **msg,
|
||||
+ struct pam_response **presp, void *appdata_ptr)
|
||||
+{
|
||||
+ const struct pam_message *message;
|
||||
+ struct pam_response *resp;
|
||||
+ int i, code;
|
||||
+ char *pwstring, pwbuf[MAXPWSIZE];
|
||||
+ unsigned int pwsize;
|
||||
+ resp = malloc(sizeof(struct pam_response) * num_msg);
|
||||
+ if (resp == NULL) {
|
||||
+ return PAM_BUF_ERR;
|
||||
+ }
|
||||
+ memset(resp, 0, sizeof(struct pam_response) * num_msg);
|
||||
+ code = PAM_SUCCESS;
|
||||
+ for (i = 0; i < num_msg; i++) {
|
||||
+ message = &(msg[0][i]); /* XXX */
|
||||
+ message = msg[i]; /* XXX */
|
||||
+ pwstring = NULL;
|
||||
+ switch (message->msg_style) {
|
||||
+ case PAM_TEXT_INFO:
|
||||
+ case PAM_ERROR_MSG:
|
||||
+ printf("[%s]\n", message->msg ? message->msg : "");
|
||||
+ fflush(stdout);
|
||||
+ resp[i].resp = NULL;
|
||||
+ resp[i].resp_retcode = PAM_SUCCESS;
|
||||
+ break;
|
||||
+ case PAM_PROMPT_ECHO_ON:
|
||||
+ case PAM_PROMPT_ECHO_OFF:
|
||||
+ if (message->msg_style == PAM_PROMPT_ECHO_ON) {
|
||||
+ if (fgets(pwbuf, sizeof(pwbuf),
|
||||
+ stdin) != NULL) {
|
||||
+ pwbuf[strcspn(pwbuf, "\r\n")] = '\0';
|
||||
+ pwstring = pwbuf;
|
||||
+ }
|
||||
+ } else {
|
||||
+ pwstring = getpass(message->msg ?
|
||||
+ message->msg :
|
||||
+ "");
|
||||
+ }
|
||||
+ if ((pwstring != NULL) && (pwstring[0] != '\0')) {
|
||||
+ pwsize = strlen(pwstring);
|
||||
+ resp[i].resp = malloc(pwsize + 1);
|
||||
+ if (resp[i].resp == NULL) {
|
||||
+ resp[i].resp_retcode = PAM_BUF_ERR;
|
||||
+ } else {
|
||||
+ memcpy(resp[i].resp, pwstring, pwsize);
|
||||
+ resp[i].resp[pwsize] = '\0';
|
||||
+ resp[i].resp_retcode = PAM_SUCCESS;
|
||||
+ }
|
||||
+ } else {
|
||||
+ resp[i].resp_retcode = PAM_CONV_ERR;
|
||||
+ code = PAM_CONV_ERR;
|
||||
+ }
|
||||
+ break;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ *presp = resp;
|
||||
+ return code;
|
||||
+}
|
||||
+static int
|
||||
+appl_pam_non_interactive_converse(int num_msg,
|
||||
+ const struct pam_message **msg,
|
||||
+ struct pam_response **presp,
|
||||
+ void *appdata_ptr)
|
||||
+{
|
||||
+ const struct pam_message *message;
|
||||
+ struct pam_response *resp;
|
||||
+ int i, code;
|
||||
+ unsigned int pwsize;
|
||||
+ struct appl_pam_non_interactive_args *args;
|
||||
+ const char *pwstring;
|
||||
+ resp = malloc(sizeof(struct pam_response) * num_msg);
|
||||
+ if (resp == NULL) {
|
||||
+ return PAM_BUF_ERR;
|
||||
+ }
|
||||
+ args = appdata_ptr;
|
||||
+ memset(resp, 0, sizeof(struct pam_response) * num_msg);
|
||||
+ code = PAM_SUCCESS;
|
||||
+ for (i = 0; i < num_msg; i++) {
|
||||
+ message = &((*msg)[i]);
|
||||
+ message = msg[i];
|
||||
+ pwstring = NULL;
|
||||
+ switch (message->msg_style) {
|
||||
+ case PAM_TEXT_INFO:
|
||||
+ case PAM_ERROR_MSG:
|
||||
+ break;
|
||||
+ case PAM_PROMPT_ECHO_ON:
|
||||
+ case PAM_PROMPT_ECHO_OFF:
|
||||
+ if (message->msg_style == PAM_PROMPT_ECHO_ON) {
|
||||
+ /* assume "user" */
|
||||
+ pwstring = args->user;
|
||||
+ } else {
|
||||
+ /* assume "password" */
|
||||
+ pwstring = args->password;
|
||||
+ }
|
||||
+ if ((pwstring != NULL) && (pwstring[0] != '\0')) {
|
||||
+ pwsize = strlen(pwstring);
|
||||
+ resp[i].resp = malloc(pwsize + 1);
|
||||
+ if (resp[i].resp == NULL) {
|
||||
+ resp[i].resp_retcode = PAM_BUF_ERR;
|
||||
+ } else {
|
||||
+ memcpy(resp[i].resp, pwstring, pwsize);
|
||||
+ resp[i].resp[pwsize] = '\0';
|
||||
+ resp[i].resp_retcode = PAM_SUCCESS;
|
||||
+ }
|
||||
+ } else {
|
||||
+ resp[i].resp_retcode = PAM_CONV_ERR;
|
||||
+ code = PAM_CONV_ERR;
|
||||
+ }
|
||||
+ break;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ *presp = resp;
|
||||
+ return code;
|
||||
+}
|
||||
+static int
|
||||
+appl_pam_start(const char *service, int interactive,
|
||||
+ const char *login_username,
|
||||
+ const char *non_interactive_password,
|
||||
+ const char *hostname,
|
||||
+ const char *ruser,
|
||||
+ const char *tty)
|
||||
+{
|
||||
+ static int exit_handler_registered;
|
||||
+ static struct appl_pam_non_interactive_args args;
|
||||
+ int ret = 0;
|
||||
+ if (appl_pam_started &&
|
||||
+ (strcmp(login_username, appl_pam_user) != 0)) {
|
||||
+ appl_pam_cleanup();
|
||||
+ appl_pam_user = NULL;
|
||||
+ }
|
||||
+ if (!appl_pam_started) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("Starting PAM up (service=\"%s\",user=\"%s\").\n",
|
||||
+ service, login_username);
|
||||
+#endif
|
||||
+ memset(&appl_pam_conv, 0, sizeof(appl_pam_conv));
|
||||
+ appl_pam_conv.conv = interactive ?
|
||||
+ &appl_pam_interactive_converse :
|
||||
+ &appl_pam_non_interactive_converse;
|
||||
+ memset(&args, 0, sizeof(args));
|
||||
+ args.user = strdup(login_username);
|
||||
+ args.password = non_interactive_password ?
|
||||
+ strdup(non_interactive_password) :
|
||||
+ NULL;
|
||||
+ appl_pam_conv.appdata_ptr = &args;
|
||||
+ ret = pam_start(service, login_username,
|
||||
+ &appl_pam_conv, &appl_pamh);
|
||||
+ if (ret == 0) {
|
||||
+ if (hostname != NULL) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("Setting PAM_RHOST to \"%s\".\n", hostname);
|
||||
+#endif
|
||||
+ pam_set_item(appl_pamh, PAM_RHOST, hostname);
|
||||
+ }
|
||||
+ if (ruser != NULL) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("Setting PAM_RUSER to \"%s\".\n", ruser);
|
||||
+#endif
|
||||
+ pam_set_item(appl_pamh, PAM_RUSER, ruser);
|
||||
+ }
|
||||
+ if (tty != NULL) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("Setting PAM_TTY to \"%s\".\n", tty);
|
||||
+#endif
|
||||
+ pam_set_item(appl_pamh, PAM_TTY, tty);
|
||||
+ }
|
||||
+ if (!exit_handler_registered &&
|
||||
+ (atexit(appl_pam_cleanup) != 0)) {
|
||||
+ pam_end(appl_pamh, 0);
|
||||
+ appl_pamh = NULL;
|
||||
+ ret = -1;
|
||||
+ } else {
|
||||
+ appl_pam_started = 1;
|
||||
+ appl_pam_starter = getpid();
|
||||
+ appl_pam_user = strdup(login_username);
|
||||
+ exit_handler_registered = 1;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+int
|
||||
+appl_pam_acct_mgmt(const char *service, int interactive,
|
||||
+ const char *login_username,
|
||||
+ const char *non_interactive_password,
|
||||
+ const char *hostname,
|
||||
+ const char *ruser,
|
||||
+ const char *tty)
|
||||
+{
|
||||
+ int ret;
|
||||
+ appl_pam_pwchange_required = 0;
|
||||
+ ret = appl_pam_start(service, interactive, login_username,
|
||||
+ non_interactive_password, hostname, ruser, tty);
|
||||
+ if (ret == 0) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("Calling pam_acct_mgmt().\n");
|
||||
+#endif
|
||||
+ ret = pam_acct_mgmt(appl_pamh, 0);
|
||||
+ switch (ret) {
|
||||
+ case PAM_IGNORE:
|
||||
+ ret = 0;
|
||||
+ break;
|
||||
+ case PAM_NEW_AUTHTOK_REQD:
|
||||
+ appl_pam_pwchange_required = 1;
|
||||
+ ret = 0;
|
||||
+ break;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+int
|
||||
+appl_pam_requires_chauthtok(void)
|
||||
+{
|
||||
+ return appl_pam_pwchange_required;
|
||||
+}
|
||||
+int
|
||||
+appl_pam_session_open(void)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+ if (appl_pam_started) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("Opening PAM session.\n");
|
||||
+#endif
|
||||
+ ret = pam_open_session(appl_pamh, 0);
|
||||
+ if (ret == 0) {
|
||||
+ appl_pam_session_opened = 1;
|
||||
+ }
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+int
|
||||
+appl_pam_setenv(void)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+#ifdef HAVE_PAM_GETENVLIST
|
||||
+#ifdef HAVE_PUTENV
|
||||
+ int i;
|
||||
+ char **list;
|
||||
+ if (appl_pam_started) {
|
||||
+ list = pam_getenvlist(appl_pamh);
|
||||
+ for (i = 0; ((list != NULL) && (list[i] != NULL)); i++) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("Setting \"%s\" in environment.\n", list[i]);
|
||||
+#endif
|
||||
+ putenv(list[i]);
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
+#endif
|
||||
+ return ret;
|
||||
+}
|
||||
+int
|
||||
+appl_pam_cred_init(void)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+ if (appl_pam_started) {
|
||||
+#ifdef DEBUG
|
||||
+ printf("Initializing PAM credentials.\n");
|
||||
+#endif
|
||||
+ ret = pam_setcred(appl_pamh, PAM_ESTABLISH_CRED);
|
||||
+ if (ret == 0) {
|
||||
+ appl_pam_creds_initialized = 1;
|
||||
+ }
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+#endif
|
||||
diff --git a/src/clients/ksu/pam.h b/src/clients/ksu/pam.h
|
||||
new file mode 100644
|
||||
index 0000000000..0ab76569cb
|
||||
--- /dev/null
|
||||
+++ b/src/clients/ksu/pam.h
|
||||
@@ -0,0 +1,57 @@
|
||||
+/*
|
||||
+ * src/clients/ksu/pam.h
|
||||
+ *
|
||||
+ * Copyright 2007,2009,2010 Red Hat, Inc.
|
||||
+ *
|
||||
+ * All Rights Reserved.
|
||||
+ *
|
||||
+ * Redistribution and use in source and binary forms, with or without
|
||||
+ * modification, are permitted provided that the following conditions are met:
|
||||
+ *
|
||||
+ * Redistributions of source code must retain the above copyright notice, this
|
||||
+ * list of conditions and the following disclaimer.
|
||||
+ *
|
||||
+ * Redistributions in binary form must reproduce the above copyright notice,
|
||||
+ * this list of conditions and the following disclaimer in the documentation
|
||||
+ * and/or other materials provided with the distribution.
|
||||
+ *
|
||||
+ * Neither the name of Red Hat, Inc. nor the names of its contributors may be
|
||||
+ * used to endorse or promote products derived from this software without
|
||||
+ * specific prior written permission.
|
||||
+ *
|
||||
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
+ * POSSIBILITY OF SUCH DAMAGE.
|
||||
+ *
|
||||
+ * Convenience wrappers for using PAM.
|
||||
+ */
|
||||
+
|
||||
+#include <krb5.h>
|
||||
+#ifdef HAVE_SECURITY_PAM_APPL_H
|
||||
+#include <security/pam_appl.h>
|
||||
+#endif
|
||||
+
|
||||
+#define USE_PAM_CONFIGURATION_KEYWORD "use_pam"
|
||||
+
|
||||
+#ifdef USE_PAM
|
||||
+int appl_pam_enabled(krb5_context context, const char *section);
|
||||
+int appl_pam_acct_mgmt(const char *service, int interactive,
|
||||
+ const char *local_username,
|
||||
+ const char *non_interactive_password,
|
||||
+ const char *hostname,
|
||||
+ const char *ruser,
|
||||
+ const char *tty);
|
||||
+int appl_pam_requires_chauthtok(void);
|
||||
+int appl_pam_session_open(void);
|
||||
+int appl_pam_setenv(void);
|
||||
+int appl_pam_cred_init(void);
|
||||
+void appl_pam_cleanup(void);
|
||||
+#endif
|
||||
diff --git a/src/configure.ac b/src/configure.ac
|
||||
index 77be7a2025..587221936e 100644
|
||||
--- a/src/configure.ac
|
||||
+++ b/src/configure.ac
|
||||
@@ -1399,6 +1399,8 @@ AC_SUBST([VERTO_VERSION])
|
||||
|
||||
AC_PATH_PROG(GROFF, groff)
|
||||
|
||||
+KRB5_WITH_PAM
|
||||
+
|
||||
# Make localedir work in autoconf 2.5x.
|
||||
if test "${localedir+set}" != set; then
|
||||
localedir='$(datadir)/locale'
|
||||
--
|
||||
2.45.1
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,44 @@
|
||||
From 393830d96000ed692aa9a99ef87187d6f2863931 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
|
||||
|
||||
We want to keep these y.tab.c files around because the debuginfo points to
|
||||
them. It would be more elegant at the end to use symbolic links, but that
|
||||
could mess up people working in the tree on other things.
|
||||
|
||||
Last-updated: krb5-1.9
|
||||
---
|
||||
src/kadmin/cli/Makefile.in | 5 +++++
|
||||
src/plugins/kdb/ldap/ldap_util/Makefile.in | 2 +-
|
||||
2 files changed, 6 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/kadmin/cli/Makefile.in b/src/kadmin/cli/Makefile.in
|
||||
index adfea6e2b5..d1327e400b 100644
|
||||
--- a/src/kadmin/cli/Makefile.in
|
||||
+++ b/src/kadmin/cli/Makefile.in
|
||||
@@ -37,3 +37,8 @@ clean-unix::
|
||||
# CC_LINK is not meant for compilation and this use may break in the future.
|
||||
datetest: getdate.c
|
||||
$(CC_LINK) $(ALL_CFLAGS) -DTEST -o datetest getdate.c
|
||||
+
|
||||
+%.c: %.y
|
||||
+ $(RM) y.tab.c $@
|
||||
+ $(YACC.y) $<
|
||||
+ $(CP) y.tab.c $@
|
||||
diff --git a/src/plugins/kdb/ldap/ldap_util/Makefile.in b/src/plugins/kdb/ldap/ldap_util/Makefile.in
|
||||
index 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)
|
||||
getdate.c: $(GETDATE)
|
||||
$(RM) getdate.c y.tab.c
|
||||
$(YACC) $(GETDATE)
|
||||
- $(MV) y.tab.c getdate.c
|
||||
+ $(CP) y.tab.c getdate.c
|
||||
|
||||
install:
|
||||
$(INSTALL_PROGRAM) $(PROG) ${DESTDIR}$(ADMIN_BINDIR)/$(PROG)
|
||||
--
|
||||
2.45.1
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,612 @@
|
||||
From 7b6453903c248a761d3ceb538dfacebbf3d3a9ff Mon Sep 17 00:00:00 2001
|
||||
From: Robbie Harwood <rharwood@redhat.com>
|
||||
Date: Fri, 9 Nov 2018 15:12:21 -0500
|
||||
Subject: [PATCH] [downstream] FIPS with PRNG and RADIUS and MD4
|
||||
|
||||
NB: Use openssl's PRNG in FIPS mode and taint within krad.
|
||||
|
||||
A lot of the FIPS error conditions from OpenSSL are incredibly
|
||||
mysterious (at best, things return NULL unexpectedly; at worst,
|
||||
internal assertions are tripped; most of the time, you just get
|
||||
ENOMEM). In order to cope with this, we need to have some level of
|
||||
awareness of what we can and can't safely call.
|
||||
|
||||
This will slow down some calls slightly (FIPS_mode() takes multiple
|
||||
locks), but not for any ciphers we care about - which is to say that
|
||||
AES is fine. Shame about SPAKE though.
|
||||
|
||||
post6 restores MD4 (and therefore keygen-only RC4).
|
||||
|
||||
post7 restores MD5 and adds radius_md5_fips_override.
|
||||
|
||||
post8 silences a static analyzer warning.
|
||||
|
||||
Last-updated: krb5-1.20
|
||||
---
|
||||
doc/admin/conf_files/krb5_conf.rst | 6 +++
|
||||
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 +++++
|
||||
src/lib/crypto/openssl/hmac.c | 6 ++-
|
||||
src/lib/krad/attr.c | 46 ++++++++++++++-----
|
||||
src/lib/krad/attrset.c | 5 +-
|
||||
src/lib/krad/internal.h | 28 ++++++++++-
|
||||
src/lib/krad/packet.c | 22 +++++----
|
||||
src/lib/krad/remote.c | 10 +++-
|
||||
src/lib/krad/t_attr.c | 3 +-
|
||||
src/lib/krad/t_attrset.c | 4 +-
|
||||
src/plugins/preauth/spake/spake_client.c | 6 +++
|
||||
src/plugins/preauth/spake/spake_kdc.c | 6 +++
|
||||
15 files changed, 155 insertions(+), 33 deletions(-)
|
||||
|
||||
diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
|
||||
index f22d5db11b..a33711d918 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:
|
||||
qualification of shortnames, set this relation to the empty string
|
||||
with ``qualify_shortname = ""``. (New in release 1.18.)
|
||||
|
||||
+**radius_md5_fips_override**
|
||||
+ Downstream-only option to enable use of MD5 in RADIUS
|
||||
+ communication (libkrad). This allows for local (or protected
|
||||
+ tunnel) communication with a RADIUS server that doesn't use krad
|
||||
+ (e.g., freeradius) while in FIPS mode.
|
||||
+
|
||||
**rdns**
|
||||
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 d6b79e2dea..9e80a03d21 100644
|
||||
--- a/src/lib/crypto/krb/prng.c
|
||||
+++ b/src/lib/crypto/krb/prng.c
|
||||
@@ -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)
|
||||
{
|
||||
@@ -96,9 +102,16 @@ cleanup:
|
||||
static krb5_boolean
|
||||
get_os_entropy(unsigned char *buf, size_t len)
|
||||
{
|
||||
-#if defined(__linux__) && defined(SYS_getrandom)
|
||||
int r;
|
||||
|
||||
+ /* A wild FIPS mode appeared! */
|
||||
+ if (FIPS_mode()) {
|
||||
+ /* The return codes on this API are not good */
|
||||
+ r = RAND_bytes(buf, len);
|
||||
+ return r == 1;
|
||||
+ }
|
||||
+
|
||||
+#if defined(__linux__) && defined(SYS_getrandom)
|
||||
while (len > 0) {
|
||||
/*
|
||||
* 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 01920e6ce1..d9f327add6 100644
|
||||
--- a/src/lib/crypto/openssl/enc_provider/camellia.c
|
||||
+++ b/src/lib/crypto/openssl/enc_provider/camellia.c
|
||||
@@ -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;
|
||||
|
||||
+ if (FIPS_mode())
|
||||
+ return KRB5_CRYPTO_INTERNAL;
|
||||
+
|
||||
if (output->length < CAMELLIA_BLOCK_SIZE)
|
||||
return KRB5_BAD_MSIZE;
|
||||
|
||||
@@ -418,6 +421,9 @@ static krb5_error_code
|
||||
krb5int_camellia_init_state (const krb5_keyblock *key, krb5_keyusage usage,
|
||||
krb5_data *state)
|
||||
{
|
||||
+ if (FIPS_mode())
|
||||
+ return KRB5_CRYPTO_INTERNAL;
|
||||
+
|
||||
state->length = 16;
|
||||
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 448d563348..ce63cb5f1b 100644
|
||||
--- a/src/lib/crypto/openssl/enc_provider/rc4.c
|
||||
+++ b/src/lib/crypto/openssl/enc_provider/rc4.c
|
||||
@@ -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;
|
||||
|
||||
+ if (FIPS_mode())
|
||||
+ return KRB5_CRYPTO_INTERNAL;
|
||||
+
|
||||
arcstate = (state != NULL) ? (void *)state->data : NULL;
|
||||
if (arcstate != NULL) {
|
||||
ctx = arcstate->ctx;
|
||||
@@ -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)
|
||||
{
|
||||
- struct arcfour_state *arcstate = (void *)state->data;
|
||||
+ struct arcfour_state *arcstate;
|
||||
+
|
||||
+ if (FIPS_mode())
|
||||
+ return;
|
||||
+
|
||||
+ arcstate = (void *) state->data;
|
||||
|
||||
EVP_CIPHER_CTX_free(arcstate->ctx);
|
||||
free(arcstate);
|
||||
@@ -128,6 +136,9 @@ k5_arcfour_init_state(const krb5_keyblock *key,
|
||||
{
|
||||
struct arcfour_state *arcstate;
|
||||
|
||||
+ if (FIPS_mode())
|
||||
+ return KRB5_CRYPTO_INTERNAL;
|
||||
+
|
||||
/*
|
||||
* 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 f2fbffdb29..11659908bb 100644
|
||||
--- a/src/lib/crypto/openssl/hash_provider/hash_evp.c
|
||||
+++ b/src/lib/crypto/openssl/hash_provider/hash_evp.c
|
||||
@@ -60,6 +60,11 @@ hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data,
|
||||
if (ctx == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
+ if (type == EVP_md4() || type == EVP_md5()) {
|
||||
+ /* See comments below in hash_md4() and hash_md5(). */
|
||||
+ EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
|
||||
+ }
|
||||
+
|
||||
ok = EVP_DigestInit_ex(ctx, type, NULL);
|
||||
for (i = 0; i < num_data; i++) {
|
||||
if (!SIGN_IOV(&data[i]))
|
||||
@@ -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)
|
||||
{
|
||||
+ /*
|
||||
+ * MD4 is needed in FIPS mode to perform key generation for RC4 keys used
|
||||
+ * by IPA. These keys are only used along a (separately) secured channel
|
||||
+ * for legacy reasons when performing trusts to Active Directory.
|
||||
+ */
|
||||
return 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)
|
||||
{
|
||||
+ /* MD5 is needed in FIPS mode for communication with RADIUS servers. This
|
||||
+ * is gated in libkrad by libdefaults->radius_md5_fips_override. */
|
||||
return hash_evp(EVP_md5(), data, num_data, output);
|
||||
}
|
||||
|
||||
diff --git a/src/lib/crypto/openssl/hmac.c b/src/lib/crypto/openssl/hmac.c
|
||||
index bf12b8d6a0..f21e268f7f 100644
|
||||
--- a/src/lib/crypto/openssl/hmac.c
|
||||
+++ b/src/lib/crypto/openssl/hmac.c
|
||||
@@ -111,7 +111,11 @@ map_digest(const struct krb5_hash_provider *hash)
|
||||
return EVP_sha256();
|
||||
else if (hash == &krb5int_hash_sha384)
|
||||
return EVP_sha384();
|
||||
- else if (hash == &krb5int_hash_md5)
|
||||
+
|
||||
+ if (FIPS_mode())
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (hash == &krb5int_hash_md5)
|
||||
return EVP_md5();
|
||||
else if (hash == &krb5int_hash_md4)
|
||||
return EVP_md4();
|
||||
diff --git a/src/lib/krad/attr.c b/src/lib/krad/attr.c
|
||||
index 9c13d9d755..42d354a3b5 100644
|
||||
--- a/src/lib/krad/attr.c
|
||||
+++ b/src/lib/krad/attr.c
|
||||
@@ -38,7 +38,8 @@
|
||||
typedef krb5_error_code
|
||||
(*attribute_transform_fn)(krb5_context ctx, const char *secret,
|
||||
const unsigned char *auth, const krb5_data *in,
|
||||
- unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen);
|
||||
+ unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
|
||||
+ krb5_boolean *is_fips);
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
@@ -51,12 +52,14 @@ typedef struct {
|
||||
static krb5_error_code
|
||||
user_password_encode(krb5_context ctx, const char *secret,
|
||||
const unsigned char *auth, const krb5_data *in,
|
||||
- unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen);
|
||||
+ unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
|
||||
+ krb5_boolean *is_fips);
|
||||
|
||||
static krb5_error_code
|
||||
user_password_decode(krb5_context ctx, const char *secret,
|
||||
const unsigned char *auth, const krb5_data *in,
|
||||
- unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen);
|
||||
+ unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
|
||||
+ krb5_boolean *ignored);
|
||||
|
||||
static const attribute_record attributes[UCHAR_MAX] = {
|
||||
{"User-Name", 1, MAX_ATTRSIZE, NULL, NULL},
|
||||
@@ -128,7 +131,8 @@ static const attribute_record attributes[UCHAR_MAX] = {
|
||||
static krb5_error_code
|
||||
user_password_encode(krb5_context ctx, const char *secret,
|
||||
const unsigned char *auth, const krb5_data *in,
|
||||
- unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen)
|
||||
+ unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
|
||||
+ krb5_boolean *is_fips)
|
||||
{
|
||||
const unsigned char *indx;
|
||||
krb5_error_code retval;
|
||||
@@ -154,8 +158,15 @@ user_password_encode(krb5_context ctx, const char *secret,
|
||||
for (blck = 0, indx = auth; blck * BLOCKSIZE < len; blck++) {
|
||||
memcpy(tmp.data + seclen, indx, BLOCKSIZE);
|
||||
|
||||
- retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &tmp,
|
||||
- &sum);
|
||||
+ if (kr_use_fips(ctx)) {
|
||||
+ /* Skip encryption here. Taint so that we won't pass it out of
|
||||
+ * the machine by accident. */
|
||||
+ *is_fips = TRUE;
|
||||
+ sum.contents = calloc(1, BLOCKSIZE);
|
||||
+ } else {
|
||||
+ retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &tmp,
|
||||
+ &sum);
|
||||
+ }
|
||||
if (retval != 0) {
|
||||
zap(tmp.data, tmp.length);
|
||||
zap(outbuf, len);
|
||||
@@ -180,7 +191,8 @@ user_password_encode(krb5_context ctx, const char *secret,
|
||||
static krb5_error_code
|
||||
user_password_decode(krb5_context ctx, const char *secret,
|
||||
const unsigned char *auth, const krb5_data *in,
|
||||
- unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen)
|
||||
+ unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
|
||||
+ krb5_boolean *is_fips)
|
||||
{
|
||||
const unsigned char *indx;
|
||||
krb5_error_code retval;
|
||||
@@ -204,8 +216,15 @@ user_password_decode(krb5_context ctx, const char *secret,
|
||||
for (blck = 0, indx = auth; blck * BLOCKSIZE < in->length; blck++) {
|
||||
memcpy(tmp.data + seclen, indx, BLOCKSIZE);
|
||||
|
||||
- retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0,
|
||||
- &tmp, &sum);
|
||||
+ if (kr_use_fips(ctx)) {
|
||||
+ /* Skip encryption here. Taint so that we won't pass it out of
|
||||
+ * the machine by accident. */
|
||||
+ *is_fips = TRUE;
|
||||
+ sum.contents = calloc(1, BLOCKSIZE);
|
||||
+ } else {
|
||||
+ retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0,
|
||||
+ &tmp, &sum);
|
||||
+ }
|
||||
if (retval != 0) {
|
||||
zap(tmp.data, tmp.length);
|
||||
zap(outbuf, in->length);
|
||||
@@ -248,7 +267,7 @@ krb5_error_code
|
||||
kr_attr_encode(krb5_context ctx, const char *secret,
|
||||
const unsigned char *auth, krad_attr type,
|
||||
const krb5_data *in, unsigned char outbuf[MAX_ATTRSIZE],
|
||||
- size_t *outlen)
|
||||
+ size_t *outlen, krb5_boolean *is_fips)
|
||||
{
|
||||
krb5_error_code retval;
|
||||
|
||||
@@ -265,7 +284,8 @@ kr_attr_encode(krb5_context ctx, const char *secret,
|
||||
return 0;
|
||||
}
|
||||
|
||||
- return attributes[type - 1].encode(ctx, secret, auth, in, outbuf, outlen);
|
||||
+ return attributes[type - 1].encode(ctx, secret, auth, in, outbuf, outlen,
|
||||
+ is_fips);
|
||||
}
|
||||
|
||||
krb5_error_code
|
||||
@@ -274,6 +294,7 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth,
|
||||
unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen)
|
||||
{
|
||||
krb5_error_code retval;
|
||||
+ krb5_boolean ignored;
|
||||
|
||||
retval = kr_attr_valid(type, in);
|
||||
if (retval != 0)
|
||||
@@ -288,7 +309,8 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth,
|
||||
return 0;
|
||||
}
|
||||
|
||||
- return attributes[type - 1].decode(ctx, secret, auth, in, outbuf, outlen);
|
||||
+ return attributes[type - 1].decode(ctx, secret, auth, in, outbuf, outlen,
|
||||
+ &ignored);
|
||||
}
|
||||
|
||||
krad_attr
|
||||
diff --git a/src/lib/krad/attrset.c b/src/lib/krad/attrset.c
|
||||
index 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)
|
||||
krb5_error_code
|
||||
kr_attrset_encode(const krad_attrset *set, const char *secret,
|
||||
const unsigned char *auth,
|
||||
- unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen)
|
||||
+ unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen,
|
||||
+ krb5_boolean *is_fips)
|
||||
{
|
||||
unsigned char buffer[MAX_ATTRSIZE];
|
||||
krb5_error_code retval;
|
||||
@@ -181,7 +182,7 @@ kr_attrset_encode(const krad_attrset *set, const char *secret,
|
||||
|
||||
K5_TAILQ_FOREACH(a, &set->list, list) {
|
||||
retval = kr_attr_encode(set->ctx, secret, auth, a->type, &a->attr,
|
||||
- buffer, &attrlen);
|
||||
+ buffer, &attrlen, is_fips);
|
||||
if (retval != 0)
|
||||
return retval;
|
||||
|
||||
diff --git a/src/lib/krad/internal.h b/src/lib/krad/internal.h
|
||||
index 7619563fc5..e123763954 100644
|
||||
--- a/src/lib/krad/internal.h
|
||||
+++ b/src/lib/krad/internal.h
|
||||
@@ -39,6 +39,8 @@
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
|
||||
+#include <openssl/crypto.h>
|
||||
+
|
||||
#ifndef UCHAR_MAX
|
||||
#define UCHAR_MAX 255
|
||||
#endif
|
||||
@@ -49,6 +51,13 @@
|
||||
|
||||
typedef struct krad_remote_st krad_remote;
|
||||
|
||||
+struct krad_packet_st {
|
||||
+ char buffer[KRAD_PACKET_SIZE_MAX];
|
||||
+ krad_attrset *attrset;
|
||||
+ krb5_data pkt;
|
||||
+ krb5_boolean is_fips;
|
||||
+};
|
||||
+
|
||||
/* Validate constraints of an attribute. */
|
||||
krb5_error_code
|
||||
kr_attr_valid(krad_attr type, const krb5_data *data);
|
||||
@@ -57,7 +66,8 @@ kr_attr_valid(krad_attr type, const krb5_data *data);
|
||||
krb5_error_code
|
||||
kr_attr_encode(krb5_context ctx, const char *secret, const unsigned char *auth,
|
||||
krad_attr type, const krb5_data *in,
|
||||
- unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen);
|
||||
+ unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
|
||||
+ krb5_boolean *is_fips);
|
||||
|
||||
/* Decode an attribute. */
|
||||
krb5_error_code
|
||||
@@ -69,7 +79,8 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth,
|
||||
krb5_error_code
|
||||
kr_attrset_encode(const krad_attrset *set, const char *secret,
|
||||
const unsigned char *auth,
|
||||
- unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen);
|
||||
+ unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen,
|
||||
+ krb5_boolean *is_fips);
|
||||
|
||||
/* Decode attributes from a buffer. */
|
||||
krb5_error_code
|
||||
@@ -156,4 +167,17 @@ gai_error_code(int err)
|
||||
}
|
||||
}
|
||||
|
||||
+static inline krb5_boolean
|
||||
+kr_use_fips(krb5_context ctx)
|
||||
+{
|
||||
+ int val = 0;
|
||||
+
|
||||
+ if (!FIPS_mode())
|
||||
+ return 0;
|
||||
+
|
||||
+ (void)profile_get_boolean(ctx->profile, "libdefaults",
|
||||
+ "radius_md5_fips_override", NULL, 0, &val);
|
||||
+ return !val;
|
||||
+}
|
||||
+
|
||||
#endif /* INTERNAL_H_ */
|
||||
diff --git a/src/lib/krad/packet.c b/src/lib/krad/packet.c
|
||||
index c597174b65..fc2d248001 100644
|
||||
--- a/src/lib/krad/packet.c
|
||||
+++ b/src/lib/krad/packet.c
|
||||
@@ -53,12 +53,6 @@ typedef unsigned char uchar;
|
||||
#define pkt_auth(p) ((uchar *)offset(&(p)->pkt, OFFSET_AUTH))
|
||||
#define pkt_attr(p) ((unsigned char *)offset(&(p)->pkt, OFFSET_ATTR))
|
||||
|
||||
-struct krad_packet_st {
|
||||
- char buffer[KRAD_PACKET_SIZE_MAX];
|
||||
- krad_attrset *attrset;
|
||||
- krb5_data pkt;
|
||||
-};
|
||||
-
|
||||
typedef struct {
|
||||
uchar x[(UCHAR_MAX + 1) / 8];
|
||||
} idmap;
|
||||
@@ -187,8 +181,14 @@ auth_generate_response(krb5_context ctx, const char *secret,
|
||||
memcpy(data.data + response->pkt.length, secret, strlen(secret));
|
||||
|
||||
/* Hash it. */
|
||||
- retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &data,
|
||||
- &hash);
|
||||
+ if (kr_use_fips(ctx)) {
|
||||
+ /* This checksum does very little security-wise anyway, so don't
|
||||
+ * taint. */
|
||||
+ hash.contents = calloc(1, AUTH_FIELD_SIZE);
|
||||
+ } else {
|
||||
+ retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &data,
|
||||
+ &hash);
|
||||
+ }
|
||||
free(data.data);
|
||||
if (retval != 0)
|
||||
return retval;
|
||||
@@ -276,7 +276,7 @@ krad_packet_new_request(krb5_context ctx, const char *secret, krad_code code,
|
||||
|
||||
/* Encode the attributes. */
|
||||
retval = kr_attrset_encode(set, secret, pkt_auth(pkt), pkt_attr(pkt),
|
||||
- &attrset_len);
|
||||
+ &attrset_len, &pkt->is_fips);
|
||||
if (retval != 0)
|
||||
goto error;
|
||||
|
||||
@@ -314,7 +314,7 @@ krad_packet_new_response(krb5_context ctx, const char *secret, krad_code code,
|
||||
|
||||
/* Encode the attributes. */
|
||||
retval = kr_attrset_encode(set, secret, pkt_auth(request), pkt_attr(pkt),
|
||||
- &attrset_len);
|
||||
+ &attrset_len, &pkt->is_fips);
|
||||
if (retval != 0)
|
||||
goto error;
|
||||
|
||||
@@ -451,6 +451,8 @@ krad_packet_decode_response(krb5_context ctx, const char *secret,
|
||||
const krb5_data *
|
||||
krad_packet_encode(const krad_packet *pkt)
|
||||
{
|
||||
+ if (pkt->is_fips)
|
||||
+ return NULL;
|
||||
return &pkt->pkt;
|
||||
}
|
||||
|
||||
diff --git a/src/lib/krad/remote.c b/src/lib/krad/remote.c
|
||||
index 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)
|
||||
request *r;
|
||||
|
||||
K5_TAILQ_FOREACH(r, &rr->list, list) {
|
||||
- tmp = krad_packet_encode(r->request);
|
||||
+ tmp = &r->request->pkt;
|
||||
|
||||
/* If the packet has already been sent, do nothing. */
|
||||
if (r->sent == tmp->length)
|
||||
@@ -359,7 +359,7 @@ on_io_read(krad_remote *rr)
|
||||
if (req != NULL) {
|
||||
K5_TAILQ_FOREACH(r, &rr->list, list) {
|
||||
if (r->request == req &&
|
||||
- r->sent == krad_packet_encode(req)->length) {
|
||||
+ r->sent == req->pkt.length) {
|
||||
request_finish(r, 0, rsp);
|
||||
break;
|
||||
}
|
||||
@@ -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;
|
||||
+ else if (tmp->is_fips && rr->info->ai_family != AF_LOCAL &&
|
||||
+ rr->info->ai_family != AF_UNIX) {
|
||||
+ /* This would expose cleartext passwords, so abort. */
|
||||
+ retval = ESOCKTNOSUPPORT;
|
||||
+ goto error;
|
||||
+ }
|
||||
|
||||
K5_TAILQ_FOREACH(r, &rr->list, list) {
|
||||
if (r->request == tmp) {
|
||||
diff --git a/src/lib/krad/t_attr.c b/src/lib/krad/t_attr.c
|
||||
index eb2a780c89..4d285ad9de 100644
|
||||
--- a/src/lib/krad/t_attr.c
|
||||
+++ b/src/lib/krad/t_attr.c
|
||||
@@ -50,6 +50,7 @@ main()
|
||||
const char *tmp;
|
||||
krb5_data in;
|
||||
size_t len;
|
||||
+ krb5_boolean is_fips = FALSE;
|
||||
|
||||
noerror(krb5_init_context(&ctx));
|
||||
|
||||
@@ -73,7 +74,7 @@ main()
|
||||
in = string2data((char *)decoded);
|
||||
retval = kr_attr_encode(ctx, secret, auth,
|
||||
krad_attr_name2num("User-Password"),
|
||||
- &in, outbuf, &len);
|
||||
+ &in, outbuf, &len, &is_fips);
|
||||
insist(retval == 0);
|
||||
insist(len == sizeof(encoded));
|
||||
insist(memcmp(outbuf, encoded, len) == 0);
|
||||
diff --git a/src/lib/krad/t_attrset.c b/src/lib/krad/t_attrset.c
|
||||
index 7928335ca4..0f95762534 100644
|
||||
--- a/src/lib/krad/t_attrset.c
|
||||
+++ b/src/lib/krad/t_attrset.c
|
||||
@@ -49,6 +49,7 @@ main()
|
||||
krb5_context ctx;
|
||||
size_t len = 0, encode_len;
|
||||
krb5_data tmp;
|
||||
+ krb5_boolean is_fips = FALSE;
|
||||
|
||||
noerror(krb5_init_context(&ctx));
|
||||
noerror(krad_attrset_new(ctx, &set));
|
||||
@@ -62,7 +63,8 @@ main()
|
||||
noerror(krad_attrset_add(set, krad_attr_name2num("User-Password"), &tmp));
|
||||
|
||||
/* Encode attrset. */
|
||||
- noerror(kr_attrset_encode(set, "foo", auth, buffer, &encode_len));
|
||||
+ noerror(kr_attrset_encode(set, "foo", auth, buffer, &encode_len,
|
||||
+ &is_fips));
|
||||
krad_attrset_free(set);
|
||||
|
||||
/* Manually encode User-Name. */
|
||||
diff --git a/src/plugins/preauth/spake/spake_client.c b/src/plugins/preauth/spake/spake_client.c
|
||||
index 00734a13b5..a3ce22b70f 100644
|
||||
--- a/src/plugins/preauth/spake/spake_client.c
|
||||
+++ b/src/plugins/preauth/spake/spake_client.c
|
||||
@@ -38,6 +38,8 @@
|
||||
#include "groups.h"
|
||||
#include <krb5/clpreauth_plugin.h>
|
||||
|
||||
+#include <openssl/crypto.h>
|
||||
+
|
||||
typedef struct reqstate_st {
|
||||
krb5_pa_spake *msg; /* set in prep_questions, used in process */
|
||||
krb5_keyblock *initial_key;
|
||||
@@ -375,6 +377,10 @@ clpreauth_spake_initvt(krb5_context context, int maj_ver, int min_ver,
|
||||
|
||||
if (maj_ver != 1)
|
||||
return KRB5_PLUGIN_VER_NOTSUPP;
|
||||
+
|
||||
+ if (FIPS_mode())
|
||||
+ return KRB5_CRYPTO_INTERNAL;
|
||||
+
|
||||
vt = (krb5_clpreauth_vtable)vtable;
|
||||
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 1a772d450f..232e78bc05 100644
|
||||
--- a/src/plugins/preauth/spake/spake_kdc.c
|
||||
+++ b/src/plugins/preauth/spake/spake_kdc.c
|
||||
@@ -41,6 +41,8 @@
|
||||
|
||||
#include <krb5/kdcpreauth_plugin.h>
|
||||
|
||||
+#include <openssl/crypto.h>
|
||||
+
|
||||
/*
|
||||
* The SPAKE kdcpreauth module uses a secure cookie containing the following
|
||||
* concatenated fields (all integer fields are big-endian):
|
||||
@@ -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;
|
||||
+
|
||||
+ if (FIPS_mode())
|
||||
+ return KRB5_CRYPTO_INTERNAL;
|
||||
+
|
||||
vt = (krb5_kdcpreauth_vtable)vtable;
|
||||
vt->name = "spake";
|
||||
vt->pa_type_list = pa_types;
|
||||
--
|
||||
2.45.1
|
||||
|
@ -0,0 +1,82 @@
|
||||
From 707fa7bd2be6327343dc8fc5c20dc77645524518 Mon Sep 17 00:00:00 2001
|
||||
From: Julien Rische <jrische@redhat.com>
|
||||
Date: Thu, 5 May 2022 17:15:12 +0200
|
||||
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
|
||||
network communication. However, FreeRadius requires connection on TCP or
|
||||
UDP ports.
|
||||
|
||||
This commit allows TCP or UDP connections in FIPS mode if destination is
|
||||
localhost.
|
||||
|
||||
Resolves: rhbz#2082189
|
||||
---
|
||||
src/lib/krad/remote.c | 35 +++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 33 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/lib/krad/remote.c b/src/lib/krad/remote.c
|
||||
index 929f1cef67..063f17a613 100644
|
||||
--- a/src/lib/krad/remote.c
|
||||
+++ b/src/lib/krad/remote.c
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
+#include <stdbool.h>
|
||||
|
||||
#include <sys/un.h>
|
||||
|
||||
@@ -74,6 +75,35 @@ on_io(verto_ctx *ctx, verto_ev *ev);
|
||||
static void
|
||||
on_timeout(verto_ctx *ctx, verto_ev *ev);
|
||||
|
||||
+static in_addr_t get_in_addr(struct addrinfo *info)
|
||||
+{ return ((struct sockaddr_in *)(info->ai_addr))->sin_addr.s_addr; }
|
||||
+
|
||||
+static struct in6_addr *get_in6_addr(struct addrinfo *info)
|
||||
+{ return &(((struct sockaddr_in6 *)(info->ai_addr))->sin6_addr); }
|
||||
+
|
||||
+static bool is_inet_localhost(struct addrinfo *info)
|
||||
+{
|
||||
+ struct addrinfo *p;
|
||||
+
|
||||
+ for (p = info; p; p = p->ai_next) {
|
||||
+ switch (p->ai_family) {
|
||||
+ case AF_INET:
|
||||
+ if (IN_LOOPBACKNET != (get_in_addr(p) & IN_CLASSA_NET
|
||||
+ >> IN_CLASSA_NSHIFT))
|
||||
+ return false;
|
||||
+ break;
|
||||
+ case AF_INET6:
|
||||
+ if (!IN6_IS_ADDR_LOOPBACK(get_in6_addr(p)))
|
||||
+ return false;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
/* Iterate over the set of outstanding packets. */
|
||||
static const krad_packet *
|
||||
iterator(request **out)
|
||||
@@ -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;
|
||||
- else if (tmp->is_fips && rr->info->ai_family != AF_LOCAL &&
|
||||
- rr->info->ai_family != AF_UNIX) {
|
||||
+ else if (tmp->is_fips && rr->info->ai_family != AF_LOCAL
|
||||
+ && rr->info->ai_family != AF_UNIX
|
||||
+ && !is_inet_localhost(rr->info)) {
|
||||
/* This would expose cleartext passwords, so abort. */
|
||||
retval = ESOCKTNOSUPPORT;
|
||||
goto error;
|
||||
--
|
||||
2.45.1
|
||||
|
@ -0,0 +1,41 @@
|
||||
From 1da88bea558348be2974470774aa688f8be634c0 Mon Sep 17 00:00:00 2001
|
||||
From: Julien Rische <jrische@redhat.com>
|
||||
Date: Wed, 7 Dec 2022 13:22:42 +0100
|
||||
Subject: [PATCH] [downstream] Make tests compatible with
|
||||
sssd_krb5_locator_plugin.so
|
||||
|
||||
The sssd_krb5_locator_plugin.so plugin provided by sssd-client conflicts
|
||||
with the upstream test t_discover_uri.py. The test has to be modified in
|
||||
order to avoid false positive.
|
||||
---
|
||||
src/lib/krb5/os/t_discover_uri.py | 9 ++++++++-
|
||||
1 file changed, 8 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/lib/krb5/os/t_discover_uri.py b/src/lib/krb5/os/t_discover_uri.py
|
||||
index 87bac17929..26bc95a8dc 100644
|
||||
--- a/src/lib/krb5/os/t_discover_uri.py
|
||||
+++ b/src/lib/krb5/os/t_discover_uri.py
|
||||
@@ -1,3 +1,4 @@
|
||||
+from os.path import exists
|
||||
from k5test import *
|
||||
|
||||
entries = ('URI _kerberos.TEST krb5srv::kkdcp:https://kdc1 1 1\n',
|
||||
@@ -37,8 +38,14 @@ realm.env['RESOLV_WRAPPER_HOSTS'] = hosts_filename
|
||||
out = realm.run(['./t_locate_kdc', 'TEST'], env=realm.env)
|
||||
l = out.splitlines()
|
||||
|
||||
+if (exists('/usr/lib/krb5/plugins/libkrb5/sssd_krb5_locator_plugin.so')
|
||||
+ or exists('/usr/lib64/krb5/plugins/libkrb5/sssd_krb5_locator_plugin.so')):
|
||||
+ line_range = range(6, 14)
|
||||
+else:
|
||||
+ line_range = range(4, 12)
|
||||
+
|
||||
j = 0
|
||||
-for i in range(4, 12):
|
||||
+for i in line_range:
|
||||
if l[i].strip() != expected[j]:
|
||||
fail('URI answers do not match')
|
||||
j += 1
|
||||
--
|
||||
2.45.1
|
||||
|
@ -0,0 +1,120 @@
|
||||
From 775ed8588cc21385fb16a4cec4a861f0d578ce04 Mon Sep 17 00:00:00 2001
|
||||
From: Julien Rische <jrische@redhat.com>
|
||||
Date: Thu, 5 Jan 2023 20:06:47 +0100
|
||||
Subject: [PATCH] [downstream] Include missing OpenSSL FIPS header
|
||||
|
||||
The inclusion of openssl/fips.h, which provides the declaration of
|
||||
FIPS_mode(), was removed from openssl/crypto.h. As a consequence, this
|
||||
header file has to be included explicitly in krb5 code.
|
||||
---
|
||||
src/lib/crypto/krb/prng.c | 4 +++-
|
||||
src/lib/crypto/openssl/enc_provider/camellia.c | 1 +
|
||||
src/lib/crypto/openssl/enc_provider/rc4.c | 4 ++++
|
||||
src/lib/crypto/openssl/hmac.c | 1 +
|
||||
src/lib/krad/internal.h | 4 ++++
|
||||
src/plugins/preauth/spake/spake_client.c | 4 ++++
|
||||
src/plugins/preauth/spake/spake_kdc.c | 4 ++++
|
||||
7 files changed, 21 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/lib/crypto/krb/prng.c b/src/lib/crypto/krb/prng.c
|
||||
index 9e80a03d21..ae37c77518 100644
|
||||
--- a/src/lib/crypto/krb/prng.c
|
||||
+++ b/src/lib/crypto/krb/prng.c
|
||||
@@ -28,7 +28,9 @@
|
||||
|
||||
#include <openssl/rand.h>
|
||||
|
||||
-#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
+#include <openssl/fips.h>
|
||||
+#else
|
||||
#include <openssl/crypto.h>
|
||||
#endif
|
||||
|
||||
diff --git a/src/lib/crypto/openssl/enc_provider/camellia.c b/src/lib/crypto/openssl/enc_provider/camellia.c
|
||||
index d9f327add6..3dd3b0624f 100644
|
||||
--- a/src/lib/crypto/openssl/enc_provider/camellia.c
|
||||
+++ b/src/lib/crypto/openssl/enc_provider/camellia.c
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <openssl/camellia.h>
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
#include <openssl/core_names.h>
|
||||
+#include <openssl/fips.h>
|
||||
#else
|
||||
#include <openssl/modes.h>
|
||||
#endif
|
||||
diff --git a/src/lib/crypto/openssl/enc_provider/rc4.c b/src/lib/crypto/openssl/enc_provider/rc4.c
|
||||
index ce63cb5f1b..6a83f10d27 100644
|
||||
--- a/src/lib/crypto/openssl/enc_provider/rc4.c
|
||||
+++ b/src/lib/crypto/openssl/enc_provider/rc4.c
|
||||
@@ -38,6 +38,10 @@
|
||||
|
||||
#include <openssl/evp.h>
|
||||
|
||||
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
+#include <openssl/fips.h>
|
||||
+#endif
|
||||
+
|
||||
/*
|
||||
* The loopback field is a pointer to the structure. If the application copies
|
||||
* the state (not a valid operation, but one which happens to works with some
|
||||
diff --git a/src/lib/crypto/openssl/hmac.c b/src/lib/crypto/openssl/hmac.c
|
||||
index f21e268f7f..25a419d73a 100644
|
||||
--- a/src/lib/crypto/openssl/hmac.c
|
||||
+++ b/src/lib/crypto/openssl/hmac.c
|
||||
@@ -59,6 +59,7 @@
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
#include <openssl/params.h>
|
||||
#include <openssl/core_names.h>
|
||||
+#include <openssl/fips.h>
|
||||
#else
|
||||
#include <openssl/hmac.h>
|
||||
#endif
|
||||
diff --git a/src/lib/krad/internal.h b/src/lib/krad/internal.h
|
||||
index e123763954..a17b6f39b1 100644
|
||||
--- a/src/lib/krad/internal.h
|
||||
+++ b/src/lib/krad/internal.h
|
||||
@@ -41,6 +41,10 @@
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
|
||||
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
+#include <openssl/fips.h>
|
||||
+#endif
|
||||
+
|
||||
#ifndef UCHAR_MAX
|
||||
#define UCHAR_MAX 255
|
||||
#endif
|
||||
diff --git a/src/plugins/preauth/spake/spake_client.c b/src/plugins/preauth/spake/spake_client.c
|
||||
index a3ce22b70f..13c699071f 100644
|
||||
--- a/src/plugins/preauth/spake/spake_client.c
|
||||
+++ b/src/plugins/preauth/spake/spake_client.c
|
||||
@@ -40,6 +40,10 @@
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
|
||||
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
+#include <openssl/fips.h>
|
||||
+#endif
|
||||
+
|
||||
typedef struct reqstate_st {
|
||||
krb5_pa_spake *msg; /* set in prep_questions, used in process */
|
||||
krb5_keyblock *initial_key;
|
||||
diff --git a/src/plugins/preauth/spake/spake_kdc.c b/src/plugins/preauth/spake/spake_kdc.c
|
||||
index 232e78bc05..3394f8a58e 100644
|
||||
--- a/src/plugins/preauth/spake/spake_kdc.c
|
||||
+++ b/src/plugins/preauth/spake/spake_kdc.c
|
||||
@@ -43,6 +43,10 @@
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
|
||||
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
+#include <openssl/fips.h>
|
||||
+#endif
|
||||
+
|
||||
/*
|
||||
* The SPAKE kdcpreauth module uses a secure cookie containing the following
|
||||
* concatenated fields (all integer fields are big-endian):
|
||||
--
|
||||
2.45.1
|
||||
|
@ -0,0 +1,31 @@
|
||||
From 4fd20741afcf76085ea62eb015cd589bb9392a7b Mon Sep 17 00:00:00 2001
|
||||
From: Julien Rische <jrische@redhat.com>
|
||||
Date: Mon, 9 Jan 2023 22:39:52 +0100
|
||||
Subject: [PATCH] [downstream] Do not set root as ksu file owner
|
||||
|
||||
Upstream Makefile uses the install command to set root as owner of the
|
||||
ksu executable file. However, this is no longer supported on latest
|
||||
versions of the Mock build environment.
|
||||
|
||||
In case of ksu, the owner, group, and mode are already set using %attr()
|
||||
in the specfile.
|
||||
---
|
||||
src/config/pre.in | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/config/pre.in b/src/config/pre.in
|
||||
index 7eaa2f351c..e9ae71471e 100644
|
||||
--- a/src/config/pre.in
|
||||
+++ b/src/config/pre.in
|
||||
@@ -185,7 +185,7 @@ INSTALL_PROGRAM=@INSTALL_PROGRAM@ $(INSTALL_STRIP)
|
||||
INSTALL_SCRIPT=@INSTALL_PROGRAM@
|
||||
INSTALL_DATA=@INSTALL_DATA@
|
||||
INSTALL_SHLIB=@INSTALL_SHLIB@
|
||||
-INSTALL_SETUID=$(INSTALL) $(INSTALL_STRIP) -m 4755 -o root
|
||||
+INSTALL_SETUID=$(INSTALL)
|
||||
## This is needed because autoconf will sometimes define @exec_prefix@ to be
|
||||
## ${prefix}.
|
||||
prefix=@prefix@
|
||||
--
|
||||
2.45.1
|
||||
|
@ -0,0 +1,165 @@
|
||||
From 16f90c007036789d8d9343e8a0cbabfd21853b5a Mon Sep 17 00:00:00 2001
|
||||
From: Julien Rische <jrische@redhat.com>
|
||||
Date: Thu, 19 Jan 2023 19:22:27 +0100
|
||||
Subject: [PATCH] [downstream] Allow KRB5KDF, MD5, and MD4 in FIPS mode
|
||||
|
||||
OpenSSL's restrictions to use KRB5KDF, MD5, and MD4 in FIPS mode are
|
||||
bypassed in case AES SHA-1 HMAC or RC4 encryption types are allowed by
|
||||
the crypto policy.
|
||||
---
|
||||
.../crypto/openssl/hash_provider/hash_evp.c | 97 +++++++++++++++++--
|
||||
src/lib/crypto/openssl/kdf.c | 2 +-
|
||||
2 files changed, 89 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/src/lib/crypto/openssl/hash_provider/hash_evp.c b/src/lib/crypto/openssl/hash_provider/hash_evp.c
|
||||
index 11659908bb..eb2e693e9f 100644
|
||||
--- a/src/lib/crypto/openssl/hash_provider/hash_evp.c
|
||||
+++ b/src/lib/crypto/openssl/hash_provider/hash_evp.c
|
||||
@@ -44,6 +44,49 @@
|
||||
#define EVP_MD_CTX_free EVP_MD_CTX_destroy
|
||||
#endif
|
||||
|
||||
+#include <openssl/provider.h>
|
||||
+#include <openssl/fips.h>
|
||||
+#include <threads.h>
|
||||
+
|
||||
+typedef struct ossl_lib_md_context {
|
||||
+ OSSL_LIB_CTX *libctx;
|
||||
+ OSSL_PROVIDER *default_provider;
|
||||
+ OSSL_PROVIDER *legacy_provider;
|
||||
+} ossl_md_context_t;
|
||||
+
|
||||
+static thread_local ossl_md_context_t *ossl_md_ctx = NULL;
|
||||
+
|
||||
+static krb5_error_code
|
||||
+init_ossl_md_ctx(ossl_md_context_t *ctx, const char *algo)
|
||||
+{
|
||||
+ ctx->libctx = OSSL_LIB_CTX_new();
|
||||
+ if (!ctx->libctx)
|
||||
+ return KRB5_CRYPTO_INTERNAL;
|
||||
+
|
||||
+ /* Load both legacy and default provider as both may be needed. */
|
||||
+ ctx->default_provider = OSSL_PROVIDER_load(ctx->libctx, "default");
|
||||
+ ctx->legacy_provider = OSSL_PROVIDER_load(ctx->libctx, "legacy");
|
||||
+
|
||||
+ if (!(ctx->default_provider && ctx->legacy_provider))
|
||||
+ return KRB5_CRYPTO_INTERNAL;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+deinit_ossl_ctx(ossl_md_context_t *ctx)
|
||||
+{
|
||||
+ if (ctx->legacy_provider)
|
||||
+ OSSL_PROVIDER_unload(ctx->legacy_provider);
|
||||
+
|
||||
+ if (ctx->default_provider)
|
||||
+ OSSL_PROVIDER_unload(ctx->default_provider);
|
||||
+
|
||||
+ if (ctx->libctx)
|
||||
+ OSSL_LIB_CTX_free(ctx->libctx);
|
||||
+}
|
||||
+
|
||||
+
|
||||
static krb5_error_code
|
||||
hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data,
|
||||
krb5_data *output)
|
||||
@@ -60,11 +103,6 @@ hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data,
|
||||
if (ctx == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
- if (type == EVP_md4() || type == EVP_md5()) {
|
||||
- /* See comments below in hash_md4() and hash_md5(). */
|
||||
- EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
|
||||
- }
|
||||
-
|
||||
ok = EVP_DigestInit_ex(ctx, type, NULL);
|
||||
for (i = 0; i < num_data; i++) {
|
||||
if (!SIGN_IOV(&data[i]))
|
||||
@@ -77,6 +115,43 @@ hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data,
|
||||
return ok ? 0 : KRB5_CRYPTO_INTERNAL;
|
||||
}
|
||||
|
||||
+static krb5_error_code
|
||||
+hash_legacy_evp(const char *algo, const krb5_crypto_iov *data, size_t num_data,
|
||||
+ krb5_data *output)
|
||||
+{
|
||||
+ krb5_error_code err;
|
||||
+ EVP_MD *md = NULL;
|
||||
+
|
||||
+ if (!ossl_md_ctx) {
|
||||
+ ossl_md_ctx = malloc(sizeof(ossl_md_context_t));
|
||||
+ if (!ossl_md_ctx) {
|
||||
+ err = ENOMEM;
|
||||
+ goto end;
|
||||
+ }
|
||||
+
|
||||
+ err = init_ossl_md_ctx(ossl_md_ctx, algo);
|
||||
+ if (err) {
|
||||
+ deinit_ossl_ctx(ossl_md_ctx);
|
||||
+ free(ossl_md_ctx);
|
||||
+ ossl_md_ctx = NULL;
|
||||
+ goto end;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ md = EVP_MD_fetch(ossl_md_ctx->libctx, algo, NULL);
|
||||
+ if (!md) {
|
||||
+ err = KRB5_CRYPTO_INTERNAL;
|
||||
+ goto end;
|
||||
+ }
|
||||
+
|
||||
+ err = hash_evp(md, data, num_data, output);
|
||||
+
|
||||
+end:
|
||||
+ if (md)
|
||||
+ EVP_MD_free(md);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
#endif
|
||||
|
||||
#ifdef K5_OPENSSL_MD4
|
||||
@@ -88,7 +163,8 @@ hash_md4(const krb5_crypto_iov *data, size_t num_data, krb5_data *output)
|
||||
* by IPA. These keys are only used along a (separately) secured channel
|
||||
* for legacy reasons when performing trusts to Active Directory.
|
||||
*/
|
||||
- return hash_evp(EVP_md4(), data, num_data, output);
|
||||
+ return FIPS_mode() ? hash_legacy_evp("MD4", data, num_data, output)
|
||||
+ : hash_evp(EVP_md4(), data, num_data, output);
|
||||
}
|
||||
|
||||
const struct krb5_hash_provider krb5int_hash_md4 = {
|
||||
@@ -100,9 +176,12 @@ const struct krb5_hash_provider krb5int_hash_md4 = {
|
||||
static krb5_error_code
|
||||
hash_md5(const krb5_crypto_iov *data, size_t num_data, krb5_data *output)
|
||||
{
|
||||
- /* MD5 is needed in FIPS mode for communication with RADIUS servers. This
|
||||
- * is gated in libkrad by libdefaults->radius_md5_fips_override. */
|
||||
- return hash_evp(EVP_md5(), data, num_data, output);
|
||||
+ /*
|
||||
+ * MD5 is needed in FIPS mode for communication with RADIUS servers. This
|
||||
+ * is gated in libkrad by libdefaults->radius_md5_fips_override.
|
||||
+ */
|
||||
+ return FIPS_mode() ? hash_legacy_evp("MD5", data, num_data, output)
|
||||
+ : hash_evp(EVP_md5(), data, num_data, output);
|
||||
}
|
||||
|
||||
const struct krb5_hash_provider krb5int_hash_md5 = {
|
||||
diff --git a/src/lib/crypto/openssl/kdf.c b/src/lib/crypto/openssl/kdf.c
|
||||
index 5a43c3d9eb..8528ddc4a9 100644
|
||||
--- a/src/lib/crypto/openssl/kdf.c
|
||||
+++ b/src/lib/crypto/openssl/kdf.c
|
||||
@@ -198,7 +198,7 @@ k5_derive_random_rfc3961(const struct krb5_enc_provider *enc, krb5_key key,
|
||||
goto done;
|
||||
}
|
||||
|
||||
- kdf = EVP_KDF_fetch(NULL, "KRB5KDF", NULL);
|
||||
+ kdf = EVP_KDF_fetch(NULL, "KRB5KDF", "-fips");
|
||||
if (kdf == NULL) {
|
||||
ret = KRB5_CRYPTO_INTERNAL;
|
||||
goto done;
|
||||
--
|
||||
2.45.1
|
||||
|
@ -0,0 +1,280 @@
|
||||
From 23b58199db429603802e338db530677b61561335 Mon Sep 17 00:00:00 2001
|
||||
From: Julien Rische <jrische@redhat.com>
|
||||
Date: Wed, 15 Mar 2023 15:56:34 +0100
|
||||
Subject: [PATCH] [downstream] Allow to set PAC ticket signature as
|
||||
optional
|
||||
|
||||
MS-PAC states that "The ticket signature SHOULD be included in tickets
|
||||
that are not encrypted to the krbtgt account". However, the
|
||||
implementation of krb5_kdc_verify_ticket() will require the ticket
|
||||
signature to be present in case the target of the request is a service
|
||||
principal.
|
||||
|
||||
In gradual upgrade environments, it results in S4U2Proxy requests
|
||||
against a 1.20 KDC using a service ticket generated by an older version
|
||||
KDC to fail.
|
||||
|
||||
This commit adds a krb5_kdc_verify_ticket_ext() function with an extra
|
||||
switch parameter to tolerate the absence of ticket signature in this
|
||||
scenario. If the ticket signature is present, it has to be valid,
|
||||
regardless of this parameter.
|
||||
|
||||
This parameter is set based on the "optional_pac_tkt_chksum" string
|
||||
attribute of the TGT KDB entry.
|
||||
---
|
||||
doc/admin/admin_commands/kadmin_local.rst | 6 ++++
|
||||
doc/appdev/refs/api/index.rst | 1 +
|
||||
src/include/kdb.h | 1 +
|
||||
src/include/krb5/krb5.hin | 40 +++++++++++++++++++++++
|
||||
src/kdc/kdc_util.c | 32 ++++++++++++++----
|
||||
src/lib/krb5/krb/pac.c | 31 +++++++++++++++---
|
||||
src/lib/krb5/libkrb5.exports | 1 +
|
||||
src/man/kadmin.man | 6 ++++
|
||||
8 files changed, 108 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/doc/admin/admin_commands/kadmin_local.rst b/doc/admin/admin_commands/kadmin_local.rst
|
||||
index 2435b3c361..58ac79549f 100644
|
||||
--- a/doc/admin/admin_commands/kadmin_local.rst
|
||||
+++ b/doc/admin/admin_commands/kadmin_local.rst
|
||||
@@ -658,6 +658,12 @@ KDC:
|
||||
Directory realm when using aes-sha2 keys on the local krbtgt
|
||||
entry.
|
||||
|
||||
+**optional_pac_tkt_chksum**
|
||||
+ Boolean value defining the behavior of the KDC in case an expected
|
||||
+ ticket checksum signed with one of this principal keys is not
|
||||
+ present in the PAC. This is typically the case for TGS or
|
||||
+ cross-realm TGS principals when processing S4U2Proxy requests.
|
||||
+
|
||||
This command requires the **modify** privilege.
|
||||
|
||||
Alias: **setstr**
|
||||
diff --git a/doc/appdev/refs/api/index.rst b/doc/appdev/refs/api/index.rst
|
||||
index d12be47c3c..9b95ebd0f9 100644
|
||||
--- a/doc/appdev/refs/api/index.rst
|
||||
+++ b/doc/appdev/refs/api/index.rst
|
||||
@@ -225,6 +225,7 @@ Rarely used public interfaces
|
||||
krb5_is_referral_realm.rst
|
||||
krb5_kdc_sign_ticket.rst
|
||||
krb5_kdc_verify_ticket.rst
|
||||
+ krb5_kdc_verify_ticket_ext.rst
|
||||
krb5_kt_add_entry.rst
|
||||
krb5_kt_end_seq_get.rst
|
||||
krb5_kt_get_entry.rst
|
||||
diff --git a/src/include/kdb.h b/src/include/kdb.h
|
||||
index 745b24f351..6075349e5e 100644
|
||||
--- a/src/include/kdb.h
|
||||
+++ b/src/include/kdb.h
|
||||
@@ -136,6 +136,7 @@
|
||||
#define KRB5_KDB_SK_PAC_PRIVSVR_ENCTYPE "pac_privsvr_enctype"
|
||||
#define KRB5_KDB_SK_SESSION_ENCTYPES "session_enctypes"
|
||||
#define KRB5_KDB_SK_REQUIRE_AUTH "require_auth"
|
||||
+#define KRB5_KDB_SK_OPTIONAL_PAC_TKT_CHKSUM "optional_pac_tkt_chksum"
|
||||
|
||||
#if !defined(_WIN32)
|
||||
|
||||
diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
|
||||
index c5a625db8f..2d9b64dc85 100644
|
||||
--- a/src/include/krb5/krb5.hin
|
||||
+++ b/src/include/krb5/krb5.hin
|
||||
@@ -8329,6 +8329,46 @@ krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt,
|
||||
const krb5_keyblock *server,
|
||||
const krb5_keyblock *privsvr, krb5_pac *pac_out);
|
||||
|
||||
+/**
|
||||
+ * Verify a PAC, possibly including ticket signature
|
||||
+ *
|
||||
+ * @param [in] context Library context
|
||||
+ * @param [in] enc_tkt Ticket enc-part, possibly containing a PAC
|
||||
+ * @param [in] server_princ Canonicalized name of ticket server
|
||||
+ * @param [in] server Key to validate server checksum (or NULL)
|
||||
+ * @param [in] privsvr Key to validate KDC checksum (or NULL)
|
||||
+ * @paran [in] optional_tkt_chksum Whether to require a ticket checksum
|
||||
+ * @param [out] pac_out Verified PAC (NULL if no PAC included)
|
||||
+ *
|
||||
+ * This function is an extension of krb5_kdc_verify_ticket(), adding the @a
|
||||
+ * optional_tkt_chksum parameter allowing to tolerate the absence of the PAC
|
||||
+ * ticket signature.
|
||||
+ *
|
||||
+ * If a PAC is present in @a enc_tkt, verify its signatures. If @a privsvr is
|
||||
+ * not NULL and @a server_princ is not a krbtgt or kadmin/changepw service and
|
||||
+ * @a optional_tkt_chksum is FALSE, require a ticket signature over @a enc_tkt
|
||||
+ * in addition to the KDC signature. Place the verified PAC in @a pac_out. If
|
||||
+ * an invalid PAC signature is found, return an error matching the Windows KDC
|
||||
+ * protocol code for that condition as closely as possible.
|
||||
+ *
|
||||
+ * If no PAC is present in @a enc_tkt, set @a pac_out to NULL and return
|
||||
+ * successfully.
|
||||
+ *
|
||||
+ * @note This function does not validate the PAC_CLIENT_INFO buffer. If a
|
||||
+ * specific value is expected, the caller can make a separate call to
|
||||
+ * krb5_pac_verify_ext() with a principal but no keys.
|
||||
+ *
|
||||
+ * @retval 0 Success; otherwise - Kerberos error codes
|
||||
+ */
|
||||
+krb5_error_code KRB5_CALLCONV
|
||||
+krb5_kdc_verify_ticket_ext(krb5_context context,
|
||||
+ const krb5_enc_tkt_part *enc_tkt,
|
||||
+ krb5_const_principal server_princ,
|
||||
+ const krb5_keyblock *server,
|
||||
+ const krb5_keyblock *privsvr,
|
||||
+ krb5_boolean optional_tkt_chksum,
|
||||
+ krb5_pac *pac_out);
|
||||
+
|
||||
/** @deprecated Use krb5_kdc_sign_ticket() instead. */
|
||||
krb5_error_code KRB5_CALLCONV
|
||||
krb5_pac_sign(krb5_context context, krb5_pac pac, krb5_timestamp authtime,
|
||||
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
|
||||
index fe4e48209a..93415ba862 100644
|
||||
--- a/src/kdc/kdc_util.c
|
||||
+++ b/src/kdc/kdc_util.c
|
||||
@@ -560,16 +560,36 @@ cleanup:
|
||||
static krb5_error_code
|
||||
try_verify_pac(krb5_context context, const krb5_enc_tkt_part *enc_tkt,
|
||||
krb5_db_entry *server, krb5_keyblock *server_key,
|
||||
- const krb5_keyblock *tgt_key, krb5_pac *pac_out)
|
||||
+ krb5_db_entry *tgt, const krb5_keyblock *tgt_key,
|
||||
+ krb5_pac *pac_out)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
+ krb5_boolean optional_tkt_chksum;
|
||||
+ char *str = NULL;
|
||||
krb5_keyblock *privsvr_key;
|
||||
|
||||
ret = pac_privsvr_key(context, server, tgt_key, &privsvr_key);
|
||||
if (ret)
|
||||
return ret;
|
||||
- ret = krb5_kdc_verify_ticket(context, enc_tkt, server->princ, server_key,
|
||||
- privsvr_key, pac_out);
|
||||
+
|
||||
+ /* Check if the absence of ticket signature is tolerated for this realm */
|
||||
+ ret = krb5_dbe_get_string(context, tgt,
|
||||
+ KRB5_KDB_SK_OPTIONAL_PAC_TKT_CHKSUM, &str);
|
||||
+ /* TODO: should be using _krb5_conf_boolean(), but os-proto.h is not
|
||||
+ * available here.
|
||||
+ */
|
||||
+ optional_tkt_chksum = !ret && str && (strncasecmp(str, "true", 4) == 0
|
||||
+ || strncasecmp(str, "t", 1) == 0
|
||||
+ || strncasecmp(str, "yes", 3) == 0
|
||||
+ || strncasecmp(str, "y", 1) == 0
|
||||
+ || strncasecmp(str, "1", 1) == 0
|
||||
+ || strncasecmp(str, "on", 2) == 0);
|
||||
+
|
||||
+ krb5_dbe_free_string(context, str);
|
||||
+
|
||||
+ ret = krb5_kdc_verify_ticket_ext(context, enc_tkt, server->princ,
|
||||
+ server_key, privsvr_key,
|
||||
+ optional_tkt_chksum, pac_out);
|
||||
krb5_free_keyblock(context, privsvr_key);
|
||||
return ret;
|
||||
}
|
||||
@@ -599,7 +619,7 @@ get_verified_pac(krb5_context context, const krb5_enc_tkt_part *enc_tkt,
|
||||
server_key, NULL, pac_out);
|
||||
}
|
||||
|
||||
- ret = try_verify_pac(context, enc_tkt, server, server_key, tgt_key,
|
||||
+ ret = try_verify_pac(context, enc_tkt, server, server_key, tgt, tgt_key,
|
||||
pac_out);
|
||||
if (ret != KRB5KRB_AP_ERR_MODIFIED && ret != KRB5_BAD_ENCTYPE)
|
||||
return ret;
|
||||
@@ -613,8 +633,8 @@ get_verified_pac(krb5_context context, const krb5_enc_tkt_part *enc_tkt,
|
||||
ret = krb5_dbe_decrypt_key_data(context, NULL, kd, &old_key, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
- ret = try_verify_pac(context, enc_tkt, server, server_key, &old_key,
|
||||
- pac_out);
|
||||
+ ret = try_verify_pac(context, enc_tkt, server, server_key, tgt,
|
||||
+ &old_key, pac_out);
|
||||
krb5_free_keyblock_contents(context, &old_key);
|
||||
if (!ret)
|
||||
return 0;
|
||||
diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c
|
||||
index 5d1fdf1ba0..0c0e2ada68 100644
|
||||
--- a/src/lib/krb5/krb/pac.c
|
||||
+++ b/src/lib/krb5/krb/pac.c
|
||||
@@ -594,6 +594,19 @@ krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt,
|
||||
krb5_const_principal server_princ,
|
||||
const krb5_keyblock *server,
|
||||
const krb5_keyblock *privsvr, krb5_pac *pac_out)
|
||||
+{
|
||||
+ return krb5_kdc_verify_ticket_ext(context, enc_tkt, server_princ, server,
|
||||
+ privsvr, FALSE, pac_out);
|
||||
+}
|
||||
+
|
||||
+krb5_error_code KRB5_CALLCONV
|
||||
+krb5_kdc_verify_ticket_ext(krb5_context context,
|
||||
+ const krb5_enc_tkt_part *enc_tkt,
|
||||
+ krb5_const_principal server_princ,
|
||||
+ const krb5_keyblock *server,
|
||||
+ const krb5_keyblock *privsvr,
|
||||
+ krb5_boolean optional_tkt_chksum,
|
||||
+ krb5_pac *pac_out)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
krb5_pac pac = NULL;
|
||||
@@ -602,7 +615,7 @@ krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt,
|
||||
krb5_authdata *orig, **ifrel = NULL, **recoded_ifrel = NULL;
|
||||
uint8_t z = 0;
|
||||
krb5_authdata zpac = { KV5M_AUTHDATA, KRB5_AUTHDATA_WIN2K_PAC, 1, &z };
|
||||
- krb5_boolean is_service_tkt;
|
||||
+ krb5_boolean is_service_tkt, has_tkt_chksum = FALSE;
|
||||
size_t i, j;
|
||||
|
||||
*pac_out = NULL;
|
||||
@@ -667,11 +680,21 @@ krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt,
|
||||
|
||||
ret = verify_checksum(context, pac, KRB5_PAC_TICKET_CHECKSUM, privsvr,
|
||||
KRB5_KEYUSAGE_APP_DATA_CKSUM, recoded_tkt);
|
||||
- if (ret)
|
||||
- goto cleanup;
|
||||
+ if (ret) {
|
||||
+ if (!optional_tkt_chksum)
|
||||
+ goto cleanup;
|
||||
+ else if (ret != ENOENT)
|
||||
+ goto cleanup;
|
||||
+ /* Otherwise ticket signature is absent but optional. Proceed... */
|
||||
+ } else {
|
||||
+ has_tkt_chksum = TRUE;
|
||||
+ }
|
||||
}
|
||||
+ /* Else, we make the assumption the ticket signature is absent in case this
|
||||
+ * is not a service ticket.
|
||||
+ */
|
||||
|
||||
- ret = verify_pac_checksums(context, pac, is_service_tkt, server, privsvr);
|
||||
+ ret = verify_pac_checksums(context, pac, has_tkt_chksum, server, privsvr);
|
||||
if (ret)
|
||||
goto cleanup;
|
||||
|
||||
diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports
|
||||
index 4c50e935a2..d4b0455c8c 100644
|
||||
--- a/src/lib/krb5/libkrb5.exports
|
||||
+++ b/src/lib/krb5/libkrb5.exports
|
||||
@@ -463,6 +463,7 @@ krb5_is_thread_safe
|
||||
krb5_kdc_rep_decrypt_proc
|
||||
krb5_kdc_sign_ticket
|
||||
krb5_kdc_verify_ticket
|
||||
+krb5_kdc_verify_ticket_ext
|
||||
krb5_kt_add_entry
|
||||
krb5_kt_client_default
|
||||
krb5_kt_close
|
||||
diff --git a/src/man/kadmin.man b/src/man/kadmin.man
|
||||
index 8413e70ccd..f68eb0569d 100644
|
||||
--- a/src/man/kadmin.man
|
||||
+++ b/src/man/kadmin.man
|
||||
@@ -724,6 +724,12 @@ encryption type. It may be necessary to set this value to
|
||||
"aes256\-sha1" on the cross\-realm krbtgt entry for an Active
|
||||
Directory realm when using aes\-sha2 keys on the local krbtgt
|
||||
entry.
|
||||
+.TP
|
||||
+\fBoptional_pac_tkt_chksum\fP
|
||||
+Boolean value defining the behavior of the KDC in case an expected ticket
|
||||
+checksum signed with one of this principal keys is not present in the PAC. This
|
||||
+is typically the case for TGS or cross-realm TGS principals when processing
|
||||
+S4U2Proxy requests.
|
||||
.UNINDENT
|
||||
.sp
|
||||
This command requires the \fBmodify\fP privilege.
|
||||
--
|
||||
2.45.1
|
||||
|
@ -0,0 +1,47 @@
|
||||
From 31b9debcf2cbd558f8f315fefb69fc8206b115b4 Mon Sep 17 00:00:00 2001
|
||||
From: Julien Rische <jrische@redhat.com>
|
||||
Date: Tue, 23 May 2023 12:19:54 +0200
|
||||
Subject: [PATCH] [downstream] Make PKINIT CMS SHA-1 signature
|
||||
verification available in FIPS mode
|
||||
|
||||
We recommend using the SHA1 crypto-module in order to allow the
|
||||
verification of SHA-1 signature for CMS messages. However, this module
|
||||
does not work in FIPS mode, because the SHA-1 algorithm is absent from
|
||||
the OpenSSL FIPS provider.
|
||||
|
||||
This commit enables the signature verification process to fetch the
|
||||
algorithm from a non-FIPS OpenSSL provider.
|
||||
|
||||
Support for SHA-1 CMS signature is still required, especially in order
|
||||
to interoperate with Active Directory. At least it is until elliptic
|
||||
curve cryptography is implemented for PKINIT in MIT krb5.
|
||||
---
|
||||
src/plugins/preauth/pkinit/pkinit_crypto_openssl.c | 11 ++++++++++-
|
||||
1 file changed, 10 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
|
||||
index cb9c79626c..17dd18e37d 100644
|
||||
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
|
||||
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
|
||||
@@ -1844,8 +1844,17 @@ cms_signeddata_verify(krb5_context context,
|
||||
if (oid == NULL)
|
||||
goto cleanup;
|
||||
|
||||
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
+ /* Do not use FIPS provider (even in FIPS mode) because it keeps from
|
||||
+ * allowing SHA-1 signature verification using the SHA1 crypto-module
|
||||
+ */
|
||||
+ cms = CMS_ContentInfo_new_ex(NULL, "-fips");
|
||||
+ if (!cms)
|
||||
+ goto cleanup;
|
||||
+#endif
|
||||
+
|
||||
/* decode received CMS message */
|
||||
- if ((cms = d2i_CMS_ContentInfo(NULL, &p, (int)signed_data_len)) == NULL) {
|
||||
+ if (!d2i_CMS_ContentInfo(&cms, &p, (int)signed_data_len)) {
|
||||
retval = oerr(context, 0, _("Failed to decode CMS message"));
|
||||
goto cleanup;
|
||||
}
|
||||
--
|
||||
2.45.1
|
||||
|
@ -0,0 +1,218 @@
|
||||
From c24c9faf859ddc04910a6bc591d8ddb2ada93e80 Mon Sep 17 00:00:00 2001
|
||||
From: Greg Hudson <ghudson@mit.edu>
|
||||
Date: Tue, 30 May 2023 01:21:48 -0400
|
||||
Subject: [PATCH] Enable PKINIT if at least one group is available
|
||||
|
||||
OpenSSL may no longer allow decoding of non-well-known Diffie-Hellman
|
||||
group parameters as EVP_PKEY objects in FIPS mode. However, OpenSSL
|
||||
does not know about MODP group 2 (1024-bit), which is considered as a
|
||||
custom group. As a consequence, the PKINIT kdcpreauth module fails to
|
||||
load in FIPS mode.
|
||||
|
||||
Allow initialization of PKINIT plugin if at least one of the MODP
|
||||
well-known group parameters successfully decodes.
|
||||
|
||||
[ghudson@mit.edu: minor commit message and code edits]
|
||||
|
||||
ticket: 9096 (new)
|
||||
(cherry picked from commit 509d8db922e9ad6f108883838473b6178f89874a)
|
||||
---
|
||||
src/plugins/preauth/pkinit/pkinit_clnt.c | 2 +-
|
||||
src/plugins/preauth/pkinit/pkinit_crypto.h | 3 +-
|
||||
.../preauth/pkinit/pkinit_crypto_openssl.c | 76 +++++++++++--------
|
||||
src/plugins/preauth/pkinit/pkinit_srv.c | 2 +-
|
||||
src/plugins/preauth/pkinit/pkinit_trace.h | 3 +
|
||||
5 files changed, 51 insertions(+), 35 deletions(-)
|
||||
|
||||
diff --git a/src/plugins/preauth/pkinit/pkinit_clnt.c b/src/plugins/preauth/pkinit/pkinit_clnt.c
|
||||
index 725d5bc438..ea9ba454df 100644
|
||||
--- a/src/plugins/preauth/pkinit/pkinit_clnt.c
|
||||
+++ b/src/plugins/preauth/pkinit/pkinit_clnt.c
|
||||
@@ -1378,7 +1378,7 @@ pkinit_client_plugin_init(krb5_context context,
|
||||
if (retval)
|
||||
goto errout;
|
||||
|
||||
- retval = pkinit_init_plg_crypto(&ctx->cryptoctx);
|
||||
+ retval = pkinit_init_plg_crypto(context, &ctx->cryptoctx);
|
||||
if (retval)
|
||||
goto errout;
|
||||
|
||||
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto.h b/src/plugins/preauth/pkinit/pkinit_crypto.h
|
||||
index 9fa315d7a0..8bdbea8e95 100644
|
||||
--- a/src/plugins/preauth/pkinit/pkinit_crypto.h
|
||||
+++ b/src/plugins/preauth/pkinit/pkinit_crypto.h
|
||||
@@ -103,7 +103,8 @@ typedef struct _pkinit_cert_matching_data {
|
||||
/*
|
||||
* Functions to initialize and cleanup crypto contexts
|
||||
*/
|
||||
-krb5_error_code pkinit_init_plg_crypto(pkinit_plg_crypto_context *);
|
||||
+krb5_error_code pkinit_init_plg_crypto(krb5_context,
|
||||
+ pkinit_plg_crypto_context *);
|
||||
void pkinit_fini_plg_crypto(pkinit_plg_crypto_context);
|
||||
|
||||
krb5_error_code pkinit_init_req_crypto(pkinit_req_crypto_context *);
|
||||
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
|
||||
index 17dd18e37d..8cdc40bfb4 100644
|
||||
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
|
||||
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
|
||||
@@ -47,7 +47,8 @@
|
||||
static krb5_error_code pkinit_init_pkinit_oids(pkinit_plg_crypto_context );
|
||||
static void pkinit_fini_pkinit_oids(pkinit_plg_crypto_context );
|
||||
|
||||
-static krb5_error_code pkinit_init_dh_params(pkinit_plg_crypto_context );
|
||||
+static krb5_error_code pkinit_init_dh_params(krb5_context,
|
||||
+ pkinit_plg_crypto_context);
|
||||
static void pkinit_fini_dh_params(pkinit_plg_crypto_context );
|
||||
|
||||
static krb5_error_code pkinit_init_certs(pkinit_identity_crypto_context ctx);
|
||||
@@ -951,7 +952,8 @@ oerr_cert(krb5_context context, krb5_error_code code, X509_STORE_CTX *certctx,
|
||||
}
|
||||
|
||||
krb5_error_code
|
||||
-pkinit_init_plg_crypto(pkinit_plg_crypto_context *cryptoctx)
|
||||
+pkinit_init_plg_crypto(krb5_context context,
|
||||
+ pkinit_plg_crypto_context *cryptoctx)
|
||||
{
|
||||
krb5_error_code retval = ENOMEM;
|
||||
pkinit_plg_crypto_context ctx = NULL;
|
||||
@@ -969,7 +971,7 @@ pkinit_init_plg_crypto(pkinit_plg_crypto_context *cryptoctx)
|
||||
if (retval)
|
||||
goto out;
|
||||
|
||||
- retval = pkinit_init_dh_params(ctx);
|
||||
+ retval = pkinit_init_dh_params(context, ctx);
|
||||
if (retval)
|
||||
goto out;
|
||||
|
||||
@@ -1278,30 +1280,36 @@ pkinit_fini_pkinit_oids(pkinit_plg_crypto_context ctx)
|
||||
ASN1_OBJECT_free(ctx->id_kp_serverAuth);
|
||||
}
|
||||
|
||||
-static krb5_error_code
|
||||
-pkinit_init_dh_params(pkinit_plg_crypto_context plgctx)
|
||||
+static int
|
||||
+try_import_group(krb5_context context, const krb5_data *params,
|
||||
+ const char *name, EVP_PKEY **pkey_out)
|
||||
{
|
||||
- krb5_error_code retval = ENOMEM;
|
||||
-
|
||||
- plgctx->dh_1024 = decode_dh_params(&oakley_1024);
|
||||
- if (plgctx->dh_1024 == NULL)
|
||||
- goto cleanup;
|
||||
-
|
||||
- plgctx->dh_2048 = decode_dh_params(&oakley_2048);
|
||||
- if (plgctx->dh_2048 == NULL)
|
||||
- goto cleanup;
|
||||
+ *pkey_out = decode_dh_params(params);
|
||||
+ if (*pkey_out == NULL)
|
||||
+ TRACE_PKINIT_DH_GROUP_UNAVAILABLE(context, name);
|
||||
+ return (*pkey_out != NULL) ? 1 : 0;
|
||||
+}
|
||||
|
||||
- plgctx->dh_4096 = decode_dh_params(&oakley_4096);
|
||||
- if (plgctx->dh_4096 == NULL)
|
||||
- goto cleanup;
|
||||
+static krb5_error_code
|
||||
+pkinit_init_dh_params(krb5_context context, pkinit_plg_crypto_context plgctx)
|
||||
+{
|
||||
+ int n = 0;
|
||||
|
||||
- retval = 0;
|
||||
+ n += try_import_group(context, &oakley_1024, "MODP 2 (1024-bit)",
|
||||
+ &plgctx->dh_1024);
|
||||
+ n += try_import_group(context, &oakley_2048, "MODP 14 (2048-bit)",
|
||||
+ &plgctx->dh_2048);
|
||||
+ n += try_import_group(context, &oakley_4096, "MODP 16 (4096-bit)",
|
||||
+ &plgctx->dh_4096);
|
||||
|
||||
-cleanup:
|
||||
- if (retval)
|
||||
+ if (n == 0) {
|
||||
pkinit_fini_dh_params(plgctx);
|
||||
+ k5_setmsg(context, ENOMEM,
|
||||
+ _("PKINIT cannot initialize any key exchange groups"));
|
||||
+ return ENOMEM;
|
||||
+ }
|
||||
|
||||
- return retval;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2912,11 +2920,11 @@ client_create_dh(krb5_context context,
|
||||
|
||||
if (cryptoctx->received_params != NULL)
|
||||
params = cryptoctx->received_params;
|
||||
- else if (dh_size == 1024)
|
||||
+ else if (plg_cryptoctx->dh_1024 != NULL && dh_size == 1024)
|
||||
params = plg_cryptoctx->dh_1024;
|
||||
- else if (dh_size == 2048)
|
||||
+ else if (plg_cryptoctx->dh_2048 != NULL && dh_size == 2048)
|
||||
params = plg_cryptoctx->dh_2048;
|
||||
- else if (dh_size == 4096)
|
||||
+ else if (plg_cryptoctx->dh_4096 != NULL && dh_size == 4096)
|
||||
params = plg_cryptoctx->dh_4096;
|
||||
else
|
||||
goto cleanup;
|
||||
@@ -3212,19 +3220,23 @@ pkinit_create_td_dh_parameters(krb5_context context,
|
||||
krb5_algorithm_identifier alg_4096 = { dh_oid, oakley_4096 };
|
||||
krb5_algorithm_identifier *alglist[4];
|
||||
|
||||
- if (opts->dh_min_bits > 4096) {
|
||||
- ret = KRB5KRB_ERR_GENERIC;
|
||||
- goto cleanup;
|
||||
- }
|
||||
-
|
||||
i = 0;
|
||||
- if (opts->dh_min_bits <= 2048)
|
||||
+ if (plg_cryptoctx->dh_2048 != NULL && opts->dh_min_bits <= 2048)
|
||||
alglist[i++] = &alg_2048;
|
||||
- alglist[i++] = &alg_4096;
|
||||
- if (opts->dh_min_bits <= 1024)
|
||||
+ if (plg_cryptoctx->dh_4096 != NULL && opts->dh_min_bits <= 4096)
|
||||
+ alglist[i++] = &alg_4096;
|
||||
+ if (plg_cryptoctx->dh_1024 != NULL && opts->dh_min_bits <= 1024)
|
||||
alglist[i++] = &alg_1024;
|
||||
alglist[i] = NULL;
|
||||
|
||||
+ if (i == 0) {
|
||||
+ ret = KRB5KRB_ERR_GENERIC;
|
||||
+ k5_setmsg(context, ret,
|
||||
+ _("OpenSSL has no supported key exchange groups for "
|
||||
+ "pkinit_dh_min_bits=%d"), opts->dh_min_bits);
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
ret = k5int_encode_krb5_td_dh_parameters(alglist, &der_alglist);
|
||||
if (ret)
|
||||
goto cleanup;
|
||||
diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c
|
||||
index 1b3bf6d4d0..768a4e559f 100644
|
||||
--- a/src/plugins/preauth/pkinit/pkinit_srv.c
|
||||
+++ b/src/plugins/preauth/pkinit/pkinit_srv.c
|
||||
@@ -1222,7 +1222,7 @@ pkinit_server_plugin_init_realm(krb5_context context, const char *realmname,
|
||||
goto errout;
|
||||
plgctx->realmname_len = strlen(plgctx->realmname);
|
||||
|
||||
- retval = pkinit_init_plg_crypto(&plgctx->cryptoctx);
|
||||
+ retval = pkinit_init_plg_crypto(context, &plgctx->cryptoctx);
|
||||
if (retval)
|
||||
goto errout;
|
||||
|
||||
diff --git a/src/plugins/preauth/pkinit/pkinit_trace.h b/src/plugins/preauth/pkinit/pkinit_trace.h
|
||||
index 259e95c6c2..5ee39c085c 100644
|
||||
--- a/src/plugins/preauth/pkinit/pkinit_trace.h
|
||||
+++ b/src/plugins/preauth/pkinit/pkinit_trace.h
|
||||
@@ -90,6 +90,9 @@
|
||||
#define TRACE_PKINIT_CLIENT_TRYAGAIN(c) \
|
||||
TRACE(c, "PKINIT client trying again with KDC-provided parameters")
|
||||
|
||||
+#define TRACE_PKINIT_DH_GROUP_UNAVAILABLE(c, name) \
|
||||
+ TRACE(c, "PKINIT key exchange group {str} unsupported", name)
|
||||
+
|
||||
#define TRACE_PKINIT_OPENSSL_ERROR(c, msg) \
|
||||
TRACE(c, "PKINIT OpenSSL error: {str}", msg)
|
||||
|
||||
--
|
||||
2.45.1
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,64 @@
|
||||
From abb95e961f4e6a5482220a64fba843a3adc171df Mon Sep 17 00:00:00 2001
|
||||
From: Julien Rische <jrische@redhat.com>
|
||||
Date: Wed, 19 Jul 2023 13:43:17 +0200
|
||||
Subject: [PATCH] Replace ssl.wrap_socket() for tests
|
||||
|
||||
The ssl.wrap_socket() function was deprecated in Python 3.7 and is
|
||||
removed in Python 3.12. The ssl.SSLContext.wrap_socket() method
|
||||
replaces it.
|
||||
|
||||
Bump the required Python version for tests to 3.4 for
|
||||
ssl.create_default_context().
|
||||
|
||||
[ghudson@mit.edu: changed minimum Python version]
|
||||
|
||||
(cherry picked from commit 0ceab6c363e65fb21d3312a663f2b9b569ecc415)
|
||||
---
|
||||
src/configure.ac | 9 ++++-----
|
||||
src/util/wsgiref-kdcproxy.py | 4 +++-
|
||||
2 files changed, 7 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/configure.ac b/src/configure.ac
|
||||
index 2561e917a2..487f393146 100644
|
||||
--- a/src/configure.ac
|
||||
+++ b/src/configure.ac
|
||||
@@ -1157,10 +1157,9 @@ AC_SUBST(PKINIT)
|
||||
# for lib/apputils
|
||||
AC_REPLACE_FUNCS(daemon)
|
||||
|
||||
-# For Python tests. Python version 3.2.4 is required as prior
|
||||
-# versions do not accept string input to subprocess.Popen.communicate
|
||||
-# when universal_newlines is set.
|
||||
-PYTHON_MINVERSION=3.2.4
|
||||
+# For Python tests. Python version 3.4 is required for
|
||||
+# ssl.create_default_context().
|
||||
+PYTHON_MINVERSION=3.4
|
||||
AC_SUBST(PYTHON_MINVERSION)
|
||||
AC_CHECK_PROG(PYTHON,python3,python3)
|
||||
if test x"$PYTHON" = x; then
|
||||
@@ -1168,7 +1167,7 @@ if test x"$PYTHON" = x; then
|
||||
fi
|
||||
HAVE_PYTHON=no
|
||||
if test x"$PYTHON" != x; then
|
||||
- wantver="(sys.hexversion >= 0x30204F0)"
|
||||
+ wantver="(sys.hexversion >= 0x30400F0)"
|
||||
if "$PYTHON" -c "import sys; sys.exit(not $wantver and 1 or 0)"; then
|
||||
HAVE_PYTHON=yes
|
||||
fi
|
||||
diff --git a/src/util/wsgiref-kdcproxy.py b/src/util/wsgiref-kdcproxy.py
|
||||
index 58759696b6..d1d10d733c 100755
|
||||
--- a/src/util/wsgiref-kdcproxy.py
|
||||
+++ b/src/util/wsgiref-kdcproxy.py
|
||||
@@ -14,6 +14,8 @@ else:
|
||||
pem = '*'
|
||||
|
||||
server = make_server('localhost', port, kdcproxy.Application())
|
||||
-server.socket = ssl.wrap_socket(server.socket, certfile=pem, server_side=True)
|
||||
+sslctx = ssl.create_default_context(purpose=ssl.Purpose.CLIENT_AUTH)
|
||||
+sslctx.load_cert_chain(certfile=pem)
|
||||
+server.socket = sslctx.wrap_socket(server.socket, server_side=True)
|
||||
os.write(sys.stdout.fileno(), b'proxy server ready\n')
|
||||
server.serve_forever()
|
||||
--
|
||||
2.45.1
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,34 @@
|
||||
From 6e898b880a0c752f83decf33d64a7d8706e6d6f8 Mon Sep 17 00:00:00 2001
|
||||
From: Greg Hudson <ghudson@mit.edu>
|
||||
Date: Fri, 27 Oct 2023 00:44:53 -0400
|
||||
Subject: [PATCH] End connection on KDC_ERR_SVC_UNAVAILABLE
|
||||
|
||||
In sendto_kdc.c:service_fds(), if a message handler indicates that a
|
||||
message should be discarded, kill the connection so we don't continue
|
||||
waiting on it for more data.
|
||||
|
||||
ticket: 7899
|
||||
(cherry picked from commit ca80f64c786341d5871ae1de18142e62af64f7b9)
|
||||
---
|
||||
src/lib/krb5/os/sendto_kdc.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c
|
||||
index 0f4bf23a95..262edf09b4 100644
|
||||
--- a/src/lib/krb5/os/sendto_kdc.c
|
||||
+++ b/src/lib/krb5/os/sendto_kdc.c
|
||||
@@ -1440,7 +1440,10 @@ service_fds(krb5_context context, struct select_state *selstate,
|
||||
if (msg_handler != NULL) {
|
||||
krb5_data reply = make_data(state->in.buf, state->in.pos);
|
||||
|
||||
- stop = (msg_handler(context, &reply, msg_handler_data) != 0);
|
||||
+ if (!msg_handler(context, &reply, msg_handler_data)) {
|
||||
+ kill_conn(context, state, selstate);
|
||||
+ stop = 0;
|
||||
+ }
|
||||
}
|
||||
|
||||
if (stop) {
|
||||
--
|
||||
2.45.1
|
||||
|
@ -0,0 +1,226 @@
|
||||
From fa711b7cb3b7cbb234bd202bc9d9b9d7ca4defad Mon Sep 17 00:00:00 2001
|
||||
From: Greg Hudson <ghudson@mit.edu>
|
||||
Date: Thu, 26 Oct 2023 14:20:34 -0400
|
||||
Subject: [PATCH] Add request_timeout configuration parameter
|
||||
|
||||
Add a parameter to limit the total amount of time taken for a KDC or
|
||||
password change request.
|
||||
|
||||
ticket: 9106 (new)
|
||||
(cherry picked from commit 802318cda963456b3ed7856c836e89da891483be)
|
||||
---
|
||||
doc/admin/conf_files/krb5_conf.rst | 9 ++++++
|
||||
src/include/k5-int.h | 2 ++
|
||||
src/lib/krb5/krb/init_ctx.c | 14 +++++++-
|
||||
src/lib/krb5/os/sendto_kdc.c | 51 ++++++++++++++++++++----------
|
||||
4 files changed, 58 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
|
||||
index a33711d918..65fb592d98 100644
|
||||
--- a/doc/admin/conf_files/krb5_conf.rst
|
||||
+++ b/doc/admin/conf_files/krb5_conf.rst
|
||||
@@ -356,6 +356,15 @@ The libdefaults section may contain any of the following relations:
|
||||
(:ref:`duration` string.) Sets the default renewable lifetime
|
||||
for initial ticket requests. The default value is 0.
|
||||
|
||||
+**request_timeout**
|
||||
+ (:ref:`duration` string.) Sets the maximum total time for KDC or
|
||||
+ password change requests. This timeout does not affect the
|
||||
+ intervals between requests, so setting a low timeout may result in
|
||||
+ fewer requests being attempted and/or some servers not being
|
||||
+ contacted. A value of 0 indicates no specific maximum, in which
|
||||
+ case requests will time out if no server responds after several
|
||||
+ tries. The default value is 0. (New in release 1.22.)
|
||||
+
|
||||
**spake_preauth_groups**
|
||||
A whitespace or comma-separated list of words which specifies the
|
||||
groups allowed for SPAKE preauthentication. The possible values
|
||||
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
|
||||
index b3e07945c1..69d6a6f569 100644
|
||||
--- a/src/include/k5-int.h
|
||||
+++ b/src/include/k5-int.h
|
||||
@@ -296,6 +296,7 @@ typedef unsigned char u_char;
|
||||
#define KRB5_CONF_SPAKE_PREAUTH_INDICATOR "spake_preauth_indicator"
|
||||
#define KRB5_CONF_SPAKE_PREAUTH_KDC_CHALLENGE "spake_preauth_kdc_challenge"
|
||||
#define KRB5_CONF_SPAKE_PREAUTH_GROUPS "spake_preauth_groups"
|
||||
+#define KRB5_CONF_REQUEST_TIMEOUT "request_timeout"
|
||||
#define KRB5_CONF_TICKET_LIFETIME "ticket_lifetime"
|
||||
#define KRB5_CONF_UDP_PREFERENCE_LIMIT "udp_preference_limit"
|
||||
#define KRB5_CONF_UNLOCKITER "unlockiter"
|
||||
@@ -1200,6 +1201,7 @@ struct _krb5_context {
|
||||
kdb5_dal_handle *dal_handle;
|
||||
/* allowable clock skew */
|
||||
krb5_deltat clockskew;
|
||||
+ krb5_deltat req_timeout;
|
||||
krb5_flags kdc_default_options;
|
||||
krb5_flags library_options;
|
||||
krb5_boolean profile_secure;
|
||||
diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c
|
||||
index 2b5abcd817..582a2945ff 100644
|
||||
--- a/src/lib/krb5/krb/init_ctx.c
|
||||
+++ b/src/lib/krb5/krb/init_ctx.c
|
||||
@@ -157,7 +157,7 @@ krb5_init_context_profile(profile_t profile, krb5_flags flags,
|
||||
krb5_context ctx = 0;
|
||||
krb5_error_code retval;
|
||||
int tmp;
|
||||
- char *plugin_dir = NULL;
|
||||
+ char *plugin_dir = NULL, *timeout_str = NULL;
|
||||
|
||||
/* Verify some assumptions. If the assumptions hold and the
|
||||
compiler is optimizing, this should result in no code being
|
||||
@@ -240,6 +240,17 @@ krb5_init_context_profile(profile_t profile, krb5_flags flags,
|
||||
get_integer(ctx, KRB5_CONF_CLOCKSKEW, DEFAULT_CLOCKSKEW, &tmp);
|
||||
ctx->clockskew = tmp;
|
||||
|
||||
+ retval = profile_get_string(ctx->profile, KRB5_CONF_LIBDEFAULTS,
|
||||
+ KRB5_CONF_REQUEST_TIMEOUT, NULL, NULL,
|
||||
+ &timeout_str);
|
||||
+ if (retval)
|
||||
+ goto cleanup;
|
||||
+ if (timeout_str != NULL) {
|
||||
+ retval = krb5_string_to_deltat(timeout_str, &ctx->req_timeout);
|
||||
+ if (retval)
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
get_integer(ctx, KRB5_CONF_KDC_DEFAULT_OPTIONS, KDC_OPT_RENEWABLE_OK,
|
||||
&tmp);
|
||||
ctx->kdc_default_options = tmp;
|
||||
@@ -281,6 +292,7 @@ krb5_init_context_profile(profile_t profile, krb5_flags flags,
|
||||
|
||||
cleanup:
|
||||
profile_release_string(plugin_dir);
|
||||
+ profile_release_string(timeout_str);
|
||||
krb5_free_context(ctx);
|
||||
return retval;
|
||||
}
|
||||
diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c
|
||||
index 262edf09b4..98247a1089 100644
|
||||
--- a/src/lib/krb5/os/sendto_kdc.c
|
||||
+++ b/src/lib/krb5/os/sendto_kdc.c
|
||||
@@ -1395,34 +1395,41 @@ get_endtime(time_ms endtime, struct conn_state *conns)
|
||||
|
||||
static krb5_boolean
|
||||
service_fds(krb5_context context, struct select_state *selstate,
|
||||
- time_ms interval, struct conn_state *conns,
|
||||
+ time_ms interval, time_ms timeout, struct conn_state *conns,
|
||||
struct select_state *seltemp, const krb5_data *realm,
|
||||
int (*msg_handler)(krb5_context, const krb5_data *, void *),
|
||||
void *msg_handler_data, struct conn_state **winner_out)
|
||||
{
|
||||
int e, selret = 0;
|
||||
- time_ms endtime;
|
||||
+ time_ms curtime, interval_end, endtime;
|
||||
struct conn_state *state;
|
||||
|
||||
*winner_out = NULL;
|
||||
|
||||
- e = get_curtime_ms(&endtime);
|
||||
+ e = get_curtime_ms(&curtime);
|
||||
if (e)
|
||||
return TRUE;
|
||||
- endtime += interval;
|
||||
+ interval_end = curtime + interval;
|
||||
|
||||
e = 0;
|
||||
while (selstate->nfds > 0) {
|
||||
- e = cm_select_or_poll(selstate, get_endtime(endtime, conns),
|
||||
- seltemp, &selret);
|
||||
+ endtime = get_endtime(interval_end, conns);
|
||||
+ /* Don't wait longer than the whole request should last. */
|
||||
+ if (timeout && endtime > timeout)
|
||||
+ endtime = timeout;
|
||||
+ e = cm_select_or_poll(selstate, endtime, seltemp, &selret);
|
||||
if (e == EINTR)
|
||||
continue;
|
||||
if (e != 0)
|
||||
break;
|
||||
|
||||
- if (selret == 0)
|
||||
- /* Timeout, return to caller. */
|
||||
+ if (selret == 0) {
|
||||
+ /* We timed out. Stop if we hit the overall request timeout. */
|
||||
+ if (timeout && (get_curtime_ms(&curtime) || curtime >= timeout))
|
||||
+ return TRUE;
|
||||
+ /* Otherwise return to the caller to send the next request. */
|
||||
return FALSE;
|
||||
+ }
|
||||
|
||||
/* Got something on a socket, process it. */
|
||||
for (state = conns; state != NULL; state = state->next) {
|
||||
@@ -1495,7 +1502,7 @@ k5_sendto(krb5_context context, const krb5_data *message,
|
||||
void *msg_handler_data)
|
||||
{
|
||||
int pass;
|
||||
- time_ms delay;
|
||||
+ time_ms delay, timeout = 0;
|
||||
krb5_error_code retval;
|
||||
struct conn_state *conns = NULL, *state, **tailptr, *next, *winner;
|
||||
size_t s;
|
||||
@@ -1505,6 +1512,13 @@ k5_sendto(krb5_context context, const krb5_data *message,
|
||||
|
||||
*reply = empty_data();
|
||||
|
||||
+ if (context->req_timeout) {
|
||||
+ retval = get_curtime_ms(&timeout);
|
||||
+ if (retval)
|
||||
+ return retval;
|
||||
+ timeout += 1000 * context->req_timeout;
|
||||
+ }
|
||||
+
|
||||
/* One for use here, listing all our fds in use, and one for
|
||||
* temporary use in service_fds, for the fds of interest. */
|
||||
sel_state = malloc(2 * sizeof(*sel_state));
|
||||
@@ -1532,8 +1546,9 @@ k5_sendto(krb5_context context, const krb5_data *message,
|
||||
if (maybe_send(context, state, message, sel_state, realm,
|
||||
callback_info))
|
||||
continue;
|
||||
- done = service_fds(context, sel_state, 1000, conns, seltemp,
|
||||
- realm, msg_handler, msg_handler_data, &winner);
|
||||
+ done = service_fds(context, sel_state, 1000, timeout, conns,
|
||||
+ seltemp, realm, msg_handler, msg_handler_data,
|
||||
+ &winner);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1545,13 +1560,13 @@ k5_sendto(krb5_context context, const krb5_data *message,
|
||||
if (maybe_send(context, state, message, sel_state, realm,
|
||||
callback_info))
|
||||
continue;
|
||||
- done = service_fds(context, sel_state, 1000, conns, seltemp,
|
||||
+ done = service_fds(context, sel_state, 1000, timeout, conns, seltemp,
|
||||
realm, msg_handler, msg_handler_data, &winner);
|
||||
}
|
||||
|
||||
/* Wait for two seconds at the end of the first pass. */
|
||||
if (!done) {
|
||||
- done = service_fds(context, sel_state, 2000, conns, seltemp,
|
||||
+ done = service_fds(context, sel_state, 2000, timeout, conns, seltemp,
|
||||
realm, msg_handler, msg_handler_data, &winner);
|
||||
}
|
||||
|
||||
@@ -1562,15 +1577,17 @@ k5_sendto(krb5_context context, const krb5_data *message,
|
||||
if (maybe_send(context, state, message, sel_state, realm,
|
||||
callback_info))
|
||||
continue;
|
||||
- done = service_fds(context, sel_state, 1000, conns, seltemp,
|
||||
- realm, msg_handler, msg_handler_data, &winner);
|
||||
+ done = service_fds(context, sel_state, 1000, timeout, conns,
|
||||
+ seltemp, realm, msg_handler, msg_handler_data,
|
||||
+ &winner);
|
||||
if (sel_state->nfds == 0)
|
||||
break;
|
||||
}
|
||||
/* Wait for the delay backoff at the end of this pass. */
|
||||
if (!done) {
|
||||
- done = service_fds(context, sel_state, delay, conns, seltemp,
|
||||
- realm, msg_handler, msg_handler_data, &winner);
|
||||
+ done = service_fds(context, sel_state, delay, timeout, conns,
|
||||
+ seltemp, realm, msg_handler, msg_handler_data,
|
||||
+ &winner);
|
||||
}
|
||||
if (sel_state->nfds == 0)
|
||||
break;
|
||||
--
|
||||
2.45.1
|
||||
|
@ -0,0 +1,138 @@
|
||||
From 58b64df22e22b9b89f9c6af96990276a1fc8e3c6 Mon Sep 17 00:00:00 2001
|
||||
From: Greg Hudson <ghudson@mit.edu>
|
||||
Date: Thu, 26 Oct 2023 16:26:42 -0400
|
||||
Subject: [PATCH] Wait indefinitely on KDC TCP connections
|
||||
|
||||
When making a KDC or password change request, wait indefinitely
|
||||
(limited only by request_timeout if set) once a KDC has accepted a TCP
|
||||
connection.
|
||||
|
||||
ticket: 9105 (new)
|
||||
(cherry picked from commit 6436a3808061da787a43c6810f5f0370cdfb6e36)
|
||||
---
|
||||
doc/admin/conf_files/krb5_conf.rst | 2 +-
|
||||
src/lib/krb5/os/sendto_kdc.c | 50 ++++++++++++++++--------------
|
||||
2 files changed, 27 insertions(+), 25 deletions(-)
|
||||
|
||||
diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
|
||||
index 65fb592d98..b7284c47df 100644
|
||||
--- a/doc/admin/conf_files/krb5_conf.rst
|
||||
+++ b/doc/admin/conf_files/krb5_conf.rst
|
||||
@@ -357,7 +357,7 @@ The libdefaults section may contain any of the following relations:
|
||||
for initial ticket requests. The default value is 0.
|
||||
|
||||
**request_timeout**
|
||||
- (:ref:`duration` string.) Sets the maximum total time for KDC or
|
||||
+ (:ref:`duration` string.) Sets the maximum total time for KDC and
|
||||
password change requests. This timeout does not affect the
|
||||
intervals between requests, so setting a low timeout may result in
|
||||
fewer requests being attempted and/or some servers not being
|
||||
diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c
|
||||
index 98247a1089..924f5b2d26 100644
|
||||
--- a/src/lib/krb5/os/sendto_kdc.c
|
||||
+++ b/src/lib/krb5/os/sendto_kdc.c
|
||||
@@ -134,7 +134,6 @@ struct conn_state {
|
||||
krb5_data callback_buffer;
|
||||
size_t server_index;
|
||||
struct conn_state *next;
|
||||
- time_ms endtime;
|
||||
krb5_boolean defer;
|
||||
struct {
|
||||
const char *uri_path;
|
||||
@@ -344,15 +343,19 @@ cm_select_or_poll(const struct select_state *in, time_ms endtime,
|
||||
struct select_state *out, int *sret)
|
||||
{
|
||||
#ifndef USE_POLL
|
||||
- struct timeval tv;
|
||||
+ struct timeval tv, *tvp;
|
||||
#endif
|
||||
krb5_error_code retval;
|
||||
time_ms curtime, interval;
|
||||
|
||||
- retval = get_curtime_ms(&curtime);
|
||||
- if (retval != 0)
|
||||
- return retval;
|
||||
- interval = (curtime < endtime) ? endtime - curtime : 0;
|
||||
+ if (endtime != 0) {
|
||||
+ retval = get_curtime_ms(&curtime);
|
||||
+ if (retval != 0)
|
||||
+ return retval;
|
||||
+ interval = (curtime < endtime) ? endtime - curtime : 0;
|
||||
+ } else {
|
||||
+ interval = -1;
|
||||
+ }
|
||||
|
||||
/* We don't need a separate copy of the selstate for poll, but use one for
|
||||
* consistency with how we use select. */
|
||||
@@ -361,9 +364,14 @@ cm_select_or_poll(const struct select_state *in, time_ms endtime,
|
||||
#ifdef USE_POLL
|
||||
*sret = poll(out->fds, out->nfds, interval);
|
||||
#else
|
||||
- tv.tv_sec = interval / 1000;
|
||||
- tv.tv_usec = interval % 1000 * 1000;
|
||||
- *sret = select(out->max, &out->rfds, &out->wfds, &out->xfds, &tv);
|
||||
+ if (interval != -1) {
|
||||
+ tv.tv_sec = interval / 1000;
|
||||
+ tv.tv_usec = interval % 1000 * 1000;
|
||||
+ tvp = &tv;
|
||||
+ } else {
|
||||
+ tvp = NULL;
|
||||
+ }
|
||||
+ *sret = select(out->max, &out->rfds, &out->wfds, &out->xfds, tvp);
|
||||
#endif
|
||||
|
||||
return (*sret < 0) ? SOCKET_ERRNO : 0;
|
||||
@@ -1099,11 +1107,6 @@ service_tcp_connect(krb5_context context, const krb5_data *realm,
|
||||
}
|
||||
|
||||
conn->state = WRITING;
|
||||
-
|
||||
- /* Record this connection's timeout for service_fds. */
|
||||
- if (get_curtime_ms(&conn->endtime) == 0)
|
||||
- conn->endtime += 10000;
|
||||
-
|
||||
return conn->service_write(context, realm, conn, selstate);
|
||||
}
|
||||
|
||||
@@ -1378,19 +1381,18 @@ kill_conn:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
-/* Return the maximum of endtime and the endtime fields of all currently active
|
||||
- * TCP connections. */
|
||||
-static time_ms
|
||||
-get_endtime(time_ms endtime, struct conn_state *conns)
|
||||
+/* Return true if conns contains any states with connected TCP sockets. */
|
||||
+static krb5_boolean
|
||||
+any_tcp_connections(struct conn_state *conns)
|
||||
{
|
||||
struct conn_state *state;
|
||||
|
||||
for (state = conns; state != NULL; state = state->next) {
|
||||
- if ((state->state == READING || state->state == WRITING) &&
|
||||
- state->endtime > endtime)
|
||||
- endtime = state->endtime;
|
||||
+ if (state->addr.transport != UDP &&
|
||||
+ (state->state == READING || state->state == WRITING))
|
||||
+ return TRUE;
|
||||
}
|
||||
- return endtime;
|
||||
+ return FALSE;
|
||||
}
|
||||
|
||||
static krb5_boolean
|
||||
@@ -1413,9 +1415,9 @@ service_fds(krb5_context context, struct select_state *selstate,
|
||||
|
||||
e = 0;
|
||||
while (selstate->nfds > 0) {
|
||||
- endtime = get_endtime(interval_end, conns);
|
||||
+ endtime = any_tcp_connections(conns) ? 0 : interval_end;
|
||||
/* Don't wait longer than the whole request should last. */
|
||||
- if (timeout && endtime > timeout)
|
||||
+ if (timeout && (!endtime || endtime > timeout))
|
||||
endtime = timeout;
|
||||
e = cm_select_or_poll(selstate, endtime, seltemp, &selret);
|
||||
if (e == EINTR)
|
||||
--
|
||||
2.45.1
|
||||
|
@ -0,0 +1,71 @@
|
||||
From fa9dfdc9d85e88b6880edde5de45333b97a53a11 Mon Sep 17 00:00:00 2001
|
||||
From: Julien Rische <jrische@redhat.com>
|
||||
Date: Mon, 8 Jan 2024 16:52:27 +0100
|
||||
Subject: [PATCH] Remove klist's defname global variable
|
||||
|
||||
Addition of a "cleanup" section in kinit's show_ccache() function as
|
||||
part of commit 6c5471176f5266564fbc8a7e02f03b4b042202f8 introduced a
|
||||
double-free bug, because defname is a global variable. After the
|
||||
first call, successive calls may take place with a dangling pointer in
|
||||
defname, which will be freed if krb5_cc_get_principal() fails.
|
||||
|
||||
Convert "defname" to a local variable initialized at the beginning of
|
||||
show_ccache().
|
||||
|
||||
[ghudson@mit.edu: edited commit message]
|
||||
|
||||
(cherry picked from commit 5b00197227231943bd2305328c8260dd0b0dbcf0)
|
||||
---
|
||||
src/clients/klist/klist.c | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/clients/klist/klist.c b/src/clients/klist/klist.c
|
||||
index b5ae96a843..b5808e5c93 100644
|
||||
--- a/src/clients/klist/klist.c
|
||||
+++ b/src/clients/klist/klist.c
|
||||
@@ -53,7 +53,6 @@ int show_flags = 0, show_time = 0, status_only = 0, show_keys = 0;
|
||||
int show_etype = 0, show_addresses = 0, no_resolve = 0, print_version = 0;
|
||||
int show_adtype = 0, show_all = 0, list_all = 0, use_client_keytab = 0;
|
||||
int show_config = 0;
|
||||
-char *defname;
|
||||
char *progname;
|
||||
krb5_timestamp now;
|
||||
unsigned int timestamp_width;
|
||||
@@ -62,7 +61,7 @@ krb5_context context;
|
||||
|
||||
static krb5_boolean is_local_tgt(krb5_principal princ, krb5_data *realm);
|
||||
static char *etype_string(krb5_enctype );
|
||||
-static void show_credential(krb5_creds *);
|
||||
+static void show_credential(krb5_creds *, const char *);
|
||||
|
||||
static void list_all_ccaches(void);
|
||||
static int list_ccache(krb5_ccache);
|
||||
@@ -473,6 +472,7 @@ show_ccache(krb5_ccache cache)
|
||||
krb5_creds creds;
|
||||
krb5_principal princ = NULL;
|
||||
krb5_error_code ret;
|
||||
+ char *defname = NULL;
|
||||
int status = 1;
|
||||
|
||||
ret = krb5_cc_get_principal(context, cache, &princ);
|
||||
@@ -503,7 +503,7 @@ show_ccache(krb5_ccache cache)
|
||||
}
|
||||
while ((ret = krb5_cc_next_cred(context, cache, &cur, &creds)) == 0) {
|
||||
if (show_config || !krb5_is_config_principal(context, creds.server))
|
||||
- show_credential(&creds);
|
||||
+ show_credential(&creds, defname);
|
||||
krb5_free_cred_contents(context, &creds);
|
||||
}
|
||||
if (ret == KRB5_CC_END) {
|
||||
@@ -676,7 +676,7 @@ print_config_data(int col, krb5_data *data)
|
||||
}
|
||||
|
||||
static void
|
||||
-show_credential(krb5_creds *cred)
|
||||
+show_credential(krb5_creds *cred, const char *defname)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
krb5_ticket *tkt = NULL;
|
||||
--
|
||||
2.45.1
|
||||
|
@ -0,0 +1,206 @@
|
||||
From 313d7b1afdcfca2bc0f6824cfeb25594c2eae176 Mon Sep 17 00:00:00 2001
|
||||
From: Greg Hudson <ghudson@mit.edu>
|
||||
Date: Tue, 5 Mar 2024 19:53:07 -0500
|
||||
Subject: [PATCH] Fix two unlikely memory leaks
|
||||
|
||||
In gss_krb5int_make_seal_token_v3(), one of the bounds checks (which
|
||||
could probably never be triggered) leaks plain.data. Fix this leak
|
||||
and use current practices for cleanup throughout the function.
|
||||
|
||||
In xmt_rmtcallres() (unused within the tree and likely elsewhere),
|
||||
store port_ptr into crp->port_ptr as soon as it is allocated;
|
||||
otherwise it could leak if the subsequent xdr_u_int32() operation
|
||||
fails.
|
||||
|
||||
(cherry picked from commit c5f9c816107f70139de11b38aa02db2f1774ee0d)
|
||||
---
|
||||
src/lib/gssapi/krb5/k5sealv3.c | 56 +++++++++++++++-------------------
|
||||
src/lib/rpc/pmap_rmt.c | 10 +++---
|
||||
2 files changed, 29 insertions(+), 37 deletions(-)
|
||||
|
||||
diff --git a/src/lib/gssapi/krb5/k5sealv3.c b/src/lib/gssapi/krb5/k5sealv3.c
|
||||
index 1fcbdfbb87..d3210c1107 100644
|
||||
--- a/src/lib/gssapi/krb5/k5sealv3.c
|
||||
+++ b/src/lib/gssapi/krb5/k5sealv3.c
|
||||
@@ -65,7 +65,7 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
|
||||
int conf_req_flag, int toktype)
|
||||
{
|
||||
size_t bufsize = 16;
|
||||
- unsigned char *outbuf = 0;
|
||||
+ unsigned char *outbuf = NULL;
|
||||
krb5_error_code err;
|
||||
int key_usage;
|
||||
unsigned char acceptor_flag;
|
||||
@@ -75,9 +75,13 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
|
||||
#endif
|
||||
size_t ec;
|
||||
unsigned short tok_id;
|
||||
- krb5_checksum sum;
|
||||
+ krb5_checksum sum = { 0 };
|
||||
krb5_key key;
|
||||
krb5_cksumtype cksumtype;
|
||||
+ krb5_data plain = empty_data();
|
||||
+
|
||||
+ token->value = NULL;
|
||||
+ token->length = 0;
|
||||
|
||||
acceptor_flag = ctx->initiate ? 0 : FLAG_SENDER_IS_ACCEPTOR;
|
||||
key_usage = (toktype == KG_TOK_WRAP_MSG
|
||||
@@ -107,14 +111,15 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
|
||||
#endif
|
||||
|
||||
if (toktype == KG_TOK_WRAP_MSG && conf_req_flag) {
|
||||
- krb5_data plain;
|
||||
krb5_enc_data cipher;
|
||||
size_t ec_max;
|
||||
size_t encrypt_size;
|
||||
|
||||
/* 300: Adds some slop. */
|
||||
- if (SIZE_MAX - 300 < message->length)
|
||||
- return ENOMEM;
|
||||
+ if (SIZE_MAX - 300 < message->length) {
|
||||
+ err = ENOMEM;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
ec_max = SIZE_MAX - message->length - 300;
|
||||
if (ec_max > 0xffff)
|
||||
ec_max = 0xffff;
|
||||
@@ -126,20 +131,20 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
|
||||
#endif
|
||||
err = alloc_data(&plain, message->length + 16 + ec);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto cleanup;
|
||||
|
||||
/* Get size of ciphertext. */
|
||||
encrypt_size = krb5_encrypt_size(plain.length, key->keyblock.enctype);
|
||||
if (encrypt_size > SIZE_MAX / 2) {
|
||||
err = ENOMEM;
|
||||
- goto error;
|
||||
+ goto cleanup;
|
||||
}
|
||||
bufsize = 16 + encrypt_size;
|
||||
/* Allocate space for header plus encrypted data. */
|
||||
outbuf = gssalloc_malloc(bufsize);
|
||||
if (outbuf == NULL) {
|
||||
- free(plain.data);
|
||||
- return ENOMEM;
|
||||
+ err = ENOMEM;
|
||||
+ goto cleanup;
|
||||
}
|
||||
|
||||
/* TOK_ID */
|
||||
@@ -164,11 +169,8 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
|
||||
cipher.ciphertext.length = bufsize - 16;
|
||||
cipher.enctype = key->keyblock.enctype;
|
||||
err = krb5_k_encrypt(context, key, key_usage, 0, &plain, &cipher);
|
||||
- zap(plain.data, plain.length);
|
||||
- free(plain.data);
|
||||
- plain.data = 0;
|
||||
if (err)
|
||||
- goto error;
|
||||
+ goto cleanup;
|
||||
|
||||
/* Now that we know we're returning a valid token.... */
|
||||
ctx->seq_send++;
|
||||
@@ -181,7 +183,6 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
|
||||
/* If the rotate fails, don't worry about it. */
|
||||
#endif
|
||||
} else if (toktype == KG_TOK_WRAP_MSG && !conf_req_flag) {
|
||||
- krb5_data plain;
|
||||
size_t cksumsize;
|
||||
|
||||
/* Here, message is the application-supplied data; message2 is
|
||||
@@ -193,21 +194,19 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
|
||||
wrap_with_checksum:
|
||||
err = alloc_data(&plain, message->length + 16);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto cleanup;
|
||||
|
||||
err = krb5_c_checksum_length(context, cksumtype, &cksumsize);
|
||||
if (err)
|
||||
- goto error;
|
||||
+ goto cleanup;
|
||||
|
||||
assert(cksumsize <= 0xffff);
|
||||
|
||||
bufsize = 16 + message2->length + cksumsize;
|
||||
outbuf = gssalloc_malloc(bufsize);
|
||||
if (outbuf == NULL) {
|
||||
- free(plain.data);
|
||||
- plain.data = 0;
|
||||
err = ENOMEM;
|
||||
- goto error;
|
||||
+ goto cleanup;
|
||||
}
|
||||
|
||||
/* TOK_ID */
|
||||
@@ -239,23 +238,15 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
|
||||
if (message2->length)
|
||||
memcpy(outbuf + 16, message2->value, message2->length);
|
||||
|
||||
- sum.contents = outbuf + 16 + message2->length;
|
||||
- sum.length = cksumsize;
|
||||
-
|
||||
err = krb5_k_make_checksum(context, cksumtype, key,
|
||||
key_usage, &plain, &sum);
|
||||
- zap(plain.data, plain.length);
|
||||
- free(plain.data);
|
||||
- plain.data = 0;
|
||||
if (err) {
|
||||
zap(outbuf,bufsize);
|
||||
- goto error;
|
||||
+ goto cleanup;
|
||||
}
|
||||
if (sum.length != cksumsize)
|
||||
abort();
|
||||
memcpy(outbuf + 16 + message2->length, sum.contents, cksumsize);
|
||||
- krb5_free_checksum_contents(context, &sum);
|
||||
- sum.contents = 0;
|
||||
/* Now that we know we're actually generating the token... */
|
||||
ctx->seq_send++;
|
||||
|
||||
@@ -285,12 +276,13 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
|
||||
|
||||
token->value = outbuf;
|
||||
token->length = bufsize;
|
||||
- return 0;
|
||||
+ outbuf = NULL;
|
||||
+ err = 0;
|
||||
|
||||
-error:
|
||||
+cleanup:
|
||||
+ krb5_free_checksum_contents(context, &sum);
|
||||
+ zapfree(plain.data, plain.length);
|
||||
gssalloc_free(outbuf);
|
||||
- token->value = NULL;
|
||||
- token->length = 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
diff --git a/src/lib/rpc/pmap_rmt.c b/src/lib/rpc/pmap_rmt.c
|
||||
index 434e4eea65..f55ca46c60 100644
|
||||
--- a/src/lib/rpc/pmap_rmt.c
|
||||
+++ b/src/lib/rpc/pmap_rmt.c
|
||||
@@ -161,12 +161,12 @@ xdr_rmtcallres(
|
||||
caddr_t port_ptr;
|
||||
|
||||
port_ptr = (caddr_t)(void *)crp->port_ptr;
|
||||
- if (xdr_reference(xdrs, &port_ptr, sizeof (uint32_t),
|
||||
- (xdrproc_t)xdr_u_int32) &&
|
||||
- xdr_u_int32(xdrs, &crp->resultslen)) {
|
||||
- crp->port_ptr = (uint32_t *)(void *)port_ptr;
|
||||
+ if (!xdr_reference(xdrs, &port_ptr, sizeof (uint32_t),
|
||||
+ (xdrproc_t)xdr_u_int32))
|
||||
+ return (FALSE);
|
||||
+ crp->port_ptr = (uint32_t *)(void *)port_ptr;
|
||||
+ if (xdr_u_int32(xdrs, &crp->resultslen))
|
||||
return ((*(crp->xdr_results))(xdrs, crp->results_ptr));
|
||||
- }
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
--
|
||||
2.45.1
|
||||
|
@ -0,0 +1 @@
|
||||
*/admin@EXAMPLE.COM *
|
@ -0,0 +1,15 @@
|
||||
[Unit]
|
||||
Description=Kerberos 5 Password-changing and Administration
|
||||
Wants=network-online.target
|
||||
After=syslog.target network.target network-online.target
|
||||
AssertPathExists=!/var/kerberos/krb5kdc/kpropd.acl
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
PIDFile=/run/kadmind.pid
|
||||
EnvironmentFile=-/etc/sysconfig/kadmin
|
||||
ExecStart=/usr/sbin/kadmind -P /run/kadmind.pid $KADMIND_ARGS
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
@ -0,0 +1 @@
|
||||
KADMIND_ARGS=
|
@ -0,0 +1,9 @@
|
||||
/var/log/kadmind.log {
|
||||
missingok
|
||||
notifempty
|
||||
monthly
|
||||
rotate 12
|
||||
postrotate
|
||||
systemctl reload kadmin.service || true
|
||||
endscript
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
[kdcdefaults]
|
||||
kdc_ports = 88
|
||||
kdc_tcp_ports = 88
|
||||
spake_preauth_kdc_challenge = edwards25519
|
||||
|
||||
[realms]
|
||||
EXAMPLE.COM = {
|
||||
master_key_type = aes256-cts-hmac-sha384-192
|
||||
acl_file = /var/kerberos/krb5kdc/kadm5.acl
|
||||
dict_file = /usr/share/dict/words
|
||||
default_principal_flags = +preauth
|
||||
admin_keytab = /var/kerberos/krb5kdc/kadm5.keytab
|
||||
supported_enctypes = aes256-cts-hmac-sha384-192:normal aes128-cts-hmac-sha256-128:normal aes256-cts-hmac-sha1-96:normal aes128-cts-hmac-sha1-96:normal camellia256-cts-cmac:normal camellia128-cts-cmac:normal arcfour-hmac-md5:normal
|
||||
# Supported encryption types for FIPS mode:
|
||||
#supported_enctypes = aes256-cts-hmac-sha384-192:normal aes128-cts-hmac-sha256-128:normal
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
[Unit]
|
||||
Description=Kerberos 5 Propagation
|
||||
Wants=network-online.target
|
||||
After=syslog.target network.target network-online.target
|
||||
AssertPathExists=/var/kerberos/krb5kdc/kpropd.acl
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
EnvironmentFile=-/etc/sysconfig/kprop
|
||||
ExecStart=/usr/sbin/kpropd $KPROPD_ARGS
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
@ -0,0 +1 @@
|
||||
KPROPD_ARGS=
|
@ -0,0 +1,16 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQIzBAABCgAdFiEExEk8tzn0qJ+YUsvCDLoIV1+Dct8FAmZ8eHkACgkQDLoIV1+D
|
||||
ct//gw//bmvy6zXbKL6epNaExVgRdqzfQWm6WqeyGNxg59BQyJwsRsArsQRbSTZl
|
||||
uUExbV4HDTI/SemnYT8MfNOUtGZBCcAMYUr79Zmwi9S2pc30ZHIGcOf5E7HvIj6y
|
||||
ZZUvddoxWvxpruCuJHb9dP4ZUPE0iU2rJnLsXR/H4E574WlrWBjXu3gimLen7+yg
|
||||
aCLxIvw6lk4f/X8l+aqbK+haWHwMnca+kWSPbmL2iblHVqmoJVEmWhy7/9WjiT5S
|
||||
5HhDJIObO2qn1pbE1ZTQqfGOfFgOUVxTl2myMxX1RXEDVFzdLDdnoUJRt4o4GG27
|
||||
Y0WfLtmN6NisVF91dkl2+F7js+xVI3m9uZnpeccKO2Uq6BQRrfOMWUAHVKMUJZjh
|
||||
h0GMeTzOhw7qGKitAiuhauyDMMTgMx78bC0DpLYtq24fp7BSvD0jNZnfjUXVCk8D
|
||||
al9cfxC5m843aKiJ01Of13PziZsTQFz/TUsOrcpx4h7+qY7nldrovkQBiyVbbtn4
|
||||
MncYq8d84G/0vsbJ/6ftJ6Y+OL20jyzfC5xgmKtK/y1D987aum2BSudISUCylOOt
|
||||
j5/KiTRe0rWUjBNtoCjrtw4xlSbygmjuiE/xtcow0CHXDtMjlo8PrDi8W+xccBv2
|
||||
zQ2B+e9ywkF4uC/M91s/bVSMkOtxv2JCoUUHOMF4ku5vzKSOhyk=
|
||||
=TH0A
|
||||
-----END PGP SIGNATURE-----
|
@ -0,0 +1 @@
|
||||
d /run/krb5kdc 0755 root root
|
@ -0,0 +1,18 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
export RPM_PACKAGE_NAME={{ name }}
|
||||
export RPM_PACKAGE_VERSION={{ version }}
|
||||
export RPM_PACKAGE_RELEASE={{ release }}
|
||||
export RPM_ARCH={{ arch }}
|
||||
export RPM_BUILD_NCPUS="$(getconf _NPROCESSORS_ONLN)"
|
||||
|
||||
testdir="$(mktemp -d)"
|
||||
trap "rm -rf ${testdir}" EXIT
|
||||
|
||||
build_flags="$(eval "echo $(rpm --eval '%{_smp_mflags}')")"
|
||||
|
||||
mkdir "${testdir}/{{ name }}-tests"
|
||||
cp -rp /usr/share/{{ name }}-tests/{{ arch }} "${testdir}/{{ name }}-tests/"
|
||||
make -C "${testdir}/{{ name }}-tests/{{ arch }}/" $build_flags
|
||||
keyctl session - make -C "${testdir}/{{ name }}-tests/{{ arch }}/" check
|
@ -0,0 +1,30 @@
|
||||
# To opt out of the system crypto-policies configuration of krb5, remove the
|
||||
# symlink at /etc/krb5.conf.d/crypto-policies which will not be recreated.
|
||||
includedir /etc/krb5.conf.d/
|
||||
|
||||
[logging]
|
||||
default = FILE:/var/log/krb5libs.log
|
||||
kdc = FILE:/var/log/krb5kdc.log
|
||||
admin_server = FILE:/var/log/kadmind.log
|
||||
|
||||
[libdefaults]
|
||||
dns_lookup_realm = false
|
||||
ticket_lifetime = 24h
|
||||
renew_lifetime = 7d
|
||||
forwardable = true
|
||||
rdns = false
|
||||
pkinit_anchors = FILE:/etc/pki/tls/certs/ca-bundle.crt
|
||||
spake_preauth_groups = edwards25519
|
||||
dns_canonicalize_hostname = fallback
|
||||
qualify_shortname = ""
|
||||
# default_realm = EXAMPLE.COM
|
||||
|
||||
[realms]
|
||||
# EXAMPLE.COM = {
|
||||
# kdc = kerberos.example.com
|
||||
# admin_server = kerberos.example.com
|
||||
# }
|
||||
|
||||
[domain_realm]
|
||||
# .example.com = EXAMPLE.COM
|
||||
# example.com = EXAMPLE.COM
|
@ -0,0 +1,9 @@
|
||||
/var/log/krb5kdc.log {
|
||||
missingok
|
||||
notifempty
|
||||
monthly
|
||||
rotate 12
|
||||
postrotate
|
||||
systemctl reload krb5kdc.service || true
|
||||
endscript
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
[Unit]
|
||||
Description=Kerberos 5 KDC
|
||||
Wants=network-online.target
|
||||
After=syslog.target network.target network-online.target
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
PIDFile=/run/krb5kdc.pid
|
||||
EnvironmentFile=-/etc/sysconfig/krb5kdc
|
||||
ExecStart=/usr/sbin/krb5kdc -P /run/krb5kdc.pid $KRB5KDC_ARGS
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
@ -0,0 +1 @@
|
||||
KRB5KDC_ARGS=
|
@ -0,0 +1,4 @@
|
||||
#%PAM-1.0
|
||||
auth include su
|
||||
account include su
|
||||
session include su
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue