Toshaan Bharvani
6 months ago
17 changed files with 10482 additions and 412 deletions
@ -0,0 +1,310 @@
@@ -0,0 +1,310 @@
|
||||
From 93bb4f5ba6fd79e72a75de20e209db219118a3a1 Mon Sep 17 00:00:00 2001 |
||||
From: Julien Rische <jrische@redhat.com> |
||||
Date: Wed, 2 Aug 2023 10:19:28 +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.41.0 |
||||
|
@ -0,0 +1,777 @@
@@ -0,0 +1,777 @@
|
||||
From d7be72b066a9b07f0426780c7931614eddf9dd9e 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.41.0 |
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,44 @@
@@ -0,0 +1,44 @@
|
||||
From 780db3e904ada1946b0d1dce04c8daa74273c7b6 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.41.0 |
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,612 @@
@@ -0,0 +1,612 @@
|
||||
From 2dc9988da95cdd76335a00007b262272ca8c45b3 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.41.0 |
||||
|
@ -0,0 +1,81 @@
@@ -0,0 +1,81 @@
|
||||
From 343e4042abdec8697d2c30eb84f70bdbd8388302 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.41.0 |
||||
|
@ -0,0 +1,41 @@
@@ -0,0 +1,41 @@
|
||||
From aa0556348373d6aca0a1bda96fe7a47888051d33 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.41.0 |
||||
|
@ -0,0 +1,120 @@
@@ -0,0 +1,120 @@
|
||||
From 52904f3693397dace4e9ef5db1cd7d14eaa3b1fb 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.41.0 |
||||
|
@ -0,0 +1,31 @@
@@ -0,0 +1,31 @@
|
||||
From f9429a9944b056376a1ff06e84dbf7e94f0d3108 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.41.0 |
||||
|
@ -0,0 +1,165 @@
@@ -0,0 +1,165 @@
|
||||
From c002d03cce1c82e74a0c76b323c1bf1e619d022e 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.41.0 |
||||
|
@ -0,0 +1,279 @@
@@ -0,0 +1,279 @@
|
||||
From 83c99246ae9b157e462142daddccca5e18c2f3fd 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 350bcf86f2..17e1b52266 100644 |
||||
--- a/src/include/krb5/krb5.hin |
||||
+++ b/src/include/krb5/krb5.hin |
||||
@@ -8356,6 +8356,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 c29638a227..1da1609cc8 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.41.0 |
||||
|
@ -0,0 +1,47 @@
@@ -0,0 +1,47 @@
|
||||
From fef5896463a50e94d3a68f59f7c78a6e943ac5ad 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 f41328763e..263ef7845e 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.41.0 |
||||
|
@ -0,0 +1,217 @@
@@ -0,0 +1,217 @@
|
||||
From 906d3441b846ed09882490b6128db6fedf39e63b 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) |
||||
--- |
||||
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 263ef7845e..d646073d55 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 |
||||
@@ -2910,11 +2918,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; |
||||
@@ -3210,19 +3218,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.41.0 |
||||
|
@ -0,0 +1,48 @@
@@ -0,0 +1,48 @@
|
||||
From 137e424f7ae7c054e1dcb41c929a961bb021ed8b Mon Sep 17 00:00:00 2001 |
||||
From: Andreas Schneider <asn@samba.org> |
||||
Date: Fri, 4 Aug 2023 09:54:06 +0200 |
||||
Subject: [PATCH] Fix double-free in KDC TGS processing |
||||
|
||||
When issuing a ticket for a TGS renew or validate request, copy only |
||||
the server field from the outer part of the header ticket to the new |
||||
ticket. Copying the whole structure causes the enc_part pointer to be |
||||
aliased to the header ticket until krb5_encrypt_tkt_part() is called, |
||||
resulting in a double-free if handle_authdata() fails. |
||||
|
||||
[ghudson@mit.edu: changed the fix to avoid aliasing enc_part rather |
||||
than check for aliasing before freeing; rewrote commit message] |
||||
|
||||
CVE-2023-39975: |
||||
|
||||
In MIT krb5 release 1.21, an authenticated attacker can cause a KDC to |
||||
free the same pointer twice if it can induce a failure in |
||||
authorization data handling. |
||||
|
||||
ticket: 9101 (new) |
||||
tags: pullup |
||||
target_version: 1.21-next |
||||
|
||||
(cherry picked from commit 88a1701b423c13991a8064feeb26952d3641d840) |
||||
--- |
||||
src/kdc/do_tgs_req.c | 5 +++-- |
||||
1 file changed, 3 insertions(+), 2 deletions(-) |
||||
|
||||
diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c |
||||
index 6e4c8fa9f3..0acc45850f 100644 |
||||
--- a/src/kdc/do_tgs_req.c |
||||
+++ b/src/kdc/do_tgs_req.c |
||||
@@ -1010,8 +1010,9 @@ tgs_issue_ticket(kdc_realm_t *realm, struct tgs_req_info *t, |
||||
} |
||||
|
||||
if (t->req->kdc_options & (KDC_OPT_VALIDATE | KDC_OPT_RENEW)) { |
||||
- /* Copy the whole header ticket except for authorization data. */ |
||||
- ticket_reply = *t->header_tkt; |
||||
+ /* Copy the header ticket server and all enc-part fields except for |
||||
+ * authorization data. */ |
||||
+ ticket_reply.server = t->header_tkt->server; |
||||
enc_tkt_reply = *t->header_tkt->enc_part2; |
||||
enc_tkt_reply.authorization_data = NULL; |
||||
} else { |
||||
-- |
||||
2.41.0 |
||||
|
Loading…
Reference in new issue