Compare commits

..

7 commits

Author SHA1 Message Date
Robbie Harwood
95cc3ea977 Explicitly use openssl rather than builtin crypto
Resolves: #1570910
2018-04-23 17:14:30 +00:00
Robbie Harwood
6208c03017 Continue after KRB5_CC_END in KCM cache iteration 2018-03-29 10:50:19 -04:00
Robbie Harwood
466fd80d0e Fix flaws in LDAP DN checking
CVE-2018-5729, CVE-2018-5730
2018-02-13 16:11:54 +00:00
Robbie Harwood
702b0a90b5 Fix leak in previous commit
Resolves: #1540939
2018-02-12 17:43:03 +00:00
Robbie Harwood
ee2993187a Process include directories in alphabetical order 2018-01-29 16:52:05 +00:00
Robbie Harwood
1884c63c38 Fix CVE-2017-15088 (Buffer overflow in get_matching_data()) 2017-10-24 15:59:37 -04:00
Robbie Harwood
91465b2b09 Drop dependency on python2-pyrad (dead upstream, broken with new python) 2017-10-23 16:52:46 +00:00
119 changed files with 23887 additions and 33019 deletions

View file

@ -1 +0,0 @@
1

146
.gitignore vendored
View file

@ -1,50 +1,49 @@
/results_krb5
/krb5-1.3.4.tar.gz
/krb5-1.3.5.tar.gz
/krb5-1.3.5.tar.gz.asc
/krb5-1.3.6.tar.gz
/krb5-1.3.6.tar.gz.asc
/krb5-1.4.tar.gz
/krb5-1.4.tar.gz.asc
/krb5-1.4.1.tar.gz
/krb5-1.4.1.tar.gz.asc
/krb5-1.4.2.tar.gz
/krb5-1.4.2.tar.gz.asc
/krb5-1.4.3.tar.gz
/krb5-1.4.3.tar.gz.asc
/krb5-1.5.tar.gz
/krb5-1.5.tar.gz.asc
/krb5-1.6.tar.gz
/krb5-1.6.tar.gz.asc
/krb5-1.6-pdf.tar.gz
/krb5-1.6.1.tar.gz
/krb5-1.6.1.tar.gz.asc
/krb5-1.6.1-pdf.tar.gz
/krb5-1.6.2.tar.gz
/krb5-1.6.2.tar.gz.asc
/krb5-1.6.2-pdf.tar.gz
/krb5-1.6.3.tar.gz
/krb5-1.6.3.tar.gz.asc
/krb5-1.6.3-pdf.tar.gz
/krb5-1.7.tar.gz
/krb5-1.7.tar.gz.asc
/krb5-1.7-pdf.tar.gz
/krb5-1.7.1.tar.gz
/krb5-1.7.1.tar.gz.asc
/krb5-1.7.1-pdf.tar.gz
/krb5-1.8.tar.gz
/krb5-1.8.tar.gz.asc
/krb5-appl-1.0.tar.gz
/krb5-appl-1.0.tar.gz.asc
/krb5-1.8-pdf.tar.gz
/krb5-1.8.1.tar.gz
/krb5-1.8.1.tar.gz.asc
/krb5-1.8.1-pdf.tar.gz
/krb5-1.8.2.tar.gz.asc
/krb5-1.8.2-pdf.tar.gz
/krb5-1.8.3.tar.gz
/krb5-1.8.3.tar.gz.asc
/krb5-1.8.3-pdf.tar.gz
krb5-1.3.4.tar.gz
krb5-1.3.5.tar.gz
krb5-1.3.5.tar.gz.asc
krb5-1.3.6.tar.gz
krb5-1.3.6.tar.gz.asc
krb5-1.4.tar.gz
krb5-1.4.tar.gz.asc
krb5-1.4.1.tar.gz
krb5-1.4.1.tar.gz.asc
krb5-1.4.2.tar.gz
krb5-1.4.2.tar.gz.asc
krb5-1.4.3.tar.gz
krb5-1.4.3.tar.gz.asc
krb5-1.5.tar.gz
krb5-1.5.tar.gz.asc
krb5-1.6.tar.gz
krb5-1.6.tar.gz.asc
krb5-1.6-pdf.tar.gz
krb5-1.6.1.tar.gz
krb5-1.6.1.tar.gz.asc
krb5-1.6.1-pdf.tar.gz
krb5-1.6.2.tar.gz
krb5-1.6.2.tar.gz.asc
krb5-1.6.2-pdf.tar.gz
krb5-1.6.3.tar.gz
krb5-1.6.3.tar.gz.asc
krb5-1.6.3-pdf.tar.gz
krb5-1.7.tar.gz
krb5-1.7.tar.gz.asc
krb5-1.7-pdf.tar.gz
krb5-1.7.1.tar.gz
krb5-1.7.1.tar.gz.asc
krb5-1.7.1-pdf.tar.gz
krb5-1.8.tar.gz
krb5-1.8.tar.gz.asc
krb5-appl-1.0.tar.gz
krb5-appl-1.0.tar.gz.asc
krb5-1.8-pdf.tar.gz
krb5-1.8.1.tar.gz
krb5-1.8.1.tar.gz.asc
krb5-1.8.1-pdf.tar.gz
krb5-1.8.2.tar.gz.asc
krb5-1.8.2-pdf.tar.gz
krb5-1.8.3.tar.gz
krb5-1.8.3.tar.gz.asc
krb5-1.8.3-pdf.tar.gz
/krb5-1.9-beta2.tar.gz
/krb5-1.9-beta2.tar.gz.asc
/krb5-1.9-beta2-pdf.tar.bz2
@ -155,56 +154,3 @@
/krb5-1.15.2-pdfs.tar
/krb5-1.15.2.tar.gz
/krb5-1.15.2.tar.gz.asc
/krb5-1.16-beta1-pdfs.tar
/krb5-1.16-beta1.tar.gz
/krb5-1.16-beta1.tar.gz.asc
/krb5-1.16-beta2.tar.gz
/krb5-1.16-beta2.tar.gz.asc
/krb5-1.16-beta2-pdfs.tar
/krb5-1.16-pdfs.tar
/krb5-1.16.tar.gz
/krb5-1.16.tar.gz.asc
/krb5-1.16.1-pdfs.tar
/krb5-1.16.1.tar.gz
/krb5-1.16.1.tar.gz.asc
/krb5-1.17-beta1.tar.gz
/krb5-1.17-beta1.tar.gz.asc
/krb5-1.17-beta1-pdfs.tar
/krb5-1.17-beta2.tar.gz
/krb5-1.17-beta2.tar.gz.asc
/krb5-1.17-beta2-pdfs.tar
/krb5-1.17-pdfs.tar
/krb5-1.17.tar.gz
/krb5-1.17.tar.gz.asc
/krb5-1.17.1.tar.gz
/krb5-1.17.1.tar.gz.asc
/krb5-1.18-beta1.tar.gz
/krb5-1.18-beta1.tar.gz.asc
/krb5-1.18-beta2.tar.gz
/krb5-1.18-beta2.tar.gz.asc
/krb5-1.18.tar.gz
/krb5-1.18.tar.gz.asc
/krb5-1.18.1.tar.gz
/krb5-1.18.1.tar.gz.asc
/krb5-1.18.2.tar.gz
/krb5-1.18.2.tar.gz.asc
/krb5-1.18.3.tar.gz
/krb5-1.18.3.tar.gz.asc
/krb5-1.19-beta1.tar.gz
/krb5-1.19-beta1.tar.gz.asc
/krb5-1.19-beta2.tar.gz
/krb5-1.19-beta2.tar.gz.asc
/krb5-1.19.tar.gz
/krb5-1.19.tar.gz.asc
/krb5-1.19.1.tar.gz
/krb5-1.19.1.tar.gz.asc
/krb5-1.19.2.tar.gz
/krb5-1.19.2.tar.gz.asc
/krb5-1.20.1.tar.gz
/krb5-1.20.1.tar.gz.asc
/krb5-1.21.tar.gz
/krb5-1.21.tar.gz.asc
/krb5-1.21.2.tar.gz
/krb5-1.21.2.tar.gz.asc
/krb5-1.21.3.tar.gz
/krb5-1.21.3.tar.gz.asc

View file

@ -1,310 +0,0 @@
From 6f7fd964539dfe4a885068f43a91db9738661870 Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Tue, 9 Jul 2024 11:15:33 +0200
Subject: [PATCH] [downstream] Revert "Don't issue session keys with
deprecated enctypes"
This reverts commit 1b57a4d134bbd0e7c52d5885a92eccc815726463.
---
doc/admin/conf_files/krb5_conf.rst | 12 ------------
doc/admin/enctypes.rst | 23 +++-------------------
src/include/k5-int.h | 4 ----
src/kdc/kdc_util.c | 10 ----------
src/lib/krb5/krb/get_in_tkt.c | 31 +++++++++++-------------------
src/lib/krb5/krb/init_ctx.c | 10 ----------
src/tests/gssapi/t_enctypes.py | 3 +--
src/tests/t_etype_info.py | 2 +-
src/tests/t_sesskeynego.py | 28 ++-------------------------
src/util/k5test.py | 4 ++--
10 files changed, 20 insertions(+), 107 deletions(-)
diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
index ecdf917501..f22d5db11b 100644
--- a/doc/admin/conf_files/krb5_conf.rst
+++ b/doc/admin/conf_files/krb5_conf.rst
@@ -95,18 +95,6 @@ Additionally, krb5.conf may include any of the relations described in
The libdefaults section may contain any of the following relations:
-**allow_des3**
- Permit the KDC to issue tickets with des3-cbc-sha1 session keys.
- In future releases, this flag will allow des3-cbc-sha1 to be used
- at all. The default value for this tag is false. (Added in
- release 1.21.)
-
-**allow_rc4**
- Permit the KDC to issue tickets with arcfour-hmac session keys.
- In future releases, this flag will allow arcfour-hmac to be used
- at all. The default value for this tag is false. (Added in
- release 1.21.)
-
**allow_weak_crypto**
If this flag is set to false, then weak encryption types (as noted
in :ref:`Encryption_types` in :ref:`kdc.conf(5)`) will be filtered
diff --git a/doc/admin/enctypes.rst b/doc/admin/enctypes.rst
index dce19ad43e..694922c0d9 100644
--- a/doc/admin/enctypes.rst
+++ b/doc/admin/enctypes.rst
@@ -48,15 +48,12 @@ Session key selection
The KDC chooses the session key enctype by taking the intersection of
its **permitted_enctypes** list, the list of long-term keys for the
most recent kvno of the service, and the client's requested list of
-enctypes. Starting in krb5-1.21, all services are assumed to support
-aes256-cts-hmac-sha1-96; also, des3-cbc-sha1 and arcfour-hmac session
-keys will not be issued by default.
+enctypes.
Starting in krb5-1.11, it is possible to set a string attribute on a
service principal to control what session key enctypes the KDC may
-issue for service tickets for that principal, overriding the service's
-long-term keys and the assumption of aes256-cts-hmac-sha1-96 support.
-See :ref:`set_string` in :ref:`kadmin(1)` for details.
+issue for service tickets for that principal. See :ref:`set_string`
+in :ref:`kadmin(1)` for details.
Choosing enctypes for a service
@@ -90,20 +87,6 @@ affect how enctypes are chosen.
acceptable risk for your environment and the weak enctypes are
required for backward compatibility.
-**allow_des3**
- was added in release 1.21 and defaults to *false*. Unless this
- flag is set to *true*, the KDC will not issue tickets with
- des3-cbc-sha1 session keys. In a future release, this flag will
- control whether des3-cbc-sha1 is permitted in similar fashion to
- weak enctypes.
-
-**allow_rc4**
- was added in release 1.21 and defaults to *false*. Unless this
- flag is set to *true*, the KDC will not issue tickets with
- arcfour-hmac session keys. In a future release, this flag will
- control whether arcfour-hmac is permitted in similar fashion to
- weak enctypes.
-
**permitted_enctypes**
controls the set of enctypes that a service will permit for
session keys and for ticket and authenticator encryption. The KDC
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index 2f7791b775..1d1c8293f4 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -180,8 +180,6 @@ typedef unsigned char u_char;
* matches the variable name. Keep these alphabetized. */
#define KRB5_CONF_ACL_FILE "acl_file"
#define KRB5_CONF_ADMIN_SERVER "admin_server"
-#define KRB5_CONF_ALLOW_DES3 "allow_des3"
-#define KRB5_CONF_ALLOW_RC4 "allow_rc4"
#define KRB5_CONF_ALLOW_WEAK_CRYPTO "allow_weak_crypto"
#define KRB5_CONF_AUTH_TO_LOCAL "auth_to_local"
#define KRB5_CONF_AUTH_TO_LOCAL_NAMES "auth_to_local_names"
@@ -1240,8 +1238,6 @@ struct _krb5_context {
struct _kdb_log_context *kdblog_context;
krb5_boolean allow_weak_crypto;
- krb5_boolean allow_des3;
- krb5_boolean allow_rc4;
krb5_boolean ignore_acceptor_hostname;
krb5_boolean enforce_ok_as_delegate;
enum dns_canonhost dns_canonicalize_hostname;
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
index e54cc751f9..75e04b73db 100644
--- a/src/kdc/kdc_util.c
+++ b/src/kdc/kdc_util.c
@@ -1088,16 +1088,6 @@ select_session_keytype(krb5_context context, krb5_db_entry *server,
if (!krb5_is_permitted_enctype(context, ktype[i]))
continue;
- /*
- * Prevent these deprecated enctypes from being used as session keys
- * unless they are explicitly allowed. In the future they will be more
- * comprehensively disabled and eventually removed.
- */
- if (ktype[i] == ENCTYPE_DES3_CBC_SHA1 && !context->allow_des3)
- continue;
- if (ktype[i] == ENCTYPE_ARCFOUR_HMAC && !context->allow_rc4)
- continue;
-
if (dbentry_supports_enctype(context, server, ktype[i]))
return ktype[i];
}
diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
index ea089f0fcc..1b420a3ac2 100644
--- a/src/lib/krb5/krb/get_in_tkt.c
+++ b/src/lib/krb5/krb/get_in_tkt.c
@@ -1582,31 +1582,22 @@ warn_pw_expiry(krb5_context context, krb5_get_init_creds_opt *options,
(*prompter)(context, data, 0, banner, 0, 0);
}
-/* Display a warning via the prompter if a deprecated enctype was used for
- * either the reply key or the session key. */
+/* Display a warning via the prompter if des3-cbc-sha1 was used for either the
+ * reply key or the session key. */
static void
-warn_deprecated(krb5_context context, krb5_init_creds_context ctx,
- krb5_enctype as_key_enctype)
+warn_des3(krb5_context context, krb5_init_creds_context ctx,
+ krb5_enctype as_key_enctype)
{
- krb5_enctype etype;
- char encbuf[128], banner[256];
+ const char *banner;
- if (ctx->prompter == NULL)
- return;
-
- if (krb5int_c_deprecated_enctype(as_key_enctype))
- etype = as_key_enctype;
- else if (krb5int_c_deprecated_enctype(ctx->cred.keyblock.enctype))
- etype = ctx->cred.keyblock.enctype;
- else
+ if (as_key_enctype != ENCTYPE_DES3_CBC_SHA1 &&
+ ctx->cred.keyblock.enctype != ENCTYPE_DES3_CBC_SHA1)
return;
-
- if (krb5_enctype_to_name(etype, FALSE, encbuf, sizeof(encbuf)) != 0)
+ if (ctx->prompter == NULL)
return;
- snprintf(banner, sizeof(banner),
- _("Warning: encryption type %s used for authentication is "
- "deprecated and will be disabled"), encbuf);
+ banner = _("Warning: encryption type des3-cbc-sha1 used for "
+ "authentication is weak and will be disabled");
/* PROMPTER_INVOCATION */
(*ctx->prompter)(context, ctx->prompter_data, NULL, banner, 0, NULL);
}
@@ -1857,7 +1848,7 @@ init_creds_step_reply(krb5_context context,
ctx->complete = TRUE;
warn_pw_expiry(context, ctx->opt, ctx->prompter, ctx->prompter_data,
ctx->in_tkt_service, ctx->reply);
- warn_deprecated(context, ctx, encrypting_key.enctype);
+ warn_des3(context, ctx, encrypting_key.enctype);
cleanup:
krb5_free_pa_data(context, kdc_padata);
diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c
index a6c2bbeb54..87b486c53f 100644
--- a/src/lib/krb5/krb/init_ctx.c
+++ b/src/lib/krb5/krb/init_ctx.c
@@ -221,16 +221,6 @@ krb5_init_context_profile(profile_t profile, krb5_flags flags,
goto cleanup;
ctx->allow_weak_crypto = tmp;
- retval = get_boolean(ctx, KRB5_CONF_ALLOW_DES3, 0, &tmp);
- if (retval)
- goto cleanup;
- ctx->allow_des3 = tmp;
-
- retval = get_boolean(ctx, KRB5_CONF_ALLOW_RC4, 0, &tmp);
- if (retval)
- goto cleanup;
- ctx->allow_rc4 = tmp;
-
retval = get_boolean(ctx, KRB5_CONF_IGNORE_ACCEPTOR_HOSTNAME, 0, &tmp);
if (retval)
goto cleanup;
diff --git a/src/tests/gssapi/t_enctypes.py b/src/tests/gssapi/t_enctypes.py
index f5f11842e2..7494d7fcdb 100755
--- a/src/tests/gssapi/t_enctypes.py
+++ b/src/tests/gssapi/t_enctypes.py
@@ -18,8 +18,7 @@ d_rc4 = 'DEPRECATED:arcfour-hmac'
# These tests make assumptions about the default enctype lists, so set
# them explicitly rather than relying on the library defaults.
supp='aes256-cts:normal aes128-cts:normal des3-cbc-sha1:normal rc4-hmac:normal'
-conf = {'libdefaults': {'permitted_enctypes': 'aes des3 rc4',
- 'allow_des3': 'true', 'allow_rc4': 'true'},
+conf = {'libdefaults': {'permitted_enctypes': 'aes des3 rc4'},
'realms': {'$realm': {'supported_enctypes': supp}}}
realm = K5Realm(krb5_conf=conf)
shutil.copyfile(realm.ccache, os.path.join(realm.testdir, 'save'))
diff --git a/src/tests/t_etype_info.py b/src/tests/t_etype_info.py
index 38cf96ca8f..c982508d8b 100644
--- a/src/tests/t_etype_info.py
+++ b/src/tests/t_etype_info.py
@@ -1,7 +1,7 @@
from k5test import *
supported_enctypes = 'aes128-cts des3-cbc-sha1 rc4-hmac'
-conf = {'libdefaults': {'allow_des3': 'true', 'allow_rc4': 'true'},
+conf = {'libdefaults': {'allow_weak_crypto': 'true'},
'realms': {'$realm': {'supported_enctypes': supported_enctypes}}}
realm = K5Realm(create_host=False, get_creds=False, krb5_conf=conf)
diff --git a/src/tests/t_sesskeynego.py b/src/tests/t_sesskeynego.py
index 5a213617b5..9024aee838 100755
--- a/src/tests/t_sesskeynego.py
+++ b/src/tests/t_sesskeynego.py
@@ -25,8 +25,6 @@ conf3 = {'libdefaults': {
'default_tkt_enctypes': 'aes128-cts',
'default_tgs_enctypes': 'rc4-hmac,aes128-cts'}}
conf4 = {'libdefaults': {'permitted_enctypes': 'aes256-cts'}}
-conf5 = {'libdefaults': {'allow_rc4': 'true'}}
-conf6 = {'libdefaults': {'allow_des3': 'true'}}
# Test with client request and session_enctypes preferring aes128, but
# aes256 long-term key.
realm = K5Realm(krb5_conf=conf1, create_host=False, get_creds=False)
@@ -56,12 +54,10 @@ realm.run([kadminl, 'setstr', 'server', 'session_enctypes',
'aes128-cts,aes256-cts'])
test_kvno(realm, 'aes128-cts-hmac-sha1-96', 'aes256-cts-hmac-sha1-96')
-# 3b: Skip RC4 (as the KDC does not allow it for session keys by
-# default) and negotiate aes128-cts session key, with only an aes256
-# long-term service key.
+# 3b: Negotiate rc4-hmac session key when principal only has aes256 long-term.
realm.run([kadminl, 'setstr', 'server', 'session_enctypes',
'rc4-hmac,aes128-cts,aes256-cts'])
-test_kvno(realm, 'aes128-cts-hmac-sha1-96', 'aes256-cts-hmac-sha1-96')
+test_kvno(realm, 'DEPRECATED:arcfour-hmac', 'aes256-cts-hmac-sha1-96')
realm.stop()
# 4: Check that permitted_enctypes is a default for session key enctypes.
@@ -71,24 +67,4 @@ realm.run([kvno, 'user'],
expected_trace=('etypes requested in TGS request: aes256-cts',))
realm.stop()
-# 5: allow_rc4 permits negotiation of rc4-hmac session key.
-realm = K5Realm(krb5_conf=conf5, create_host=False, get_creds=False)
-realm.run([kadminl, 'addprinc', '-randkey', '-e', 'aes256-cts', 'server'])
-realm.run([kadminl, 'setstr', 'server', 'session_enctypes', 'rc4-hmac'])
-test_kvno(realm, 'DEPRECATED:arcfour-hmac', 'aes256-cts-hmac-sha1-96')
-realm.stop()
-
-# 6: allow_des3 permits negotiation of des3-cbc-sha1 session key.
-realm = K5Realm(krb5_conf=conf6, create_host=False, get_creds=False)
-realm.run([kadminl, 'addprinc', '-randkey', '-e', 'aes256-cts', 'server'])
-realm.run([kadminl, 'setstr', 'server', 'session_enctypes', 'des3-cbc-sha1'])
-test_kvno(realm, 'DEPRECATED:des3-cbc-sha1', 'aes256-cts-hmac-sha1-96')
-realm.stop()
-
-# 7: default config negotiates aes256-sha1 session key for RC4-only service.
-realm = K5Realm(create_host=False, get_creds=False)
-realm.run([kadminl, 'addprinc', '-randkey', '-e', 'rc4-hmac', 'server'])
-test_kvno(realm, 'aes256-cts-hmac-sha1-96', 'DEPRECATED:arcfour-hmac')
-realm.stop()
-
success('sesskeynego')
diff --git a/src/util/k5test.py b/src/util/k5test.py
index 8e5f5ba8e9..2a86c5cdfc 100644
--- a/src/util/k5test.py
+++ b/src/util/k5test.py
@@ -1340,14 +1340,14 @@ _passes = [
# Exercise the DES3 enctype.
('des3', None,
- {'libdefaults': {'permitted_enctypes': 'des3 aes256-sha1'}},
+ {'libdefaults': {'permitted_enctypes': 'des3'}},
{'realms': {'$realm': {
'supported_enctypes': 'des3-cbc-sha1:normal',
'master_key_type': 'des3-cbc-sha1'}}}),
# Exercise the arcfour enctype.
('arcfour', None,
- {'libdefaults': {'permitted_enctypes': 'rc4 aes256-sha1'}},
+ {'libdefaults': {'permitted_enctypes': 'rc4'}},
{'realms': {'$realm': {
'supported_enctypes': 'arcfour-hmac:normal',
'master_key_type': 'arcfour-hmac'}}}),
--
2.45.1

File diff suppressed because it is too large Load diff

View file

@ -1,612 +0,0 @@
From 7b6453903c248a761d3ceb538dfacebbf3d3a9ff Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Fri, 9 Nov 2018 15:12:21 -0500
Subject: [PATCH] [downstream] FIPS with PRNG and RADIUS and MD4
NB: Use openssl's PRNG in FIPS mode and taint within krad.
A lot of the FIPS error conditions from OpenSSL are incredibly
mysterious (at best, things return NULL unexpectedly; at worst,
internal assertions are tripped; most of the time, you just get
ENOMEM). In order to cope with this, we need to have some level of
awareness of what we can and can't safely call.
This will slow down some calls slightly (FIPS_mode() takes multiple
locks), but not for any ciphers we care about - which is to say that
AES is fine. Shame about SPAKE though.
post6 restores MD4 (and therefore keygen-only RC4).
post7 restores MD5 and adds radius_md5_fips_override.
post8 silences a static analyzer warning.
Last-updated: krb5-1.20
---
doc/admin/conf_files/krb5_conf.rst | 6 +++
src/lib/crypto/krb/prng.c | 15 +++++-
.../crypto/openssl/enc_provider/camellia.c | 6 +++
src/lib/crypto/openssl/enc_provider/rc4.c | 13 +++++-
.../crypto/openssl/hash_provider/hash_evp.c | 12 +++++
src/lib/crypto/openssl/hmac.c | 6 ++-
src/lib/krad/attr.c | 46 ++++++++++++++-----
src/lib/krad/attrset.c | 5 +-
src/lib/krad/internal.h | 28 ++++++++++-
src/lib/krad/packet.c | 22 +++++----
src/lib/krad/remote.c | 10 +++-
src/lib/krad/t_attr.c | 3 +-
src/lib/krad/t_attrset.c | 4 +-
src/plugins/preauth/spake/spake_client.c | 6 +++
src/plugins/preauth/spake/spake_kdc.c | 6 +++
15 files changed, 155 insertions(+), 33 deletions(-)
diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
index f22d5db11b..a33711d918 100644
--- a/doc/admin/conf_files/krb5_conf.rst
+++ b/doc/admin/conf_files/krb5_conf.rst
@@ -330,6 +330,12 @@ The libdefaults section may contain any of the following relations:
qualification of shortnames, set this relation to the empty string
with ``qualify_shortname = ""``. (New in release 1.18.)
+**radius_md5_fips_override**
+ Downstream-only option to enable use of MD5 in RADIUS
+ communication (libkrad). This allows for local (or protected
+ tunnel) communication with a RADIUS server that doesn't use krad
+ (e.g., freeradius) while in FIPS mode.
+
**rdns**
If this flag is true, reverse name lookup will be used in addition
to forward name lookup to canonicalizing hostnames for use in
diff --git a/src/lib/crypto/krb/prng.c b/src/lib/crypto/krb/prng.c
index d6b79e2dea..9e80a03d21 100644
--- a/src/lib/crypto/krb/prng.c
+++ b/src/lib/crypto/krb/prng.c
@@ -26,6 +26,12 @@
#include "crypto_int.h"
+#include <openssl/rand.h>
+
+#if OPENSSL_VERSION_NUMBER < 0x30000000L
+#include <openssl/crypto.h>
+#endif
+
krb5_error_code KRB5_CALLCONV
krb5_c_random_seed(krb5_context context, krb5_data *data)
{
@@ -96,9 +102,16 @@ cleanup:
static krb5_boolean
get_os_entropy(unsigned char *buf, size_t len)
{
-#if defined(__linux__) && defined(SYS_getrandom)
int r;
+ /* A wild FIPS mode appeared! */
+ if (FIPS_mode()) {
+ /* The return codes on this API are not good */
+ r = RAND_bytes(buf, len);
+ return r == 1;
+ }
+
+#if defined(__linux__) && defined(SYS_getrandom)
while (len > 0) {
/*
* Pull from the /dev/urandom pool, but require it to have been seeded.
diff --git a/src/lib/crypto/openssl/enc_provider/camellia.c b/src/lib/crypto/openssl/enc_provider/camellia.c
index 01920e6ce1..d9f327add6 100644
--- a/src/lib/crypto/openssl/enc_provider/camellia.c
+++ b/src/lib/crypto/openssl/enc_provider/camellia.c
@@ -387,6 +387,9 @@ krb5int_camellia_cbc_mac(krb5_key key, const krb5_crypto_iov *data,
unsigned char blockY[CAMELLIA_BLOCK_SIZE], blockB[CAMELLIA_BLOCK_SIZE];
struct iov_cursor cursor;
+ if (FIPS_mode())
+ return KRB5_CRYPTO_INTERNAL;
+
if (output->length < CAMELLIA_BLOCK_SIZE)
return KRB5_BAD_MSIZE;
@@ -418,6 +421,9 @@ static krb5_error_code
krb5int_camellia_init_state (const krb5_keyblock *key, krb5_keyusage usage,
krb5_data *state)
{
+ if (FIPS_mode())
+ return KRB5_CRYPTO_INTERNAL;
+
state->length = 16;
state->data = (void *) malloc(16);
if (state->data == NULL)
diff --git a/src/lib/crypto/openssl/enc_provider/rc4.c b/src/lib/crypto/openssl/enc_provider/rc4.c
index 448d563348..ce63cb5f1b 100644
--- a/src/lib/crypto/openssl/enc_provider/rc4.c
+++ b/src/lib/crypto/openssl/enc_provider/rc4.c
@@ -69,6 +69,9 @@ k5_arcfour_docrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data,
EVP_CIPHER_CTX *ctx = NULL;
struct arcfour_state *arcstate;
+ if (FIPS_mode())
+ return KRB5_CRYPTO_INTERNAL;
+
arcstate = (state != NULL) ? (void *)state->data : NULL;
if (arcstate != NULL) {
ctx = arcstate->ctx;
@@ -116,7 +119,12 @@ k5_arcfour_docrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data,
static void
k5_arcfour_free_state(krb5_data *state)
{
- struct arcfour_state *arcstate = (void *)state->data;
+ struct arcfour_state *arcstate;
+
+ if (FIPS_mode())
+ return;
+
+ arcstate = (void *) state->data;
EVP_CIPHER_CTX_free(arcstate->ctx);
free(arcstate);
@@ -128,6 +136,9 @@ k5_arcfour_init_state(const krb5_keyblock *key,
{
struct arcfour_state *arcstate;
+ if (FIPS_mode())
+ return KRB5_CRYPTO_INTERNAL;
+
/*
* The cipher state here is a saved pointer to a struct arcfour_state
* object, rather than a flat byte array as in most enc providers. The
diff --git a/src/lib/crypto/openssl/hash_provider/hash_evp.c b/src/lib/crypto/openssl/hash_provider/hash_evp.c
index f2fbffdb29..11659908bb 100644
--- a/src/lib/crypto/openssl/hash_provider/hash_evp.c
+++ b/src/lib/crypto/openssl/hash_provider/hash_evp.c
@@ -60,6 +60,11 @@ hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data,
if (ctx == NULL)
return ENOMEM;
+ if (type == EVP_md4() || type == EVP_md5()) {
+ /* See comments below in hash_md4() and hash_md5(). */
+ EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
+ }
+
ok = EVP_DigestInit_ex(ctx, type, NULL);
for (i = 0; i < num_data; i++) {
if (!SIGN_IOV(&data[i]))
@@ -78,6 +83,11 @@ hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data,
static krb5_error_code
hash_md4(const krb5_crypto_iov *data, size_t num_data, krb5_data *output)
{
+ /*
+ * MD4 is needed in FIPS mode to perform key generation for RC4 keys used
+ * by IPA. These keys are only used along a (separately) secured channel
+ * for legacy reasons when performing trusts to Active Directory.
+ */
return hash_evp(EVP_md4(), data, num_data, output);
}
@@ -90,6 +100,8 @@ const struct krb5_hash_provider krb5int_hash_md4 = {
static krb5_error_code
hash_md5(const krb5_crypto_iov *data, size_t num_data, krb5_data *output)
{
+ /* MD5 is needed in FIPS mode for communication with RADIUS servers. This
+ * is gated in libkrad by libdefaults->radius_md5_fips_override. */
return hash_evp(EVP_md5(), data, num_data, output);
}
diff --git a/src/lib/crypto/openssl/hmac.c b/src/lib/crypto/openssl/hmac.c
index bf12b8d6a0..f21e268f7f 100644
--- a/src/lib/crypto/openssl/hmac.c
+++ b/src/lib/crypto/openssl/hmac.c
@@ -111,7 +111,11 @@ map_digest(const struct krb5_hash_provider *hash)
return EVP_sha256();
else if (hash == &krb5int_hash_sha384)
return EVP_sha384();
- else if (hash == &krb5int_hash_md5)
+
+ if (FIPS_mode())
+ return NULL;
+
+ if (hash == &krb5int_hash_md5)
return EVP_md5();
else if (hash == &krb5int_hash_md4)
return EVP_md4();
diff --git a/src/lib/krad/attr.c b/src/lib/krad/attr.c
index 9c13d9d755..42d354a3b5 100644
--- a/src/lib/krad/attr.c
+++ b/src/lib/krad/attr.c
@@ -38,7 +38,8 @@
typedef krb5_error_code
(*attribute_transform_fn)(krb5_context ctx, const char *secret,
const unsigned char *auth, const krb5_data *in,
- unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen);
+ unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
+ krb5_boolean *is_fips);
typedef struct {
const char *name;
@@ -51,12 +52,14 @@ typedef struct {
static krb5_error_code
user_password_encode(krb5_context ctx, const char *secret,
const unsigned char *auth, const krb5_data *in,
- unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen);
+ unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
+ krb5_boolean *is_fips);
static krb5_error_code
user_password_decode(krb5_context ctx, const char *secret,
const unsigned char *auth, const krb5_data *in,
- unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen);
+ unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
+ krb5_boolean *ignored);
static const attribute_record attributes[UCHAR_MAX] = {
{"User-Name", 1, MAX_ATTRSIZE, NULL, NULL},
@@ -128,7 +131,8 @@ static const attribute_record attributes[UCHAR_MAX] = {
static krb5_error_code
user_password_encode(krb5_context ctx, const char *secret,
const unsigned char *auth, const krb5_data *in,
- unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen)
+ unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
+ krb5_boolean *is_fips)
{
const unsigned char *indx;
krb5_error_code retval;
@@ -154,8 +158,15 @@ user_password_encode(krb5_context ctx, const char *secret,
for (blck = 0, indx = auth; blck * BLOCKSIZE < len; blck++) {
memcpy(tmp.data + seclen, indx, BLOCKSIZE);
- retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &tmp,
- &sum);
+ if (kr_use_fips(ctx)) {
+ /* Skip encryption here. Taint so that we won't pass it out of
+ * the machine by accident. */
+ *is_fips = TRUE;
+ sum.contents = calloc(1, BLOCKSIZE);
+ } else {
+ retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &tmp,
+ &sum);
+ }
if (retval != 0) {
zap(tmp.data, tmp.length);
zap(outbuf, len);
@@ -180,7 +191,8 @@ user_password_encode(krb5_context ctx, const char *secret,
static krb5_error_code
user_password_decode(krb5_context ctx, const char *secret,
const unsigned char *auth, const krb5_data *in,
- unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen)
+ unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
+ krb5_boolean *is_fips)
{
const unsigned char *indx;
krb5_error_code retval;
@@ -204,8 +216,15 @@ user_password_decode(krb5_context ctx, const char *secret,
for (blck = 0, indx = auth; blck * BLOCKSIZE < in->length; blck++) {
memcpy(tmp.data + seclen, indx, BLOCKSIZE);
- retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0,
- &tmp, &sum);
+ if (kr_use_fips(ctx)) {
+ /* Skip encryption here. Taint so that we won't pass it out of
+ * the machine by accident. */
+ *is_fips = TRUE;
+ sum.contents = calloc(1, BLOCKSIZE);
+ } else {
+ retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0,
+ &tmp, &sum);
+ }
if (retval != 0) {
zap(tmp.data, tmp.length);
zap(outbuf, in->length);
@@ -248,7 +267,7 @@ krb5_error_code
kr_attr_encode(krb5_context ctx, const char *secret,
const unsigned char *auth, krad_attr type,
const krb5_data *in, unsigned char outbuf[MAX_ATTRSIZE],
- size_t *outlen)
+ size_t *outlen, krb5_boolean *is_fips)
{
krb5_error_code retval;
@@ -265,7 +284,8 @@ kr_attr_encode(krb5_context ctx, const char *secret,
return 0;
}
- return attributes[type - 1].encode(ctx, secret, auth, in, outbuf, outlen);
+ return attributes[type - 1].encode(ctx, secret, auth, in, outbuf, outlen,
+ is_fips);
}
krb5_error_code
@@ -274,6 +294,7 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth,
unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen)
{
krb5_error_code retval;
+ krb5_boolean ignored;
retval = kr_attr_valid(type, in);
if (retval != 0)
@@ -288,7 +309,8 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth,
return 0;
}
- return attributes[type - 1].decode(ctx, secret, auth, in, outbuf, outlen);
+ return attributes[type - 1].decode(ctx, secret, auth, in, outbuf, outlen,
+ &ignored);
}
krad_attr
diff --git a/src/lib/krad/attrset.c b/src/lib/krad/attrset.c
index f309f1581c..6ec031e320 100644
--- a/src/lib/krad/attrset.c
+++ b/src/lib/krad/attrset.c
@@ -167,7 +167,8 @@ krad_attrset_copy(const krad_attrset *set, krad_attrset **copy)
krb5_error_code
kr_attrset_encode(const krad_attrset *set, const char *secret,
const unsigned char *auth,
- unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen)
+ unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen,
+ krb5_boolean *is_fips)
{
unsigned char buffer[MAX_ATTRSIZE];
krb5_error_code retval;
@@ -181,7 +182,7 @@ kr_attrset_encode(const krad_attrset *set, const char *secret,
K5_TAILQ_FOREACH(a, &set->list, list) {
retval = kr_attr_encode(set->ctx, secret, auth, a->type, &a->attr,
- buffer, &attrlen);
+ buffer, &attrlen, is_fips);
if (retval != 0)
return retval;
diff --git a/src/lib/krad/internal.h b/src/lib/krad/internal.h
index 7619563fc5..e123763954 100644
--- a/src/lib/krad/internal.h
+++ b/src/lib/krad/internal.h
@@ -39,6 +39,8 @@
#include <sys/socket.h>
#include <netdb.h>
+#include <openssl/crypto.h>
+
#ifndef UCHAR_MAX
#define UCHAR_MAX 255
#endif
@@ -49,6 +51,13 @@
typedef struct krad_remote_st krad_remote;
+struct krad_packet_st {
+ char buffer[KRAD_PACKET_SIZE_MAX];
+ krad_attrset *attrset;
+ krb5_data pkt;
+ krb5_boolean is_fips;
+};
+
/* Validate constraints of an attribute. */
krb5_error_code
kr_attr_valid(krad_attr type, const krb5_data *data);
@@ -57,7 +66,8 @@ kr_attr_valid(krad_attr type, const krb5_data *data);
krb5_error_code
kr_attr_encode(krb5_context ctx, const char *secret, const unsigned char *auth,
krad_attr type, const krb5_data *in,
- unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen);
+ unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen,
+ krb5_boolean *is_fips);
/* Decode an attribute. */
krb5_error_code
@@ -69,7 +79,8 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth,
krb5_error_code
kr_attrset_encode(const krad_attrset *set, const char *secret,
const unsigned char *auth,
- unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen);
+ unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen,
+ krb5_boolean *is_fips);
/* Decode attributes from a buffer. */
krb5_error_code
@@ -156,4 +167,17 @@ gai_error_code(int err)
}
}
+static inline krb5_boolean
+kr_use_fips(krb5_context ctx)
+{
+ int val = 0;
+
+ if (!FIPS_mode())
+ return 0;
+
+ (void)profile_get_boolean(ctx->profile, "libdefaults",
+ "radius_md5_fips_override", NULL, 0, &val);
+ return !val;
+}
+
#endif /* INTERNAL_H_ */
diff --git a/src/lib/krad/packet.c b/src/lib/krad/packet.c
index c597174b65..fc2d248001 100644
--- a/src/lib/krad/packet.c
+++ b/src/lib/krad/packet.c
@@ -53,12 +53,6 @@ typedef unsigned char uchar;
#define pkt_auth(p) ((uchar *)offset(&(p)->pkt, OFFSET_AUTH))
#define pkt_attr(p) ((unsigned char *)offset(&(p)->pkt, OFFSET_ATTR))
-struct krad_packet_st {
- char buffer[KRAD_PACKET_SIZE_MAX];
- krad_attrset *attrset;
- krb5_data pkt;
-};
-
typedef struct {
uchar x[(UCHAR_MAX + 1) / 8];
} idmap;
@@ -187,8 +181,14 @@ auth_generate_response(krb5_context ctx, const char *secret,
memcpy(data.data + response->pkt.length, secret, strlen(secret));
/* Hash it. */
- retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &data,
- &hash);
+ if (kr_use_fips(ctx)) {
+ /* This checksum does very little security-wise anyway, so don't
+ * taint. */
+ hash.contents = calloc(1, AUTH_FIELD_SIZE);
+ } else {
+ retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &data,
+ &hash);
+ }
free(data.data);
if (retval != 0)
return retval;
@@ -276,7 +276,7 @@ krad_packet_new_request(krb5_context ctx, const char *secret, krad_code code,
/* Encode the attributes. */
retval = kr_attrset_encode(set, secret, pkt_auth(pkt), pkt_attr(pkt),
- &attrset_len);
+ &attrset_len, &pkt->is_fips);
if (retval != 0)
goto error;
@@ -314,7 +314,7 @@ krad_packet_new_response(krb5_context ctx, const char *secret, krad_code code,
/* Encode the attributes. */
retval = kr_attrset_encode(set, secret, pkt_auth(request), pkt_attr(pkt),
- &attrset_len);
+ &attrset_len, &pkt->is_fips);
if (retval != 0)
goto error;
@@ -451,6 +451,8 @@ krad_packet_decode_response(krb5_context ctx, const char *secret,
const krb5_data *
krad_packet_encode(const krad_packet *pkt)
{
+ if (pkt->is_fips)
+ return NULL;
return &pkt->pkt;
}
diff --git a/src/lib/krad/remote.c b/src/lib/krad/remote.c
index 06ae751bc8..929f1cef67 100644
--- a/src/lib/krad/remote.c
+++ b/src/lib/krad/remote.c
@@ -263,7 +263,7 @@ on_io_write(krad_remote *rr)
request *r;
K5_TAILQ_FOREACH(r, &rr->list, list) {
- tmp = krad_packet_encode(r->request);
+ tmp = &r->request->pkt;
/* If the packet has already been sent, do nothing. */
if (r->sent == tmp->length)
@@ -359,7 +359,7 @@ on_io_read(krad_remote *rr)
if (req != NULL) {
K5_TAILQ_FOREACH(r, &rr->list, list) {
if (r->request == req &&
- r->sent == krad_packet_encode(req)->length) {
+ r->sent == req->pkt.length) {
request_finish(r, 0, rsp);
break;
}
@@ -460,6 +460,12 @@ kr_remote_send(krad_remote *rr, krad_code code, krad_attrset *attrs,
(krad_packet_iter_cb)iterator, &r, &tmp);
if (retval != 0)
goto error;
+ else if (tmp->is_fips && rr->info->ai_family != AF_LOCAL &&
+ rr->info->ai_family != AF_UNIX) {
+ /* This would expose cleartext passwords, so abort. */
+ retval = ESOCKTNOSUPPORT;
+ goto error;
+ }
K5_TAILQ_FOREACH(r, &rr->list, list) {
if (r->request == tmp) {
diff --git a/src/lib/krad/t_attr.c b/src/lib/krad/t_attr.c
index eb2a780c89..4d285ad9de 100644
--- a/src/lib/krad/t_attr.c
+++ b/src/lib/krad/t_attr.c
@@ -50,6 +50,7 @@ main()
const char *tmp;
krb5_data in;
size_t len;
+ krb5_boolean is_fips = FALSE;
noerror(krb5_init_context(&ctx));
@@ -73,7 +74,7 @@ main()
in = string2data((char *)decoded);
retval = kr_attr_encode(ctx, secret, auth,
krad_attr_name2num("User-Password"),
- &in, outbuf, &len);
+ &in, outbuf, &len, &is_fips);
insist(retval == 0);
insist(len == sizeof(encoded));
insist(memcmp(outbuf, encoded, len) == 0);
diff --git a/src/lib/krad/t_attrset.c b/src/lib/krad/t_attrset.c
index 7928335ca4..0f95762534 100644
--- a/src/lib/krad/t_attrset.c
+++ b/src/lib/krad/t_attrset.c
@@ -49,6 +49,7 @@ main()
krb5_context ctx;
size_t len = 0, encode_len;
krb5_data tmp;
+ krb5_boolean is_fips = FALSE;
noerror(krb5_init_context(&ctx));
noerror(krad_attrset_new(ctx, &set));
@@ -62,7 +63,8 @@ main()
noerror(krad_attrset_add(set, krad_attr_name2num("User-Password"), &tmp));
/* Encode attrset. */
- noerror(kr_attrset_encode(set, "foo", auth, buffer, &encode_len));
+ noerror(kr_attrset_encode(set, "foo", auth, buffer, &encode_len,
+ &is_fips));
krad_attrset_free(set);
/* Manually encode User-Name. */
diff --git a/src/plugins/preauth/spake/spake_client.c b/src/plugins/preauth/spake/spake_client.c
index 00734a13b5..a3ce22b70f 100644
--- a/src/plugins/preauth/spake/spake_client.c
+++ b/src/plugins/preauth/spake/spake_client.c
@@ -38,6 +38,8 @@
#include "groups.h"
#include <krb5/clpreauth_plugin.h>
+#include <openssl/crypto.h>
+
typedef struct reqstate_st {
krb5_pa_spake *msg; /* set in prep_questions, used in process */
krb5_keyblock *initial_key;
@@ -375,6 +377,10 @@ clpreauth_spake_initvt(krb5_context context, int maj_ver, int min_ver,
if (maj_ver != 1)
return KRB5_PLUGIN_VER_NOTSUPP;
+
+ if (FIPS_mode())
+ return KRB5_CRYPTO_INTERNAL;
+
vt = (krb5_clpreauth_vtable)vtable;
vt->name = "spake";
vt->pa_type_list = pa_types;
diff --git a/src/plugins/preauth/spake/spake_kdc.c b/src/plugins/preauth/spake/spake_kdc.c
index 1a772d450f..232e78bc05 100644
--- a/src/plugins/preauth/spake/spake_kdc.c
+++ b/src/plugins/preauth/spake/spake_kdc.c
@@ -41,6 +41,8 @@
#include <krb5/kdcpreauth_plugin.h>
+#include <openssl/crypto.h>
+
/*
* The SPAKE kdcpreauth module uses a secure cookie containing the following
* concatenated fields (all integer fields are big-endian):
@@ -551,6 +553,10 @@ kdcpreauth_spake_initvt(krb5_context context, int maj_ver, int min_ver,
if (maj_ver != 1)
return KRB5_PLUGIN_VER_NOTSUPP;
+
+ if (FIPS_mode())
+ return KRB5_CRYPTO_INTERNAL;
+
vt = (krb5_kdcpreauth_vtable)vtable;
vt->name = "spake";
vt->pa_type_list = pa_types;
--
2.45.1

View file

@ -1,82 +0,0 @@
From 707fa7bd2be6327343dc8fc5c20dc77645524518 Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Thu, 5 May 2022 17:15:12 +0200
Subject: [PATCH] [downstream] Allow krad UDP/TCP localhost connection
with FIPS
libkrad allows to establish connections only to UNIX socket in FIPS
mode, because MD5 digest is not considered safe enough to be used for
network communication. However, FreeRadius requires connection on TCP or
UDP ports.
This commit allows TCP or UDP connections in FIPS mode if destination is
localhost.
Resolves: rhbz#2082189
---
src/lib/krad/remote.c | 35 +++++++++++++++++++++++++++++++++--
1 file changed, 33 insertions(+), 2 deletions(-)
diff --git a/src/lib/krad/remote.c b/src/lib/krad/remote.c
index 929f1cef67..063f17a613 100644
--- a/src/lib/krad/remote.c
+++ b/src/lib/krad/remote.c
@@ -33,6 +33,7 @@
#include <string.h>
#include <unistd.h>
+#include <stdbool.h>
#include <sys/un.h>
@@ -74,6 +75,35 @@ on_io(verto_ctx *ctx, verto_ev *ev);
static void
on_timeout(verto_ctx *ctx, verto_ev *ev);
+static in_addr_t get_in_addr(struct addrinfo *info)
+{ return ((struct sockaddr_in *)(info->ai_addr))->sin_addr.s_addr; }
+
+static struct in6_addr *get_in6_addr(struct addrinfo *info)
+{ return &(((struct sockaddr_in6 *)(info->ai_addr))->sin6_addr); }
+
+static bool is_inet_localhost(struct addrinfo *info)
+{
+ struct addrinfo *p;
+
+ for (p = info; p; p = p->ai_next) {
+ switch (p->ai_family) {
+ case AF_INET:
+ if (IN_LOOPBACKNET != (get_in_addr(p) & IN_CLASSA_NET
+ >> IN_CLASSA_NSHIFT))
+ return false;
+ break;
+ case AF_INET6:
+ if (!IN6_IS_ADDR_LOOPBACK(get_in6_addr(p)))
+ return false;
+ break;
+ default:
+ return false;
+ }
+ }
+
+ return true;
+}
+
/* Iterate over the set of outstanding packets. */
static const krad_packet *
iterator(request **out)
@@ -460,8 +490,9 @@ kr_remote_send(krad_remote *rr, krad_code code, krad_attrset *attrs,
(krad_packet_iter_cb)iterator, &r, &tmp);
if (retval != 0)
goto error;
- else if (tmp->is_fips && rr->info->ai_family != AF_LOCAL &&
- rr->info->ai_family != AF_UNIX) {
+ else if (tmp->is_fips && rr->info->ai_family != AF_LOCAL
+ && rr->info->ai_family != AF_UNIX
+ && !is_inet_localhost(rr->info)) {
/* This would expose cleartext passwords, so abort. */
retval = ESOCKTNOSUPPORT;
goto error;
--
2.45.1

View file

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

View file

@ -1,120 +0,0 @@
From 775ed8588cc21385fb16a4cec4a861f0d578ce04 Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Thu, 5 Jan 2023 20:06:47 +0100
Subject: [PATCH] [downstream] Include missing OpenSSL FIPS header
The inclusion of openssl/fips.h, which provides the declaration of
FIPS_mode(), was removed from openssl/crypto.h. As a consequence, this
header file has to be included explicitly in krb5 code.
---
src/lib/crypto/krb/prng.c | 4 +++-
src/lib/crypto/openssl/enc_provider/camellia.c | 1 +
src/lib/crypto/openssl/enc_provider/rc4.c | 4 ++++
src/lib/crypto/openssl/hmac.c | 1 +
src/lib/krad/internal.h | 4 ++++
src/plugins/preauth/spake/spake_client.c | 4 ++++
src/plugins/preauth/spake/spake_kdc.c | 4 ++++
7 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/src/lib/crypto/krb/prng.c b/src/lib/crypto/krb/prng.c
index 9e80a03d21..ae37c77518 100644
--- a/src/lib/crypto/krb/prng.c
+++ b/src/lib/crypto/krb/prng.c
@@ -28,7 +28,9 @@
#include <openssl/rand.h>
-#if OPENSSL_VERSION_NUMBER < 0x30000000L
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+#include <openssl/fips.h>
+#else
#include <openssl/crypto.h>
#endif
diff --git a/src/lib/crypto/openssl/enc_provider/camellia.c b/src/lib/crypto/openssl/enc_provider/camellia.c
index d9f327add6..3dd3b0624f 100644
--- a/src/lib/crypto/openssl/enc_provider/camellia.c
+++ b/src/lib/crypto/openssl/enc_provider/camellia.c
@@ -32,6 +32,7 @@
#include <openssl/camellia.h>
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
#include <openssl/core_names.h>
+#include <openssl/fips.h>
#else
#include <openssl/modes.h>
#endif
diff --git a/src/lib/crypto/openssl/enc_provider/rc4.c b/src/lib/crypto/openssl/enc_provider/rc4.c
index ce63cb5f1b..6a83f10d27 100644
--- a/src/lib/crypto/openssl/enc_provider/rc4.c
+++ b/src/lib/crypto/openssl/enc_provider/rc4.c
@@ -38,6 +38,10 @@
#include <openssl/evp.h>
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+#include <openssl/fips.h>
+#endif
+
/*
* The loopback field is a pointer to the structure. If the application copies
* the state (not a valid operation, but one which happens to works with some
diff --git a/src/lib/crypto/openssl/hmac.c b/src/lib/crypto/openssl/hmac.c
index f21e268f7f..25a419d73a 100644
--- a/src/lib/crypto/openssl/hmac.c
+++ b/src/lib/crypto/openssl/hmac.c
@@ -59,6 +59,7 @@
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
#include <openssl/params.h>
#include <openssl/core_names.h>
+#include <openssl/fips.h>
#else
#include <openssl/hmac.h>
#endif
diff --git a/src/lib/krad/internal.h b/src/lib/krad/internal.h
index e123763954..a17b6f39b1 100644
--- a/src/lib/krad/internal.h
+++ b/src/lib/krad/internal.h
@@ -41,6 +41,10 @@
#include <openssl/crypto.h>
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+#include <openssl/fips.h>
+#endif
+
#ifndef UCHAR_MAX
#define UCHAR_MAX 255
#endif
diff --git a/src/plugins/preauth/spake/spake_client.c b/src/plugins/preauth/spake/spake_client.c
index a3ce22b70f..13c699071f 100644
--- a/src/plugins/preauth/spake/spake_client.c
+++ b/src/plugins/preauth/spake/spake_client.c
@@ -40,6 +40,10 @@
#include <openssl/crypto.h>
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+#include <openssl/fips.h>
+#endif
+
typedef struct reqstate_st {
krb5_pa_spake *msg; /* set in prep_questions, used in process */
krb5_keyblock *initial_key;
diff --git a/src/plugins/preauth/spake/spake_kdc.c b/src/plugins/preauth/spake/spake_kdc.c
index 232e78bc05..3394f8a58e 100644
--- a/src/plugins/preauth/spake/spake_kdc.c
+++ b/src/plugins/preauth/spake/spake_kdc.c
@@ -43,6 +43,10 @@
#include <openssl/crypto.h>
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+#include <openssl/fips.h>
+#endif
+
/*
* The SPAKE kdcpreauth module uses a secure cookie containing the following
* concatenated fields (all integer fields are big-endian):
--
2.45.1

View file

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

View file

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

View file

@ -1,280 +0,0 @@
From 23b58199db429603802e338db530677b61561335 Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Wed, 15 Mar 2023 15:56:34 +0100
Subject: [PATCH] [downstream] Allow to set PAC ticket signature as
optional
MS-PAC states that "The ticket signature SHOULD be included in tickets
that are not encrypted to the krbtgt account". However, the
implementation of krb5_kdc_verify_ticket() will require the ticket
signature to be present in case the target of the request is a service
principal.
In gradual upgrade environments, it results in S4U2Proxy requests
against a 1.20 KDC using a service ticket generated by an older version
KDC to fail.
This commit adds a krb5_kdc_verify_ticket_ext() function with an extra
switch parameter to tolerate the absence of ticket signature in this
scenario. If the ticket signature is present, it has to be valid,
regardless of this parameter.
This parameter is set based on the "optional_pac_tkt_chksum" string
attribute of the TGT KDB entry.
---
doc/admin/admin_commands/kadmin_local.rst | 6 ++++
doc/appdev/refs/api/index.rst | 1 +
src/include/kdb.h | 1 +
src/include/krb5/krb5.hin | 40 +++++++++++++++++++++++
src/kdc/kdc_util.c | 32 ++++++++++++++----
src/lib/krb5/krb/pac.c | 31 +++++++++++++++---
src/lib/krb5/libkrb5.exports | 1 +
src/man/kadmin.man | 6 ++++
8 files changed, 108 insertions(+), 10 deletions(-)
diff --git a/doc/admin/admin_commands/kadmin_local.rst b/doc/admin/admin_commands/kadmin_local.rst
index 2435b3c361..58ac79549f 100644
--- a/doc/admin/admin_commands/kadmin_local.rst
+++ b/doc/admin/admin_commands/kadmin_local.rst
@@ -658,6 +658,12 @@ KDC:
Directory realm when using aes-sha2 keys on the local krbtgt
entry.
+**optional_pac_tkt_chksum**
+ Boolean value defining the behavior of the KDC in case an expected
+ ticket checksum signed with one of this principal keys is not
+ present in the PAC. This is typically the case for TGS or
+ cross-realm TGS principals when processing S4U2Proxy requests.
+
This command requires the **modify** privilege.
Alias: **setstr**
diff --git a/doc/appdev/refs/api/index.rst b/doc/appdev/refs/api/index.rst
index d12be47c3c..9b95ebd0f9 100644
--- a/doc/appdev/refs/api/index.rst
+++ b/doc/appdev/refs/api/index.rst
@@ -225,6 +225,7 @@ Rarely used public interfaces
krb5_is_referral_realm.rst
krb5_kdc_sign_ticket.rst
krb5_kdc_verify_ticket.rst
+ krb5_kdc_verify_ticket_ext.rst
krb5_kt_add_entry.rst
krb5_kt_end_seq_get.rst
krb5_kt_get_entry.rst
diff --git a/src/include/kdb.h b/src/include/kdb.h
index 745b24f351..6075349e5e 100644
--- a/src/include/kdb.h
+++ b/src/include/kdb.h
@@ -136,6 +136,7 @@
#define KRB5_KDB_SK_PAC_PRIVSVR_ENCTYPE "pac_privsvr_enctype"
#define KRB5_KDB_SK_SESSION_ENCTYPES "session_enctypes"
#define KRB5_KDB_SK_REQUIRE_AUTH "require_auth"
+#define KRB5_KDB_SK_OPTIONAL_PAC_TKT_CHKSUM "optional_pac_tkt_chksum"
#if !defined(_WIN32)
diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
index c5a625db8f..2d9b64dc85 100644
--- a/src/include/krb5/krb5.hin
+++ b/src/include/krb5/krb5.hin
@@ -8329,6 +8329,46 @@ krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt,
const krb5_keyblock *server,
const krb5_keyblock *privsvr, krb5_pac *pac_out);
+/**
+ * Verify a PAC, possibly including ticket signature
+ *
+ * @param [in] context Library context
+ * @param [in] enc_tkt Ticket enc-part, possibly containing a PAC
+ * @param [in] server_princ Canonicalized name of ticket server
+ * @param [in] server Key to validate server checksum (or NULL)
+ * @param [in] privsvr Key to validate KDC checksum (or NULL)
+ * @paran [in] optional_tkt_chksum Whether to require a ticket checksum
+ * @param [out] pac_out Verified PAC (NULL if no PAC included)
+ *
+ * This function is an extension of krb5_kdc_verify_ticket(), adding the @a
+ * optional_tkt_chksum parameter allowing to tolerate the absence of the PAC
+ * ticket signature.
+ *
+ * If a PAC is present in @a enc_tkt, verify its signatures. If @a privsvr is
+ * not NULL and @a server_princ is not a krbtgt or kadmin/changepw service and
+ * @a optional_tkt_chksum is FALSE, require a ticket signature over @a enc_tkt
+ * in addition to the KDC signature. Place the verified PAC in @a pac_out. If
+ * an invalid PAC signature is found, return an error matching the Windows KDC
+ * protocol code for that condition as closely as possible.
+ *
+ * If no PAC is present in @a enc_tkt, set @a pac_out to NULL and return
+ * successfully.
+ *
+ * @note This function does not validate the PAC_CLIENT_INFO buffer. If a
+ * specific value is expected, the caller can make a separate call to
+ * krb5_pac_verify_ext() with a principal but no keys.
+ *
+ * @retval 0 Success; otherwise - Kerberos error codes
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_kdc_verify_ticket_ext(krb5_context context,
+ const krb5_enc_tkt_part *enc_tkt,
+ krb5_const_principal server_princ,
+ const krb5_keyblock *server,
+ const krb5_keyblock *privsvr,
+ krb5_boolean optional_tkt_chksum,
+ krb5_pac *pac_out);
+
/** @deprecated Use krb5_kdc_sign_ticket() instead. */
krb5_error_code KRB5_CALLCONV
krb5_pac_sign(krb5_context context, krb5_pac pac, krb5_timestamp authtime,
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
index fe4e48209a..93415ba862 100644
--- a/src/kdc/kdc_util.c
+++ b/src/kdc/kdc_util.c
@@ -560,16 +560,36 @@ cleanup:
static krb5_error_code
try_verify_pac(krb5_context context, const krb5_enc_tkt_part *enc_tkt,
krb5_db_entry *server, krb5_keyblock *server_key,
- const krb5_keyblock *tgt_key, krb5_pac *pac_out)
+ krb5_db_entry *tgt, const krb5_keyblock *tgt_key,
+ krb5_pac *pac_out)
{
krb5_error_code ret;
+ krb5_boolean optional_tkt_chksum;
+ char *str = NULL;
krb5_keyblock *privsvr_key;
ret = pac_privsvr_key(context, server, tgt_key, &privsvr_key);
if (ret)
return ret;
- ret = krb5_kdc_verify_ticket(context, enc_tkt, server->princ, server_key,
- privsvr_key, pac_out);
+
+ /* Check if the absence of ticket signature is tolerated for this realm */
+ ret = krb5_dbe_get_string(context, tgt,
+ KRB5_KDB_SK_OPTIONAL_PAC_TKT_CHKSUM, &str);
+ /* TODO: should be using _krb5_conf_boolean(), but os-proto.h is not
+ * available here.
+ */
+ optional_tkt_chksum = !ret && str && (strncasecmp(str, "true", 4) == 0
+ || strncasecmp(str, "t", 1) == 0
+ || strncasecmp(str, "yes", 3) == 0
+ || strncasecmp(str, "y", 1) == 0
+ || strncasecmp(str, "1", 1) == 0
+ || strncasecmp(str, "on", 2) == 0);
+
+ krb5_dbe_free_string(context, str);
+
+ ret = krb5_kdc_verify_ticket_ext(context, enc_tkt, server->princ,
+ server_key, privsvr_key,
+ optional_tkt_chksum, pac_out);
krb5_free_keyblock(context, privsvr_key);
return ret;
}
@@ -599,7 +619,7 @@ get_verified_pac(krb5_context context, const krb5_enc_tkt_part *enc_tkt,
server_key, NULL, pac_out);
}
- ret = try_verify_pac(context, enc_tkt, server, server_key, tgt_key,
+ ret = try_verify_pac(context, enc_tkt, server, server_key, tgt, tgt_key,
pac_out);
if (ret != KRB5KRB_AP_ERR_MODIFIED && ret != KRB5_BAD_ENCTYPE)
return ret;
@@ -613,8 +633,8 @@ get_verified_pac(krb5_context context, const krb5_enc_tkt_part *enc_tkt,
ret = krb5_dbe_decrypt_key_data(context, NULL, kd, &old_key, NULL);
if (ret)
return ret;
- ret = try_verify_pac(context, enc_tkt, server, server_key, &old_key,
- pac_out);
+ ret = try_verify_pac(context, enc_tkt, server, server_key, tgt,
+ &old_key, pac_out);
krb5_free_keyblock_contents(context, &old_key);
if (!ret)
return 0;
diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c
index 5d1fdf1ba0..0c0e2ada68 100644
--- a/src/lib/krb5/krb/pac.c
+++ b/src/lib/krb5/krb/pac.c
@@ -594,6 +594,19 @@ krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt,
krb5_const_principal server_princ,
const krb5_keyblock *server,
const krb5_keyblock *privsvr, krb5_pac *pac_out)
+{
+ return krb5_kdc_verify_ticket_ext(context, enc_tkt, server_princ, server,
+ privsvr, FALSE, pac_out);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_kdc_verify_ticket_ext(krb5_context context,
+ const krb5_enc_tkt_part *enc_tkt,
+ krb5_const_principal server_princ,
+ const krb5_keyblock *server,
+ const krb5_keyblock *privsvr,
+ krb5_boolean optional_tkt_chksum,
+ krb5_pac *pac_out)
{
krb5_error_code ret;
krb5_pac pac = NULL;
@@ -602,7 +615,7 @@ krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt,
krb5_authdata *orig, **ifrel = NULL, **recoded_ifrel = NULL;
uint8_t z = 0;
krb5_authdata zpac = { KV5M_AUTHDATA, KRB5_AUTHDATA_WIN2K_PAC, 1, &z };
- krb5_boolean is_service_tkt;
+ krb5_boolean is_service_tkt, has_tkt_chksum = FALSE;
size_t i, j;
*pac_out = NULL;
@@ -667,11 +680,21 @@ krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt,
ret = verify_checksum(context, pac, KRB5_PAC_TICKET_CHECKSUM, privsvr,
KRB5_KEYUSAGE_APP_DATA_CKSUM, recoded_tkt);
- if (ret)
- goto cleanup;
+ if (ret) {
+ if (!optional_tkt_chksum)
+ goto cleanup;
+ else if (ret != ENOENT)
+ goto cleanup;
+ /* Otherwise ticket signature is absent but optional. Proceed... */
+ } else {
+ has_tkt_chksum = TRUE;
+ }
}
+ /* Else, we make the assumption the ticket signature is absent in case this
+ * is not a service ticket.
+ */
- ret = verify_pac_checksums(context, pac, is_service_tkt, server, privsvr);
+ ret = verify_pac_checksums(context, pac, has_tkt_chksum, server, privsvr);
if (ret)
goto cleanup;
diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports
index 4c50e935a2..d4b0455c8c 100644
--- a/src/lib/krb5/libkrb5.exports
+++ b/src/lib/krb5/libkrb5.exports
@@ -463,6 +463,7 @@ krb5_is_thread_safe
krb5_kdc_rep_decrypt_proc
krb5_kdc_sign_ticket
krb5_kdc_verify_ticket
+krb5_kdc_verify_ticket_ext
krb5_kt_add_entry
krb5_kt_client_default
krb5_kt_close
diff --git a/src/man/kadmin.man b/src/man/kadmin.man
index 8413e70ccd..f68eb0569d 100644
--- a/src/man/kadmin.man
+++ b/src/man/kadmin.man
@@ -724,6 +724,12 @@ encryption type. It may be necessary to set this value to
"aes256\-sha1" on the cross\-realm krbtgt entry for an Active
Directory realm when using aes\-sha2 keys on the local krbtgt
entry.
+.TP
+\fBoptional_pac_tkt_chksum\fP
+Boolean value defining the behavior of the KDC in case an expected ticket
+checksum signed with one of this principal keys is not present in the PAC. This
+is typically the case for TGS or cross-realm TGS principals when processing
+S4U2Proxy requests.
.UNINDENT
.sp
This command requires the \fBmodify\fP privilege.
--
2.45.1

View file

@ -1,47 +0,0 @@
From 31b9debcf2cbd558f8f315fefb69fc8206b115b4 Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Tue, 23 May 2023 12:19:54 +0200
Subject: [PATCH] [downstream] Make PKINIT CMS SHA-1 signature
verification available in FIPS mode
We recommend using the SHA1 crypto-module in order to allow the
verification of SHA-1 signature for CMS messages. However, this module
does not work in FIPS mode, because the SHA-1 algorithm is absent from
the OpenSSL FIPS provider.
This commit enables the signature verification process to fetch the
algorithm from a non-FIPS OpenSSL provider.
Support for SHA-1 CMS signature is still required, especially in order
to interoperate with Active Directory. At least it is until elliptic
curve cryptography is implemented for PKINIT in MIT krb5.
---
src/plugins/preauth/pkinit/pkinit_crypto_openssl.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
index cb9c79626c..17dd18e37d 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
@@ -1844,8 +1844,17 @@ cms_signeddata_verify(krb5_context context,
if (oid == NULL)
goto cleanup;
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ /* Do not use FIPS provider (even in FIPS mode) because it keeps from
+ * allowing SHA-1 signature verification using the SHA1 crypto-module
+ */
+ cms = CMS_ContentInfo_new_ex(NULL, "-fips");
+ if (!cms)
+ goto cleanup;
+#endif
+
/* decode received CMS message */
- if ((cms = d2i_CMS_ContentInfo(NULL, &p, (int)signed_data_len)) == NULL) {
+ if (!d2i_CMS_ContentInfo(&cms, &p, (int)signed_data_len)) {
retval = oerr(context, 0, _("Failed to decode CMS message"));
goto cleanup;
}
--
2.45.1

View file

@ -1,218 +0,0 @@
From c24c9faf859ddc04910a6bc591d8ddb2ada93e80 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Tue, 30 May 2023 01:21:48 -0400
Subject: [PATCH] Enable PKINIT if at least one group is available
OpenSSL may no longer allow decoding of non-well-known Diffie-Hellman
group parameters as EVP_PKEY objects in FIPS mode. However, OpenSSL
does not know about MODP group 2 (1024-bit), which is considered as a
custom group. As a consequence, the PKINIT kdcpreauth module fails to
load in FIPS mode.
Allow initialization of PKINIT plugin if at least one of the MODP
well-known group parameters successfully decodes.
[ghudson@mit.edu: minor commit message and code edits]
ticket: 9096 (new)
(cherry picked from commit 509d8db922e9ad6f108883838473b6178f89874a)
---
src/plugins/preauth/pkinit/pkinit_clnt.c | 2 +-
src/plugins/preauth/pkinit/pkinit_crypto.h | 3 +-
.../preauth/pkinit/pkinit_crypto_openssl.c | 76 +++++++++++--------
src/plugins/preauth/pkinit/pkinit_srv.c | 2 +-
src/plugins/preauth/pkinit/pkinit_trace.h | 3 +
5 files changed, 51 insertions(+), 35 deletions(-)
diff --git a/src/plugins/preauth/pkinit/pkinit_clnt.c b/src/plugins/preauth/pkinit/pkinit_clnt.c
index 725d5bc438..ea9ba454df 100644
--- a/src/plugins/preauth/pkinit/pkinit_clnt.c
+++ b/src/plugins/preauth/pkinit/pkinit_clnt.c
@@ -1378,7 +1378,7 @@ pkinit_client_plugin_init(krb5_context context,
if (retval)
goto errout;
- retval = pkinit_init_plg_crypto(&ctx->cryptoctx);
+ retval = pkinit_init_plg_crypto(context, &ctx->cryptoctx);
if (retval)
goto errout;
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto.h b/src/plugins/preauth/pkinit/pkinit_crypto.h
index 9fa315d7a0..8bdbea8e95 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto.h
+++ b/src/plugins/preauth/pkinit/pkinit_crypto.h
@@ -103,7 +103,8 @@ typedef struct _pkinit_cert_matching_data {
/*
* Functions to initialize and cleanup crypto contexts
*/
-krb5_error_code pkinit_init_plg_crypto(pkinit_plg_crypto_context *);
+krb5_error_code pkinit_init_plg_crypto(krb5_context,
+ pkinit_plg_crypto_context *);
void pkinit_fini_plg_crypto(pkinit_plg_crypto_context);
krb5_error_code pkinit_init_req_crypto(pkinit_req_crypto_context *);
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
index 17dd18e37d..8cdc40bfb4 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
@@ -47,7 +47,8 @@
static krb5_error_code pkinit_init_pkinit_oids(pkinit_plg_crypto_context );
static void pkinit_fini_pkinit_oids(pkinit_plg_crypto_context );
-static krb5_error_code pkinit_init_dh_params(pkinit_plg_crypto_context );
+static krb5_error_code pkinit_init_dh_params(krb5_context,
+ pkinit_plg_crypto_context);
static void pkinit_fini_dh_params(pkinit_plg_crypto_context );
static krb5_error_code pkinit_init_certs(pkinit_identity_crypto_context ctx);
@@ -951,7 +952,8 @@ oerr_cert(krb5_context context, krb5_error_code code, X509_STORE_CTX *certctx,
}
krb5_error_code
-pkinit_init_plg_crypto(pkinit_plg_crypto_context *cryptoctx)
+pkinit_init_plg_crypto(krb5_context context,
+ pkinit_plg_crypto_context *cryptoctx)
{
krb5_error_code retval = ENOMEM;
pkinit_plg_crypto_context ctx = NULL;
@@ -969,7 +971,7 @@ pkinit_init_plg_crypto(pkinit_plg_crypto_context *cryptoctx)
if (retval)
goto out;
- retval = pkinit_init_dh_params(ctx);
+ retval = pkinit_init_dh_params(context, ctx);
if (retval)
goto out;
@@ -1278,30 +1280,36 @@ pkinit_fini_pkinit_oids(pkinit_plg_crypto_context ctx)
ASN1_OBJECT_free(ctx->id_kp_serverAuth);
}
-static krb5_error_code
-pkinit_init_dh_params(pkinit_plg_crypto_context plgctx)
+static int
+try_import_group(krb5_context context, const krb5_data *params,
+ const char *name, EVP_PKEY **pkey_out)
{
- krb5_error_code retval = ENOMEM;
-
- plgctx->dh_1024 = decode_dh_params(&oakley_1024);
- if (plgctx->dh_1024 == NULL)
- goto cleanup;
-
- plgctx->dh_2048 = decode_dh_params(&oakley_2048);
- if (plgctx->dh_2048 == NULL)
- goto cleanup;
+ *pkey_out = decode_dh_params(params);
+ if (*pkey_out == NULL)
+ TRACE_PKINIT_DH_GROUP_UNAVAILABLE(context, name);
+ return (*pkey_out != NULL) ? 1 : 0;
+}
- plgctx->dh_4096 = decode_dh_params(&oakley_4096);
- if (plgctx->dh_4096 == NULL)
- goto cleanup;
+static krb5_error_code
+pkinit_init_dh_params(krb5_context context, pkinit_plg_crypto_context plgctx)
+{
+ int n = 0;
- retval = 0;
+ n += try_import_group(context, &oakley_1024, "MODP 2 (1024-bit)",
+ &plgctx->dh_1024);
+ n += try_import_group(context, &oakley_2048, "MODP 14 (2048-bit)",
+ &plgctx->dh_2048);
+ n += try_import_group(context, &oakley_4096, "MODP 16 (4096-bit)",
+ &plgctx->dh_4096);
-cleanup:
- if (retval)
+ if (n == 0) {
pkinit_fini_dh_params(plgctx);
+ k5_setmsg(context, ENOMEM,
+ _("PKINIT cannot initialize any key exchange groups"));
+ return ENOMEM;
+ }
- return retval;
+ return 0;
}
static void
@@ -2912,11 +2920,11 @@ client_create_dh(krb5_context context,
if (cryptoctx->received_params != NULL)
params = cryptoctx->received_params;
- else if (dh_size == 1024)
+ else if (plg_cryptoctx->dh_1024 != NULL && dh_size == 1024)
params = plg_cryptoctx->dh_1024;
- else if (dh_size == 2048)
+ else if (plg_cryptoctx->dh_2048 != NULL && dh_size == 2048)
params = plg_cryptoctx->dh_2048;
- else if (dh_size == 4096)
+ else if (plg_cryptoctx->dh_4096 != NULL && dh_size == 4096)
params = plg_cryptoctx->dh_4096;
else
goto cleanup;
@@ -3212,19 +3220,23 @@ pkinit_create_td_dh_parameters(krb5_context context,
krb5_algorithm_identifier alg_4096 = { dh_oid, oakley_4096 };
krb5_algorithm_identifier *alglist[4];
- if (opts->dh_min_bits > 4096) {
- ret = KRB5KRB_ERR_GENERIC;
- goto cleanup;
- }
-
i = 0;
- if (opts->dh_min_bits <= 2048)
+ if (plg_cryptoctx->dh_2048 != NULL && opts->dh_min_bits <= 2048)
alglist[i++] = &alg_2048;
- alglist[i++] = &alg_4096;
- if (opts->dh_min_bits <= 1024)
+ if (plg_cryptoctx->dh_4096 != NULL && opts->dh_min_bits <= 4096)
+ alglist[i++] = &alg_4096;
+ if (plg_cryptoctx->dh_1024 != NULL && opts->dh_min_bits <= 1024)
alglist[i++] = &alg_1024;
alglist[i] = NULL;
+ if (i == 0) {
+ ret = KRB5KRB_ERR_GENERIC;
+ k5_setmsg(context, ret,
+ _("OpenSSL has no supported key exchange groups for "
+ "pkinit_dh_min_bits=%d"), opts->dh_min_bits);
+ goto cleanup;
+ }
+
ret = k5int_encode_krb5_td_dh_parameters(alglist, &der_alglist);
if (ret)
goto cleanup;
diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c
index 1b3bf6d4d0..768a4e559f 100644
--- a/src/plugins/preauth/pkinit/pkinit_srv.c
+++ b/src/plugins/preauth/pkinit/pkinit_srv.c
@@ -1222,7 +1222,7 @@ pkinit_server_plugin_init_realm(krb5_context context, const char *realmname,
goto errout;
plgctx->realmname_len = strlen(plgctx->realmname);
- retval = pkinit_init_plg_crypto(&plgctx->cryptoctx);
+ retval = pkinit_init_plg_crypto(context, &plgctx->cryptoctx);
if (retval)
goto errout;
diff --git a/src/plugins/preauth/pkinit/pkinit_trace.h b/src/plugins/preauth/pkinit/pkinit_trace.h
index 259e95c6c2..5ee39c085c 100644
--- a/src/plugins/preauth/pkinit/pkinit_trace.h
+++ b/src/plugins/preauth/pkinit/pkinit_trace.h
@@ -90,6 +90,9 @@
#define TRACE_PKINIT_CLIENT_TRYAGAIN(c) \
TRACE(c, "PKINIT client trying again with KDC-provided parameters")
+#define TRACE_PKINIT_DH_GROUP_UNAVAILABLE(c, name) \
+ TRACE(c, "PKINIT key exchange group {str} unsupported", name)
+
#define TRACE_PKINIT_OPENSSL_ERROR(c, msg) \
TRACE(c, "PKINIT OpenSSL error: {str}", msg)
--
2.45.1

View file

@ -1,64 +0,0 @@
From e92365b510a2407eaceaec90836f5c713403d75f Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Wed, 19 Jul 2023 13:43:17 +0200
Subject: [PATCH] Replace ssl.wrap_socket() for tests
The ssl.wrap_socket() function was deprecated in Python 3.7 and is
removed in Python 3.12. The ssl.SSLContext.wrap_socket() method
replaces it.
Bump the required Python version for tests to 3.4 for
ssl.create_default_context().
[ghudson@mit.edu: changed minimum Python version]
(cherry picked from commit 0ceab6c363e65fb21d3312a663f2b9b569ecc415)
---
src/configure.ac | 9 ++++-----
src/util/wsgiref-kdcproxy.py | 4 +++-
2 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/src/configure.ac b/src/configure.ac
index 2561e917a2..487f393146 100644
--- a/src/configure.ac
+++ b/src/configure.ac
@@ -1157,10 +1157,9 @@ AC_SUBST(PKINIT)
# for lib/apputils
AC_REPLACE_FUNCS(daemon)
-# For Python tests. Python version 3.2.4 is required as prior
-# versions do not accept string input to subprocess.Popen.communicate
-# when universal_newlines is set.
-PYTHON_MINVERSION=3.2.4
+# For Python tests. Python version 3.4 is required for
+# ssl.create_default_context().
+PYTHON_MINVERSION=3.4
AC_SUBST(PYTHON_MINVERSION)
AC_CHECK_PROG(PYTHON,python3,python3)
if test x"$PYTHON" = x; then
@@ -1168,7 +1167,7 @@ if test x"$PYTHON" = x; then
fi
HAVE_PYTHON=no
if test x"$PYTHON" != x; then
- wantver="(sys.hexversion >= 0x30204F0)"
+ wantver="(sys.hexversion >= 0x30400F0)"
if "$PYTHON" -c "import sys; sys.exit(not $wantver and 1 or 0)"; then
HAVE_PYTHON=yes
fi
diff --git a/src/util/wsgiref-kdcproxy.py b/src/util/wsgiref-kdcproxy.py
index 58759696b6..d1d10d733c 100755
--- a/src/util/wsgiref-kdcproxy.py
+++ b/src/util/wsgiref-kdcproxy.py
@@ -14,6 +14,8 @@ else:
pem = '*'
server = make_server('localhost', port, kdcproxy.Application())
-server.socket = ssl.wrap_socket(server.socket, certfile=pem, server_side=True)
+sslctx = ssl.create_default_context(purpose=ssl.Purpose.CLIENT_AUTH)
+sslctx.load_cert_chain(certfile=pem)
+server.socket = sslctx.wrap_socket(server.socket, server_side=True)
os.write(sys.stdout.fileno(), b'proxy server ready\n')
server.serve_forever()
--
2.45.1

File diff suppressed because it is too large Load diff

View file

@ -1,206 +0,0 @@
From ee66c1feedb57ce06ce51aaa823f9a61f564c58e Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Tue, 5 Mar 2024 19:53:07 -0500
Subject: [PATCH] Fix two unlikely memory leaks
In gss_krb5int_make_seal_token_v3(), one of the bounds checks (which
could probably never be triggered) leaks plain.data. Fix this leak
and use current practices for cleanup throughout the function.
In xmt_rmtcallres() (unused within the tree and likely elsewhere),
store port_ptr into crp->port_ptr as soon as it is allocated;
otherwise it could leak if the subsequent xdr_u_int32() operation
fails.
(cherry picked from commit c5f9c816107f70139de11b38aa02db2f1774ee0d)
---
src/lib/gssapi/krb5/k5sealv3.c | 56 +++++++++++++++-------------------
src/lib/rpc/pmap_rmt.c | 10 +++---
2 files changed, 29 insertions(+), 37 deletions(-)
diff --git a/src/lib/gssapi/krb5/k5sealv3.c b/src/lib/gssapi/krb5/k5sealv3.c
index 1fcbdfbb87..d3210c1107 100644
--- a/src/lib/gssapi/krb5/k5sealv3.c
+++ b/src/lib/gssapi/krb5/k5sealv3.c
@@ -65,7 +65,7 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
int conf_req_flag, int toktype)
{
size_t bufsize = 16;
- unsigned char *outbuf = 0;
+ unsigned char *outbuf = NULL;
krb5_error_code err;
int key_usage;
unsigned char acceptor_flag;
@@ -75,9 +75,13 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
#endif
size_t ec;
unsigned short tok_id;
- krb5_checksum sum;
+ krb5_checksum sum = { 0 };
krb5_key key;
krb5_cksumtype cksumtype;
+ krb5_data plain = empty_data();
+
+ token->value = NULL;
+ token->length = 0;
acceptor_flag = ctx->initiate ? 0 : FLAG_SENDER_IS_ACCEPTOR;
key_usage = (toktype == KG_TOK_WRAP_MSG
@@ -107,14 +111,15 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
#endif
if (toktype == KG_TOK_WRAP_MSG && conf_req_flag) {
- krb5_data plain;
krb5_enc_data cipher;
size_t ec_max;
size_t encrypt_size;
/* 300: Adds some slop. */
- if (SIZE_MAX - 300 < message->length)
- return ENOMEM;
+ if (SIZE_MAX - 300 < message->length) {
+ err = ENOMEM;
+ goto cleanup;
+ }
ec_max = SIZE_MAX - message->length - 300;
if (ec_max > 0xffff)
ec_max = 0xffff;
@@ -126,20 +131,20 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
#endif
err = alloc_data(&plain, message->length + 16 + ec);
if (err)
- return err;
+ goto cleanup;
/* Get size of ciphertext. */
encrypt_size = krb5_encrypt_size(plain.length, key->keyblock.enctype);
if (encrypt_size > SIZE_MAX / 2) {
err = ENOMEM;
- goto error;
+ goto cleanup;
}
bufsize = 16 + encrypt_size;
/* Allocate space for header plus encrypted data. */
outbuf = gssalloc_malloc(bufsize);
if (outbuf == NULL) {
- free(plain.data);
- return ENOMEM;
+ err = ENOMEM;
+ goto cleanup;
}
/* TOK_ID */
@@ -164,11 +169,8 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
cipher.ciphertext.length = bufsize - 16;
cipher.enctype = key->keyblock.enctype;
err = krb5_k_encrypt(context, key, key_usage, 0, &plain, &cipher);
- zap(plain.data, plain.length);
- free(plain.data);
- plain.data = 0;
if (err)
- goto error;
+ goto cleanup;
/* Now that we know we're returning a valid token.... */
ctx->seq_send++;
@@ -181,7 +183,6 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
/* If the rotate fails, don't worry about it. */
#endif
} else if (toktype == KG_TOK_WRAP_MSG && !conf_req_flag) {
- krb5_data plain;
size_t cksumsize;
/* Here, message is the application-supplied data; message2 is
@@ -193,21 +194,19 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
wrap_with_checksum:
err = alloc_data(&plain, message->length + 16);
if (err)
- return err;
+ goto cleanup;
err = krb5_c_checksum_length(context, cksumtype, &cksumsize);
if (err)
- goto error;
+ goto cleanup;
assert(cksumsize <= 0xffff);
bufsize = 16 + message2->length + cksumsize;
outbuf = gssalloc_malloc(bufsize);
if (outbuf == NULL) {
- free(plain.data);
- plain.data = 0;
err = ENOMEM;
- goto error;
+ goto cleanup;
}
/* TOK_ID */
@@ -239,23 +238,15 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
if (message2->length)
memcpy(outbuf + 16, message2->value, message2->length);
- sum.contents = outbuf + 16 + message2->length;
- sum.length = cksumsize;
-
err = krb5_k_make_checksum(context, cksumtype, key,
key_usage, &plain, &sum);
- zap(plain.data, plain.length);
- free(plain.data);
- plain.data = 0;
if (err) {
zap(outbuf,bufsize);
- goto error;
+ goto cleanup;
}
if (sum.length != cksumsize)
abort();
memcpy(outbuf + 16 + message2->length, sum.contents, cksumsize);
- krb5_free_checksum_contents(context, &sum);
- sum.contents = 0;
/* Now that we know we're actually generating the token... */
ctx->seq_send++;
@@ -285,12 +276,13 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
token->value = outbuf;
token->length = bufsize;
- return 0;
+ outbuf = NULL;
+ err = 0;
-error:
+cleanup:
+ krb5_free_checksum_contents(context, &sum);
+ zapfree(plain.data, plain.length);
gssalloc_free(outbuf);
- token->value = NULL;
- token->length = 0;
return err;
}
diff --git a/src/lib/rpc/pmap_rmt.c b/src/lib/rpc/pmap_rmt.c
index 434e4eea65..f55ca46c60 100644
--- a/src/lib/rpc/pmap_rmt.c
+++ b/src/lib/rpc/pmap_rmt.c
@@ -161,12 +161,12 @@ xdr_rmtcallres(
caddr_t port_ptr;
port_ptr = (caddr_t)(void *)crp->port_ptr;
- if (xdr_reference(xdrs, &port_ptr, sizeof (uint32_t),
- (xdrproc_t)xdr_u_int32) &&
- xdr_u_int32(xdrs, &crp->resultslen)) {
- crp->port_ptr = (uint32_t *)(void *)port_ptr;
+ if (!xdr_reference(xdrs, &port_ptr, sizeof (uint32_t),
+ (xdrproc_t)xdr_u_int32))
+ return (FALSE);
+ crp->port_ptr = (uint32_t *)(void *)port_ptr;
+ if (xdr_u_int32(xdrs, &crp->resultslen))
return ((*(crp->xdr_results))(xdrs, crp->results_ptr));
- }
return (FALSE);
}
--
2.45.1

File diff suppressed because it is too large Load diff

View file

@ -1,71 +0,0 @@
From 05bb6d9c729a3c6a4ba35270368bc0f6e1875ad0 Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Mon, 8 Jan 2024 16:52:27 +0100
Subject: [PATCH] Remove klist's defname global variable
Addition of a "cleanup" section in kinit's show_ccache() function as
part of commit 6c5471176f5266564fbc8a7e02f03b4b042202f8 introduced a
double-free bug, because defname is a global variable. After the
first call, successive calls may take place with a dangling pointer in
defname, which will be freed if krb5_cc_get_principal() fails.
Convert "defname" to a local variable initialized at the beginning of
show_ccache().
[ghudson@mit.edu: edited commit message]
(cherry picked from commit 5b00197227231943bd2305328c8260dd0b0dbcf0)
---
src/clients/klist/klist.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/clients/klist/klist.c b/src/clients/klist/klist.c
index b5ae96a843..b5808e5c93 100644
--- a/src/clients/klist/klist.c
+++ b/src/clients/klist/klist.c
@@ -53,7 +53,6 @@ int show_flags = 0, show_time = 0, status_only = 0, show_keys = 0;
int show_etype = 0, show_addresses = 0, no_resolve = 0, print_version = 0;
int show_adtype = 0, show_all = 0, list_all = 0, use_client_keytab = 0;
int show_config = 0;
-char *defname;
char *progname;
krb5_timestamp now;
unsigned int timestamp_width;
@@ -62,7 +61,7 @@ krb5_context context;
static krb5_boolean is_local_tgt(krb5_principal princ, krb5_data *realm);
static char *etype_string(krb5_enctype );
-static void show_credential(krb5_creds *);
+static void show_credential(krb5_creds *, const char *);
static void list_all_ccaches(void);
static int list_ccache(krb5_ccache);
@@ -473,6 +472,7 @@ show_ccache(krb5_ccache cache)
krb5_creds creds;
krb5_principal princ = NULL;
krb5_error_code ret;
+ char *defname = NULL;
int status = 1;
ret = krb5_cc_get_principal(context, cache, &princ);
@@ -503,7 +503,7 @@ show_ccache(krb5_ccache cache)
}
while ((ret = krb5_cc_next_cred(context, cache, &cur, &creds)) == 0) {
if (show_config || !krb5_is_config_principal(context, creds.server))
- show_credential(&creds);
+ show_credential(&creds, defname);
krb5_free_cred_contents(context, &creds);
}
if (ret == KRB5_CC_END) {
@@ -676,7 +676,7 @@ print_config_data(int col, krb5_data *data)
}
static void
-show_credential(krb5_creds *cred)
+show_credential(krb5_creds *cred, const char *defname)
{
krb5_error_code ret;
krb5_ticket *tkt = NULL;
--
2.45.1

View file

@ -1,34 +0,0 @@
From d7bcca2a215de880f4419afc450a96a747d48560 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Fri, 27 Oct 2023 00:44:53 -0400
Subject: [PATCH] End connection on KDC_ERR_SVC_UNAVAILABLE
In sendto_kdc.c:service_fds(), if a message handler indicates that a
message should be discarded, kill the connection so we don't continue
waiting on it for more data.
ticket: 7899
(cherry picked from commit ca80f64c786341d5871ae1de18142e62af64f7b9)
---
src/lib/krb5/os/sendto_kdc.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c
index 0f4bf23a95..262edf09b4 100644
--- a/src/lib/krb5/os/sendto_kdc.c
+++ b/src/lib/krb5/os/sendto_kdc.c
@@ -1440,7 +1440,10 @@ service_fds(krb5_context context, struct select_state *selstate,
if (msg_handler != NULL) {
krb5_data reply = make_data(state->in.buf, state->in.pos);
- stop = (msg_handler(context, &reply, msg_handler_data) != 0);
+ if (!msg_handler(context, &reply, msg_handler_data)) {
+ kill_conn(context, state, selstate);
+ stop = 0;
+ }
}
if (stop) {
--
2.46.0

View file

@ -1,226 +0,0 @@
From a07b3ae29fd972c40e30b95f6bcc8fb3ed4d9991 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Thu, 26 Oct 2023 14:20:34 -0400
Subject: [PATCH] Add request_timeout configuration parameter
Add a parameter to limit the total amount of time taken for a KDC or
password change request.
ticket: 9106 (new)
(cherry picked from commit 802318cda963456b3ed7856c836e89da891483be)
---
doc/admin/conf_files/krb5_conf.rst | 9 ++++++
src/include/k5-int.h | 2 ++
src/lib/krb5/krb/init_ctx.c | 14 +++++++-
src/lib/krb5/os/sendto_kdc.c | 51 ++++++++++++++++++++----------
4 files changed, 58 insertions(+), 18 deletions(-)
diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
index a33711d918..65fb592d98 100644
--- a/doc/admin/conf_files/krb5_conf.rst
+++ b/doc/admin/conf_files/krb5_conf.rst
@@ -356,6 +356,15 @@ The libdefaults section may contain any of the following relations:
(:ref:`duration` string.) Sets the default renewable lifetime
for initial ticket requests. The default value is 0.
+**request_timeout**
+ (:ref:`duration` string.) Sets the maximum total time for KDC or
+ password change requests. This timeout does not affect the
+ intervals between requests, so setting a low timeout may result in
+ fewer requests being attempted and/or some servers not being
+ contacted. A value of 0 indicates no specific maximum, in which
+ case requests will time out if no server responds after several
+ tries. The default value is 0. (New in release 1.22.)
+
**spake_preauth_groups**
A whitespace or comma-separated list of words which specifies the
groups allowed for SPAKE preauthentication. The possible values
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index b3e07945c1..69d6a6f569 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -296,6 +296,7 @@ typedef unsigned char u_char;
#define KRB5_CONF_SPAKE_PREAUTH_INDICATOR "spake_preauth_indicator"
#define KRB5_CONF_SPAKE_PREAUTH_KDC_CHALLENGE "spake_preauth_kdc_challenge"
#define KRB5_CONF_SPAKE_PREAUTH_GROUPS "spake_preauth_groups"
+#define KRB5_CONF_REQUEST_TIMEOUT "request_timeout"
#define KRB5_CONF_TICKET_LIFETIME "ticket_lifetime"
#define KRB5_CONF_UDP_PREFERENCE_LIMIT "udp_preference_limit"
#define KRB5_CONF_UNLOCKITER "unlockiter"
@@ -1200,6 +1201,7 @@ struct _krb5_context {
kdb5_dal_handle *dal_handle;
/* allowable clock skew */
krb5_deltat clockskew;
+ krb5_deltat req_timeout;
krb5_flags kdc_default_options;
krb5_flags library_options;
krb5_boolean profile_secure;
diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c
index 2b5abcd817..582a2945ff 100644
--- a/src/lib/krb5/krb/init_ctx.c
+++ b/src/lib/krb5/krb/init_ctx.c
@@ -157,7 +157,7 @@ krb5_init_context_profile(profile_t profile, krb5_flags flags,
krb5_context ctx = 0;
krb5_error_code retval;
int tmp;
- char *plugin_dir = NULL;
+ char *plugin_dir = NULL, *timeout_str = NULL;
/* Verify some assumptions. If the assumptions hold and the
compiler is optimizing, this should result in no code being
@@ -240,6 +240,17 @@ krb5_init_context_profile(profile_t profile, krb5_flags flags,
get_integer(ctx, KRB5_CONF_CLOCKSKEW, DEFAULT_CLOCKSKEW, &tmp);
ctx->clockskew = tmp;
+ retval = profile_get_string(ctx->profile, KRB5_CONF_LIBDEFAULTS,
+ KRB5_CONF_REQUEST_TIMEOUT, NULL, NULL,
+ &timeout_str);
+ if (retval)
+ goto cleanup;
+ if (timeout_str != NULL) {
+ retval = krb5_string_to_deltat(timeout_str, &ctx->req_timeout);
+ if (retval)
+ goto cleanup;
+ }
+
get_integer(ctx, KRB5_CONF_KDC_DEFAULT_OPTIONS, KDC_OPT_RENEWABLE_OK,
&tmp);
ctx->kdc_default_options = tmp;
@@ -281,6 +292,7 @@ krb5_init_context_profile(profile_t profile, krb5_flags flags,
cleanup:
profile_release_string(plugin_dir);
+ profile_release_string(timeout_str);
krb5_free_context(ctx);
return retval;
}
diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c
index 262edf09b4..98247a1089 100644
--- a/src/lib/krb5/os/sendto_kdc.c
+++ b/src/lib/krb5/os/sendto_kdc.c
@@ -1395,34 +1395,41 @@ get_endtime(time_ms endtime, struct conn_state *conns)
static krb5_boolean
service_fds(krb5_context context, struct select_state *selstate,
- time_ms interval, struct conn_state *conns,
+ time_ms interval, time_ms timeout, struct conn_state *conns,
struct select_state *seltemp, const krb5_data *realm,
int (*msg_handler)(krb5_context, const krb5_data *, void *),
void *msg_handler_data, struct conn_state **winner_out)
{
int e, selret = 0;
- time_ms endtime;
+ time_ms curtime, interval_end, endtime;
struct conn_state *state;
*winner_out = NULL;
- e = get_curtime_ms(&endtime);
+ e = get_curtime_ms(&curtime);
if (e)
return TRUE;
- endtime += interval;
+ interval_end = curtime + interval;
e = 0;
while (selstate->nfds > 0) {
- e = cm_select_or_poll(selstate, get_endtime(endtime, conns),
- seltemp, &selret);
+ endtime = get_endtime(interval_end, conns);
+ /* Don't wait longer than the whole request should last. */
+ if (timeout && endtime > timeout)
+ endtime = timeout;
+ e = cm_select_or_poll(selstate, endtime, seltemp, &selret);
if (e == EINTR)
continue;
if (e != 0)
break;
- if (selret == 0)
- /* Timeout, return to caller. */
+ if (selret == 0) {
+ /* We timed out. Stop if we hit the overall request timeout. */
+ if (timeout && (get_curtime_ms(&curtime) || curtime >= timeout))
+ return TRUE;
+ /* Otherwise return to the caller to send the next request. */
return FALSE;
+ }
/* Got something on a socket, process it. */
for (state = conns; state != NULL; state = state->next) {
@@ -1495,7 +1502,7 @@ k5_sendto(krb5_context context, const krb5_data *message,
void *msg_handler_data)
{
int pass;
- time_ms delay;
+ time_ms delay, timeout = 0;
krb5_error_code retval;
struct conn_state *conns = NULL, *state, **tailptr, *next, *winner;
size_t s;
@@ -1505,6 +1512,13 @@ k5_sendto(krb5_context context, const krb5_data *message,
*reply = empty_data();
+ if (context->req_timeout) {
+ retval = get_curtime_ms(&timeout);
+ if (retval)
+ return retval;
+ timeout += 1000 * context->req_timeout;
+ }
+
/* One for use here, listing all our fds in use, and one for
* temporary use in service_fds, for the fds of interest. */
sel_state = malloc(2 * sizeof(*sel_state));
@@ -1532,8 +1546,9 @@ k5_sendto(krb5_context context, const krb5_data *message,
if (maybe_send(context, state, message, sel_state, realm,
callback_info))
continue;
- done = service_fds(context, sel_state, 1000, conns, seltemp,
- realm, msg_handler, msg_handler_data, &winner);
+ done = service_fds(context, sel_state, 1000, timeout, conns,
+ seltemp, realm, msg_handler, msg_handler_data,
+ &winner);
}
}
@@ -1545,13 +1560,13 @@ k5_sendto(krb5_context context, const krb5_data *message,
if (maybe_send(context, state, message, sel_state, realm,
callback_info))
continue;
- done = service_fds(context, sel_state, 1000, conns, seltemp,
+ done = service_fds(context, sel_state, 1000, timeout, conns, seltemp,
realm, msg_handler, msg_handler_data, &winner);
}
/* Wait for two seconds at the end of the first pass. */
if (!done) {
- done = service_fds(context, sel_state, 2000, conns, seltemp,
+ done = service_fds(context, sel_state, 2000, timeout, conns, seltemp,
realm, msg_handler, msg_handler_data, &winner);
}
@@ -1562,15 +1577,17 @@ k5_sendto(krb5_context context, const krb5_data *message,
if (maybe_send(context, state, message, sel_state, realm,
callback_info))
continue;
- done = service_fds(context, sel_state, 1000, conns, seltemp,
- realm, msg_handler, msg_handler_data, &winner);
+ done = service_fds(context, sel_state, 1000, timeout, conns,
+ seltemp, realm, msg_handler, msg_handler_data,
+ &winner);
if (sel_state->nfds == 0)
break;
}
/* Wait for the delay backoff at the end of this pass. */
if (!done) {
- done = service_fds(context, sel_state, delay, conns, seltemp,
- realm, msg_handler, msg_handler_data, &winner);
+ done = service_fds(context, sel_state, delay, timeout, conns,
+ seltemp, realm, msg_handler, msg_handler_data,
+ &winner);
}
if (sel_state->nfds == 0)
break;
--
2.46.0

View file

@ -1,138 +0,0 @@
From 1da153d97d7fb30a44fca35f9b71b8f4ed5385b9 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Thu, 26 Oct 2023 16:26:42 -0400
Subject: [PATCH] Wait indefinitely on KDC TCP connections
When making a KDC or password change request, wait indefinitely
(limited only by request_timeout if set) once a KDC has accepted a TCP
connection.
ticket: 9105 (new)
(cherry picked from commit 6436a3808061da787a43c6810f5f0370cdfb6e36)
---
doc/admin/conf_files/krb5_conf.rst | 2 +-
src/lib/krb5/os/sendto_kdc.c | 50 ++++++++++++++++--------------
2 files changed, 27 insertions(+), 25 deletions(-)
diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
index 65fb592d98..b7284c47df 100644
--- a/doc/admin/conf_files/krb5_conf.rst
+++ b/doc/admin/conf_files/krb5_conf.rst
@@ -357,7 +357,7 @@ The libdefaults section may contain any of the following relations:
for initial ticket requests. The default value is 0.
**request_timeout**
- (:ref:`duration` string.) Sets the maximum total time for KDC or
+ (:ref:`duration` string.) Sets the maximum total time for KDC and
password change requests. This timeout does not affect the
intervals between requests, so setting a low timeout may result in
fewer requests being attempted and/or some servers not being
diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c
index 98247a1089..924f5b2d26 100644
--- a/src/lib/krb5/os/sendto_kdc.c
+++ b/src/lib/krb5/os/sendto_kdc.c
@@ -134,7 +134,6 @@ struct conn_state {
krb5_data callback_buffer;
size_t server_index;
struct conn_state *next;
- time_ms endtime;
krb5_boolean defer;
struct {
const char *uri_path;
@@ -344,15 +343,19 @@ cm_select_or_poll(const struct select_state *in, time_ms endtime,
struct select_state *out, int *sret)
{
#ifndef USE_POLL
- struct timeval tv;
+ struct timeval tv, *tvp;
#endif
krb5_error_code retval;
time_ms curtime, interval;
- retval = get_curtime_ms(&curtime);
- if (retval != 0)
- return retval;
- interval = (curtime < endtime) ? endtime - curtime : 0;
+ if (endtime != 0) {
+ retval = get_curtime_ms(&curtime);
+ if (retval != 0)
+ return retval;
+ interval = (curtime < endtime) ? endtime - curtime : 0;
+ } else {
+ interval = -1;
+ }
/* We don't need a separate copy of the selstate for poll, but use one for
* consistency with how we use select. */
@@ -361,9 +364,14 @@ cm_select_or_poll(const struct select_state *in, time_ms endtime,
#ifdef USE_POLL
*sret = poll(out->fds, out->nfds, interval);
#else
- tv.tv_sec = interval / 1000;
- tv.tv_usec = interval % 1000 * 1000;
- *sret = select(out->max, &out->rfds, &out->wfds, &out->xfds, &tv);
+ if (interval != -1) {
+ tv.tv_sec = interval / 1000;
+ tv.tv_usec = interval % 1000 * 1000;
+ tvp = &tv;
+ } else {
+ tvp = NULL;
+ }
+ *sret = select(out->max, &out->rfds, &out->wfds, &out->xfds, tvp);
#endif
return (*sret < 0) ? SOCKET_ERRNO : 0;
@@ -1099,11 +1107,6 @@ service_tcp_connect(krb5_context context, const krb5_data *realm,
}
conn->state = WRITING;
-
- /* Record this connection's timeout for service_fds. */
- if (get_curtime_ms(&conn->endtime) == 0)
- conn->endtime += 10000;
-
return conn->service_write(context, realm, conn, selstate);
}
@@ -1378,19 +1381,18 @@ kill_conn:
return FALSE;
}
-/* Return the maximum of endtime and the endtime fields of all currently active
- * TCP connections. */
-static time_ms
-get_endtime(time_ms endtime, struct conn_state *conns)
+/* Return true if conns contains any states with connected TCP sockets. */
+static krb5_boolean
+any_tcp_connections(struct conn_state *conns)
{
struct conn_state *state;
for (state = conns; state != NULL; state = state->next) {
- if ((state->state == READING || state->state == WRITING) &&
- state->endtime > endtime)
- endtime = state->endtime;
+ if (state->addr.transport != UDP &&
+ (state->state == READING || state->state == WRITING))
+ return TRUE;
}
- return endtime;
+ return FALSE;
}
static krb5_boolean
@@ -1413,9 +1415,9 @@ service_fds(krb5_context context, struct select_state *selstate,
e = 0;
while (selstate->nfds > 0) {
- endtime = get_endtime(interval_end, conns);
+ endtime = any_tcp_connections(conns) ? 0 : interval_end;
/* Don't wait longer than the whole request should last. */
- if (timeout && endtime > timeout)
+ if (timeout && (!endtime || endtime > timeout))
endtime = timeout;
e = cm_select_or_poll(selstate, endtime, seltemp, &selret);
if (e == EINTR)
--
2.46.0

File diff suppressed because it is too large Load diff

View file

@ -1,265 +0,0 @@
From 3999883b9745bfd7065d41ff05b19e56bcb2e791 Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Fri, 6 Sep 2024 17:18:11 +0200
Subject: [PATCH] Fix various issues detected by static analysis
In klists's show_credential(), ensure that the column counter doesn't
decrease if printf() fails.
In process_k5beta7_princ(), bounds-check the e_length field.
In ndr_enc_delegation_info(), initialize b so it is always valid for
the cleanup handler.
In krb5_dbe_def_decrypt_key_data(), change the flow control so ret is
always set by the end of the function. Return KRB5_KDB_INVALIDKEYSIZE
if there isn't enough data in the first key_data_contents field or if
the serialized key length is invalid.
In svcauth_gss_validate(), expand rpchdr to accomodate the header plus
MAX_AUTH_BYTES.
In svcudp_reply(), change slen to unsigned to match the return type of
XDR_GETPOS() and eliminate an unnecessary check for slen >= 0.
In krb5int_pthread_loaded()(), remove pthread_equal() from the weak
symbol checks. It is implemented as an inline function in some glibc
versions, which makes the comparison "&pthread_equal == 0" always
false.
[ghudson@mit.edu: further modified krb5_dbe_def_decrypt_key_data() for
clarity; added detail to commit message]
(cherry picked from commit a96541981ee34c8642ddeb6101b98e883e41c6e5)
---
src/clients/klist/klist.c | 12 ++++-----
src/kadmin/dbutil/dump.c | 5 ++++
src/kdc/ndr.c | 2 +-
src/lib/kdb/decrypt_key.c | 54 ++++++++++++++++++++------------------
src/lib/rpc/svc_auth_gss.c | 5 +++-
src/lib/rpc/svc_udp.c | 13 ++++-----
src/util/support/threads.c | 2 --
7 files changed, 51 insertions(+), 42 deletions(-)
diff --git a/src/clients/klist/klist.c b/src/clients/klist/klist.c
index b5808e5c93..ba9539fd23 100644
--- a/src/clients/klist/klist.c
+++ b/src/clients/klist/klist.c
@@ -681,7 +681,7 @@ show_credential(krb5_creds *cred, const char *defname)
krb5_error_code ret;
krb5_ticket *tkt = NULL;
char *name = NULL, *sname = NULL, *tktsname, *flags;
- int extra_field = 0, ccol = 0, i;
+ int extra_field = 0, ccol = 0, i, r;
krb5_boolean is_config = krb5_is_config_principal(context, cred->server);
ret = krb5_unparse_name(context, cred->client, &name);
@@ -711,11 +711,11 @@ show_credential(krb5_creds *cred, const char *defname)
fputs("config: ", stdout);
ccol = 8;
for (i = 1; i < cred->server->length; i++) {
- ccol += printf("%s%.*s%s",
- i > 1 ? "(" : "",
- (int)cred->server->data[i].length,
- cred->server->data[i].data,
- i > 1 ? ")" : "");
+ r = printf("%s%.*s%s", i > 1 ? "(" : "",
+ (int)cred->server->data[i].length,
+ cred->server->data[i].data, i > 1 ? ")" : "");
+ if (r >= 0)
+ ccol += r;
}
fputs(" = ", stdout);
ccol += 3;
diff --git a/src/kadmin/dbutil/dump.c b/src/kadmin/dbutil/dump.c
index 4d6cc0bdf9..feb053d834 100644
--- a/src/kadmin/dbutil/dump.c
+++ b/src/kadmin/dbutil/dump.c
@@ -704,6 +704,11 @@ process_k5beta7_princ(krb5_context context, const char *fname, FILE *filep,
dbentry->len = u1;
dbentry->n_key_data = u4;
+
+ if (u5 > UINT16_MAX) {
+ load_err(fname, *linenop, _("invalid principal extra data size"));
+ goto fail;
+ }
dbentry->e_length = u5;
if (kp != NULL) {
diff --git a/src/kdc/ndr.c b/src/kdc/ndr.c
index d438408ee2..38be9fe42a 100644
--- a/src/kdc/ndr.c
+++ b/src/kdc/ndr.c
@@ -242,7 +242,7 @@ ndr_enc_delegation_info(struct pac_s4u_delegation_info *in, krb5_data *out)
{
krb5_error_code ret;
size_t i;
- struct k5buf b;
+ struct k5buf b = EMPTY_K5BUF;
struct encoded_wchars pt_encoded = { 0 }, *tss_encoded = NULL;
uint32_t pointer = 0;
diff --git a/src/lib/kdb/decrypt_key.c b/src/lib/kdb/decrypt_key.c
index 82bbed6312..21aa3742b1 100644
--- a/src/lib/kdb/decrypt_key.c
+++ b/src/lib/kdb/decrypt_key.c
@@ -60,7 +60,7 @@ krb5_dbe_def_decrypt_key_data(krb5_context context, const krb5_keyblock *mkey,
krb5_keyblock *dbkey_out,
krb5_keysalt *keysalt_out)
{
- krb5_error_code ret;
+ krb5_error_code ret = KRB5_CRYPTO_INTERNAL;
int16_t keylen;
krb5_enc_data cipher;
krb5_data plain = empty_data();
@@ -74,36 +74,38 @@ krb5_dbe_def_decrypt_key_data(krb5_context context, const krb5_keyblock *mkey,
if (mkey == NULL)
return KRB5_KDB_BADSTORED_MKEY;
- if (kd->key_data_contents[0] != NULL && kd->key_data_length[0] >= 2) {
- keylen = load_16_le(kd->key_data_contents[0]);
- if (keylen < 0)
- return EINVAL;
- cipher.enctype = ENCTYPE_UNKNOWN;
- cipher.ciphertext = make_data(kd->key_data_contents[0] + 2,
- kd->key_data_length[0] - 2);
- ret = alloc_data(&plain, kd->key_data_length[0] - 2);
- if (ret)
- goto cleanup;
+ if (kd->key_data_contents[0] == NULL || kd->key_data_length[0] < 2)
+ return KRB5_KDB_INVALIDKEYSIZE;
- ret = krb5_c_decrypt(context, mkey, 0, 0, &cipher, &plain);
- if (ret)
- goto cleanup;
+ keylen = load_16_le(kd->key_data_contents[0]);
+ if (keylen < 0)
+ return KRB5_KDB_INVALIDKEYSIZE;
- /* Make sure the plaintext has at least as many bytes as the true ke
- * length (it may have more due to padding). */
- if ((unsigned int)keylen > plain.length) {
- ret = KRB5_CRYPTO_INTERNAL;
- if (ret)
- goto cleanup;
- }
+ cipher.enctype = ENCTYPE_UNKNOWN;
+ cipher.ciphertext = make_data(kd->key_data_contents[0] + 2,
+ kd->key_data_length[0] - 2);
+ ret = alloc_data(&plain, kd->key_data_length[0] - 2);
+ if (ret)
+ goto cleanup;
- kb.magic = KV5M_KEYBLOCK;
- kb.enctype = kd->key_data_type[0];
- kb.length = keylen;
- kb.contents = (uint8_t *)plain.data;
- plain = empty_data();
+ ret = krb5_c_decrypt(context, mkey, 0, 0, &cipher, &plain);
+ if (ret)
+ goto cleanup;
+
+ /* Make sure the plaintext has at least as many bytes as the true key
+ * length (it may have more due to padding). */
+ if ((unsigned int)keylen > plain.length) {
+ ret = KRB5_CRYPTO_INTERNAL;
+ if (ret)
+ goto cleanup;
}
+ kb.magic = KV5M_KEYBLOCK;
+ kb.enctype = kd->key_data_type[0];
+ kb.length = keylen;
+ kb.contents = (uint8_t *)plain.data;
+ plain = empty_data();
+
/* Decode salt data. */
if (keysalt_out != NULL) {
if (kd->key_data_ver == 2) {
diff --git a/src/lib/rpc/svc_auth_gss.c b/src/lib/rpc/svc_auth_gss.c
index 98d601c8ab..4f1d2911b0 100644
--- a/src/lib/rpc/svc_auth_gss.c
+++ b/src/lib/rpc/svc_auth_gss.c
@@ -297,7 +297,7 @@ svcauth_gss_validate(struct svc_req *rqst, struct svc_rpc_gss_data *gd, struct r
struct opaque_auth *oa;
gss_buffer_desc rpcbuf, checksum;
OM_uint32 maj_stat, min_stat, qop_state;
- u_char rpchdr[128];
+ u_char rpchdr[32 + MAX_AUTH_BYTES];
int32_t *buf;
log_debug("in svcauth_gss_validate()");
@@ -315,6 +315,8 @@ svcauth_gss_validate(struct svc_req *rqst, struct svc_rpc_gss_data *gd, struct r
return (FALSE);
buf = (int32_t *)(void *)rpchdr;
+
+ /* Write the 32 first bytes of the header. */
IXDR_PUT_LONG(buf, msg->rm_xid);
IXDR_PUT_ENUM(buf, msg->rm_direction);
IXDR_PUT_LONG(buf, msg->rm_call.cb_rpcvers);
@@ -323,6 +325,7 @@ svcauth_gss_validate(struct svc_req *rqst, struct svc_rpc_gss_data *gd, struct r
IXDR_PUT_LONG(buf, msg->rm_call.cb_proc);
IXDR_PUT_ENUM(buf, oa->oa_flavor);
IXDR_PUT_LONG(buf, oa->oa_length);
+
if (oa->oa_length) {
memcpy((caddr_t)buf, oa->oa_base, oa->oa_length);
buf += RNDUP(oa->oa_length) / sizeof(int32_t);
diff --git a/src/lib/rpc/svc_udp.c b/src/lib/rpc/svc_udp.c
index 8ecbdf2b33..3aff277eb7 100644
--- a/src/lib/rpc/svc_udp.c
+++ b/src/lib/rpc/svc_udp.c
@@ -248,8 +248,9 @@ static bool_t svcudp_reply(
{
struct svcudp_data *su = su_data(xprt);
XDR *xdrs = &su->su_xdrs;
- int slen;
+ u_int slen;
bool_t stat = FALSE;
+ ssize_t r;
xdrproc_t xdr_results = NULL;
caddr_t xdr_location = 0;
@@ -272,12 +273,12 @@ static bool_t svcudp_reply(
if (xdr_replymsg(xdrs, msg) &&
(!has_args ||
(SVCAUTH_WRAP(xprt->xp_auth, xdrs, xdr_results, xdr_location)))) {
- slen = (int)XDR_GETPOS(xdrs);
- if (sendto(xprt->xp_sock, rpc_buffer(xprt), slen, 0,
- (struct sockaddr *)&(xprt->xp_raddr), xprt->xp_addrlen)
- == slen) {
+ slen = XDR_GETPOS(xdrs);
+ r = sendto(xprt->xp_sock, rpc_buffer(xprt), slen, 0,
+ (struct sockaddr *)&(xprt->xp_raddr), xprt->xp_addrlen);
+ if (r >= 0 && (u_int)r == slen) {
stat = TRUE;
- if (su->su_cache && slen >= 0) {
+ if (su->su_cache) {
cache_set(xprt, (uint32_t) slen);
}
}
diff --git a/src/util/support/threads.c b/src/util/support/threads.c
index be7e4c2e3f..4ded805b79 100644
--- a/src/util/support/threads.c
+++ b/src/util/support/threads.c
@@ -118,7 +118,6 @@ struct tsd_block {
# pragma weak pthread_mutex_destroy
# pragma weak pthread_mutex_init
# pragma weak pthread_self
-# pragma weak pthread_equal
# pragma weak pthread_getspecific
# pragma weak pthread_setspecific
# pragma weak pthread_key_create
@@ -151,7 +150,6 @@ int krb5int_pthread_loaded (void)
|| &pthread_mutex_destroy == 0
|| &pthread_mutex_init == 0
|| &pthread_self == 0
- || &pthread_equal == 0
/* Any program that's really multithreaded will have to be
able to create threads. */
|| &pthread_create == 0
--
2.46.0

View file

@ -1,629 +0,0 @@
From ea02fd7bb79861b8e36517c7c95af821a16657c4 Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Thu, 22 Aug 2024 17:15:50 +0200
Subject: [PATCH] Generate and verify message MACs in libkrad
Implement some of the measures specified in
draft-ietf-radext-deprecating-radius-03 for mitigating the BlastRADIUS
attack (CVE-2024-3596):
* Include a Message-Authenticator MAC as the first attribute when
generating a packet of type Access-Request, Access-Reject,
Access-Accept, or Access-Challenge (sections 5.2.1 and 5.2.4), if
the secret is non-empty. (An empty secret indicates the use of Unix
domain socket transport.)
* Validate the Message-Authenticator MAC in received packets, if
present.
FreeRADIUS enforces Message-Authenticator as of versions 3.2.5 and
3.0.27. libkrad must generate Message-Authenticator attributes in
order to remain compatible with these implementations.
[ghudson@mit.edu: adjusted style and naming; simplified some
functions; edited commit message]
ticket: 9142 (new)
tags: pullup
target_version: 1.21-next
(cherry picked from commit 871125fea8ce0370a972bf65f7d1de63f619b06c)
---
src/include/k5-int.h | 5 +
src/lib/crypto/krb/checksum_hmac_md5.c | 28 ++++
src/lib/crypto/libk5crypto.exports | 1 +
src/lib/krad/attr.c | 17 ++
src/lib/krad/attrset.c | 59 +++++--
src/lib/krad/internal.h | 7 +-
src/lib/krad/packet.c | 206 +++++++++++++++++++++++--
src/lib/krad/t_attrset.c | 2 +-
src/lib/krad/t_daemon.py | 3 +-
src/lib/krad/t_packet.c | 11 ++
src/tests/t_otp.py | 3 +
11 files changed, 311 insertions(+), 31 deletions(-)
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index 69d6a6f569..b7789a2dd8 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -2403,4 +2403,9 @@ krb5_boolean
k5_sname_compare(krb5_context context, krb5_const_principal sname,
krb5_const_principal princ);
+/* Generate an HMAC-MD5 keyed checksum as specified by RFC 2104. */
+krb5_error_code
+k5_hmac_md5(const krb5_data *key, const krb5_crypto_iov *data, size_t num_data,
+ krb5_data *output);
+
#endif /* _KRB5_INT_H */
diff --git a/src/lib/crypto/krb/checksum_hmac_md5.c b/src/lib/crypto/krb/checksum_hmac_md5.c
index ec024f3966..a809388549 100644
--- a/src/lib/crypto/krb/checksum_hmac_md5.c
+++ b/src/lib/crypto/krb/checksum_hmac_md5.c
@@ -92,3 +92,31 @@ cleanup:
free(hash_iov);
return ret;
}
+
+krb5_error_code
+k5_hmac_md5(const krb5_data *key, const krb5_crypto_iov *data, size_t num_data,
+ krb5_data *output)
+{
+ krb5_error_code ret;
+ const struct krb5_hash_provider *hash = &krb5int_hash_md5;
+ krb5_keyblock keyblock = { 0 };
+ krb5_data hashed_key;
+ uint8_t hkeybuf[16];
+ krb5_crypto_iov iov;
+
+ /* Hash the key if it is longer than the block size. */
+ if (key->length > hash->blocksize) {
+ hashed_key = make_data(hkeybuf, sizeof(hkeybuf));
+ iov.flags = KRB5_CRYPTO_TYPE_DATA;
+ iov.data = *key;
+ ret = hash->hash(&iov, 1, &hashed_key);
+ if (ret)
+ return ret;
+ key = &hashed_key;
+ }
+
+ keyblock.magic = KV5M_KEYBLOCK;
+ keyblock.length = key->length;
+ keyblock.contents = (uint8_t *)key->data;
+ return krb5int_hmac_keyblock(hash, &keyblock, data, num_data, output);
+}
diff --git a/src/lib/crypto/libk5crypto.exports b/src/lib/crypto/libk5crypto.exports
index d8ffa63304..00e0ce1812 100644
--- a/src/lib/crypto/libk5crypto.exports
+++ b/src/lib/crypto/libk5crypto.exports
@@ -102,3 +102,4 @@ krb5_c_prfplus
krb5_c_derive_prfplus
k5_enctype_to_ssf
krb5int_c_deprecated_enctype
+k5_hmac_md5
diff --git a/src/lib/krad/attr.c b/src/lib/krad/attr.c
index 42d354a3b5..65ed1d35e7 100644
--- a/src/lib/krad/attr.c
+++ b/src/lib/krad/attr.c
@@ -125,6 +125,23 @@ static const attribute_record attributes[UCHAR_MAX] = {
{"NAS-Port-Type", 4, 4, NULL, NULL},
{"Port-Limit", 4, 4, NULL, NULL},
{"Login-LAT-Port", 1, MAX_ATTRSIZE, NULL, NULL},
+ {NULL, 0, 0, NULL, NULL}, /* Reserved for tunnelling */
+ {NULL, 0, 0, NULL, NULL}, /* Reserved for tunnelling */
+ {NULL, 0, 0, NULL, NULL}, /* Reserved for tunnelling */
+ {NULL, 0, 0, NULL, NULL}, /* Reserved for tunnelling */
+ {NULL, 0, 0, NULL, NULL}, /* Reserved for tunnelling */
+ {NULL, 0, 0, NULL, NULL}, /* Reserved for tunnelling */
+ {NULL, 0, 0, NULL, NULL}, /* Reserved for Apple Remote Access Protocol */
+ {NULL, 0, 0, NULL, NULL}, /* Reserved for Apple Remote Access Protocol */
+ {NULL, 0, 0, NULL, NULL}, /* Reserved for Apple Remote Access Protocol */
+ {NULL, 0, 0, NULL, NULL}, /* Reserved for Apple Remote Access Protocol */
+ {NULL, 0, 0, NULL, NULL}, /* Reserved for Apple Remote Access Protocol */
+ {NULL, 0, 0, NULL, NULL}, /* Password-Retry */
+ {NULL, 0, 0, NULL, NULL}, /* Prompt */
+ {NULL, 0, 0, NULL, NULL}, /* Connect-Info */
+ {NULL, 0, 0, NULL, NULL}, /* Configuration-Token */
+ {NULL, 0, 0, NULL, NULL}, /* EAP-Message */
+ {"Message-Authenticator", MD5_DIGEST_SIZE, MD5_DIGEST_SIZE, NULL, NULL},
};
/* Encode User-Password attribute. */
diff --git a/src/lib/krad/attrset.c b/src/lib/krad/attrset.c
index 6ec031e320..e5457ebfd7 100644
--- a/src/lib/krad/attrset.c
+++ b/src/lib/krad/attrset.c
@@ -164,15 +164,44 @@ krad_attrset_copy(const krad_attrset *set, krad_attrset **copy)
return 0;
}
+/* Place an encoded attributes into outbuf at position *i. Increment *i by the
+ * length of the encoding. */
+static krb5_error_code
+append_attr(krb5_context ctx, const char *secret,
+ const uint8_t *auth, krad_attr type, const krb5_data *data,
+ uint8_t outbuf[MAX_ATTRSETSIZE], size_t *i, krb5_boolean *is_fips)
+{
+ uint8_t buffer[MAX_ATTRSIZE];
+ size_t attrlen;
+ krb5_error_code retval;
+
+ retval = kr_attr_encode(ctx, secret, auth, type, data, buffer, &attrlen,
+ is_fips);
+ if (retval)
+ return retval;
+
+ if (attrlen > MAX_ATTRSETSIZE - *i - 2)
+ return EMSGSIZE;
+
+ outbuf[(*i)++] = type;
+ outbuf[(*i)++] = attrlen + 2;
+ memcpy(outbuf + *i, buffer, attrlen);
+ *i += attrlen;
+
+ return 0;
+}
+
krb5_error_code
kr_attrset_encode(const krad_attrset *set, const char *secret,
- const unsigned char *auth,
+ const uint8_t *auth, krb5_boolean add_msgauth,
unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen,
krb5_boolean *is_fips)
{
- unsigned char buffer[MAX_ATTRSIZE];
krb5_error_code retval;
- size_t i = 0, attrlen;
+ krad_attr msgauth_type = krad_attr_name2num("Message-Authenticator");
+ const uint8_t zeroes[MD5_DIGEST_SIZE] = { 0 };
+ krb5_data zerodata;
+ size_t i = 0;
attr *a;
if (set == NULL) {
@@ -180,19 +209,21 @@ kr_attrset_encode(const krad_attrset *set, const char *secret,
return 0;
}
- K5_TAILQ_FOREACH(a, &set->list, list) {
- retval = kr_attr_encode(set->ctx, secret, auth, a->type, &a->attr,
- buffer, &attrlen, is_fips);
- if (retval != 0)
+ if (add_msgauth) {
+ /* Encode Message-Authenticator as the first attribute, per
+ * draft-ietf-radext-deprecating-radius-03 section 5.2. */
+ zerodata = make_data((uint8_t *)zeroes, MD5_DIGEST_SIZE);
+ retval = append_attr(set->ctx, secret, auth, msgauth_type, &zerodata,
+ outbuf, &i, is_fips);
+ if (retval)
return retval;
+ }
- if (i + attrlen + 2 > MAX_ATTRSETSIZE)
- return EMSGSIZE;
-
- outbuf[i++] = a->type;
- outbuf[i++] = attrlen + 2;
- memcpy(&outbuf[i], buffer, attrlen);
- i += attrlen;
+ K5_TAILQ_FOREACH(a, &set->list, list) {
+ retval = append_attr(set->ctx, secret, auth, a->type, &a->attr,
+ outbuf, &i, is_fips);
+ if (retval)
+ return retval;
}
*outlen = i;
diff --git a/src/lib/krad/internal.h b/src/lib/krad/internal.h
index a17b6f39b1..ca66f3ec68 100644
--- a/src/lib/krad/internal.h
+++ b/src/lib/krad/internal.h
@@ -49,6 +49,8 @@
#define UCHAR_MAX 255
#endif
+#define MD5_DIGEST_SIZE 16
+
/* RFC 2865 */
#define MAX_ATTRSIZE (UCHAR_MAX - 2)
#define MAX_ATTRSETSIZE (KRAD_PACKET_SIZE_MAX - 20)
@@ -79,10 +81,11 @@ kr_attr_decode(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);
-/* Encode the attributes into the buffer. */
+/* Encode set into outbuf. If add_msgauth is true, include a zeroed
+ * Message-Authenticator as the first attribute. */
krb5_error_code
kr_attrset_encode(const krad_attrset *set, const char *secret,
- const unsigned char *auth,
+ const uint8_t *auth, krb5_boolean add_msgauth,
unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen,
krb5_boolean *is_fips);
diff --git a/src/lib/krad/packet.c b/src/lib/krad/packet.c
index c5446b890c..3c1a4d507e 100644
--- a/src/lib/krad/packet.c
+++ b/src/lib/krad/packet.c
@@ -36,6 +36,7 @@
typedef unsigned char uchar;
/* RFC 2865 */
+#define MSGAUTH_SIZE (2 + MD5_DIGEST_SIZE)
#define OFFSET_CODE 0
#define OFFSET_ID 1
#define OFFSET_LENGTH 2
@@ -222,6 +223,106 @@ packet_set_attrset(krb5_context ctx, const char *secret, krad_packet *pkt)
return kr_attrset_decode(ctx, &tmp, secret, pkt_auth(pkt), &pkt->attrset);
}
+/* Determine if a packet requires a Message-Authenticator attribute. */
+static inline krb5_boolean
+requires_msgauth(const char *secret, krad_code code)
+{
+ /* If no secret is provided, assume that the transport is a UNIX socket.
+ * Message-Authenticator is required only on UDP and TCP connections. */
+ if (*secret == '\0')
+ return FALSE;
+
+ /*
+ * Per draft-ietf-radext-deprecating-radius-03 sections 5.2.1 and 5.2.4,
+ * Message-Authenticator is required in Access-Request packets and all
+ * potential responses when UDP or TCP transport is used.
+ */
+ return code == krad_code_name2num("Access-Request") ||
+ code == krad_code_name2num("Access-Reject") ||
+ code == krad_code_name2num("Access-Accept") ||
+ code == krad_code_name2num("Access-Challenge");
+}
+
+/* Check if the packet has a Message-Authenticator attribute. */
+static inline krb5_boolean
+has_pkt_msgauth(const krad_packet *pkt)
+{
+ krad_attr msgauth_type = krad_attr_name2num("Message-Authenticator");
+
+ return krad_attrset_get(pkt->attrset, msgauth_type, 0) != NULL;
+}
+
+/* Return the beginning of the Message-Authenticator attribute in pkt, or NULL
+ * if no such attribute is present. */
+static const uint8_t *
+lookup_msgauth_addr(const krad_packet *pkt)
+{
+ krad_attr msgauth_type = krad_attr_name2num("Message-Authenticator");
+ size_t i;
+ uint8_t *p;
+
+ i = OFFSET_ATTR;
+ while (i + 2 < pkt->pkt.length) {
+ p = (uint8_t *)offset(&pkt->pkt, i);
+ if (msgauth_type == *p)
+ return p;
+ i += p[1];
+ }
+
+ return NULL;
+}
+
+/*
+ * Calculate the message authenticator MAC for pkt as specified in RFC 2869
+ * section 5.14, placing the result in mac_out. Use the provided authenticator
+ * auth, which may be from pkt or from a corresponding request.
+ */
+static krb5_error_code
+calculate_mac(const char *secret, const krad_packet *pkt,
+ const uint8_t auth[AUTH_FIELD_SIZE],
+ uint8_t mac_out[MD5_DIGEST_SIZE])
+{
+ uint8_t zeroed_msgauth[MSGAUTH_SIZE];
+ krad_attr msgauth_type = krad_attr_name2num("Message-Authenticator");
+ const uint8_t *msgauth_attr, *msgauth_end, *pkt_end;
+ krb5_crypto_iov input[5];
+ krb5_data ksecr, mac;
+
+ msgauth_attr = lookup_msgauth_addr(pkt);
+ if (msgauth_attr == NULL)
+ return EINVAL;
+ msgauth_end = msgauth_attr + MSGAUTH_SIZE;
+ pkt_end = (const uint8_t *)pkt->pkt.data + pkt->pkt.length;
+
+ /* Read code, id, and length from the packet. */
+ input[0].flags = KRB5_CRYPTO_TYPE_DATA;
+ input[0].data = make_data(pkt->pkt.data, OFFSET_AUTH);
+
+ /* Read the provided authenticator. */
+ input[1].flags = KRB5_CRYPTO_TYPE_DATA;
+ input[1].data = make_data((uint8_t *)auth, AUTH_FIELD_SIZE);
+
+ /* Read any attributes before Message-Authenticator. */
+ input[2].flags = KRB5_CRYPTO_TYPE_DATA;
+ input[2].data = make_data(pkt_attr(pkt), msgauth_attr - pkt_attr(pkt));
+
+ /* Read Message-Authenticator with the data bytes all set to zero, per RFC
+ * 2869 section 5.14. */
+ zeroed_msgauth[0] = msgauth_type;
+ zeroed_msgauth[1] = MSGAUTH_SIZE;
+ memset(zeroed_msgauth + 2, 0, MD5_DIGEST_SIZE);
+ input[3].flags = KRB5_CRYPTO_TYPE_DATA;
+ input[3].data = make_data(zeroed_msgauth, MSGAUTH_SIZE);
+
+ /* Read any attributes after Message-Authenticator. */
+ input[4].flags = KRB5_CRYPTO_TYPE_DATA;
+ input[4].data = make_data((uint8_t *)msgauth_end, pkt_end - msgauth_end);
+
+ mac = make_data(mac_out, MD5_DIGEST_SIZE);
+ ksecr = string2data((char *)secret);
+ return k5_hmac_md5(&ksecr, input, 5, &mac);
+}
+
ssize_t
krad_packet_bytes_needed(const krb5_data *buffer)
{
@@ -255,6 +356,7 @@ krad_packet_new_request(krb5_context ctx, const char *secret, krad_code code,
krad_packet *pkt;
uchar id;
size_t attrset_len;
+ krb5_boolean msgauth_required;
pkt = packet_new();
if (pkt == NULL) {
@@ -274,9 +376,13 @@ krad_packet_new_request(krb5_context ctx, const char *secret, krad_code code,
if (retval != 0)
goto error;
+ /* Determine if Message-Authenticator is required. */
+ msgauth_required = (*secret != '\0' &&
+ code == krad_code_name2num("Access-Request"));
+
/* Encode the attributes. */
- retval = kr_attrset_encode(set, secret, pkt_auth(pkt), pkt_attr(pkt),
- &attrset_len, &pkt->is_fips);
+ retval = kr_attrset_encode(set, secret, pkt_auth(pkt), msgauth_required,
+ pkt_attr(pkt), &attrset_len, &pkt->is_fips);
if (retval != 0)
goto error;
@@ -285,6 +391,13 @@ krad_packet_new_request(krb5_context ctx, const char *secret, krad_code code,
pkt_code_set(pkt, code);
pkt_len_set(pkt, pkt->pkt.length);
+ if (msgauth_required) {
+ /* Calculate and set the Message-Authenticator MAC. */
+ retval = calculate_mac(secret, pkt, pkt_auth(pkt), pkt_attr(pkt) + 2);
+ if (retval != 0)
+ goto error;
+ }
+
/* Copy the attrset for future use. */
retval = packet_set_attrset(ctx, secret, pkt);
if (retval != 0)
@@ -307,14 +420,19 @@ krad_packet_new_response(krb5_context ctx, const char *secret, krad_code code,
krb5_error_code retval;
krad_packet *pkt;
size_t attrset_len;
+ krb5_boolean msgauth_required;
pkt = packet_new();
if (pkt == NULL)
return ENOMEM;
+ /* Determine if Message-Authenticator is required. */
+ msgauth_required = requires_msgauth(secret, code);
+
/* Encode the attributes. */
- retval = kr_attrset_encode(set, secret, pkt_auth(request), pkt_attr(pkt),
- &attrset_len, &pkt->is_fips);
+ retval = kr_attrset_encode(set, secret, pkt_auth(request),
+ msgauth_required, pkt_attr(pkt), &attrset_len,
+ &pkt->is_fips);
if (retval != 0)
goto error;
@@ -330,6 +448,18 @@ krad_packet_new_response(krb5_context ctx, const char *secret, krad_code code,
if (retval != 0)
goto error;
+ if (msgauth_required) {
+ /*
+ * Calculate and replace the Message-Authenticator MAC. Per RFC 2869
+ * section 5.14, use the authenticator from the request, not from the
+ * response.
+ */
+ retval = calculate_mac(secret, pkt, pkt_auth(request),
+ pkt_attr(pkt) + 2);
+ if (retval != 0)
+ goto error;
+ }
+
/* Copy the attrset for future use. */
retval = packet_set_attrset(ctx, secret, pkt);
if (retval != 0)
@@ -343,6 +473,34 @@ error:
return retval;
}
+/* Verify the Message-Authenticator value in pkt, using the provided
+ * authenticator (which may be from pkt or from a corresponding request). */
+static krb5_error_code
+verify_msgauth(const char *secret, const krad_packet *pkt,
+ const uint8_t auth[AUTH_FIELD_SIZE])
+{
+ uint8_t mac[MD5_DIGEST_SIZE];
+ krad_attr msgauth_type = krad_attr_name2num("Message-Authenticator");
+ const krb5_data *msgauth;
+ krb5_error_code retval;
+
+ msgauth = krad_packet_get_attr(pkt, msgauth_type, 0);
+ if (msgauth == NULL)
+ return ENODATA;
+
+ retval = calculate_mac(secret, pkt, auth, mac);
+ if (retval)
+ return retval;
+
+ if (msgauth->length != MD5_DIGEST_SIZE)
+ return EMSGSIZE;
+
+ if (k5_bcmp(mac, msgauth->data, MD5_DIGEST_SIZE) != 0)
+ return EBADMSG;
+
+ return 0;
+}
+
/* Decode a packet. */
static krb5_error_code
decode_packet(krb5_context ctx, const char *secret, const krb5_data *buffer,
@@ -394,21 +552,35 @@ krad_packet_decode_request(krb5_context ctx, const char *secret,
krad_packet **reqpkt)
{
const krad_packet *tmp = NULL;
+ krad_packet *req;
krb5_error_code retval;
- retval = decode_packet(ctx, secret, buffer, reqpkt);
- if (cb != NULL && retval == 0) {
+ retval = decode_packet(ctx, secret, buffer, &req);
+ if (retval)
+ return retval;
+
+ /* Verify Message-Authenticator if present. */
+ if (has_pkt_msgauth(req)) {
+ retval = verify_msgauth(secret, req, pkt_auth(req));
+ if (retval) {
+ krad_packet_free(req);
+ return retval;
+ }
+ }
+
+ if (cb != NULL) {
for (tmp = (*cb)(data, FALSE); tmp != NULL; tmp = (*cb)(data, FALSE)) {
if (pkt_id_get(*reqpkt) == pkt_id_get(tmp))
break;
}
- }
- if (cb != NULL && (retval != 0 || tmp != NULL))
- (*cb)(data, TRUE);
+ if (tmp != NULL)
+ (*cb)(data, TRUE);
+ }
+ *reqpkt = req;
*duppkt = tmp;
- return retval;
+ return 0;
}
krb5_error_code
@@ -435,9 +607,17 @@ krad_packet_decode_response(krb5_context ctx, const char *secret,
break;
}
- /* If the authenticator matches, then the response is valid. */
- if (memcmp(pkt_auth(*rsppkt), auth, sizeof(auth)) == 0)
- break;
+ /* Verify the response authenticator. */
+ if (k5_bcmp(pkt_auth(*rsppkt), auth, sizeof(auth)) != 0)
+ continue;
+
+ /* Verify Message-Authenticator if present. */
+ if (has_pkt_msgauth(*rsppkt)) {
+ if (verify_msgauth(secret, *rsppkt, pkt_auth(tmp)) != 0)
+ continue;
+ }
+
+ break;
}
}
diff --git a/src/lib/krad/t_attrset.c b/src/lib/krad/t_attrset.c
index 4cdb8b7d8e..f9c66509bd 100644
--- a/src/lib/krad/t_attrset.c
+++ b/src/lib/krad/t_attrset.c
@@ -63,7 +63,7 @@ main(void)
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, FALSE, buffer, &encode_len,
&is_fips));
krad_attrset_free(set);
diff --git a/src/lib/krad/t_daemon.py b/src/lib/krad/t_daemon.py
index 4a3de079c7..647d4894eb 100755
--- a/src/lib/krad/t_daemon.py
+++ b/src/lib/krad/t_daemon.py
@@ -40,6 +40,7 @@ DICTIONARY = """
ATTRIBUTE\tUser-Name\t1\tstring
ATTRIBUTE\tUser-Password\t2\toctets
ATTRIBUTE\tNAS-Identifier\t32\tstring
+ATTRIBUTE\tMessage-Authenticator\t80\toctets
"""
class TestServer(server.Server):
@@ -52,7 +53,7 @@ class TestServer(server.Server):
if key == "User-Password":
passwd = [pkt.PwDecrypt(x) for x in pkt[key]]
- reply = self.CreateReplyPacket(pkt)
+ reply = self.CreateReplyPacket(pkt, message_authenticator=True)
if passwd == ['accept']:
reply.code = packet.AccessAccept
else:
diff --git a/src/lib/krad/t_packet.c b/src/lib/krad/t_packet.c
index c22489144f..104b6507a2 100644
--- a/src/lib/krad/t_packet.c
+++ b/src/lib/krad/t_packet.c
@@ -172,6 +172,9 @@ main(int argc, const char **argv)
krb5_data username, password;
krb5_boolean auth = FALSE;
krb5_context ctx;
+ const krad_packet *dupreq;
+ const krb5_data *encpkt;
+ krad_packet *decreq;
username = string2data("testUser");
@@ -184,9 +187,17 @@ main(int argc, const char **argv)
password = string2data("accept");
noerror(make_packet(ctx, &username, &password, &packets[ACCEPT_PACKET]));
+ encpkt = krad_packet_encode(packets[ACCEPT_PACKET]);
+ noerror(krad_packet_decode_request(ctx, "foo", encpkt, NULL, NULL,
+ &dupreq, &decreq));
+ krad_packet_free(decreq);
password = string2data("reject");
noerror(make_packet(ctx, &username, &password, &packets[REJECT_PACKET]));
+ encpkt = krad_packet_encode(packets[REJECT_PACKET]);
+ noerror(krad_packet_decode_request(ctx, "foo", encpkt, NULL, NULL,
+ &dupreq, &decreq));
+ krad_packet_free(decreq);
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
diff --git a/src/tests/t_otp.py b/src/tests/t_otp.py
index c3b820a411..dd5cdc5c26 100755
--- a/src/tests/t_otp.py
+++ b/src/tests/t_otp.py
@@ -49,6 +49,7 @@ ATTRIBUTE User-Name 1 string
ATTRIBUTE User-Password 2 octets
ATTRIBUTE Service-Type 6 integer
ATTRIBUTE NAS-Identifier 32 string
+ATTRIBUTE Message-Authenticator 80 octets
'''
class RadiusDaemon(Process):
@@ -97,6 +98,8 @@ class RadiusDaemon(Process):
reply.code = packet.AccessReject
replyq['reply'] = False
+ reply.add_message_authenticator()
+
outq.put(replyq)
if addr is None:
sock.send(reply.ReplyPacket())
--
2.46.0

File diff suppressed because it is too large Load diff

View file

@ -1,78 +0,0 @@
From 43d10f1580c033fe706470e7588c720ac7854918 Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Wed, 21 Jun 2023 18:27:11 +0200
Subject: [PATCH] Add ecdsa-with-sha512/256 to supportedCMSTypes
Elliptic curve certificates are already supported for PKINIT
pre-authentication, but their associated signature types aren't
advertized. Add ecdsa-with-sha512 and ecdsa-with-sha256 OIDs to the
supportedCMSTypes list sent by the client.
[ghudson@mit.edu: edited commit message]
ticket: 9100 (new)
(cherry picked from commit 9913e5c92c4e5cb76d6ae58386f744766d2e6454)
---
src/plugins/preauth/pkinit/pkinit_constants.c | 38 +++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/src/plugins/preauth/pkinit/pkinit_constants.c b/src/plugins/preauth/pkinit/pkinit_constants.c
index 10f8688ec2..905e90d29c 100644
--- a/src/plugins/preauth/pkinit/pkinit_constants.c
+++ b/src/plugins/preauth/pkinit/pkinit_constants.c
@@ -64,14 +64,52 @@ static char sha512WithRSAEncr_oid[9] = {
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d
};
+/* RFC 3279 ecdsa-with-SHA1: iso(1) member-body(2) us(840) ansi-X9-62(10045)
+ * signatures(4) 1 */
+static char ecdsaWithSha1_oid[] = {
+ 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x01
+};
+
+/* RFC 5758 ecdsa-with-SHA256: iso(1) member-body(2) us(840) ansi-X9-62(10045)
+ * signatures(4) ecdsa-with-SHA2(3) 2 */
+static char ecdsaWithSha256_oid[] = {
+ 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02
+};
+
+/* RFC 5758 ecdsa-with-SHA384: iso(1) member-body(2) us(840) ansi-X9-62(10045)
+ * signatures(4) ecdsa-with-SHA2(3) 3 */
+static char ecdsaWithSha384_oid[] = {
+ 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03
+};
+
+/* RFC 5758 ecdsa-with-SHA512: iso(1) member-body(2) us(840) ansi-X9-62(10045)
+ * signatures(4) ecdsa-with-SHA2(3) 4 */
+static char ecdsaWithSha512_oid[] = {
+ 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04
+};
+
const krb5_data sha256WithRSAEncr_id = {
KV5M_DATA, sizeof(sha256WithRSAEncr_oid), sha256WithRSAEncr_oid
};
const krb5_data sha512WithRSAEncr_id = {
KV5M_DATA, sizeof(sha512WithRSAEncr_oid), sha512WithRSAEncr_oid
};
+const krb5_data ecdsaWithSha1_id = {
+ KV5M_DATA, sizeof(ecdsaWithSha1_oid), ecdsaWithSha1_oid
+};
+const krb5_data ecdsaWithSha256_id = {
+ KV5M_DATA, sizeof(ecdsaWithSha256_oid), ecdsaWithSha256_oid
+};
+const krb5_data ecdsaWithSha384_id = {
+ KV5M_DATA, sizeof(ecdsaWithSha384_oid), ecdsaWithSha384_oid
+};
+const krb5_data ecdsaWithSha512_id = {
+ KV5M_DATA, sizeof(ecdsaWithSha512_oid), ecdsaWithSha512_oid
+};
krb5_data const * const supported_cms_algs[] = {
+ &ecdsaWithSha512_id,
+ &ecdsaWithSha256_id,
&sha512WithRSAEncr_id,
&sha256WithRSAEncr_id,
NULL
--
2.47.1

View file

@ -1,264 +0,0 @@
From fba4cbf0bc50569b8ea6d1e1c3303eaab84935e1 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Sun, 30 Jul 2023 01:07:38 -0400
Subject: [PATCH] Get rid of pkinit_crypto_openssl.h
Fold pkinit_crypto_openssl.h into the one source file where it was
used. Also clean up the include of <arpa/inet.h>, as htonl() is no
longer used after commit 1c87ce6c44a9de0824580a2d72a8a202237e01f4.
(cherry picked from commit b3352945fb8836f8b4095e0b8aad04b54aca3152)
---
src/plugins/preauth/pkinit/deps | 2 +-
.../preauth/pkinit/pkinit_crypto_openssl.c | 85 +++++++++++-
.../preauth/pkinit/pkinit_crypto_openssl.h | 121 ------------------
3 files changed, 83 insertions(+), 125 deletions(-)
delete mode 100644 src/plugins/preauth/pkinit/pkinit_crypto_openssl.h
diff --git a/src/plugins/preauth/pkinit/deps b/src/plugins/preauth/pkinit/deps
index 58320aa801..b6f4476fe8 100644
--- a/src/plugins/preauth/pkinit/deps
+++ b/src/plugins/preauth/pkinit/deps
@@ -112,4 +112,4 @@ pkinit_crypto_openssl.so pkinit_crypto_openssl.po $(OUTPRE)pkinit_crypto_openssl
$(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/krb5/preauth_plugin.h \
$(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
pkcs11.h pkinit.h pkinit_accessor.h pkinit_crypto.h \
- pkinit_crypto_openssl.c pkinit_crypto_openssl.h pkinit_trace.h
+ pkinit_crypto_openssl.c pkinit_trace.h
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
index f6d494bd11..ae8599d5a2 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
@@ -30,20 +30,99 @@
*/
#include "k5-int.h"
-#include "pkinit_crypto_openssl.h"
#include "k5-buf.h"
#include "k5-err.h"
#include "k5-hex.h"
-#include <unistd.h>
+#include "pkinit.h"
#include <dirent.h>
-#include <arpa/inet.h>
+#include <openssl/bn.h>
+#include <openssl/dh.h>
+#include <openssl/x509.h>
+#include <openssl/pkcs7.h>
+#include <openssl/pkcs12.h>
+#include <openssl/obj_mac.h>
+#include <openssl/x509v3.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/sha.h>
+#include <openssl/asn1.h>
+#include <openssl/pem.h>
+#include <openssl/asn1t.h>
+#include <openssl/cms.h>
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
#include <openssl/core_names.h>
#include <openssl/kdf.h>
+#include <openssl/decoder.h>
#include <openssl/params.h>
#endif
+#define DN_BUF_LEN 256
+#define MAX_CREDS_ALLOWED 20
+
+struct _pkinit_cred_info {
+ char *name;
+ X509 *cert;
+ EVP_PKEY *key;
+#ifndef WITHOUT_PKCS11
+ CK_BYTE_PTR cert_id;
+ int cert_id_len;
+#endif
+};
+typedef struct _pkinit_cred_info *pkinit_cred_info;
+
+struct _pkinit_identity_crypto_context {
+ pkinit_cred_info creds[MAX_CREDS_ALLOWED+1];
+ STACK_OF(X509) *my_certs; /* available user certs */
+ char *identity; /* identity name for user cert */
+ int cert_index; /* cert to use out of available certs*/
+ EVP_PKEY *my_key; /* available user keys if in filesystem */
+ STACK_OF(X509) *trustedCAs; /* available trusted ca certs */
+ STACK_OF(X509) *intermediateCAs; /* available intermediate ca certs */
+ STACK_OF(X509_CRL) *revoked; /* available crls */
+ int pkcs11_method;
+ krb5_prompter_fct prompter;
+ void *prompter_data;
+#ifndef WITHOUT_PKCS11
+ char *p11_module_name;
+ CK_SLOT_ID slotid;
+ char *token_label;
+ char *cert_label;
+ /* These are crypto-specific. */
+ struct plugin_file_handle *p11_module;
+ CK_SESSION_HANDLE session;
+ CK_FUNCTION_LIST_PTR p11;
+ uint8_t *cert_id;
+ size_t cert_id_len;
+ CK_MECHANISM_TYPE mech;
+#endif
+ krb5_boolean defer_id_prompt;
+ pkinit_deferred_id *deferred_ids;
+};
+
+struct _pkinit_plg_crypto_context {
+ EVP_PKEY *dh_1024;
+ EVP_PKEY *dh_2048;
+ EVP_PKEY *dh_4096;
+ EVP_PKEY *ec_p256;
+ EVP_PKEY *ec_p384;
+ EVP_PKEY *ec_p521;
+ ASN1_OBJECT *id_pkinit_authData;
+ ASN1_OBJECT *id_pkinit_DHKeyData;
+ ASN1_OBJECT *id_pkinit_rkeyData;
+ ASN1_OBJECT *id_pkinit_san;
+ ASN1_OBJECT *id_ms_san_upn;
+ ASN1_OBJECT *id_pkinit_KPClientAuth;
+ ASN1_OBJECT *id_pkinit_KPKdc;
+ ASN1_OBJECT *id_ms_kp_sc_logon;
+ ASN1_OBJECT *id_kp_serverAuth;
+};
+
+struct _pkinit_req_crypto_context {
+ X509 *received_cert;
+ EVP_PKEY *client_pkey;
+};
+
static krb5_error_code pkinit_init_pkinit_oids(pkinit_plg_crypto_context );
static void pkinit_fini_pkinit_oids(pkinit_plg_crypto_context );
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.h b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.h
deleted file mode 100644
index b7a3358800..0000000000
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * COPYRIGHT (C) 2006,2007
- * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
- * ALL RIGHTS RESERVED
- *
- * Permission is granted to use, copy, create derivative works
- * and redistribute this software and such derivative works
- * for any purpose, so long as the name of The University of
- * Michigan is not used in any advertising or publicity
- * pertaining to the use of distribution of this software
- * without specific, written prior authorization. If the
- * above copyright notice or any other identification of the
- * University of Michigan is included in any copy of any
- * portion of this software, then the disclaimer below must
- * also be included.
- *
- * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
- * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
- * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
- * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
- * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
- * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
- * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
- * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
- * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGES.
- */
-
-#ifndef _PKINIT_CRYPTO_OPENSSL_H
-#define _PKINIT_CRYPTO_OPENSSL_H
-
-#include "pkinit.h"
-
-#include <openssl/bn.h>
-#include <openssl/dh.h>
-#include <openssl/x509.h>
-#include <openssl/pkcs7.h>
-#include <openssl/pkcs12.h>
-#include <openssl/obj_mac.h>
-#include <openssl/x509v3.h>
-#include <openssl/err.h>
-#include <openssl/evp.h>
-#include <openssl/sha.h>
-#include <openssl/asn1.h>
-#include <openssl/pem.h>
-#include <openssl/asn1t.h>
-#include <openssl/cms.h>
-#if OPENSSL_VERSION_NUMBER >= 0x30000000L
-#include <openssl/core_names.h>
-#include <openssl/decoder.h>
-#endif
-
-#define DN_BUF_LEN 256
-#define MAX_CREDS_ALLOWED 20
-
-struct _pkinit_cred_info {
- char *name;
- X509 *cert;
- EVP_PKEY *key;
-#ifndef WITHOUT_PKCS11
- CK_BYTE_PTR cert_id;
- int cert_id_len;
-#endif
-};
-typedef struct _pkinit_cred_info * pkinit_cred_info;
-
-struct _pkinit_identity_crypto_context {
- pkinit_cred_info creds[MAX_CREDS_ALLOWED+1];
- STACK_OF(X509) *my_certs; /* available user certs */
- char *identity; /* identity name for user cert */
- int cert_index; /* cert to use out of available certs*/
- EVP_PKEY *my_key; /* available user keys if in filesystem */
- STACK_OF(X509) *trustedCAs; /* available trusted ca certs */
- STACK_OF(X509) *intermediateCAs; /* available intermediate ca certs */
- STACK_OF(X509_CRL) *revoked; /* available crls */
- int pkcs11_method;
- krb5_prompter_fct prompter;
- void *prompter_data;
-#ifndef WITHOUT_PKCS11
- char *p11_module_name;
- CK_SLOT_ID slotid;
- char *token_label;
- char *cert_label;
- /* These are crypto-specific */
- struct plugin_file_handle *p11_module;
- CK_SESSION_HANDLE session;
- CK_FUNCTION_LIST_PTR p11;
- uint8_t *cert_id;
- size_t cert_id_len;
- CK_MECHANISM_TYPE mech;
-#endif
- krb5_boolean defer_id_prompt;
- pkinit_deferred_id *deferred_ids;
-};
-
-struct _pkinit_plg_crypto_context {
- EVP_PKEY *dh_1024;
- EVP_PKEY *dh_2048;
- EVP_PKEY *dh_4096;
- EVP_PKEY *ec_p256;
- EVP_PKEY *ec_p384;
- EVP_PKEY *ec_p521;
- ASN1_OBJECT *id_pkinit_authData;
- ASN1_OBJECT *id_pkinit_DHKeyData;
- ASN1_OBJECT *id_pkinit_rkeyData;
- ASN1_OBJECT *id_pkinit_san;
- ASN1_OBJECT *id_ms_san_upn;
- ASN1_OBJECT *id_pkinit_KPClientAuth;
- ASN1_OBJECT *id_pkinit_KPKdc;
- ASN1_OBJECT *id_ms_kp_sc_logon;
- ASN1_OBJECT *id_kp_serverAuth;
-};
-
-struct _pkinit_req_crypto_context {
- X509 *received_cert;
- EVP_PKEY *client_pkey;
-};
-
-#endif /* _PKINIT_CRYPTO_OPENSSL_H */
--
2.47.1

View file

@ -1,157 +0,0 @@
From 1b01057df4c2223fbf92be44f1e764207208ef03 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Mon, 26 Feb 2024 19:03:38 -0500
Subject: [PATCH] Use SoftHSMv2 for PKCS11 PKINIT tests
Instead of softpkcs11, use SoftHSMv2 to mock the PKCS11 token for
PKINIT tests. Use pkcs11-tool from OpenSC to initialize the token and
import a certificate and key. SoftHSM does not support PIN-less
tokens (see https://github.com/opendnssec/SoftHSMv2/issues/480) so
remove that test for now.
(cherry picked from commit 8ab61608236883fdc5c2d43f4bd1ff2094401d19)
---
.github/workflows/build.yml | 2 +-
src/tests/t_pkinit.py | 82 ++++++++++++++++++++-----------------
2 files changed, 45 insertions(+), 39 deletions(-)
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 68a4788adb..d7ae86b150 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -33,7 +33,7 @@ jobs:
if: startsWith(matrix.os, 'ubuntu')
run: |
sudo apt-get update -qq
- sudo apt-get install -y bison gettext keyutils ldap-utils libcmocka-dev libldap2-dev libkeyutils-dev libsasl2-dev libssl-dev python3-kdcproxy python3-pip slapd tcsh
+ sudo apt-get install -y bison gettext keyutils ldap-utils libcmocka-dev libldap2-dev libkeyutils-dev libsasl2-dev libssl-dev python3-kdcproxy python3-pip slapd tcsh softhsm2 opensc
pip3 install pyrad
- name: Build
env:
diff --git a/src/tests/t_pkinit.py b/src/tests/t_pkinit.py
index f8f2debc1b..4435746429 100755
--- a/src/tests/t_pkinit.py
+++ b/src/tests/t_pkinit.py
@@ -1,11 +1,10 @@
from k5test import *
+import re
# Skip this test if pkinit wasn't built.
if not pkinit_enabled:
skip_rest('PKINIT tests', 'PKINIT module not built')
-soft_pkcs11 = os.path.join(buildtop, 'tests', 'softpkcs11', 'softpkcs11.so')
-
# Construct a krb5.conf fragment configuring pkinit.
user_pem = os.path.join(pkinit_certs, 'user.pem')
privkey_pem = os.path.join(pkinit_certs, 'privkey.pem')
@@ -55,9 +54,6 @@ p12_upn2_identity = 'PKCS12:%s' % user_upn2_p12
p12_upn3_identity = 'PKCS12:%s' % user_upn3_p12
p12_generic_identity = 'PKCS12:%s' % generic_p12
p12_enc_identity = 'PKCS12:%s' % user_enc_p12
-p11_identity = 'PKCS11:' + soft_pkcs11
-p11_token_identity = ('PKCS11:module_name=' + soft_pkcs11 +
- ':slotid=1:token=SoftToken (token)')
# Start a realm with the test kdb module for the following UPN SAN tests.
realm = K5Realm(kdc_conf=alias_kdc_conf, create_kdb=False, pkinit=True)
@@ -389,53 +385,63 @@ realm.klist(realm.user_princ)
realm.kinit(realm.user_princ, flags=['-X', 'X509_user_identity=,'],
expected_code=1, expected_msg='Preauthentication failed while')
-softpkcs11rc = os.path.join(os.getcwd(), 'testdir', 'soft-pkcs11.rc')
-realm.env['SOFTPKCS11RC'] = softpkcs11rc
+softhsm2 = '/usr/lib/softhsm/libsofthsm2.so'
+if not os.path.exists(softhsm2):
+ skip_rest('PKCS11 tests', 'SoftHSMv2 required')
+pkcs11_tool = which('pkcs11-tool')
+if not pkcs11_tool:
+ skip_rest('PKCS11 tests', 'pkcs11-tool from OpenSC required')
+tool_cmd = [pkcs11_tool, '--module', softhsm2]
+
+# Prepare a SoftHSM token.
+softhsm2_conf = os.path.join(realm.testdir, 'softhsm2.conf')
+softhsm2_tokens = os.path.join(realm.testdir, 'tokens')
+os.mkdir(softhsm2_tokens)
+realm.env['SOFTHSM2_CONF'] = softhsm2_conf
+with open(softhsm2_conf, 'w') as f:
+ f.write('directories.tokendir = %s\n' % softhsm2_tokens)
+realm.run(tool_cmd + ['--init-token', '--label', 'user',
+ '--so-pin', 'sopin', '--init-pin', '--pin', 'userpin'])
+realm.run(tool_cmd + ['-w', user_pem, '-y', 'cert'])
+realm.run(tool_cmd + ['-w', privkey_pem, '-y', 'privkey',
+ '-l', '--pin', 'userpin'])
+
+# Extract the slot ID generated by SoftHSM.
+out = realm.run(tool_cmd + ['-L'])
+m = re.search(r'slot ID 0x([0-9a-f]+)\n', out)
+if not m:
+ fail('could not extract slot ID from SoftHSM token')
+slot_id = int(m.group(1), 16)
+
+p11_attr = 'X509_user_identity=PKCS11:' + softhsm2
+p11_token_identity = ('PKCS11:module_name=%s:slotid=%d:token=user' %
+ (softhsm2, slot_id))
-# PKINIT with PKCS11: identity, with no need for a PIN.
-mark('PKCS11 identity, no PIN')
-conf = open(softpkcs11rc, 'w')
-conf.write("%s\t%s\t%s\t%s\n" % ('user', 'user token', user_pem, privkey_pem))
-conf.close()
-# Expect to succeed without having to supply any more information.
-realm.kinit(realm.user_princ,
- flags=['-X', 'X509_user_identity=%s' % p11_identity])
+mark('PKCS11 identity, with PIN (prompter)')
+realm.kinit(realm.user_princ, flags=['-X', p11_attr], password='userpin')
realm.klist(realm.user_princ)
realm.run([kvno, realm.host_princ])
-# PKINIT with PKCS11: identity, with a PIN supplied by the prompter.
-mark('PKCS11 identity, with PIN (prompter)')
-os.remove(softpkcs11rc)
-conf = open(softpkcs11rc, 'w')
-conf.write("%s\t%s\t%s\t%s\n" % ('user', 'user token', user_pem,
- privkey_enc_pem))
-conf.close()
-# Expect failure if the responder does nothing, and there's no prompter
+mark('PKCS11 identity, unavailable PIN')
realm.run(['./responder', '-x', 'pkinit={"%s": 0}' % p11_token_identity,
- '-X', 'X509_user_identity=%s' % p11_identity, realm.user_princ],
- expected_code=2)
-realm.kinit(realm.user_princ,
- flags=['-X', 'X509_user_identity=%s' % p11_identity],
- password='encrypted')
-realm.klist(realm.user_princ)
-realm.run([kvno, realm.host_princ])
+ '-X', p11_attr, realm.user_princ], expected_code=2)
-# Supply the wrong PIN.
mark('PKCS11 identity, wrong PIN')
expected_trace = ('PKINIT client has no configured identity; giving up',)
realm.kinit(realm.user_princ,
- flags=['-X', 'X509_user_identity=%s' % p11_identity],
+ flags=['-X', p11_attr],
password='wrong', expected_code=1, expected_trace=expected_trace)
# PKINIT with PKCS11: identity, with a PIN supplied by the responder.
-# Supply the response in raw form.
+# Supply the response in raw form. Expect the PIN_COUNT_LOW flag (1)
+# to be set due to the previous test.
mark('PKCS11 identity, with PIN (responder)')
-realm.run(['./responder', '-x', 'pkinit={"%s": 0}' % p11_token_identity,
- '-r', 'pkinit={"%s": "encrypted"}' % p11_token_identity,
- '-X', 'X509_user_identity=%s' % p11_identity, realm.user_princ])
+realm.run(['./responder', '-x', 'pkinit={"%s": 1}' % p11_token_identity,
+ '-r', 'pkinit={"%s": "userpin"}' % p11_token_identity,
+ '-X', p11_attr, realm.user_princ])
# Supply the response through the convenience API.
-realm.run(['./responder', '-X', 'X509_user_identity=%s' % p11_identity,
- '-p', '%s=%s' % (p11_token_identity, 'encrypted'),
+realm.run(['./responder', '-X', p11_attr,
+ '-p', '%s=%s' % (p11_token_identity, 'userpin'),
realm.user_princ])
realm.klist(realm.user_princ)
realm.run([kvno, realm.host_princ])
--
2.47.1

View file

@ -1,202 +0,0 @@
From b0315d30f066c4241fcecc33dd9e4d1c7c28b9d8 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Fri, 9 Feb 2024 17:32:40 -0500
Subject: [PATCH] Simplify PKINIT cert representation
In the _pkinit_identity_crypto_context structure, the my_certs field
is a stack which only ever contains one cert and is only ever used to
retrieve that one cert. The cert_index field is always 0. Replace
these fields with a my_cert field pointing directly to the X509
certificate.
Simplify crypto_cert_select_default() by making it call
crypto_cert_select() with index 0 after verifying the certificate
count.
(cherry picked from commit f95dfb7908456f9563cee66706216a21df8d791f)
---
.../preauth/pkinit/pkinit_crypto_openssl.c | 74 +++++--------------
1 file changed, 20 insertions(+), 54 deletions(-)
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
index ae8599d5a2..da59cb1e02 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
@@ -73,10 +73,9 @@ typedef struct _pkinit_cred_info *pkinit_cred_info;
struct _pkinit_identity_crypto_context {
pkinit_cred_info creds[MAX_CREDS_ALLOWED+1];
- STACK_OF(X509) *my_certs; /* available user certs */
+ X509 *my_cert; /* selected user or KDC cert */
char *identity; /* identity name for user cert */
- int cert_index; /* cert to use out of available certs*/
- EVP_PKEY *my_key; /* available user keys if in filesystem */
+ EVP_PKEY *my_key; /* selected cert key if in filesystem */
STACK_OF(X509) *trustedCAs; /* available trusted ca certs */
STACK_OF(X509) *intermediateCAs; /* available intermediate ca certs */
STACK_OF(X509_CRL) *revoked; /* available crls */
@@ -1489,8 +1488,7 @@ pkinit_init_certs(pkinit_identity_crypto_context ctx)
for (i = 0; i < MAX_CREDS_ALLOWED; i++)
ctx->creds[i] = NULL;
- ctx->my_certs = NULL;
- ctx->cert_index = 0;
+ ctx->my_cert = NULL;
ctx->my_key = NULL;
ctx->trustedCAs = NULL;
ctx->intermediateCAs = NULL;
@@ -1506,8 +1504,8 @@ pkinit_fini_certs(pkinit_identity_crypto_context ctx)
if (ctx == NULL)
return;
- if (ctx->my_certs != NULL)
- sk_X509_pop_free(ctx->my_certs, X509_free);
+ if (ctx->my_cert != NULL)
+ X509_free(ctx->my_cert);
if (ctx->my_key != NULL)
EVP_PKEY_free(ctx->my_key);
@@ -1696,7 +1694,6 @@ cms_signeddata_create(krb5_context context,
ASN1_OCTET_STRING *digest = NULL;
unsigned int alg_len = 0, digest_len = 0;
unsigned char *y = NULL;
- X509 *cert = NULL;
ASN1_OBJECT *oid = NULL, *oid_copy;
/* Start creating PKCS7 data. */
@@ -1715,7 +1712,7 @@ cms_signeddata_create(krb5_context context,
if (oid == NULL)
goto cleanup;
- if (id_cryptoctx->my_certs != NULL) {
+ if (id_cryptoctx->my_cert != NULL) {
X509_STORE *certstore = NULL;
X509_STORE_CTX *certctx;
STACK_OF(X509) *certstack = NULL;
@@ -1726,8 +1723,6 @@ cms_signeddata_create(krb5_context context,
if ((cert_stack = sk_X509_new_null()) == NULL)
goto cleanup;
- cert = sk_X509_value(id_cryptoctx->my_certs, id_cryptoctx->cert_index);
-
certstore = X509_STORE_new();
if (certstore == NULL)
goto cleanup;
@@ -1736,7 +1731,7 @@ cms_signeddata_create(krb5_context context,
certctx = X509_STORE_CTX_new();
if (certctx == NULL)
goto cleanup;
- X509_STORE_CTX_init(certctx, certstore, cert,
+ X509_STORE_CTX_init(certctx, certstore, id_cryptoctx->my_cert,
id_cryptoctx->intermediateCAs);
X509_STORE_CTX_trusted_stack(certctx, id_cryptoctx->trustedCAs);
if (!X509_verify_cert(certctx)) {
@@ -1764,13 +1759,13 @@ cms_signeddata_create(krb5_context context,
if (!ASN1_INTEGER_set(p7si->version, 1))
goto cleanup;
if (!X509_NAME_set(&p7si->issuer_and_serial->issuer,
- X509_get_issuer_name(cert)))
+ X509_get_issuer_name(id_cryptoctx->my_cert)))
goto cleanup;
/* because ASN1_INTEGER_set is used to set a 'long' we will do
* things the ugly way. */
ASN1_INTEGER_free(p7si->issuer_and_serial->serial);
if (!(p7si->issuer_and_serial->serial =
- ASN1_INTEGER_dup(X509_get_serialNumber(cert))))
+ ASN1_INTEGER_dup(X509_get_serialNumber(id_cryptoctx->my_cert))))
goto cleanup;
/* will not fill-out EVP_PKEY because it's on the smartcard */
@@ -3311,7 +3306,7 @@ pkinit_check_kdc_pkid(krb5_context context,
PKCS7_ISSUER_AND_SERIAL *is = NULL;
const unsigned char *p = pdid_buf;
int status = 1;
- X509 *kdc_cert = sk_X509_value(id_cryptoctx->my_certs, id_cryptoctx->cert_index);
+ X509 *kdc_cert = id_cryptoctx->my_cert;
*valid_kdcPkId = 0;
pkiDebug("found kdcPkId in AS REQ\n");
@@ -4783,7 +4778,8 @@ cleanup:
}
/*
- * Set the certificate in idctx->creds[cred_index] as the selected certificate.
+ * Set the certificate in idctx->creds[cred_index] as the selected certificate,
+ * stealing pointers from it.
*/
krb5_error_code
crypto_cert_select(krb5_context context, pkinit_identity_crypto_context idctx,
@@ -4795,20 +4791,17 @@ crypto_cert_select(krb5_context context, pkinit_identity_crypto_context idctx,
return ENOENT;
ci = idctx->creds[cred_index];
- /* copy the selected cert into our id_cryptoctx */
- if (idctx->my_certs != NULL)
- sk_X509_pop_free(idctx->my_certs, X509_free);
- idctx->my_certs = sk_X509_new_null();
- sk_X509_push(idctx->my_certs, ci->cert);
- free(idctx->identity);
+
+ idctx->my_cert = ci->cert;
+ ci->cert = NULL;
+
/* hang on to the selected credential name */
+ free(idctx->identity);
if (ci->name != NULL)
idctx->identity = strdup(ci->name);
else
idctx->identity = NULL;
- ci->cert = NULL; /* Don't free it twice */
- idctx->cert_index = 0;
if (idctx->pkcs11_method != 1) {
idctx->my_key = ci->key;
ci->key = NULL; /* Don't free it twice */
@@ -4837,41 +4830,14 @@ crypto_cert_select_default(krb5_context context,
retval = crypto_cert_get_count(id_cryptoctx, &cert_count);
if (retval)
- goto errout;
+ return retval;
if (cert_count != 1) {
TRACE_PKINIT_NO_DEFAULT_CERT(context, cert_count);
- retval = EINVAL;
- goto errout;
- }
- /* copy the selected cert into our id_cryptoctx */
- if (id_cryptoctx->my_certs != NULL) {
- sk_X509_pop_free(id_cryptoctx->my_certs, X509_free);
+ return EINVAL;
}
- id_cryptoctx->my_certs = sk_X509_new_null();
- sk_X509_push(id_cryptoctx->my_certs, id_cryptoctx->creds[0]->cert);
- id_cryptoctx->creds[0]->cert = NULL; /* Don't free it twice */
- id_cryptoctx->cert_index = 0;
- /* hang on to the selected credential name */
- if (id_cryptoctx->creds[0]->name != NULL)
- id_cryptoctx->identity = strdup(id_cryptoctx->creds[0]->name);
- else
- id_cryptoctx->identity = NULL;
- if (id_cryptoctx->pkcs11_method != 1) {
- id_cryptoctx->my_key = id_cryptoctx->creds[0]->key;
- id_cryptoctx->creds[0]->key = NULL; /* Don't free it twice */
- }
-#ifndef WITHOUT_PKCS11
- else {
- id_cryptoctx->cert_id = id_cryptoctx->creds[0]->cert_id;
- id_cryptoctx->creds[0]->cert_id = NULL; /* Don't free it twice */
- id_cryptoctx->cert_id_len = id_cryptoctx->creds[0]->cert_id_len;
- }
-#endif
- retval = 0;
-errout:
- return retval;
+ return crypto_cert_select(context, id_cryptoctx, 0);
}
--
2.47.1

File diff suppressed because it is too large Load diff

View file

@ -1,599 +0,0 @@
From e43c05e7b0b93401dd68fc3ec3186c3a455b04ea Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Fri, 23 Feb 2024 13:51:26 -0500
Subject: [PATCH] Improve PKCS11 error reporting in PKINIT
Create a helper p11err() to set extended error message for failed
PKCS11 operations, and use it instead of pkiDebug() and pkcs11error().
ticket: 9113 (new)
(cherry picked from commit 98afb314d13939cbee19c69885dcb655db8460da)
---
.../preauth/pkinit/pkinit_crypto_openssl.c | 262 ++++++++++--------
src/plugins/preauth/pkinit/pkinit_trace.h | 9 -
2 files changed, 142 insertions(+), 129 deletions(-)
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
index 4accfc2664..402bf1b9b3 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
@@ -161,9 +161,11 @@ static krb5_error_code pkinit_create_sequence_of_principal_identifiers
int type, krb5_pa_data ***e_data_out);
#ifndef WITHOUT_PKCS11
-static krb5_error_code pkinit_find_private_key
-(pkinit_identity_crypto_context, CK_ATTRIBUTE_TYPE usage,
- CK_OBJECT_HANDLE *objp);
+static krb5_error_code
+pkinit_find_private_key(krb5_context context,
+ pkinit_identity_crypto_context id_cryptoctx,
+ CK_ATTRIBUTE_TYPE usage,
+ CK_OBJECT_HANDLE *objp);
static krb5_error_code pkinit_login
(krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
CK_TOKEN_INFO *tip, const char *password);
@@ -180,6 +182,8 @@ static krb5_error_code pkinit_sign_data_pkcs11
(krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
unsigned char *data, unsigned int data_len,
unsigned char **sig, unsigned int *sig_len);
+
+static krb5_error_code p11err(krb5_context context, CK_RV rv, const char *op);
#endif /* WITHOUT_PKCS11 */
static krb5_error_code pkinit_sign_data_fs
@@ -197,9 +201,6 @@ create_krb5_invalidCertificates(krb5_context context,
static krb5_error_code
create_identifiers_from_stack(STACK_OF(X509) *sk,
krb5_external_principal_identifier *** ids);
-static const char *
-pkcs11err(int err);
-
#if OPENSSL_VERSION_NUMBER < 0x10100000L
@@ -944,8 +945,9 @@ cleanup:
#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */
+#ifndef WITHOUT_PKC11
static struct pkcs11_errstrings {
- short code;
+ CK_RV code;
char *text;
} pkcs11_errstrings[] = {
{ 0x0, "ok" },
@@ -1035,6 +1037,7 @@ static struct pkcs11_errstrings {
{ 0x200, "function rejected" },
{ -1, NULL }
};
+#endif
MAKE_INIT_FUNCTION(pkinit_openssl_init);
@@ -1563,6 +1566,8 @@ pkinit_fini_pkcs11(pkinit_identity_crypto_context ctx)
free(ctx->token_label);
free(ctx->cert_id);
free(ctx->cert_label);
+ ctx->p11_module_name = ctx->token_label = ctx->cert_label = NULL;
+ ctx->cert_id = NULL;
#endif
}
@@ -3344,48 +3349,53 @@ pkinit_pkcs7type2oid(pkinit_plg_crypto_context cryptoctx, int pkcs7_type)
}
#ifndef WITHOUT_PKCS11
-static struct plugin_file_handle *
+static krb5_error_code
load_pkcs11_module(krb5_context context, const char *modname,
- CK_FUNCTION_LIST_PTR_PTR p11p)
+ struct plugin_file_handle **handle_out,
+ CK_FUNCTION_LIST_PTR_PTR p11_out)
{
struct plugin_file_handle *handle = NULL;
- CK_RV (*getflist)(CK_FUNCTION_LIST_PTR_PTR);
+ CK_RV rv, (*getflist)(CK_FUNCTION_LIST_PTR_PTR);
struct errinfo einfo = EMPTY_ERRINFO;
- const char *errmsg = NULL;
+ const char *errmsg = NULL, *failure;
void (*sym)(void);
long err;
- CK_RV rv;
TRACE_PKINIT_PKCS11_OPEN(context, modname);
err = krb5int_open_plugin(modname, &handle, &einfo);
if (err) {
- errmsg = k5_get_error(&einfo, err);
- TRACE_PKINIT_PKCS11_OPEN_FAILED(context, errmsg);
+ failure = _("Cannot load PKCS11 module");
goto error;
}
err = krb5int_get_plugin_func(handle, "C_GetFunctionList", &sym, &einfo);
if (err) {
- errmsg = k5_get_error(&einfo, err);
- TRACE_PKINIT_PKCS11_GETSYM_FAILED(context, errmsg);
+ failure = _("Cannot find C_GetFunctionList in PKCS11 module");
goto error;
}
getflist = (CK_RV (*)(CK_FUNCTION_LIST_PTR_PTR))sym;
- rv = (*getflist)(p11p);
+ rv = (*getflist)(p11_out);
if (rv != CKR_OK) {
- TRACE_PKINIT_PKCS11_GETFLIST_FAILED(context, pkcs11err(rv));
+ failure = _("Cannot retrieve function list in PKCS11 module");
goto error;
}
- return handle;
+ *handle_out = handle;
+ return 0;
error:
- k5_free_error(&einfo, errmsg);
+ if (err) {
+ errmsg = k5_get_error(&einfo, err);
+ k5_setmsg(context, err, _("%s: %s"), failure, errmsg);
+ } else {
+ err = KRB5KDC_ERR_PREAUTH_FAILED;
+ k5_setmsg(context, err, "%s", failure);
+ }
k5_clear_error(&einfo);
if (handle != NULL)
krb5int_close_plugin(handle);
- return NULL;
+ return err;
}
static krb5_error_code
@@ -3393,12 +3403,13 @@ pkinit_login(krb5_context context,
pkinit_identity_crypto_context id_cryptoctx,
CK_TOKEN_INFO *tip, const char *password)
{
+ krb5_error_code ret = 0;
+ CK_RV rv;
krb5_data rdat;
char *prompt;
const char *warning;
krb5_prompt kprompt;
krb5_prompt_type prompt_type;
- int r = 0;
if (tip->flags & CKF_PROTECTED_AUTHENTICATION_PATH) {
rdat.data = NULL;
@@ -3407,7 +3418,7 @@ pkinit_login(krb5_context context,
rdat.data = strdup(password);
rdat.length = strlen(password);
} else if (id_cryptoctx->prompter == NULL) {
- r = KRB5_LIBOS_CANTREADPWD;
+ ret = KRB5_LIBOS_CANTREADPWD;
rdat.data = NULL;
} else {
if (tip->flags & CKF_USER_PIN_LOCKED)
@@ -3431,31 +3442,28 @@ pkinit_login(krb5_context context,
/* PROMPTER_INVOCATION */
k5int_set_prompt_types(context, &prompt_type);
- r = (*id_cryptoctx->prompter)(context, id_cryptoctx->prompter_data,
- NULL, NULL, 1, &kprompt);
+ ret = (*id_cryptoctx->prompter)(context, id_cryptoctx->prompter_data,
+ NULL, NULL, 1, &kprompt);
k5int_set_prompt_types(context, 0);
free(prompt);
}
- if (r == 0) {
- r = id_cryptoctx->p11->C_Login(id_cryptoctx->session, CKU_USER,
- (u_char *) rdat.data, rdat.length);
-
- if (r != CKR_OK) {
- TRACE_PKINIT_PKCS11_LOGIN_FAILED(context, pkcs11err(r));
- r = KRB5KDC_ERR_PREAUTH_FAILED;
- }
+ if (!ret) {
+ rv = id_cryptoctx->p11->C_Login(id_cryptoctx->session, CKU_USER,
+ (uint8_t *)rdat.data, rdat.length);
+ if (rv != CKR_OK)
+ ret = p11err(context, rv, "C_Login");
}
free(rdat.data);
- return r;
+ return ret;
}
static krb5_error_code
pkinit_open_session(krb5_context context,
pkinit_identity_crypto_context cctx)
{
- CK_ULONG i, pret;
+ CK_ULONG i, rv;
unsigned char *cp;
size_t label_len;
CK_ULONG count = 0;
@@ -3469,30 +3477,35 @@ pkinit_open_session(krb5_context context,
return 0; /* session already open */
/* Load module */
- cctx->p11_module = load_pkcs11_module(context, cctx->p11_module_name,
- &cctx->p11);
- if (cctx->p11_module == NULL)
- return KRB5KDC_ERR_PREAUTH_FAILED;
+ ret = load_pkcs11_module(context, cctx->p11_module_name, &cctx->p11_module,
+ &cctx->p11);
+ if (ret)
+ goto cleanup;
/* Init */
- pret = cctx->p11->C_Initialize(NULL);
- if (pret != CKR_OK) {
- pkiDebug("C_Initialize: %s\n", pkcs11err(pret));
- return KRB5KDC_ERR_PREAUTH_FAILED;
+ rv = cctx->p11->C_Initialize(NULL);
+ if (rv != CKR_OK) {
+ ret = p11err(context, rv, "C_Initialize");
+ goto cleanup;
}
/* Get the list of available slots */
- if (cctx->p11->C_GetSlotList(TRUE, NULL, &count) != CKR_OK)
- return KRB5KDC_ERR_PREAUTH_FAILED;
+ rv = cctx->p11->C_GetSlotList(TRUE, NULL, &count);
+ if (rv != CKR_OK) {
+ ret = p11err(context, rv, "C_GetSlotList");
+ goto cleanup;
+ }
if (count == 0) {
TRACE_PKINIT_PKCS11_NO_TOKEN(context);
- return KRB5KDC_ERR_PREAUTH_FAILED;
+ ret = KRB5KDC_ERR_PREAUTH_FAILED;
+ goto cleanup;
}
- slotlist = calloc(count, sizeof(CK_SLOT_ID));
+ slotlist = k5calloc(count, sizeof(CK_SLOT_ID), &ret);
if (slotlist == NULL)
- return ENOMEM;
- if (cctx->p11->C_GetSlotList(TRUE, slotlist, &count) != CKR_OK) {
- ret = KRB5KDC_ERR_PREAUTH_FAILED;
+ goto cleanup;
+ rv = cctx->p11->C_GetSlotList(TRUE, slotlist, &count);
+ if (rv != CKR_OK) {
+ ret = p11err(context, rv, "C_GetSlotList");
goto cleanup;
}
@@ -3503,19 +3516,17 @@ pkinit_open_session(krb5_context context,
continue;
/* Open session */
- pret = cctx->p11->C_OpenSession(slotlist[i], CKF_SERIAL_SESSION,
- NULL, NULL, &cctx->session);
- if (pret != CKR_OK) {
- pkiDebug("C_OpenSession: %s\n", pkcs11err(pret));
- ret = KRB5KDC_ERR_PREAUTH_FAILED;
+ rv = cctx->p11->C_OpenSession(slotlist[i], CKF_SERIAL_SESSION,
+ NULL, NULL, &cctx->session);
+ if (rv != CKR_OK) {
+ ret = p11err(context, rv, "C_OpenSession");
goto cleanup;
}
/* Get token info */
- pret = cctx->p11->C_GetTokenInfo(slotlist[i], &tinfo);
- if (pret != CKR_OK) {
- pkiDebug("C_GetTokenInfo: %s\n", pkcs11err(pret));
- ret = KRB5KDC_ERR_PREAUTH_FAILED;
+ rv = cctx->p11->C_GetTokenInfo(slotlist[i], &tinfo);
+ if (rv != CKR_OK) {
+ ret = p11err(context, rv, "C_GetTokenInfo");
goto cleanup;
}
@@ -3577,6 +3588,10 @@ pkinit_open_session(krb5_context context,
ret = 0;
cleanup:
+ /* On error, finalize the PKCS11 fields to ensure that we don't mistakenly
+ * short-circuit with success on the next call. */
+ if (ret)
+ pkinit_fini_pkcs11(cctx);
free(slotlist);
free(p11name);
return ret;
@@ -3598,16 +3613,17 @@ cleanup:
* If there are more than one, we just take the first one.
*/
-krb5_error_code
-pkinit_find_private_key(pkinit_identity_crypto_context id_cryptoctx,
+static krb5_error_code
+pkinit_find_private_key(krb5_context context,
+ pkinit_identity_crypto_context id_cryptoctx,
CK_ATTRIBUTE_TYPE usage,
CK_OBJECT_HANDLE *objp)
{
CK_OBJECT_CLASS cls;
CK_ATTRIBUTE attrs[4];
CK_ULONG count;
+ CK_RV rv;
unsigned int nattrs = 0;
- int r;
#ifdef PKINIT_USE_KEY_USAGE
CK_BBOOL true_false;
#endif
@@ -3637,18 +3653,21 @@ pkinit_find_private_key(pkinit_identity_crypto_context id_cryptoctx,
attrs[nattrs].ulValueLen = id_cryptoctx->cert_id_len;
nattrs++;
- r = id_cryptoctx->p11->C_FindObjectsInit(id_cryptoctx->session, attrs, nattrs);
- if (r != CKR_OK) {
- pkiDebug("krb5_pkinit_sign_data: C_FindObjectsInit: %s\n",
- pkcs11err(r));
- return KRB5KDC_ERR_PREAUTH_FAILED;
- }
+ rv = id_cryptoctx->p11->C_FindObjectsInit(id_cryptoctx->session, attrs,
+ nattrs);
+ if (rv != CKR_OK)
+ return p11err(context, rv, _("C_FindObjectsInit"));
- r = id_cryptoctx->p11->C_FindObjects(id_cryptoctx->session, objp, 1, &count);
+ rv = id_cryptoctx->p11->C_FindObjects(id_cryptoctx->session, objp, 1,
+ &count);
id_cryptoctx->p11->C_FindObjectsFinal(id_cryptoctx->session);
- pkiDebug("found %d private keys (%s)\n", (int)count, pkcs11err(r));
- if (r != CKR_OK || count < 1)
+ if (rv != CKR_OK)
+ return p11err(context, rv, _("C_FindObjects"));
+ if (count < 1) {
+ k5_setmsg(context, KRB5KDC_ERR_PREAUTH_FAILED,
+ _("Found no private keys in PKCS11 token"));
return KRB5KDC_ERR_PREAUTH_FAILED;
+ }
return 0;
}
#endif
@@ -3796,34 +3815,32 @@ pkinit_sign_data_pkcs11(krb5_context context,
CK_FUNCTION_LIST_PTR p11;
CK_ATTRIBUTE attr;
CK_KEY_TYPE keytype;
+ CK_RV rv;
EVP_MD_CTX *ctx;
const EVP_MD *md = EVP_sha256();
unsigned int mdlen;
uint8_t mdbuf[EVP_MAX_MD_SIZE], *dinfo = NULL, *sigbuf = NULL, *input;
size_t dinfo_len, input_len;
- int r;
*sig = NULL;
*sig_len = 0;
- if (pkinit_open_session(context, id_cryptoctx)) {
- pkiDebug("can't open pkcs11 session\n");
- return KRB5KDC_ERR_PREAUTH_FAILED;
- }
+ ret = pkinit_open_session(context, id_cryptoctx);
+ if (ret)
+ return ret;
p11 = id_cryptoctx->p11;
session = id_cryptoctx->session;
- ret = pkinit_find_private_key(id_cryptoctx, CKA_SIGN, &obj);
+ ret = pkinit_find_private_key(context, id_cryptoctx, CKA_SIGN, &obj);
if (ret)
return ret;
attr.type = CKA_KEY_TYPE;
attr.pValue = &keytype;
attr.ulValueLen = sizeof(keytype);
- r = p11->C_GetAttributeValue(session, obj, &attr, 1);
- if (r) {
- pkiDebug("C_GetAttributeValue: %s\n", pkcs11err(r));
- ret = KRB5KDC_ERR_PREAUTH_FAILED;
+ rv = p11->C_GetAttributeValue(session, obj, &attr, 1);
+ if (rv != CKR_OK) {
+ ret = p11err(context, rv, "C_GetAttributeValue");
goto cleanup;
}
@@ -3865,10 +3882,9 @@ pkinit_sign_data_pkcs11(krb5_context context,
mech.pParameter = NULL;
mech.ulParameterLen = 0;
- r = p11->C_SignInit(session, &mech, obj);
- if (r != CKR_OK) {
- pkiDebug("C_SignInit: %s\n", pkcs11err(r));
- ret = KRB5KDC_ERR_PREAUTH_FAILED;
+ rv = p11->C_SignInit(session, &mech, obj);
+ if (rv != CKR_OK) {
+ ret = p11err(context, rv, "C_SignInit");
goto cleanup;
}
@@ -3881,18 +3897,17 @@ pkinit_sign_data_pkcs11(krb5_context context,
if (sigbuf == NULL)
goto cleanup;
- r = p11->C_Sign(session, input, input_len, sigbuf, &len);
- if (r == CKR_BUFFER_TOO_SMALL || (r == CKR_OK && len >= PK_SIGLEN_GUESS)) {
+ rv = p11->C_Sign(session, input, input_len, sigbuf, &len);
+ if (rv == CKR_BUFFER_TOO_SMALL ||
+ (rv == CKR_OK && len >= PK_SIGLEN_GUESS)) {
free(sigbuf);
- pkiDebug("C_Sign realloc %d\n", (int) len);
sigbuf = k5alloc(len, &ret);
if (sigbuf == NULL)
goto cleanup;
- r = p11->C_Sign(session, input, input_len, sigbuf, &len);
+ rv = p11->C_Sign(session, input, input_len, sigbuf, &len);
}
- if (r != CKR_OK) {
- pkiDebug("C_Sign: %s\n", pkcs11err(r));
- ret = KRB5KDC_ERR_PREAUTH_FAILED;
+ if (rv != CKR_OK) {
+ ret = p11err(context, rv, "C_Sign");
goto cleanup;
}
@@ -4348,13 +4363,14 @@ reassemble_pkcs11_name(pkinit_identity_opts *idopts)
}
static krb5_error_code
-load_one_cert(CK_FUNCTION_LIST_PTR p11, CK_SESSION_HANDLE session,
- pkinit_identity_opts *idopts, pkinit_cred_info *cred_out)
+load_one_cert(krb5_context context, CK_FUNCTION_LIST_PTR p11,
+ CK_SESSION_HANDLE session, pkinit_identity_opts *idopts,
+ pkinit_cred_info *cred_out)
{
krb5_error_code ret;
CK_ATTRIBUTE attrs[2];
CK_BYTE_PTR cert = NULL, cert_id = NULL;
- CK_RV pret;
+ CK_RV rv;
const unsigned char *cp;
CK_OBJECT_HANDLE obj;
CK_ULONG count;
@@ -4364,8 +4380,8 @@ load_one_cert(CK_FUNCTION_LIST_PTR p11, CK_SESSION_HANDLE session,
*cred_out = NULL;
/* Look for X.509 cert. */
- pret = p11->C_FindObjects(session, &obj, 1, &count);
- if (pret != CKR_OK || count <= 0)
+ rv = p11->C_FindObjects(session, &obj, 1, &count);
+ if (rv != CKR_OK || count <= 0)
return 0;
/* Get cert and id len. */
@@ -4375,10 +4391,9 @@ load_one_cert(CK_FUNCTION_LIST_PTR p11, CK_SESSION_HANDLE session,
attrs[1].type = CKA_ID;
attrs[1].pValue = NULL;
attrs[1].ulValueLen = 0;
- pret = p11->C_GetAttributeValue(session, obj, attrs, 2);
- if (pret != CKR_OK && pret != CKR_BUFFER_TOO_SMALL) {
- pkiDebug("C_GetAttributeValue: %s\n", pkcs11err(pret));
- ret = KRB5KDC_ERR_PREAUTH_FAILED;
+ rv = p11->C_GetAttributeValue(session, obj, attrs, 2);
+ if (rv != CKR_OK && rv != CKR_BUFFER_TOO_SMALL) {
+ ret = p11err(context, rv, "C_GetAttributeValue");
goto cleanup;
}
@@ -4393,10 +4408,9 @@ load_one_cert(CK_FUNCTION_LIST_PTR p11, CK_SESSION_HANDLE session,
attrs[0].pValue = cert;
attrs[1].type = CKA_ID;
attrs[1].pValue = cert_id;
- pret = p11->C_GetAttributeValue(session, obj, attrs, 2);
- if (pret != CKR_OK) {
- pkiDebug("C_GetAttributeValue: %s\n", pkcs11err(pret));
- ret = KRB5KDC_ERR_PREAUTH_FAILED;
+ rv = p11->C_GetAttributeValue(session, obj, attrs, 2);
+ if (rv != CKR_OK) {
+ ret = p11err(context, rv, "C_GetAttributeValue");
goto cleanup;
}
@@ -4406,7 +4420,8 @@ load_one_cert(CK_FUNCTION_LIST_PTR p11, CK_SESSION_HANDLE session,
cp = (unsigned char *)cert;
x = d2i_X509(NULL, &cp, (int)attrs[0].ulValueLen);
if (x == NULL) {
- ret = KRB5KDC_ERR_PREAUTH_FAILED;
+ ret = oerr(context, 0,
+ _("Failed to decode X509 certificate from PKCS11 token"));
goto cleanup;
}
@@ -4444,7 +4459,7 @@ pkinit_get_certs_pkcs11(krb5_context context,
int i;
unsigned int nattrs;
krb5_error_code ret;
- CK_RV pret;
+ CK_RV rv;
/* Copy stuff from idopts -> id_cryptoctx */
if (idopts->p11_module_name != NULL) {
@@ -4516,16 +4531,16 @@ pkinit_get_certs_pkcs11(krb5_context context,
nattrs++;
}
- pret = id_cryptoctx->p11->C_FindObjectsInit(id_cryptoctx->session, attrs,
- nattrs);
- if (pret != CKR_OK) {
- pkiDebug("C_FindObjectsInit: %s\n", pkcs11err(pret));
+ rv = id_cryptoctx->p11->C_FindObjectsInit(id_cryptoctx->session, attrs,
+ nattrs);
+ if (rv != CKR_OK) {
+ ret = p11err(context, rv, "C_FindObjectsInit");
return KRB5KDC_ERR_PREAUTH_FAILED;
}
for (i = 0; i < MAX_CREDS_ALLOWED; i++) {
- ret = load_one_cert(id_cryptoctx->p11, id_cryptoctx->session, idopts,
- &id_cryptoctx->creds[i]);
+ ret = load_one_cert(context, id_cryptoctx->p11, id_cryptoctx->session,
+ idopts, &id_cryptoctx->creds[i]);
if (ret)
return ret;
if (id_cryptoctx->creds[i] == NULL)
@@ -5510,19 +5525,26 @@ print_pubkey(BIGNUM * key, char *msg)
}
#endif
-static const char *
-pkcs11err(int err)
+#ifndef WITHOUT_PKCS11
+static krb5_error_code
+p11err(krb5_context context, CK_RV rv, const char *op)
{
+ krb5_error_code code = KRB5KDC_ERR_PREAUTH_FAILED;
int i;
+ const char *msg;
- for (i = 0; pkcs11_errstrings[i].text != NULL; i++)
- if (pkcs11_errstrings[i].code == err)
+ for (i = 0; pkcs11_errstrings[i].text != NULL; i++) {
+ if (pkcs11_errstrings[i].code == rv)
break;
- if (pkcs11_errstrings[i].text != NULL)
- return (pkcs11_errstrings[i].text);
+ }
+ msg = pkcs11_errstrings[i].text;
+ if (msg == NULL)
+ msg = "unknown PKCS11 error";
- return "unknown PKCS11 error";
+ krb5_set_error_message(context, code, _("PKCS11 error (%s): %s"), op, msg);
+ return code;
}
+#endif
/*
* Add an item to the pkinit_identity_crypto_context's list of deferred
diff --git a/src/plugins/preauth/pkinit/pkinit_trace.h b/src/plugins/preauth/pkinit/pkinit_trace.h
index 1c1ceb5a41..1faa6816d7 100644
--- a/src/plugins/preauth/pkinit/pkinit_trace.h
+++ b/src/plugins/preauth/pkinit/pkinit_trace.h
@@ -98,21 +98,12 @@
#define TRACE_PKINIT_OPENSSL_ERROR(c, msg) \
TRACE(c, "PKINIT OpenSSL error: {str}", msg)
-#define TRACE_PKINIT_PKCS11_GETFLIST_FAILED(c, errstr) \
- TRACE(c, "PKINIT PKCS11 C_GetFunctionList failed: {str}", errstr)
-#define TRACE_PKINIT_PKCS11_GETSYM_FAILED(c, errstr) \
- TRACE(c, "PKINIT unable to find PKCS11 plugin symbol " \
- "C_GetFunctionList: {str}", errstr)
-#define TRACE_PKINIT_PKCS11_LOGIN_FAILED(c, errstr) \
- TRACE(c, "PKINIT PKCS11 C_Login failed: {str}", errstr)
#define TRACE_PKINIT_PKCS11_NO_MATCH_TOKEN(c) \
TRACE(c, "PKINIT PKCS#11 module has no matching tokens")
#define TRACE_PKINIT_PKCS11_NO_TOKEN(c) \
TRACE(c, "PKINIT PKCS#11 module shows no slots with tokens")
#define TRACE_PKINIT_PKCS11_OPEN(c, name) \
TRACE(c, "PKINIT opening PKCS#11 module \"{str}\"", name)
-#define TRACE_PKINIT_PKCS11_OPEN_FAILED(c, errstr) \
- TRACE(c, "PKINIT PKCS#11 module open failed: {str}", errstr)
#define TRACE_PKINIT_PKCS11_SLOT(c, slot, len, label) \
TRACE(c, "PKINIT PKCS#11 slotid {int} token {lenstr}", \
slot, len, label)
--
2.47.1

View file

@ -1,61 +0,0 @@
From 946f7dba8cea3d2ed0e68c5e7594cbd7e1364609 Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Thu, 1 Aug 2024 10:56:07 +0200
Subject: [PATCH] Set missing mask flags for kdb5_util operations
Set KADM5_TL_DATA for the use_mkey and update_princ_encryption
commands. (Commit c877f13c8985d820583b0d7ac1bb4c5dc36e677e did this
for the add_new_mkey and purge_mkeys commands.) Set appropriate flags
for the add_random_key command.
[ghudson@mit.edu: combined two commits; pruned out proposed mask flag
additions for values represented within key data or tl-data (like
KADM5_MKVNO), as those flags are currently only used in the kadm5
protocol, not to communicate with the KDB module]
ticket: 9158 (new)
(cherry picked from commit 4ed7da378940198cf4415f86d4eb013de6ac6455)
---
src/kadmin/dbutil/kdb5_mkey.c | 4 +++-
src/kadmin/dbutil/kdb5_util.c | 3 +++
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/kadmin/dbutil/kdb5_mkey.c b/src/kadmin/dbutil/kdb5_mkey.c
index aceb0a9b80..ac5c51d05e 100644
--- a/src/kadmin/dbutil/kdb5_mkey.c
+++ b/src/kadmin/dbutil/kdb5_mkey.c
@@ -525,6 +525,8 @@ kdb5_use_mkey(int argc, char *argv[])
goto cleanup_return;
}
+ master_entry->mask |= KADM5_TL_DATA;
+
if ((retval = krb5_db_put_principal(util_context, master_entry))) {
com_err(progname, retval,
_("while adding master key entry to the database"));
@@ -814,7 +816,7 @@ update_princ_encryption_1(void *cb, krb5_db_entry *ent)
goto fail;
}
- ent->mask |= KADM5_KEY_DATA;
+ ent->mask |= KADM5_KEY_DATA | KADM5_TL_DATA;
if ((retval = krb5_db_put_principal(util_context, ent))) {
com_err(progname, retval, _("while updating principal '%s' key data "
diff --git a/src/kadmin/dbutil/kdb5_util.c b/src/kadmin/dbutil/kdb5_util.c
index 55d529fa4c..afc817891b 100644
--- a/src/kadmin/dbutil/kdb5_util.c
+++ b/src/kadmin/dbutil/kdb5_util.c
@@ -600,6 +600,9 @@ add_random_key(int argc, char **argv)
exit_status++;
return;
}
+
+ dbent->mask |= KADM5_ATTRIBUTES | KADM5_KEY_DATA | KADM5_TL_DATA;
+
ret = krb5_db_put_principal(util_context, dbent);
krb5_db_free_principal(util_context, dbent);
if (ret) {
--
2.47.1

View file

@ -1,64 +0,0 @@
From 9b669dd42b28e7900f5ccac2816204e7d04ea23c Mon Sep 17 00:00:00 2001
From: Zoltan Borbely <Zoltan.Borbely@morganstanley.com>
Date: Tue, 28 Jan 2025 16:39:25 -0500
Subject: [PATCH] Prevent overflow when calculating ulog block size
In kdb_log.c:resize(), log an error and fail if the update size is
larger than the largest possible block size (2^16-1).
CVE-2025-24528:
In MIT krb5 release 1.7 and later with incremental propagation
enabled, an authenticated attacker can cause kadmind to write beyond
the end of the mapped region for the iprop log file, likely causing a
process crash.
[ghudson@mit.edu: edited commit message and added CVE description]
ticket: 9159 (new)
tags: pullup
target_version: 1.21-next
(cherry picked from commit 78ceba024b64d49612375be4a12d1c066b0bfbd0)
---
src/lib/kdb/kdb_log.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/src/lib/kdb/kdb_log.c b/src/lib/kdb/kdb_log.c
index e9b95fce59..c805ebd988 100644
--- a/src/lib/kdb/kdb_log.c
+++ b/src/lib/kdb/kdb_log.c
@@ -183,7 +183,7 @@ extend_file_to(int fd, unsigned int new_size)
*/
static krb5_error_code
resize(kdb_hlog_t *ulog, uint32_t ulogentries, int ulogfd,
- unsigned int recsize)
+ unsigned int recsize, const kdb_incr_update_t *upd)
{
unsigned int new_block, new_size;
@@ -195,6 +195,12 @@ resize(kdb_hlog_t *ulog, uint32_t ulogentries, int ulogfd,
new_block *= ULOG_BLOCK;
new_size += ulogentries * new_block;
+ if (new_block > UINT16_MAX) {
+ syslog(LOG_ERR, _("ulog overflow caused by principal %.*s"),
+ upd->kdb_princ_name.utf8str_t_len,
+ upd->kdb_princ_name.utf8str_t_val);
+ return KRB5_LOG_ERROR;
+ }
if (new_size > MAXLOGLEN)
return KRB5_LOG_ERROR;
@@ -291,7 +297,7 @@ store_update(kdb_log_context *log_ctx, kdb_incr_update_t *upd)
recsize = sizeof(kdb_ent_header_t) + upd_size;
if (recsize > ulog->kdb_block) {
- retval = resize(ulog, ulogentries, log_ctx->ulogfd, recsize);
+ retval = resize(ulog, ulogentries, log_ctx->ulogfd, recsize, upd);
if (retval)
return retval;
}
--
2.48.1

View file

@ -1,327 +0,0 @@
From c617915958a5cb05463713adcf03b6a0e0512ac3 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Fri, 16 Dec 2022 18:31:07 -0500
Subject: [PATCH] Don't issue session keys with deprecated enctypes
A paper by Tom Tervoort noted that rc4-hmac pre-hashes the input for
its checksum and GSS operations before applying HMAC, and is therefore
potentially vulnerable to hash collision attacks if a protocol
contains a restricted signing oracle.
In light of these potential attacks, begin the functional deprecation
of DES3 and RC4 by disallowing their use as session key enctypes by
default. Add the variables allow_des3 and allow_rc4 in case
negotiability of these enctypes for session keys needs to be turned
back on, with the expectation that in future releases the enctypes
will be more comprehensively deprecated.
ticket: 9081
(cherry picked from 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 | 5 +++--
src/tests/t_etype_info.py | 5 +++--
src/tests/t_sesskeynego.py | 28 +++++++++++++++++++++++++--
src/util/k5test.py | 9 ++++++++-
10 files changed, 116 insertions(+), 21 deletions(-)
diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
index dca52e1426..d51fd3ce7e 100644
--- a/doc/admin/conf_files/krb5_conf.rst
+++ b/doc/admin/conf_files/krb5_conf.rst
@@ -95,6 +95,18 @@ 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 c4d5499d3b..2b4ed7da0b 100644
--- a/doc/admin/enctypes.rst
+++ b/doc/admin/enctypes.rst
@@ -48,12 +48,15 @@ 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.
+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.
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. See :ref:`set_string`
-in :ref:`kadmin(1)` for details.
+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.
Choosing enctypes for a service
@@ -87,6 +90,20 @@ 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 b7789a2dd8..d0a263aa7d 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -181,6 +181,8 @@ 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"
@@ -1241,6 +1243,8 @@ 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 93415ba862..c7b6e4090d 100644
--- a/src/kdc/kdc_util.c
+++ b/src/kdc/kdc_util.c
@@ -1108,6 +1108,16 @@ 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 1b420a3ac2..ea089f0fcc 100644
--- a/src/lib/krb5/krb/get_in_tkt.c
+++ b/src/lib/krb5/krb/get_in_tkt.c
@@ -1582,22 +1582,31 @@ 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 des3-cbc-sha1 was used for either the
- * reply key or the session key. */
+/* Display a warning via the prompter if a deprecated enctype was used for
+ * either the reply key or the session key. */
static void
-warn_des3(krb5_context context, krb5_init_creds_context ctx,
- krb5_enctype as_key_enctype)
+warn_deprecated(krb5_context context, krb5_init_creds_context ctx,
+ krb5_enctype as_key_enctype)
{
- const char *banner;
+ krb5_enctype etype;
+ char encbuf[128], banner[256];
- if (as_key_enctype != ENCTYPE_DES3_CBC_SHA1 &&
- ctx->cred.keyblock.enctype != ENCTYPE_DES3_CBC_SHA1)
- return;
if (ctx->prompter == NULL)
return;
- banner = _("Warning: encryption type des3-cbc-sha1 used for "
- "authentication is weak and will be disabled");
+ 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
+ return;
+
+ if (krb5_enctype_to_name(etype, FALSE, encbuf, sizeof(encbuf)) != 0)
+ return;
+ snprintf(banner, sizeof(banner),
+ _("Warning: encryption type %s used for authentication is "
+ "deprecated and will be disabled"), encbuf);
+
/* PROMPTER_INVOCATION */
(*ctx->prompter)(context, ctx->prompter_data, NULL, banner, 0, NULL);
}
@@ -1848,7 +1857,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_des3(context, ctx, encrypting_key.enctype);
+ warn_deprecated(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 582a2945ff..a32f8dbf03 100644
--- a/src/lib/krb5/krb/init_ctx.c
+++ b/src/lib/krb5/krb/init_ctx.c
@@ -220,6 +220,16 @@ 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 2f95d89967..e6bde47afc 100755
--- a/src/tests/gssapi/t_enctypes.py
+++ b/src/tests/gssapi/t_enctypes.py
@@ -10,8 +10,9 @@ 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 rc4-hmac:normal'
-conf = {'libdefaults': {'permitted_enctypes': 'aes rc4'},
+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'},
'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 a6f538b66d..75d9621dd6 100644
--- a/src/tests/t_etype_info.py
+++ b/src/tests/t_etype_info.py
@@ -1,7 +1,8 @@
from k5test import *
-supported_enctypes = 'aes128-cts rc4-hmac'
-conf = {'realms': {'$realm': {'supported_enctypes': supported_enctypes}}}
+supported_enctypes = 'aes128-cts des3-cbc-sha1 rc4-hmac'
+conf = {'libdefaults': {'allow_des3': 'true', 'allow_rc4': 'true'},
+ 'realms': {'$realm': {'supported_enctypes': supported_enctypes}}}
realm = K5Realm(create_host=False, get_creds=False, krb5_conf=conf)
realm.run([kadminl, 'addprinc', '-pw', 'pw', '+requires_preauth',
diff --git a/src/tests/t_sesskeynego.py b/src/tests/t_sesskeynego.py
index 9024aee838..5a213617b5 100755
--- a/src/tests/t_sesskeynego.py
+++ b/src/tests/t_sesskeynego.py
@@ -25,6 +25,8 @@ 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)
@@ -54,10 +56,12 @@ 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: Negotiate rc4-hmac session key when principal only has aes256 long-term.
+# 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.
realm.run([kadminl, 'setstr', 'server', 'session_enctypes',
'rc4-hmac,aes128-cts,aes256-cts'])
-test_kvno(realm, 'DEPRECATED:arcfour-hmac', 'aes256-cts-hmac-sha1-96')
+test_kvno(realm, 'aes128-cts-hmac-sha1-96', 'aes256-cts-hmac-sha1-96')
realm.stop()
# 4: Check that permitted_enctypes is a default for session key enctypes.
@@ -67,4 +71,24 @@ 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 d823653aa0..8e5f5ba8e9 100644
--- a/src/util/k5test.py
+++ b/src/util/k5test.py
@@ -1338,9 +1338,16 @@ _passes = [
# No special settings; exercises AES256.
('default', None, None, None),
+ # Exercise the DES3 enctype.
+ ('des3', None,
+ {'libdefaults': {'permitted_enctypes': 'des3 aes256-sha1'}},
+ {'realms': {'$realm': {
+ 'supported_enctypes': 'des3-cbc-sha1:normal',
+ 'master_key_type': 'des3-cbc-sha1'}}}),
+
# Exercise the arcfour enctype.
('arcfour', None,
- {'libdefaults': {'permitted_enctypes': 'rc4'}},
+ {'libdefaults': {'permitted_enctypes': 'rc4 aes256-sha1'}},
{'realms': {'$realm': {
'supported_enctypes': 'arcfour-hmac:normal',
'master_key_type': 'arcfour-hmac'}}}),
--
2.49.0

View file

@ -1,260 +0,0 @@
From b0993b57dbe584f9308cc7773b930efe76e19ba3 Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Fri, 4 Apr 2025 15:08:36 +0200
Subject: [PATCH] [downstream] Remove 3des support (cumulative 1)
Remove mentions for the triple-DES encryption type which were added
since the previous downstream patch.
---
README | 15 +++++++--------
doc/admin/conf_files/krb5_conf.rst | 6 ------
doc/admin/enctypes.rst | 11 ++---------
doc/mitK5features.rst | 5 ++---
src/include/k5-int.h | 2 --
src/kdc/kdc_util.c | 2 --
src/lib/krb5/krb/init_ctx.c | 5 -----
src/man/krb5.conf.man | 6 ------
src/tests/gssapi/t_enctypes.py | 5 ++---
src/tests/t_etype_info.py | 4 ++--
src/tests/t_sesskeynego.py | 8 --------
src/util/k5test.py | 7 -------
12 files changed, 15 insertions(+), 61 deletions(-)
diff --git a/README b/README
index 6d6f7f16e3..9341bd3dd8 100644
--- a/README
+++ b/README
@@ -81,11 +81,11 @@ Triple-DES and RC4 transitions
------------------------------
Beginning with the krb5-1.21 release, the KDC will not issue tickets
-with triple-DES or RC4 session keys unless explicitly configured using
-the new allow_des3 and allow_rc4 variables in [libdefaults]. To
-facilitate the negotiation of session keys, the KDC will assume that
-all services can handle aes256-sha1 session keys unless the service
-principal has a session_enctypes string attribute.
+with RC4 session keys unless explicitly configured using the new
+allow_rc4 variable in [libdefaults]. To facilitate the negotiation of
+session keys, the KDC will assume that all services can handle
+aes256-sha1 session keys unless the service principal has a
+session_enctypes string attribute.
Beginning with the krb5-1.19 release, a warning will be issued if
initial credentials are acquired using the des3-cbc-sha1 encryption
@@ -164,9 +164,8 @@ Developer experience:
Protocol evolution:
-* The KDC will no longer issue tickets with RC4 or triple-DES session
- keys unless explicitly configured with the new allow_rc4 or
- allow_des3 variables respectively.
+* The KDC will no longer issue tickets with RC4 session keys unless
+ explicitly configured with the new allow_rc4 variable.
* The KDC will assume that all services can handle aes256-sha1 session
keys unless the service principal has a session_enctypes string
diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
index d51fd3ce7e..d20dcf18e3 100644
--- a/doc/admin/conf_files/krb5_conf.rst
+++ b/doc/admin/conf_files/krb5_conf.rst
@@ -95,12 +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
diff --git a/doc/admin/enctypes.rst b/doc/admin/enctypes.rst
index 2b4ed7da0b..6ce4638d5e 100644
--- a/doc/admin/enctypes.rst
+++ b/doc/admin/enctypes.rst
@@ -49,8 +49,8 @@ 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.
+aes256-cts-hmac-sha1-96; also, arcfour-hmac session keys will not be
+issued by default.
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
@@ -90,13 +90,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
diff --git a/doc/mitK5features.rst b/doc/mitK5features.rst
index cad0855724..64d746b0af 100644
--- a/doc/mitK5features.rst
+++ b/doc/mitK5features.rst
@@ -659,9 +659,8 @@ Release 1.21
* Protocol evolution:
- - The KDC will no longer issue tickets with RC4 or triple-DES
- session keys unless explicitly configured with the new allow_rc4
- or allow_des3 variables respectively.
+ - The KDC will no longer issue tickets with RC4 session keys unless
+ explicitly configured with the new allow_rc4 variable.
- The KDC will assume that all services can handle aes256-sha1
session keys unless the service principal has a session_enctypes
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index d0a263aa7d..82a763298d 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -181,7 +181,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"
@@ -1243,7 +1242,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;
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
index c7b6e4090d..bafcf5f728 100644
--- a/src/kdc/kdc_util.c
+++ b/src/kdc/kdc_util.c
@@ -1113,8 +1113,6 @@ select_session_keytype(krb5_context context, krb5_db_entry *server,
* 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;
diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c
index a32f8dbf03..82aba64c5e 100644
--- a/src/lib/krb5/krb/init_ctx.c
+++ b/src/lib/krb5/krb/init_ctx.c
@@ -220,11 +220,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;
diff --git a/src/man/krb5.conf.man b/src/man/krb5.conf.man
index 6c0e9aff8c..4b53988712 100644
--- a/src/man/krb5.conf.man
+++ b/src/man/krb5.conf.man
@@ -178,12 +178,6 @@ kdc.conf(5), but it is not a recommended practice.
The libdefaults section may contain any of the following relations:
.INDENT 0.0
.TP
-\fBallow_des3\fP
-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.)
-.TP
\fBallow_rc4\fP
Permit the KDC to issue tickets with arcfour\-hmac session keys.
In future releases, this flag will allow arcfour\-hmac to be used
diff --git a/src/tests/gssapi/t_enctypes.py b/src/tests/gssapi/t_enctypes.py
index e6bde47afc..1bb8c40b6b 100755
--- a/src/tests/gssapi/t_enctypes.py
+++ b/src/tests/gssapi/t_enctypes.py
@@ -10,9 +10,8 @@ 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'},
+supp='aes256-cts:normal aes128-cts:normal rc4-hmac:normal'
+conf = {'libdefaults': {'permitted_enctypes': 'aes rc4', 'allow_rc4': 'true'},
'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 75d9621dd6..e82ff7ff07 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'},
+supported_enctypes = 'aes128-cts rc4-hmac'
+conf = {'libdefaults': {'allow_rc4': '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..c7dba0ff5b 100755
--- a/src/tests/t_sesskeynego.py
+++ b/src/tests/t_sesskeynego.py
@@ -26,7 +26,6 @@ conf3 = {'libdefaults': {
'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)
@@ -78,13 +77,6 @@ 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'])
diff --git a/src/util/k5test.py b/src/util/k5test.py
index 8e5f5ba8e9..b953827018 100644
--- a/src/util/k5test.py
+++ b/src/util/k5test.py
@@ -1338,13 +1338,6 @@ _passes = [
# No special settings; exercises AES256.
('default', None, None, None),
- # Exercise the DES3 enctype.
- ('des3', None,
- {'libdefaults': {'permitted_enctypes': 'des3 aes256-sha1'}},
- {'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'}},
--
2.49.0

View file

@ -1,692 +0,0 @@
From 9d03713af124c2096d071ba36893018da8d71655 Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Tue, 14 Jan 2025 13:31:11 +0100
Subject: [PATCH] Add PKINIT paChecksum2 from MS-PKCA v20230920
In 2023, Microsoft updated MS-PKCA to add the optional paChecksum2
element in the PKAuthenticator sequence. This checksum accepts SHA-1,
SHA-256, SHA-384, and SHA-512 digests.
In Windows Server 2025, this checksum becomes mandatory when using
PKINIT with FFDH (but strangely not with ECDH if SHA-1 is configured as
allowed).
[ghudson@mit.edu: refactored crypto interfaces to reduce complexity of
calling code]
ticket: 9166 (new)
(cherry picked from commit 310793ba63782af5ffa3a95d20e41f8f03ca7e00)
---
src/include/k5-int-pkinit.h | 25 ++--
src/lib/krb5/asn.1/asn1_k_encode.c | 18 ++-
src/plugins/preauth/pkinit/pkinit.h | 1 +
src/plugins/preauth/pkinit/pkinit_clnt.c | 41 +++----
src/plugins/preauth/pkinit/pkinit_constants.c | 42 +++++--
src/plugins/preauth/pkinit/pkinit_crypto.h | 24 +++-
.../preauth/pkinit/pkinit_crypto_openssl.c | 116 +++++++++++++++++-
src/plugins/preauth/pkinit/pkinit_kdf_test.c | 4 +-
src/plugins/preauth/pkinit/pkinit_lib.c | 16 ++-
src/plugins/preauth/pkinit/pkinit_srv.c | 38 ++----
src/plugins/preauth/pkinit/pkinit_trace.h | 5 +-
src/tests/asn.1/krb5_decode_test.c | 2 +-
src/tests/asn.1/ktest.c | 7 +-
src/tests/asn.1/ktest_equal.c | 2 +-
src/tests/asn.1/pkinit_encode.out | 2 +-
src/tests/asn.1/pkinit_trval.out | 2 +-
16 files changed, 250 insertions(+), 95 deletions(-)
diff --git a/src/include/k5-int-pkinit.h b/src/include/k5-int-pkinit.h
index 915904e518..cf6b1f99c5 100644
--- a/src/include/k5-int-pkinit.h
+++ b/src/include/k5-int-pkinit.h
@@ -36,21 +36,28 @@
* pkinit structures
*/
-/* PKAuthenticator */
-typedef struct _krb5_pk_authenticator {
- krb5_int32 cusec; /* (0..999999) */
- krb5_timestamp ctime;
- krb5_int32 nonce; /* (0..4294967295) */
- krb5_checksum paChecksum;
- krb5_data *freshnessToken;
-} krb5_pk_authenticator;
-
/* AlgorithmIdentifier */
typedef struct _krb5_algorithm_identifier {
krb5_data algorithm; /* OID */
krb5_data parameters; /* Optional */
} krb5_algorithm_identifier;
+/* PAChecksum2 */
+typedef struct _krb5_pachecksum2 {
+ krb5_data checksum;
+ krb5_algorithm_identifier algorithmIdentifier;
+} krb5_pachecksum2;
+
+/* PKAuthenticator */
+typedef struct _krb5_pk_authenticator {
+ krb5_int32 cusec; /* (0..999999) */
+ krb5_timestamp ctime;
+ krb5_int32 nonce; /* (0..4294967295) */
+ krb5_data paChecksum;
+ krb5_data *freshnessToken; /* Optional */
+ krb5_pachecksum2 *paChecksum2; /* Optional */
+} krb5_pk_authenticator;
+
/** AuthPack from RFC 4556*/
typedef struct _krb5_auth_pack {
krb5_pk_authenticator pkAuthenticator;
diff --git a/src/lib/krb5/asn.1/asn1_k_encode.c b/src/lib/krb5/asn.1/asn1_k_encode.c
index 5378b5c23b..cf7b500837 100644
--- a/src/lib/krb5/asn.1/asn1_k_encode.c
+++ b/src/lib/krb5/asn.1/asn1_k_encode.c
@@ -1394,20 +1394,30 @@ DEFSEQTYPE(pkinit_supp_pub_info, krb5_pkinit_supp_pub_info,
MAKE_ENCODER(encode_krb5_pkinit_supp_pub_info, pkinit_supp_pub_info);
MAKE_ENCODER(encode_krb5_sp80056a_other_info, sp80056a_other_info);
-/* A krb5_checksum encoded as an OCTET STRING, for PKAuthenticator. */
-DEFCOUNTEDTYPE(ostring_checksum, krb5_checksum, contents, length, octetstring);
+DEFFIELD(pachecksum2_0, krb5_pachecksum2, checksum, 0, ostring_data);
+DEFFIELD(pachecksum2_1, krb5_pachecksum2, algorithmIdentifier, 1,
+ algorithm_identifier);
+static const struct atype_info *pachecksum2_fields[] = {
+ &k5_atype_pachecksum2_0, &k5_atype_pachecksum2_1
+};
+DEFSEQTYPE(pachecksum2, krb5_pachecksum2, pachecksum2_fields);
+
+DEFPTRTYPE(pachecksum2_ptr, pachecksum2);
+DEFOPTIONALZEROTYPE(opt_pachecksum2_ptr, pachecksum2_ptr);
DEFFIELD(pk_authenticator_0, krb5_pk_authenticator, cusec, 0, int32);
DEFFIELD(pk_authenticator_1, krb5_pk_authenticator, ctime, 1, kerberos_time);
DEFFIELD(pk_authenticator_2, krb5_pk_authenticator, nonce, 2, int32);
DEFFIELD(pk_authenticator_3, krb5_pk_authenticator, paChecksum, 3,
- ostring_checksum);
+ ostring_data);
DEFFIELD(pk_authenticator_4, krb5_pk_authenticator, freshnessToken, 4,
opt_ostring_data_ptr);
+DEFFIELD(pk_authenticator_5, krb5_pk_authenticator, paChecksum2, 5,
+ opt_pachecksum2_ptr);
static const struct atype_info *pk_authenticator_fields[] = {
&k5_atype_pk_authenticator_0, &k5_atype_pk_authenticator_1,
&k5_atype_pk_authenticator_2, &k5_atype_pk_authenticator_3,
- &k5_atype_pk_authenticator_4
+ &k5_atype_pk_authenticator_4, &k5_atype_pk_authenticator_5
};
DEFSEQTYPE(pk_authenticator, krb5_pk_authenticator, pk_authenticator_fields);
diff --git a/src/plugins/preauth/pkinit/pkinit.h b/src/plugins/preauth/pkinit/pkinit.h
index 7ba7155bb4..a1564b6df2 100644
--- a/src/plugins/preauth/pkinit/pkinit.h
+++ b/src/plugins/preauth/pkinit/pkinit.h
@@ -338,6 +338,7 @@ void free_krb5_external_principal_identifier(krb5_external_principal_identifier
void free_krb5_algorithm_identifiers(krb5_algorithm_identifier ***in);
void free_krb5_algorithm_identifier(krb5_algorithm_identifier *in);
void free_krb5_kdc_dh_key_info(krb5_kdc_dh_key_info **in);
+void free_pachecksum2(krb5_context context, krb5_pachecksum2 **in);
krb5_error_code pkinit_copy_krb5_data(krb5_data *dst, const krb5_data *src);
diff --git a/src/plugins/preauth/pkinit/pkinit_clnt.c b/src/plugins/preauth/pkinit/pkinit_clnt.c
index b08022a214..433f477538 100644
--- a/src/plugins/preauth/pkinit/pkinit_clnt.c
+++ b/src/plugins/preauth/pkinit/pkinit_clnt.c
@@ -56,10 +56,9 @@ use_content_info(krb5_context context, pkinit_req_context req,
static krb5_error_code
pkinit_as_req_create(krb5_context context, pkinit_context plgctx,
pkinit_req_context reqctx, krb5_timestamp ctsec,
- krb5_int32 cusec, krb5_ui_4 nonce,
- const krb5_checksum *cksum,
- krb5_principal client, krb5_principal server,
- krb5_data **as_req);
+ krb5_int32 cusec, krb5_ui_4 nonce, const krb5_data *cksum,
+ const krb5_pachecksum2 *cksum2, krb5_principal client,
+ krb5_principal server, krb5_data **as_req);
static krb5_error_code
pkinit_as_rep_parse(krb5_context context, pkinit_context plgctx,
@@ -89,7 +88,8 @@ pa_pkinit_gen_req(krb5_context context,
krb5_timestamp ctsec = 0;
krb5_int32 cusec = 0;
krb5_ui_4 nonce = 0;
- krb5_checksum cksum;
+ krb5_data cksum = empty_data();
+ krb5_pachecksum2 *cksum2 = NULL;
krb5_data *der_req = NULL;
krb5_pa_data **return_pa_data = NULL;
@@ -118,15 +118,10 @@ pa_pkinit_gen_req(krb5_context context,
goto cleanup;
}
- retval = krb5_c_make_checksum(context, CKSUMTYPE_SHA1, NULL, 0, der_req,
- &cksum);
+ retval = crypto_generate_checksums(context, der_req, &cksum, &cksum2);
if (retval)
goto cleanup;
- TRACE_PKINIT_CLIENT_REQ_CHECKSUM(context, &cksum);
-#ifdef DEBUG_CKSUM
- pkiDebug("calculating checksum on buf size (%d)\n", der_req->length);
- print_buffer(der_req->data, der_req->length);
-#endif
+ TRACE_PKINIT_CLIENT_REQ_CHECKSUMS(context, &cksum, cksum2);
retval = cb->get_preauth_time(context, rock, TRUE, &ctsec, &cusec);
if (retval)
@@ -140,7 +135,8 @@ pa_pkinit_gen_req(krb5_context context,
nonce = request->nonce;
retval = pkinit_as_req_create(context, plgctx, reqctx, ctsec, cusec,
- nonce, &cksum, request->client, request->server, &out_data);
+ nonce, &cksum, cksum2, request->client,
+ request->server, &out_data);
if (retval) {
pkiDebug("error %d on pkinit_as_req_create; aborting PKINIT\n",
(int) retval);
@@ -168,23 +164,19 @@ pa_pkinit_gen_req(krb5_context context,
cleanup:
krb5_free_data(context, der_req);
- krb5_free_checksum_contents(context, &cksum);
+ krb5_free_data_contents(context, &cksum);
+ free_pachecksum2(context, &cksum2);
krb5_free_data(context, out_data);
krb5_free_pa_data(context, return_pa_data);
return retval;
}
static krb5_error_code
-pkinit_as_req_create(krb5_context context,
- pkinit_context plgctx,
- pkinit_req_context reqctx,
- krb5_timestamp ctsec,
- krb5_int32 cusec,
- krb5_ui_4 nonce,
- const krb5_checksum * cksum,
- krb5_principal client,
- krb5_principal server,
- krb5_data ** as_req)
+pkinit_as_req_create(krb5_context context, pkinit_context plgctx,
+ pkinit_req_context reqctx, krb5_timestamp ctsec,
+ krb5_int32 cusec, krb5_ui_4 nonce, const krb5_data *cksum,
+ const krb5_pachecksum2 *cksum2, krb5_principal client,
+ krb5_principal server, krb5_data **as_req)
{
krb5_error_code retval = ENOMEM;
krb5_data spki = empty_data(), *coded_auth_pack = NULL;
@@ -202,6 +194,7 @@ pkinit_as_req_create(krb5_context context,
auth_pack.pkAuthenticator.paChecksum = *cksum;
if (!reqctx->opts->disable_freshness)
auth_pack.pkAuthenticator.freshnessToken = reqctx->freshness_token;
+ auth_pack.pkAuthenticator.paChecksum2 = (krb5_pachecksum2 *)cksum2;
auth_pack.clientDHNonce.length = 0;
auth_pack.supportedKDFs = (krb5_data **)supported_kdf_alg_ids;
diff --git a/src/plugins/preauth/pkinit/pkinit_constants.c b/src/plugins/preauth/pkinit/pkinit_constants.c
index 905e90d29c..a32b373c32 100644
--- a/src/plugins/preauth/pkinit/pkinit_constants.c
+++ b/src/plugins/preauth/pkinit/pkinit_constants.c
@@ -34,25 +34,49 @@
/* RFC 8636 id-pkinit-kdf-ah-sha1: iso(1) identified-organization(3) dod(6)
* internet(1) security(5) kerberosv5(2) pkinit(3) kdf(6) sha1(1) */
-static char sha1_oid[8] = { 0x2B, 0x06, 0x01, 0x05, 0x02, 0x03, 0x06, 0x01 };
+static char kdf_sha1[8] = { 0x2B, 0x06, 0x01, 0x05, 0x02, 0x03, 0x06, 0x01 };
/* RFC 8636 id-pkinit-kdf-ah-sha256: iso(1) identified-organization(3) dod(6)
* internet(1) security(5) kerberosv5(2) pkinit(3) kdf(6) sha256(2) */
-static char sha256_oid[8] = { 0x2B, 0x06, 0x01, 0x05, 0x02, 0x03, 0x06, 0x02 };
+static char kdf_sha256[8] = { 0x2B, 0x06, 0x01, 0x05, 0x02, 0x03, 0x06, 0x02 };
/* RFC 8636 id-pkinit-kdf-ah-sha512: iso(1) identified-organization(3) dod(6)
* internet(1) security(5) kerberosv5(2) pkinit(3) kdf(6) sha512(3) */
-static char sha512_oid[8] = { 0x2B, 0x06, 0x01, 0x05, 0x02, 0x03, 0x06, 0x03 };
+static char kdf_sha512[8] = { 0x2B, 0x06, 0x01, 0x05, 0x02, 0x03, 0x06, 0x03 };
-const krb5_data sha1_id = { KV5M_DATA, sizeof(sha1_oid), sha1_oid };
-const krb5_data sha256_id = { KV5M_DATA, sizeof(sha256_oid), sha256_oid };
-const krb5_data sha512_id = { KV5M_DATA, sizeof(sha512_oid), sha512_oid };
+const krb5_data kdf_sha1_id = { KV5M_DATA, sizeof(kdf_sha1), kdf_sha1 };
+const krb5_data kdf_sha256_id = { KV5M_DATA, sizeof(kdf_sha256), kdf_sha256 };
+const krb5_data kdf_sha512_id = { KV5M_DATA, sizeof(kdf_sha512), kdf_sha512 };
krb5_data const * const supported_kdf_alg_ids[] = {
- &sha256_id,
- &sha1_id,
- &sha512_id,
+ &kdf_sha256_id,
+ &kdf_sha1_id,
+ &kdf_sha512_id,
NULL
};
+/* RFC 3370 sha-1: iso(1) identified-organization(3) oiw(14) secsig(3)
+ * algorithm(2) 26 */
+static char cms_sha1[] = { 0x2b, 0x0e, 0x03, 0x02, 0x1a };
+/* RFC 5754 id-sha256: joint-iso-itu-t(2) country(16) us(840) organization(1)
+ * gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 */
+static char cms_sha256[] = {
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01
+};
+/* RFC 5754 id-sha384: joint-iso-itu-t(2) country(16) us(840) organization(1)
+ * gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 */
+static char cms_sha384[] = {
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02
+};
+/* RFC 5754 id-sha512: joint-iso-itu-t(2) country(16) us(840) organization(1)
+ * gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 */
+static char cms_sha512[] = {
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03
+};
+
+const krb5_data cms_sha1_id = { KV5M_DATA, sizeof(cms_sha1), cms_sha1 };
+const krb5_data cms_sha256_id = { KV5M_DATA, sizeof(cms_sha256), cms_sha256 };
+const krb5_data cms_sha384_id = { KV5M_DATA, sizeof(cms_sha384), cms_sha384 };
+const krb5_data cms_sha512_id = { KV5M_DATA, sizeof(cms_sha512), cms_sha512 };
+
/* RFC 4055 sha256WithRSAEncryption: iso(1) member-body(2) us(840)
* rsadsi(113549) pkcs(1) 1 11 */
static char sha256WithRSAEncr_oid[9] = {
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto.h b/src/plugins/preauth/pkinit/pkinit_crypto.h
index fd876e4850..3b12e904b1 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto.h
+++ b/src/plugins/preauth/pkinit/pkinit_crypto.h
@@ -562,9 +562,13 @@ pkinit_alg_agility_kdf(krb5_context context,
krb5_data *pk_as_rep,
krb5_keyblock *key_block);
-extern const krb5_data sha1_id;
-extern const krb5_data sha256_id;
-extern const krb5_data sha512_id;
+extern const krb5_data kdf_sha1_id;
+extern const krb5_data kdf_sha256_id;
+extern const krb5_data kdf_sha512_id;
+extern const krb5_data cms_sha1_id;
+extern const krb5_data cms_sha256_id;
+extern const krb5_data cms_sha384_id;
+extern const krb5_data cms_sha512_id;
extern const krb5_data oakley_1024;
extern const krb5_data oakley_2048;
extern const krb5_data oakley_4096;
@@ -597,4 +601,18 @@ crypto_req_cert_matching_data(krb5_context context,
int parse_dh_min_bits(krb5_context context, const char *str);
+/* Generate a SHA-1 checksum over body in *cksum1_out and a SHA-256 checksum
+ * over body in *cksum2_out with appropriate metadata. */
+krb5_error_code
+crypto_generate_checksums(krb5_context context, const krb5_data *body,
+ krb5_data *cksum1_out,
+ krb5_pachecksum2 **cksum2_out);
+
+/* Verify the SHA-1 checksum in cksum1 and the tagged checksum in cksum2.
+ * cksum2 may be NULL, in which case only cksum1 is verified. */
+krb5_error_code
+crypto_verify_checksums(krb5_context context, krb5_data *body,
+ const krb5_data *cksum1,
+ const krb5_pachecksum2 *cksum2);
+
#endif /* _PKINIT_CRYPTO_H */
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
index 402bf1b9b3..429b7d202c 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
@@ -2616,11 +2616,11 @@ cleanup:
static const EVP_MD *
algid_to_md(const krb5_data *alg_id)
{
- if (data_eq(*alg_id, sha1_id))
+ if (data_eq(*alg_id, kdf_sha1_id))
return EVP_sha1();
- if (data_eq(*alg_id, sha256_id))
+ if (data_eq(*alg_id, kdf_sha256_id))
return EVP_sha256();
- if (data_eq(*alg_id, sha512_id))
+ if (data_eq(*alg_id, kdf_sha512_id))
return EVP_sha512();
return NULL;
}
@@ -5663,3 +5663,113 @@ parse_dh_min_bits(krb5_context context, const char *str)
TRACE_PKINIT_DH_INVALID_MIN_BITS(context, str);
return PKINIT_DEFAULT_DH_MIN_BITS;
}
+
+/* Return the OpenSSL message digest type matching the given CMS OID, or NULL
+ * if it doesn't match any of the CMS OIDs we know about. */
+static const EVP_MD *
+md_from_cms_oid(const krb5_data *alg_id)
+{
+ if (data_eq(*alg_id, cms_sha1_id))
+ return EVP_sha1();
+ if (data_eq(*alg_id, cms_sha256_id))
+ return EVP_sha256();
+ if (data_eq(*alg_id, cms_sha384_id))
+ return EVP_sha384();
+ if (data_eq(*alg_id, cms_sha512_id))
+ return EVP_sha512();
+ return NULL;
+}
+
+/* Compute a message digest of the given type over body, placing the result in
+ * *digest_out in allocated storage. Return true on success. */
+static krb5_boolean
+make_digest(const krb5_data *body, const EVP_MD *md, krb5_data *digest_out)
+{
+ krb5_error_code ret;
+ krb5_data d;
+
+ if (md == NULL)
+ return FALSE;
+ ret = alloc_data(&d, EVP_MD_size(md));
+ if (ret)
+ return FALSE;
+ if (!EVP_Digest(body->data, body->length, (uint8_t *)d.data, &d.length, md,
+ NULL)) {
+ free(d.data);
+ return FALSE;
+ }
+ *digest_out = d;
+ return TRUE;
+}
+
+/* Return true if digest verifies for the given body and message digest
+ * type. */
+static krb5_boolean
+check_digest(const krb5_data *body, const EVP_MD *md, const krb5_data *digest)
+{
+ unsigned int digest_len;
+ uint8_t buf[EVP_MAX_MD_SIZE];
+
+ if (md == NULL)
+ return FALSE;
+ if (!EVP_Digest(body->data, body->length, buf, &digest_len, md, NULL))
+ return FALSE;
+ return (digest->length == digest_len &&
+ CRYPTO_memcmp(digest->data, buf, digest_len) == 0);
+}
+
+krb5_error_code
+crypto_generate_checksums(krb5_context context, const krb5_data *body,
+ krb5_data *cksum1_out, krb5_pachecksum2 **cksum2_out)
+{
+ krb5_data cksum1 = empty_data();
+ krb5_pachecksum2 *cksum2 = NULL;
+ krb5_error_code ret;
+
+ if (!make_digest(body, EVP_sha1(), &cksum1))
+ goto fail;
+
+ cksum2 = k5alloc(sizeof(*cksum2), &ret);
+ if (cksum2 == NULL)
+ goto fail;
+
+ if (!make_digest(body, EVP_sha256(), &cksum2->checksum))
+ goto fail;
+
+ if (krb5int_copy_data_contents(context, &cms_sha256_id,
+ &cksum2->algorithmIdentifier.algorithm))
+ goto fail;
+
+ cksum2->algorithmIdentifier.parameters = empty_data();
+
+ *cksum1_out = cksum1;
+ *cksum2_out = cksum2;
+ return 0;
+
+fail:
+ krb5_free_data_contents(context, &cksum1);
+ free_pachecksum2(context, &cksum2);
+ return KRB5_CRYPTO_INTERNAL;
+}
+
+krb5_error_code
+crypto_verify_checksums(krb5_context context, krb5_data *body,
+ const krb5_data *cksum1,
+ const krb5_pachecksum2 *cksum2)
+{
+ const EVP_MD *md;
+
+ /* RFC 4556 doesn't say what error to return if the checksum doesn't match.
+ * Windows returns this one. */
+ if (!check_digest(body, EVP_sha1(), cksum1))
+ return KRB5KRB_AP_ERR_MODIFIED;
+
+ if (cksum2 == NULL)
+ return 0;
+
+ md = md_from_cms_oid(&cksum2->algorithmIdentifier.algorithm);
+ if (!check_digest(body, md, &cksum2->checksum))
+ return KRB5KRB_AP_ERR_MODIFIED;
+
+ return 0;
+}
diff --git a/src/plugins/preauth/pkinit/pkinit_kdf_test.c b/src/plugins/preauth/pkinit/pkinit_kdf_test.c
index 99c93ac128..dd6e8d7503 100644
--- a/src/plugins/preauth/pkinit/pkinit_kdf_test.c
+++ b/src/plugins/preauth/pkinit/pkinit_kdf_test.c
@@ -126,7 +126,7 @@ main(int argc, char **argv)
/* TEST 1: SHA-1/AES */
/* set up algorithm id */
- alg_id.algorithm = sha1_id;
+ alg_id.algorithm = kdf_sha1_id;
enctype = enctype_aes;
@@ -157,7 +157,7 @@ main(int argc, char **argv)
/* TEST 2: SHA-256/AES */
/* set up algorithm id */
- alg_id.algorithm = sha256_id;
+ alg_id.algorithm = kdf_sha256_id;
enctype = enctype_aes;
diff --git a/src/plugins/preauth/pkinit/pkinit_lib.c b/src/plugins/preauth/pkinit/pkinit_lib.c
index 25965eb5d2..891f47fd26 100644
--- a/src/plugins/preauth/pkinit/pkinit_lib.c
+++ b/src/plugins/preauth/pkinit/pkinit_lib.c
@@ -29,6 +29,7 @@
* SUCH DAMAGES.
*/
+#include "k5-int.h"
#include "pkinit.h"
#define FAKECERT
@@ -119,8 +120,9 @@ free_krb5_auth_pack(krb5_auth_pack **in)
{
if ((*in) == NULL) return;
krb5_free_data_contents(NULL, &(*in)->clientPublicValue);
- free((*in)->pkAuthenticator.paChecksum.contents);
+ free((*in)->pkAuthenticator.paChecksum.data);
krb5_free_data(NULL, (*in)->pkAuthenticator.freshnessToken);
+ free_pachecksum2(NULL, &(*in)->pkAuthenticator.paChecksum2);
if ((*in)->supportedCMSTypes != NULL)
free_krb5_algorithm_identifiers(&((*in)->supportedCMSTypes));
if ((*in)->supportedKDFs) {
@@ -196,6 +198,18 @@ free_krb5_kdc_dh_key_info(krb5_kdc_dh_key_info **in)
free(*in);
}
+void
+free_pachecksum2(krb5_context context, krb5_pachecksum2 **in)
+{
+ if (*in == NULL)
+ return;
+ krb5_free_data_contents(context, &(*in)->checksum);
+ krb5_free_data_contents(context, &(*in)->algorithmIdentifier.algorithm);
+ krb5_free_data_contents(context, &(*in)->algorithmIdentifier.parameters);
+ free(*in);
+ *in = NULL;
+}
+
void
init_krb5_pa_pk_as_req(krb5_pa_pk_as_req **in)
{
diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c
index e22bcb195b..f558308483 100644
--- a/src/plugins/preauth/pkinit/pkinit_srv.c
+++ b/src/plugins/preauth/pkinit/pkinit_srv.c
@@ -428,11 +428,12 @@ pkinit_server_verify_padata(krb5_context context,
krb5_data authp_data = {0, 0, NULL}, krb5_authz = {0, 0, NULL};
krb5_pa_pk_as_req *reqp = NULL;
krb5_auth_pack *auth_pack = NULL;
+ krb5_pk_authenticator *pka;
pkinit_kdc_context plgctx = NULL;
pkinit_kdc_req_context reqctx = NULL;
krb5_checksum cksum = {0, 0, 0, NULL};
krb5_data *der_req = NULL;
- krb5_data k5data, *ftoken;
+ krb5_data k5data;
int is_signed = 1;
krb5_pa_data **e_data = NULL;
krb5_kdcpreauth_modreq modreq = NULL;
@@ -524,8 +525,9 @@ pkinit_server_verify_padata(krb5_context context,
pkiDebug("failed to decode krb5_auth_pack\n");
goto cleanup;
}
+ pka = &auth_pack->pkAuthenticator;
- retval = krb5_check_clockskew(context, auth_pack->pkAuthenticator.ctime);
+ retval = krb5_check_clockskew(context, pka->ctime);
if (retval)
goto cleanup;
@@ -548,36 +550,14 @@ pkinit_server_verify_padata(krb5_context context,
goto cleanup;
}
der_req = cb->request_body(context, rock);
- retval = krb5_c_make_checksum(context, CKSUMTYPE_SHA1, NULL, 0, der_req,
- &cksum);
- if (retval) {
- pkiDebug("unable to calculate AS REQ checksum\n");
- goto cleanup;
- }
- if (cksum.length != auth_pack->pkAuthenticator.paChecksum.length ||
- k5_bcmp(cksum.contents, auth_pack->pkAuthenticator.paChecksum.contents,
- cksum.length) != 0) {
- pkiDebug("failed to match the checksum\n");
-#ifdef DEBUG_CKSUM
- pkiDebug("calculating checksum on buf size (%d)\n", req_pkt->length);
- print_buffer(req_pkt->data, req_pkt->length);
- pkiDebug("received checksum type=%d size=%d ",
- auth_pack->pkAuthenticator.paChecksum.checksum_type,
- auth_pack->pkAuthenticator.paChecksum.length);
- print_buffer(auth_pack->pkAuthenticator.paChecksum.contents,
- auth_pack->pkAuthenticator.paChecksum.length);
- pkiDebug("expected checksum type=%d size=%d ",
- cksum.checksum_type, cksum.length);
- print_buffer(cksum.contents, cksum.length);
-#endif
- retval = KRB5KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED;
+ retval = crypto_verify_checksums(context, der_req, &pka->paChecksum,
+ pka->paChecksum2);
+ if (retval)
goto cleanup;
- }
- ftoken = auth_pack->pkAuthenticator.freshnessToken;
- if (ftoken != NULL) {
- retval = cb->check_freshness_token(context, rock, ftoken);
+ if (pka->freshnessToken != NULL) {
+ retval = cb->check_freshness_token(context, rock, pka->freshnessToken);
if (retval)
goto cleanup;
valid_freshness_token = TRUE;
diff --git a/src/plugins/preauth/pkinit/pkinit_trace.h b/src/plugins/preauth/pkinit/pkinit_trace.h
index 1faa6816d7..7b68d4b3b1 100644
--- a/src/plugins/preauth/pkinit/pkinit_trace.h
+++ b/src/plugins/preauth/pkinit/pkinit_trace.h
@@ -58,8 +58,9 @@
TRACE(c, "PKINIT client verified DH reply")
#define TRACE_PKINIT_CLIENT_REP_DH_FAIL(c) \
TRACE(c, "PKINIT client could not verify DH reply")
-#define TRACE_PKINIT_CLIENT_REQ_CHECKSUM(c, cksum) \
- TRACE(c, "PKINIT client computed kdc-req-body checksum {cksum}", cksum)
+#define TRACE_PKINIT_CLIENT_REQ_CHECKSUMS(c, ck1, ck2) \
+ TRACE(c, "PKINIT client computed checksums: {hexdata} {hexdata}", \
+ ck1, &(ck2)->checksum)
#define TRACE_PKINIT_CLIENT_REQ_DH(c) \
TRACE(c, "PKINIT client making DH request")
#define TRACE_PKINIT_CLIENT_SAN_CONFIG_DNSNAME(c, host) \
diff --git a/src/tests/asn.1/krb5_decode_test.c b/src/tests/asn.1/krb5_decode_test.c
index 2fa6dce8eb..f47849abad 100644
--- a/src/tests/asn.1/krb5_decode_test.c
+++ b/src/tests/asn.1/krb5_decode_test.c
@@ -1174,7 +1174,7 @@ main(int argc, char **argv)
/* decode_krb5_auth_pack */
{
setup(krb5_auth_pack,ktest_make_sample_auth_pack);
- decode_run("krb5_auth_pack","","30 81 85 A0 35 30 33 A0 05 02 03 01 E2 40 A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 03 02 01 2A A3 06 04 04 31 32 33 34 A4 0A 04 08 6B 72 62 35 64 61 74 61 A1 08 04 06 70 76 61 6C 75 65 A2 24 30 22 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 30 0B 06 09 2A 86 48 86 F7 12 01 02 02 A3 0A 04 08 6B 72 62 35 64 61 74 61 A4 10 30 0E 30 0C A0 0A 06 08 6B 72 62 35 64 61 74 61",
+ decode_run("krb5_auth_pack","","30 81 89 A0 39 30 37 A0 05 02 03 01 E2 40 A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 03 02 01 2A A3 0A 04 08 6B 72 62 35 64 61 74 61 A4 0A 04 08 6B 72 62 35 64 61 74 61 A1 08 04 06 70 76 61 6C 75 65 A2 24 30 22 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 30 0B 06 09 2A 86 48 86 F7 12 01 02 02 A3 0A 04 08 6B 72 62 35 64 61 74 61 A4 10 30 0E 30 0C A0 0A 06 08 6B 72 62 35 64 61 74 61",
acc.decode_krb5_auth_pack,
ktest_equal_auth_pack,ktest_free_auth_pack);
ktest_empty_auth_pack(&ref);
diff --git a/src/tests/asn.1/ktest.c b/src/tests/asn.1/ktest.c
index d37e4fa7e6..7f54aa3184 100644
--- a/src/tests/asn.1/ktest.c
+++ b/src/tests/asn.1/ktest.c
@@ -700,9 +700,7 @@ ktest_make_sample_pk_authenticator(krb5_pk_authenticator *p)
p->cusec = SAMPLE_USEC;
p->ctime = SAMPLE_TIME;
p->nonce = SAMPLE_NONCE;
- ktest_make_sample_checksum(&p->paChecksum);
- /* We don't encode the checksum type, only the contents. */
- p->paChecksum.checksum_type = 0;
+ ktest_make_sample_data(&p->paChecksum);
p->freshnessToken = ealloc(sizeof(krb5_data));
ktest_make_sample_data(p->freshnessToken);
}
@@ -1604,8 +1602,7 @@ ktest_empty_pa_otp_req(krb5_pa_otp_req *p)
static void
ktest_empty_pk_authenticator(krb5_pk_authenticator *p)
{
- ktest_empty_checksum(&p->paChecksum);
- p->paChecksum.contents = NULL;
+ ktest_empty_data(&p->paChecksum);
krb5_free_data(NULL, p->freshnessToken);
p->freshnessToken = NULL;
}
diff --git a/src/tests/asn.1/ktest_equal.c b/src/tests/asn.1/ktest_equal.c
index b48a0285d2..13786dd1e5 100644
--- a/src/tests/asn.1/ktest_equal.c
+++ b/src/tests/asn.1/ktest_equal.c
@@ -844,7 +844,7 @@ ktest_equal_pk_authenticator(krb5_pk_authenticator *ref,
p = p && scalar_equal(cusec);
p = p && scalar_equal(ctime);
p = p && scalar_equal(nonce);
- p = p && struct_equal(paChecksum, ktest_equal_checksum);
+ p = p && data_eq(ref->paChecksum, var->paChecksum);
return p;
}
diff --git a/src/tests/asn.1/pkinit_encode.out b/src/tests/asn.1/pkinit_encode.out
index 6ec7aaa36a..a764182e15 100644
--- a/src/tests/asn.1/pkinit_encode.out
+++ b/src/tests/asn.1/pkinit_encode.out
@@ -1,7 +1,7 @@
encode_krb5_pa_pk_as_req: 30 38 80 08 6B 72 62 35 64 61 74 61 A1 22 30 20 30 1E 80 08 6B 72 62 35 64 61 74 61 81 08 6B 72 62 35 64 61 74 61 82 08 6B 72 62 35 64 61 74 61 82 08 6B 72 62 35 64 61 74 61
encode_krb5_pa_pk_as_rep(dhInfo): A0 28 30 26 80 08 6B 72 62 35 64 61 74 61 A1 0A 04 08 6B 72 62 35 64 61 74 61 A2 0E 30 0C A0 0A 06 08 6B 72 62 35 64 61 74 61
encode_krb5_pa_pk_as_rep(encKeyPack): 81 08 6B 72 62 35 64 61 74 61
-encode_krb5_auth_pack: 30 81 85 A0 35 30 33 A0 05 02 03 01 E2 40 A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 03 02 01 2A A3 06 04 04 31 32 33 34 A4 0A 04 08 6B 72 62 35 64 61 74 61 A1 08 04 06 70 76 61 6C 75 65 A2 24 30 22 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 30 0B 06 09 2A 86 48 86 F7 12 01 02 02 A3 0A 04 08 6B 72 62 35 64 61 74 61 A4 10 30 0E 30 0C A0 0A 06 08 6B 72 62 35 64 61 74 61
+encode_krb5_auth_pack: 30 81 89 A0 39 30 37 A0 05 02 03 01 E2 40 A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 03 02 01 2A A3 0A 04 08 6B 72 62 35 64 61 74 61 A4 0A 04 08 6B 72 62 35 64 61 74 61 A1 08 04 06 70 76 61 6C 75 65 A2 24 30 22 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 30 0B 06 09 2A 86 48 86 F7 12 01 02 02 A3 0A 04 08 6B 72 62 35 64 61 74 61 A4 10 30 0E 30 0C A0 0A 06 08 6B 72 62 35 64 61 74 61
encode_krb5_kdc_dh_key_info: 30 25 A0 0B 03 09 00 6B 72 62 35 64 61 74 61 A1 03 02 01 2A A2 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A
encode_krb5_reply_key_pack: 30 26 A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A1 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34
encode_krb5_sp80056a_other_info: 30 81 81 30 0B 06 09 2A 86 48 86 F7 12 01 02 02 A0 32 04 30 30 2E A0 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A1 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A1 32 04 30 30 2E A0 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A1 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A2 0A 04 08 6B 72 62 35 64 61 74 61
diff --git a/src/tests/asn.1/pkinit_trval.out b/src/tests/asn.1/pkinit_trval.out
index 46f4a34108..c47bd71f67 100644
--- a/src/tests/asn.1/pkinit_trval.out
+++ b/src/tests/asn.1/pkinit_trval.out
@@ -38,7 +38,7 @@ encode_krb5_auth_pack:
. . [0] [Integer] 123456
. . [1] [Generalized Time] "19940610060317Z"
. . [2] [Integer] 42
-. . [3] [Octet String] "1234"
+. . [3] [Octet String] "krb5data"
. . [4] [Octet String] "krb5data"
. [1] [Octet String] "pvalue"
. [2] [Sequence/Sequence Of]
--
2.49.0

View file

@ -1,381 +0,0 @@
From 33afd2a6cfdf87d153170b41fbabfb92be49c422 Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Thu, 10 Apr 2025 10:04:22 +0200
Subject: [PATCH] [downstream] Do not block HMAC-MD4/5 in FIPS mode
To ensure RC4 HMAC-MD5 was not used in FIPS mode, access to HMAC-MD4/5
was not allowed in this mode. However, since we provide the
"radius_md5_fips_override" configuration parameter to allow using RADIUS
regardless to the FIPS restrictions, we should allow HMAC-MD5 to be used
too in this case, because it is required for the newly supported
Message-Authenticator attribute.
A FIPS mode check is added in calculate_mac() which will fail if
"radius_md5_fips_override" is not true. It will not affect interactions
between krb5kdc and ipa-otpd, because the Message-Authenticator
attribute is not generated in this case.
---
src/lib/crypto/krb/crypto_int.h | 9 +++
src/lib/crypto/openssl/Makefile.in | 9 ++-
src/lib/crypto/openssl/common.c | 80 +++++++++++++++++++
.../crypto/openssl/hash_provider/hash_evp.c | 62 ++------------
src/lib/crypto/openssl/hmac.c | 15 ++--
src/lib/krad/packet.c | 19 +++--
6 files changed, 120 insertions(+), 74 deletions(-)
create mode 100644 src/lib/crypto/openssl/common.c
diff --git a/src/lib/crypto/krb/crypto_int.h b/src/lib/crypto/krb/crypto_int.h
index 1ee4b30e02..ff67b6bd35 100644
--- a/src/lib/crypto/krb/crypto_int.h
+++ b/src/lib/crypto/krb/crypto_int.h
@@ -36,6 +36,9 @@
#include <openssl/opensslv.h>
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+
+#include <openssl/provider.h>
+
/*
* OpenSSL 3.0 relegates MD4 and RC4 to the legacy provider, which must be
* explicitly loaded into a library context. Performing this loading within a
@@ -660,4 +663,10 @@ iov_cursor_advance(struct iov_cursor *c, size_t nblocks)
c->out_pos += nblocks * c->block_size;
}
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+
+krb5_error_code k5_get_ossl_legacy_libctx(OSSL_LIB_CTX **libctx);
+
+#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
+
#endif /* CRYPTO_INT_H */
diff --git a/src/lib/crypto/openssl/Makefile.in b/src/lib/crypto/openssl/Makefile.in
index 8e4cdb8bbf..cc131000bd 100644
--- a/src/lib/crypto/openssl/Makefile.in
+++ b/src/lib/crypto/openssl/Makefile.in
@@ -8,21 +8,24 @@ STLIBOBJS=\
hmac.o \
kdf.o \
pbkdf2.o \
- sha256.o
+ sha256.o \
+ common.o
OBJS=\
$(OUTPRE)cmac.$(OBJEXT) \
$(OUTPRE)hmac.$(OBJEXT) \
$(OUTPRE)kdf.$(OBJEXT) \
$(OUTPRE)pbkdf2.$(OBJEXT) \
- $(OUTPRE)sha256.$(OBJEXT)
+ $(OUTPRE)sha256.$(OBJEXT) \
+ $(OUTPRE)common.$(OBJEXT)
SRCS=\
$(srcdir)/cmac.c \
$(srcdir)/hmac.c \
$(srcdir)/kdf.c \
$(srcdir)/pbkdf2.c \
- $(srcdir)/sha256.c
+ $(srcdir)/sha256.c \
+ $(srcdir)/common.c
SUBDIROBJLISTS= md4/OBJS.ST \
md5/OBJS.ST sha1/OBJS.ST sha2/OBJS.ST \
diff --git a/src/lib/crypto/openssl/common.c b/src/lib/crypto/openssl/common.c
new file mode 100644
index 0000000000..ced43fd54c
--- /dev/null
+++ b/src/lib/crypto/openssl/common.c
@@ -0,0 +1,80 @@
+#include "crypto_int.h"
+
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+
+#include <openssl/provider.h>
+#include <openssl/fips.h>
+#include <threads.h>
+#include <stdbool.h>
+
+typedef struct ossl_legacy_context {
+ bool initialized;
+ OSSL_LIB_CTX *libctx;
+ OSSL_PROVIDER *default_provider;
+ OSSL_PROVIDER *legacy_provider;
+} ossl_legacy_context_t;
+
+static thread_local ossl_legacy_context_t g_ossl_legacy_ctx;
+
+static krb5_error_code
+init_ossl_legacy_ctx(ossl_legacy_context_t *ctx)
+{
+ 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;
+
+ ctx->initialized = true;
+ return 0;
+}
+
+static void
+deinit_ossl_legacy_ctx(ossl_legacy_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);
+
+ ctx->initialized = false;
+}
+
+krb5_error_code
+k5_get_ossl_legacy_libctx(OSSL_LIB_CTX **libctx)
+{
+ krb5_error_code err;
+
+ if (!FIPS_mode()) {
+ if (libctx)
+ *libctx = NULL;
+ err = 0;
+ goto end;
+ }
+
+ if (!g_ossl_legacy_ctx.initialized) {
+ err = init_ossl_legacy_ctx(&g_ossl_legacy_ctx);
+ if (err) {
+ deinit_ossl_legacy_ctx(&g_ossl_legacy_ctx);
+ goto end;
+ }
+ }
+
+ if (libctx)
+ *libctx = g_ossl_legacy_ctx.libctx;
+ err = 0;
+
+end:
+ return err;
+}
+
+#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
diff --git a/src/lib/crypto/openssl/hash_provider/hash_evp.c b/src/lib/crypto/openssl/hash_provider/hash_evp.c
index eb2e693e9f..2fd5d383d6 100644
--- a/src/lib/crypto/openssl/hash_provider/hash_evp.c
+++ b/src/lib/crypto/openssl/hash_provider/hash_evp.c
@@ -44,48 +44,7 @@
#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,
@@ -120,25 +79,14 @@ hash_legacy_evp(const char *algo, const krb5_crypto_iov *data, size_t num_data,
krb5_data *output)
{
krb5_error_code err;
+ OSSL_LIB_CTX *ossl_libctx;
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;
- }
- }
+ err = k5_get_ossl_legacy_libctx(&ossl_libctx);
+ if (err)
+ goto end;
- md = EVP_MD_fetch(ossl_md_ctx->libctx, algo, NULL);
+ md = EVP_MD_fetch(ossl_libctx, algo, NULL);
if (!md) {
err = KRB5_CRYPTO_INTERNAL;
goto end;
diff --git a/src/lib/crypto/openssl/hmac.c b/src/lib/crypto/openssl/hmac.c
index 25a419d73a..8f9e88fec9 100644
--- a/src/lib/crypto/openssl/hmac.c
+++ b/src/lib/crypto/openssl/hmac.c
@@ -59,7 +59,6 @@
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
#include <openssl/params.h>
#include <openssl/core_names.h>
-#include <openssl/fips.h>
#else
#include <openssl/hmac.h>
#endif
@@ -112,11 +111,7 @@ map_digest(const struct krb5_hash_provider *hash)
return EVP_sha256();
else if (hash == &krb5int_hash_sha384)
return EVP_sha384();
-
- if (FIPS_mode())
- return NULL;
-
- if (hash == &krb5int_hash_md5)
+ else if (hash == &krb5int_hash_md5)
return EVP_md5();
else if (hash == &krb5int_hash_md4)
return EVP_md4();
@@ -138,13 +133,19 @@ krb5int_hmac_keyblock(const struct krb5_hash_provider *hash,
EVP_MAC_CTX *ctx = NULL;
OSSL_PARAM params[2], *p = params;
size_t i = 0, md_len;
+ OSSL_LIB_CTX *ossl_libctx;
+ krb5_error_code err;
if (md == NULL || keyblock->length > hash->blocksize)
return KRB5_CRYPTO_INTERNAL;
if (output->length < hash->hashsize)
return KRB5_BAD_MSIZE;
- mac = EVP_MAC_fetch(NULL, "HMAC", NULL);
+ err = k5_get_ossl_legacy_libctx(&ossl_libctx);
+ if (err)
+ return err;
+
+ mac = EVP_MAC_fetch(ossl_libctx, "HMAC", NULL);
if (mac == NULL)
return KRB5_CRYPTO_INTERNAL;
diff --git a/src/lib/krad/packet.c b/src/lib/krad/packet.c
index 3c1a4d507e..b95c99df65 100644
--- a/src/lib/krad/packet.c
+++ b/src/lib/krad/packet.c
@@ -278,7 +278,7 @@ lookup_msgauth_addr(const krad_packet *pkt)
* auth, which may be from pkt or from a corresponding request.
*/
static krb5_error_code
-calculate_mac(const char *secret, const krad_packet *pkt,
+calculate_mac(krb5_context ctx, const char *secret, const krad_packet *pkt,
const uint8_t auth[AUTH_FIELD_SIZE],
uint8_t mac_out[MD5_DIGEST_SIZE])
{
@@ -288,6 +288,10 @@ calculate_mac(const char *secret, const krad_packet *pkt,
krb5_crypto_iov input[5];
krb5_data ksecr, mac;
+ /* Do not use HMAC-MD5 if not explicitly allowed */
+ if (kr_use_fips(ctx))
+ return KRB5_CRYPTO_INTERNAL;
+
msgauth_attr = lookup_msgauth_addr(pkt);
if (msgauth_attr == NULL)
return EINVAL;
@@ -393,7 +397,8 @@ krad_packet_new_request(krb5_context ctx, const char *secret, krad_code code,
if (msgauth_required) {
/* Calculate and set the Message-Authenticator MAC. */
- retval = calculate_mac(secret, pkt, pkt_auth(pkt), pkt_attr(pkt) + 2);
+ retval = calculate_mac(ctx, secret, pkt, pkt_auth(pkt),
+ pkt_attr(pkt) + 2);
if (retval != 0)
goto error;
}
@@ -454,7 +459,7 @@ krad_packet_new_response(krb5_context ctx, const char *secret, krad_code code,
* section 5.14, use the authenticator from the request, not from the
* response.
*/
- retval = calculate_mac(secret, pkt, pkt_auth(request),
+ retval = calculate_mac(ctx, secret, pkt, pkt_auth(request),
pkt_attr(pkt) + 2);
if (retval != 0)
goto error;
@@ -476,7 +481,7 @@ error:
/* Verify the Message-Authenticator value in pkt, using the provided
* authenticator (which may be from pkt or from a corresponding request). */
static krb5_error_code
-verify_msgauth(const char *secret, const krad_packet *pkt,
+verify_msgauth(krb5_context ctx, const char *secret, const krad_packet *pkt,
const uint8_t auth[AUTH_FIELD_SIZE])
{
uint8_t mac[MD5_DIGEST_SIZE];
@@ -488,7 +493,7 @@ verify_msgauth(const char *secret, const krad_packet *pkt,
if (msgauth == NULL)
return ENODATA;
- retval = calculate_mac(secret, pkt, auth, mac);
+ retval = calculate_mac(ctx, secret, pkt, auth, mac);
if (retval)
return retval;
@@ -561,7 +566,7 @@ krad_packet_decode_request(krb5_context ctx, const char *secret,
/* Verify Message-Authenticator if present. */
if (has_pkt_msgauth(req)) {
- retval = verify_msgauth(secret, req, pkt_auth(req));
+ retval = verify_msgauth(ctx, secret, req, pkt_auth(req));
if (retval) {
krad_packet_free(req);
return retval;
@@ -613,7 +618,7 @@ krad_packet_decode_response(krb5_context ctx, const char *secret,
/* Verify Message-Authenticator if present. */
if (has_pkt_msgauth(*rsppkt)) {
- if (verify_msgauth(secret, *rsppkt, pkt_auth(tmp)) != 0)
+ if (verify_msgauth(ctx, secret, *rsppkt, pkt_auth(tmp)) != 0)
continue;
}
--
2.49.0

View file

@ -1,189 +0,0 @@
From 1761e06398e4f043e4f540f57131c37fcc53a1b9 Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <abokovoy@redhat.com>
Date: Wed, 10 Dec 2025 10:42:02 +0200
Subject: [PATCH] Fix strchr() conformance to C23
C23 7.28.5.1 specifies search functions such as strchr() as generic,
returning const char * if the first argument is of type const char *.
Fix uses of strchr() to conform to this change.
[jrische@redhat.com: altered changes to avoid casts; fixed an
additional case]
[ghudson@mit.edu: condensed some declarations; rewrote commit message]
ticket: 9191 (new)
(cherry picked from commit 6cd8580d823585d50ee4f30efd9f7e855823a369)
---
src/lib/krb5/ccache/ccbase.c | 4 ++--
src/lib/krb5/os/expand_path.c | 3 ++-
src/lib/krb5/os/locate_kdc.c | 15 +++++++--------
src/plugins/preauth/pkinit/pkinit_crypto.h | 2 +-
.../preauth/pkinit/pkinit_crypto_openssl.c | 6 +++---
src/plugins/preauth/pkinit/pkinit_identity.c | 2 +-
src/plugins/preauth/pkinit/pkinit_matching.c | 2 +-
src/tests/responder.c | 3 +--
8 files changed, 18 insertions(+), 19 deletions(-)
diff --git a/src/lib/krb5/ccache/ccbase.c b/src/lib/krb5/ccache/ccbase.c
index 5a01320832..1aada91b5e 100644
--- a/src/lib/krb5/ccache/ccbase.c
+++ b/src/lib/krb5/ccache/ccbase.c
@@ -201,8 +201,8 @@ krb5_cc_register(krb5_context context, const krb5_cc_ops *ops,
krb5_error_code KRB5_CALLCONV
krb5_cc_resolve (krb5_context context, const char *name, krb5_ccache *cache)
{
- char *pfx, *cp;
- const char *resid;
+ char *pfx;
+ const char *cp, *resid;
unsigned int pfxlen;
krb5_error_code err;
const krb5_cc_ops *ops;
diff --git a/src/lib/krb5/os/expand_path.c b/src/lib/krb5/os/expand_path.c
index 5cbccf08c8..6569b8820b 100644
--- a/src/lib/krb5/os/expand_path.c
+++ b/src/lib/krb5/os/expand_path.c
@@ -454,7 +454,8 @@ k5_expand_path_tokens_extra(krb5_context context, const char *path_in,
{
krb5_error_code ret;
struct k5buf buf;
- char *tok_begin, *tok_end, *tok_val, **extra_tokens = NULL, *path;
+ const char *tok_begin, *tok_end;
+ char *tok_val, **extra_tokens = NULL, *path;
const char *path_left;
size_t nargs = 0, i;
va_list ap;
diff --git a/src/lib/krb5/os/locate_kdc.c b/src/lib/krb5/os/locate_kdc.c
index edca5ac7eb..47e15c849f 100644
--- a/src/lib/krb5/os/locate_kdc.c
+++ b/src/lib/krb5/os/locate_kdc.c
@@ -188,8 +188,8 @@ oom:
}
static void
-parse_uri_if_https(const char *host_or_uri, k5_transport *transport,
- const char **host, const char **uri_path)
+parse_uri_if_https(char *host_or_uri, k5_transport *transport,
+ char **host, const char **uri_path)
{
char *cp;
@@ -229,8 +229,7 @@ locate_srv_conf_1(krb5_context context, const krb5_data *realm,
k5_transport transport, int udpport)
{
const char *realm_srv_names[4];
- char **hostlist = NULL, *realmstr = NULL, *host = NULL;
- const char *hostspec;
+ char **hostlist = NULL, *realmstr = NULL, *host = NULL, *hostspec;
krb5_error_code code;
int i, default_port;
@@ -535,8 +534,8 @@ prof_locate_server(krb5_context context, const krb5_data *realm,
* Return a NULL *host_out if there are any problems parsing the URI.
*/
static void
-parse_uri_fields(const char *uri, k5_transport *transport_out,
- const char **host_out, int *primary_out)
+parse_uri_fields(char *uri, k5_transport *transport_out,
+ char **host_out, int *primary_out)
{
k5_transport transport;
@@ -604,8 +603,8 @@ locate_uri(krb5_context context, const krb5_data *realm,
krb5_error_code ret;
k5_transport transport, host_trans;
struct srv_dns_entry *answers, *entry;
- char *host;
- const char *host_field, *path;
+ char *host, *host_field;
+ const char *path;
int port, def_port, primary;
ret = k5_make_uri_query(context, realm, req_service, &answers);
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto.h b/src/plugins/preauth/pkinit/pkinit_crypto.h
index 3b12e904b1..99e2394040 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto.h
+++ b/src/plugins/preauth/pkinit/pkinit_crypto.h
@@ -456,7 +456,7 @@ krb5_error_code crypto_load_cas_and_crls
defines the storage type (file, directory, etc) */
int catype, /* IN
defines the ca type (anchor, intermediate, crls) */
- char *id); /* IN
+ const char *id); /* IN
defines the location (filename, directory name, etc) */
/*
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
index 429b7d202c..6013080afc 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
@@ -4956,7 +4956,7 @@ load_cas_and_crls(krb5_context context,
pkinit_req_crypto_context req_cryptoctx,
pkinit_identity_crypto_context id_cryptoctx,
int catype,
- char *filename)
+ const char *filename)
{
STACK_OF(X509_INFO) *sk = NULL;
STACK_OF(X509) *ca_certs = NULL;
@@ -5114,7 +5114,7 @@ load_cas_and_crls_dir(krb5_context context,
pkinit_req_crypto_context req_cryptoctx,
pkinit_identity_crypto_context id_cryptoctx,
int catype,
- char *dirname)
+ const char *dirname)
{
krb5_error_code retval = EINVAL;
DIR *d = NULL;
@@ -5166,7 +5166,7 @@ crypto_load_cas_and_crls(krb5_context context,
pkinit_identity_crypto_context id_cryptoctx,
int idtype,
int catype,
- char *id)
+ const char *id)
{
switch (idtype) {
case IDTYPE_FILE:
diff --git a/src/plugins/preauth/pkinit/pkinit_identity.c b/src/plugins/preauth/pkinit/pkinit_identity.c
index a5a979f279..b06d519c66 100644
--- a/src/plugins/preauth/pkinit/pkinit_identity.c
+++ b/src/plugins/preauth/pkinit/pkinit_identity.c
@@ -474,7 +474,7 @@ process_option_ca_crl(krb5_context context,
const char *value,
int catype)
{
- char *residual;
+ const char *residual;
unsigned int typelen;
int idtype;
diff --git a/src/plugins/preauth/pkinit/pkinit_matching.c b/src/plugins/preauth/pkinit/pkinit_matching.c
index b42485a50a..5a7f2ba3fa 100644
--- a/src/plugins/preauth/pkinit/pkinit_matching.c
+++ b/src/plugins/preauth/pkinit/pkinit_matching.c
@@ -263,7 +263,7 @@ parse_rule_component(krb5_context context,
char err_buf[128];
int ret;
struct keyword_desc *kw, *nextkw;
- char *nk;
+ const char *nk;
int found_next_kw = 0;
char *value = NULL;
size_t len;
diff --git a/src/tests/responder.c b/src/tests/responder.c
index 82f870ea5d..4221a20283 100644
--- a/src/tests/responder.c
+++ b/src/tests/responder.c
@@ -282,8 +282,7 @@ responder(krb5_context ctx, void *rawdata, krb5_responder_context rctx)
/* Provide a particular response for an OTP challenge. */
if (data->otp_answer != NULL) {
if (krb5_responder_otp_get_challenge(ctx, rctx, &ochl) == 0) {
- key = strchr(data->otp_answer, '=');
- if (key != NULL) {
+ if (strchr(data->otp_answer, '=') != NULL) {
/* Make a copy of the answer that we can chop up. */
key = strdup(data->otp_answer);
if (key == NULL)
--
2.51.1

View file

@ -1,226 +0,0 @@
From 3baf9b93dc1dfe38585722c71d7268304cb4a01a Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <abokovoy@redhat.com>
Date: Sun, 21 Sep 2025 11:14:51 +0300
Subject: libkrb5: in case PKINIT is configured, attempt Anonymous
PKINIT for FAST
If auto_fast_armor is configured for the realm or globally, optimistically
assume that Anonymous PKINIT is supported as well and try to obtain it for
FAST use in case no pre-made FAST channel was established by the caller.
This behavior will automatically enable use of passwordless pre-authentication
methods which rely on FAST channel presence in deployments such as FreeIPA.
Notably, Microsoft Active Directory KDCs do not support Anonymous PKINIT. For
these deployments only a machine account (host keytab) can be used to build a
FAST channel. However, libkrb5 does not have access to /etc/krb5.keytab in a
general case.
Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
---
src/lib/krb5/krb/fast.c | 118 ++++++++++++++++++++++++++++++++++++++++
src/lib/krb5/krb/fast.h | 2 +
src/man/krb5.conf.man | 13 +++++
3 files changed, 133 insertions(+)
diff --git a/src/lib/krb5/krb/fast.c b/src/lib/krb5/krb/fast.c
index 62c9f0841..ee2e08189 100644
--- a/src/lib/krb5/krb/fast.c
+++ b/src/lib/krb5/krb/fast.c
@@ -168,6 +168,109 @@ krb5int_fast_prep_req_body(krb5_context context,
return retval;
}
+static krb5_boolean
+fast_is_pkinit_allowed(krb5_context context, krb5_data *realm)
+{
+ int value;
+ krb5_error_code retval = EINVAL;
+ char realmstr[1024];
+ const char *option = "auto_fast_armor";
+ const int def_value = FALSE;
+
+ if (realm != NULL && realm->length > sizeof(realmstr)-1)
+ return FALSE;
+
+ if (realm != NULL) {
+ strncpy(realmstr, realm->data, realm->length);
+ realmstr[realm->length] = '\0';
+
+ retval = profile_get_boolean(context->profile,
+ KRB5_CONF_REALMS, realmstr,
+ option, def_value, &value);
+ }
+
+ return retval ? FALSE : value;
+
+}
+
+static krb5_error_code
+fast_acquire_pkinit_armor(krb5_context context,
+ struct krb5int_fast_request_state *state,
+ krb5_get_init_creds_opt *opt, krb5_kdc_req *request)
+{
+ krb5_context ctx;
+ krb5_get_init_creds_opt *options = NULL;
+ krb5_error_code retval = 0;
+ krb5_data *target_realm = &request->server->realm;
+ krb5_creds creds;
+ krb5_principal anon_princ = NULL;
+ krb5_ccache out_cc;
+
+ /* short circuit, we are asked to perform Anonymous PKINIT already */
+ if (opt->flags & KRB5_GET_INIT_CREDS_OPT_ANONYMOUS) {
+ return EINVAL;
+ }
+
+ /* skip realms which do not allow use of automated FAST armor */
+ if (!fast_is_pkinit_allowed(context, target_realm)) {
+ return EINVAL;
+ }
+
+ retval = krb5_init_context(&ctx);
+ if (retval != 0) {
+ return retval;
+ }
+ retval = krb5_get_init_creds_opt_alloc(ctx, &options);
+ if (retval != 0) {
+ goto cleanup;
+ }
+ krb5_get_init_creds_opt_set_anonymous(options, 1);
+ retval = krb5_cc_new_unique(ctx, "MEMORY", NULL, &out_cc);
+ if (retval != 0) {
+ goto cleanup;
+ }
+
+ retval = krb5_get_init_creds_opt_set_out_ccache(ctx, options, out_cc);
+ if (retval != 0) {
+ goto cleanup;
+ }
+
+ retval = krb5_build_principal_ext(ctx, &anon_princ,
+ target_realm->length, target_realm->data,
+ strlen(KRB5_WELLKNOWN_NAMESTR),
+ KRB5_WELLKNOWN_NAMESTR,
+ strlen(KRB5_ANONYMOUS_PRINCSTR),
+ KRB5_ANONYMOUS_PRINCSTR, 0);
+ if (retval != 0) {
+ goto cleanup;
+ }
+
+ retval = krb5_get_init_creds_password(ctx, &creds, anon_princ, 0,
+ NULL /* no prompter */, NULL,
+ 0, NULL /* service name */,
+ options);
+ if (retval == 0) {
+ state->fast_state_flags |= KRB5INT_FAST_OWN_ARMOR;
+ state->armor_ccache = out_cc;
+ }
+cleanup:
+ if (retval != 0 && out_cc != NULL) {
+ (void) krb5_cc_destroy(ctx, out_cc);
+ }
+ if (retval == 0) {
+ krb5_free_cred_contents(ctx, &creds);
+ }
+ if (options != NULL) {
+ krb5_get_init_creds_opt_free(ctx, options);
+ }
+ if (anon_princ != NULL) {
+ krb5_free_principal(ctx, anon_princ);
+ }
+ krb5_free_context(ctx);
+
+ return retval;
+}
+
krb5_error_code
krb5int_fast_as_armor(krb5_context context,
struct krb5int_fast_request_state *state,
@@ -178,10 +281,20 @@ krb5int_fast_as_armor(krb5_context context,
krb5_principal target_principal = NULL;
krb5_data *target_realm;
const char *ccname = k5_gic_opt_get_fast_ccache_name(opt);
+ char *fast_ccname = NULL;
krb5_flags fast_flags;
krb5_clear_error_message(context);
target_realm = &request->server->realm;
+ if (ccname == NULL) {
+ retval = fast_acquire_pkinit_armor(context, state, opt, request);
+ if (retval == 0) {
+ retval = krb5_cc_get_full_name(context, state->armor_ccache, &fast_ccname);
+ if (retval == 0 && fast_ccname != NULL)
+ ccname = fast_ccname;
+ }
+ retval = 0;
+ }
if (ccname != NULL) {
TRACE_FAST_ARMOR_CCACHE(context, ccname);
state->fast_state_flags |= KRB5INT_FAST_ARMOR_AVAIL;
@@ -220,6 +333,8 @@ krb5int_fast_as_armor(krb5_context context,
krb5_cc_close(context, ccache);
if (target_principal)
krb5_free_principal(context, target_principal);
+ if (fast_ccname)
+ free(fast_ccname);
return retval;
}
@@ -615,6 +730,9 @@ krb5int_fast_free_state(krb5_context context,
/*We are responsible for none of the store in the fast_outer_req*/
krb5_free_keyblock(context, state->armor_key);
krb5_free_fast_armor(context, state->armor);
+ if (state->fast_state_flags & KRB5INT_FAST_OWN_ARMOR) {
+ krb5_cc_destroy(context, state->armor_ccache);
+ }
free(state);
}
diff --git a/src/lib/krb5/krb/fast.h b/src/lib/krb5/krb/fast.h
index 7156ea203..e5fe8bd54 100644
--- a/src/lib/krb5/krb/fast.h
+++ b/src/lib/krb5/krb/fast.h
@@ -34,6 +34,7 @@ struct krb5int_fast_request_state {
krb5_kdc_req fast_outer_request;
krb5_keyblock *armor_key; /*non-null means fast is in use*/
krb5_fast_armor *armor;
+ krb5_ccache armor_ccache;
krb5_ui_4 fast_state_flags;
krb5_ui_4 fast_options;
krb5_int32 nonce;
@@ -41,6 +42,7 @@ struct krb5int_fast_request_state {
#define KRB5INT_FAST_DO_FAST (1l<<0) /* Perform FAST */
#define KRB5INT_FAST_ARMOR_AVAIL (1l<<1)
+#define KRB5INT_FAST_OWN_ARMOR (1l<<2)
krb5_error_code
krb5int_fast_prep_req_body(krb5_context context,
diff --git a/src/man/krb5.conf.man b/src/man/krb5.conf.man
index d4caa2bd3..ac7649647 100644
--- a/src/man/krb5.conf.man
+++ b/src/man/krb5.conf.man
@@ -650,6 +650,19 @@ primary KDC, in case the user\(aqs password has just been changed, and
the updated database has not been propagated to the replica
servers yet. New in release 1.19.
.TP
+\fBauto_fast_armor\fP
+If this flag is true, then initial ticket request will use Anonymous
+PKINIT to protect the communication as a FAST channel in case an application
+did not provide its own FAST channel. This is useful for deployments where
+pre-authentication methods require use of the FAST channel, such as
+passwordless methods provided by FreeIPA. Microsoft Active Directory
+implementation of PKINIT does not support Anonymous PKINIT feature.
+As a result, \fIauto_fast_armor\fP defaults to false.
+.sp
+Use of \fIauto_fast_armor = true\fP requires properly configured PKINIT and
+WELLKNOWN/ANONYMOUS principal defined on the KDC side. Consult KDC documentation
+for details.
+.TP
\fBv4_instance_convert\fP
This subsection allows the administrator to configure exceptions
to the \fBdefault_domain\fP mapping rule. It contains V4 instances
--
2.51.0

View file

@ -1,40 +0,0 @@
From ff580d9cf86202d45454a6b6f53accc22cb40b62 Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <abokovoy@redhat.com>
Date: Sun, 19 Oct 2025 18:14:29 +0300
Subject: [PATCH] bail if prompter is not specified but required
GSSAPI gss_init_sec_context() may trigger credential re-initialization
if the cred in ccache is expired. If automatic FAST armor is in use,
we'd request Anonymous PKINIT and use it as an armor and this will
enable seeing pre-authentication methods which require armor presence.
OTP is one of such methods and its use requires prompter to be set,
but GSSAPI cannot specify a prompter and thus we should fail any
pre-auth where a prompter wasn't passed.
PKINIT PKCS11 and SAM-2 preauth methods use KRB5_LIBOS_CANTREADPWD while PKINIT
and gic_pwd.c use EIO. Use EIO here because we technically attempt to read a
PIN rather than a password.
Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
---
src/lib/krb5/krb/preauth_otp.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/lib/krb5/krb/preauth_otp.c b/src/lib/krb5/krb/preauth_otp.c
index 07ffc15c2..48003da62 100644
--- a/src/lib/krb5/krb/preauth_otp.c
+++ b/src/lib/krb5/krb/preauth_otp.c
@@ -479,6 +479,9 @@ doprompt(krb5_context context, krb5_prompter_fct prompter, void *prompter_data,
krb5_error_code retval;
krb5_prompt_type prompt_type = KRB5_PROMPT_TYPE_PREAUTH;
+ if (prompter == NULL)
+ return EIO;
+
if (prompttxt == NULL || out == NULL)
return EINVAL;
--
2.51.0

202
2010-007-patch.txt Normal file
View file

@ -0,0 +1,202 @@
Index: krb5-1.8/src/plugins/preauth/pkinit/pkinit_srv.c
===================================================================
--- krb5-1.8/src/plugins/preauth/pkinit/pkinit_srv.c (revision 24455)
+++ krb5-1.8/src/plugins/preauth/pkinit/pkinit_srv.c (working copy)
@@ -691,8 +691,7 @@
krb5_reply_key_pack *key_pack = NULL;
krb5_reply_key_pack_draft9 *key_pack9 = NULL;
krb5_data *encoded_key_pack = NULL;
- unsigned int num_types;
- krb5_cksumtype *cksum_types = NULL;
+ krb5_cksumtype cksum_type;
pkinit_kdc_context plgctx;
pkinit_kdc_req_context reqctx;
@@ -882,14 +881,25 @@
retval = ENOMEM;
goto cleanup;
}
- /* retrieve checksums for a given enctype of the reply key */
- retval = krb5_c_keyed_checksum_types(context,
- encrypting_key->enctype, &num_types, &cksum_types);
- if (retval)
- goto cleanup;
- /* pick the first of acceptable enctypes for the checksum */
- retval = krb5_c_make_checksum(context, cksum_types[0],
+ switch (encrypting_key->enctype) {
+ case ENCTYPE_DES_CBC_MD4:
+ cksum_type = CKSUMTYPE_RSA_MD4_DES;
+ break;
+ case ENCTYPE_DES_CBC_MD5:
+ case ENCTYPE_DES_CBC_CRC:
+ cksum_type = CKSUMTYPE_RSA_MD5_DES;
+ break;
+ default:
+ retval = krb5int_c_mandatory_cksumtype(context,
+ encrypting_key->enctype,
+ &cksum_type);
+ if (retval)
+ goto cleanup;
+ break;
+ }
+
+ retval = krb5_c_make_checksum(context, cksum_type,
encrypting_key, KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM,
req_pkt, &key_pack->asChecksum);
if (retval) {
@@ -1033,7 +1043,6 @@
krb5_free_data(context, encoded_key_pack);
free(dh_pubkey);
free(server_key);
- free(cksum_types);
switch ((int)padata->pa_type) {
case KRB5_PADATA_PK_AS_REQ:
Index: krb5-1.8/src/lib/crypto/krb/cksumtypes.c
===================================================================
--- krb5-1.8/src/lib/crypto/krb/cksumtypes.c (revision 24455)
+++ krb5-1.8/src/lib/crypto/krb/cksumtypes.c (working copy)
@@ -101,7 +101,7 @@
{ CKSUMTYPE_MD5_HMAC_ARCFOUR,
"md5-hmac-rc4", { 0 }, "Microsoft MD5 HMAC",
- NULL, &krb5int_hash_md5,
+ &krb5int_enc_arcfour, &krb5int_hash_md5,
krb5int_hmacmd5_checksum, NULL,
16, 16, 0 },
};
Index: krb5-1.8/src/lib/crypto/krb/keyed_checksum_types.c
===================================================================
--- krb5-1.8/src/lib/crypto/krb/keyed_checksum_types.c (revision 24455)
+++ krb5-1.8/src/lib/crypto/krb/keyed_checksum_types.c (working copy)
@@ -35,6 +35,13 @@
{
if (ctp->flags & CKSUM_UNKEYED)
return FALSE;
+ /* Stream ciphers do not play well with RFC 3961 key derivation, so be
+ * conservative with RC4. */
+ if ((ktp->etype == ENCTYPE_ARCFOUR_HMAC ||
+ ktp->etype == ENCTYPE_ARCFOUR_HMAC_EXP) &&
+ ctp->ctype != CKSUMTYPE_HMAC_MD5_ARCFOUR &&
+ ctp->ctype != CKSUMTYPE_MD5_HMAC_ARCFOUR)
+ return FALSE;
return (!ctp->enc || ktp->enc == ctp->enc);
}
Index: krb5-1.8/src/lib/crypto/krb/dk/derive.c
===================================================================
--- krb5-1.8/src/lib/crypto/krb/dk/derive.c (revision 24455)
+++ krb5-1.8/src/lib/crypto/krb/dk/derive.c (working copy)
@@ -91,6 +91,8 @@
blocksize = enc->block_size;
keybytes = enc->keybytes;
+ if (blocksize == 1)
+ return KRB5_BAD_ENCTYPE;
if (inkey->keyblock.length != enc->keylength || outrnd->length != keybytes)
return KRB5_CRYPTO_INTERNAL;
Index: krb5-1.8/src/lib/gssapi/krb5/util_crypt.c
===================================================================
--- krb5-1.8/src/lib/gssapi/krb5/util_crypt.c (revision 24455)
+++ krb5-1.8/src/lib/gssapi/krb5/util_crypt.c (working copy)
@@ -119,10 +119,22 @@
if (code != 0)
return code;
- code = (*kaccess.mandatory_cksumtype)(context, subkey->keyblock.enctype,
- cksumtype);
- if (code != 0)
- return code;
+ switch (subkey->keyblock.enctype) {
+ case ENCTYPE_DES_CBC_MD4:
+ *cksumtype = CKSUMTYPE_RSA_MD4_DES;
+ break;
+ case ENCTYPE_DES_CBC_MD5:
+ case ENCTYPE_DES_CBC_CRC:
+ *cksumtype = CKSUMTYPE_RSA_MD5_DES;
+ break;
+ default:
+ code = (*kaccess.mandatory_cksumtype)(context,
+ subkey->keyblock.enctype,
+ cksumtype);
+ if (code != 0)
+ return code;
+ break;
+ }
switch (subkey->keyblock.enctype) {
case ENCTYPE_DES_CBC_MD5:
Index: krb5-1.8/src/lib/krb5/krb/pac.c
===================================================================
--- krb5-1.8/src/lib/krb5/krb/pac.c (revision 24455)
+++ krb5-1.8/src/lib/krb5/krb/pac.c (working copy)
@@ -582,6 +582,8 @@
checksum.checksum_type = load_32_le(p);
checksum.length = checksum_data.length - PAC_SIGNATURE_DATA_LENGTH;
checksum.contents = p + PAC_SIGNATURE_DATA_LENGTH;
+ if (!krb5_c_is_keyed_cksum(checksum.checksum_type))
+ return KRB5KRB_AP_ERR_INAPP_CKSUM;
pac_data.length = pac->data.length;
pac_data.data = malloc(pac->data.length);
Index: krb5-1.8/src/lib/krb5/krb/preauth2.c
===================================================================
--- krb5-1.8/src/lib/krb5/krb/preauth2.c (revision 24455)
+++ krb5-1.8/src/lib/krb5/krb/preauth2.c (working copy)
@@ -1578,7 +1578,9 @@
cksum = sc2->sam_cksum;
- while (*cksum) {
+ for (; *cksum; cksum++) {
+ if (!krb5_c_is_keyed_cksum((*cksum)->checksum_type))
+ continue;
/* Check this cksum */
retval = krb5_c_verify_checksum(context, as_key,
KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM,
@@ -1592,7 +1594,6 @@
}
if (valid_cksum)
break;
- cksum++;
}
if (!valid_cksum) {
Index: krb5-1.8/src/lib/krb5/krb/mk_safe.c
===================================================================
--- krb5-1.8/src/lib/krb5/krb/mk_safe.c (revision 24455)
+++ krb5-1.8/src/lib/krb5/krb/mk_safe.c (working copy)
@@ -215,10 +215,28 @@
for (i = 0; i < nsumtypes; i++)
if (auth_context->safe_cksumtype == sumtypes[i])
break;
- if (i == nsumtypes)
- i = 0;
- sumtype = sumtypes[i];
krb5_free_cksumtypes (context, sumtypes);
+ if (i < nsumtypes)
+ sumtype = auth_context->safe_cksumtype;
+ else {
+ switch (enctype) {
+ case ENCTYPE_DES_CBC_MD4:
+ sumtype = CKSUMTYPE_RSA_MD4_DES;
+ break;
+ case ENCTYPE_DES_CBC_MD5:
+ case ENCTYPE_DES_CBC_CRC:
+ sumtype = CKSUMTYPE_RSA_MD5_DES;
+ break;
+ default:
+ retval = krb5int_c_mandatory_cksumtype(context, enctype,
+ &sumtype);
+ if (retval) {
+ CLEANUP_DONE();
+ goto error;
+ }
+ break;
+ }
+ }
}
if ((retval = krb5_mk_safe_basic(context, userdata, key, &replaydata,
plocal_fulladdr, premote_fulladdr,

9333
Add-German-translation.patch Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,994 @@
From 78a1f155701f94a228c4f58f98846195a39991c4 Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Tue, 27 Jun 2017 17:15:39 -0400
Subject: [PATCH] Add KDC policy pluggable interface
Add the header include/krb5/kdcpolicy_plugin.h, defining a pluggable
interface for modules to deny AS and TGS requests and set maximum
ticket lifetimes. This interface replaces the policy.c stub functions.
Add check_kdcpolicy_as() and check_kdcpolicy_tgs() as entry functions.
Call them after auth indicators and ticket lifetimes have been
determined.
Add a test module and a test script with basic kdcpolicy tests. Add
plugin interface documentation in doc/plugindev/policy.rst.
Also authored by Matt Rogers <mrogers@redhat.com>.
ticket: 8606 (new)
(cherry picked from commit d0969f6a8170344031ef58fd2a161190f1edfb96)
[rharwood@redhat.com: mention but do not use kadm_auth]
---
doc/plugindev/index.rst | 1 +
doc/plugindev/kdcpolicy.rst | 24 +++
src/Makefile.in | 1 +
src/configure.in | 1 +
src/include/Makefile.in | 1 +
src/include/k5-int.h | 4 +-
src/include/k5-trace.h | 5 +
src/include/krb5/kdcpolicy_plugin.h | 128 ++++++++++++
src/kdc/do_as_req.c | 7 +
src/kdc/do_tgs_req.c | 6 +
src/kdc/kdc_util.c | 7 -
src/kdc/kdc_util.h | 11 -
src/kdc/main.c | 8 +
src/kdc/policy.c | 267 +++++++++++++++++++++----
src/kdc/policy.h | 19 +-
src/kdc/tgs_policy.c | 6 -
src/lib/krb5/krb/plugin.c | 4 +-
src/plugins/kdcpolicy/test/Makefile.in | 20 ++
src/plugins/kdcpolicy/test/deps | 0
src/plugins/kdcpolicy/test/main.c | 111 ++++++++++
src/plugins/kdcpolicy/test/policy_test.exports | 1 +
src/tests/Makefile.in | 1 +
src/tests/t_kdcpolicy.py | 57 ++++++
23 files changed, 616 insertions(+), 74 deletions(-)
create mode 100644 doc/plugindev/kdcpolicy.rst
create mode 100644 src/include/krb5/kdcpolicy_plugin.h
create mode 100644 src/plugins/kdcpolicy/test/Makefile.in
create mode 100644 src/plugins/kdcpolicy/test/deps
create mode 100644 src/plugins/kdcpolicy/test/main.c
create mode 100644 src/plugins/kdcpolicy/test/policy_test.exports
create mode 100644 src/tests/t_kdcpolicy.py
diff --git a/doc/plugindev/index.rst b/doc/plugindev/index.rst
index 67dbc2790..0a012b82b 100644
--- a/doc/plugindev/index.rst
+++ b/doc/plugindev/index.rst
@@ -32,5 +32,6 @@ Contents
gssapi.rst
internal.rst
certauth.rst
+ kdcpolicy.rst
.. TODO: GSSAPI mechanism plugins
diff --git a/doc/plugindev/kdcpolicy.rst b/doc/plugindev/kdcpolicy.rst
new file mode 100644
index 000000000..74f21f08f
--- /dev/null
+++ b/doc/plugindev/kdcpolicy.rst
@@ -0,0 +1,24 @@
+.. _kdcpolicy_plugin:
+
+KDC policy interface (kdcpolicy)
+================================
+
+The kdcpolicy interface was first introduced in release 1.16. It
+allows modules to veto otherwise valid AS and TGS requests or restrict
+the lifetime and renew time of the resulting ticket. For a detailed
+description of the kdcpolicy interface, see the header file
+``<krb5/kdcpolicy_plugin.h>``.
+
+The optional **check_as** and **check_tgs** functions allow the module
+to perform access control. Additionally, a module can create and
+destroy module data with the **init** and **fini** methods. Module
+data objects last for the lifetime of the KDC process, and are
+provided to all other methods. The data has the type
+krb5_kdcpolicy_moddata, which should be cast to the appropriate
+internal type.
+
+kdcpolicy modules can optionally inspect principal entries. To do
+this, the module must also include ``<kdb.h>`` to gain access to the
+principal entry structure definition. As the KDB interface is
+explicitly not as stable as other public interfaces, modules which do
+this may not retain compatibility across releases.
diff --git a/src/Makefile.in b/src/Makefile.in
index ad8565056..e47bddcb1 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -21,6 +21,7 @@ SUBDIRS=util include lib \
plugins/kdb/db2 \
@ldap_plugin_dir@ \
plugins/kdb/test \
+ plugins/kdcpolicy/test \
plugins/preauth/otp \
plugins/preauth/pkinit \
plugins/preauth/test \
diff --git a/src/configure.in b/src/configure.in
index 4ae2c07d5..ee1983043 100644
--- a/src/configure.in
+++ b/src/configure.in
@@ -1470,6 +1470,7 @@ dnl ccapi ccapi/lib ccapi/lib/unix ccapi/server ccapi/server/unix ccapi/test
plugins/kdb/db2/libdb2/recno
plugins/kdb/db2/libdb2/test
plugins/kdb/test
+ plugins/kdcpolicy/test
plugins/preauth/otp
plugins/preauth/test
plugins/authdata/greet_client
diff --git a/src/include/Makefile.in b/src/include/Makefile.in
index 0239338a1..6a3fa8242 100644
--- a/src/include/Makefile.in
+++ b/src/include/Makefile.in
@@ -144,6 +144,7 @@ install-headers-unix install: krb5/krb5.h profile.h
$(INSTALL_DATA) $(srcdir)/krb5/ccselect_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)ccselect_plugin.h
$(INSTALL_DATA) $(srcdir)/krb5/clpreauth_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)clpreauth_plugin.h
$(INSTALL_DATA) $(srcdir)/krb5/hostrealm_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)hostrealm_plugin.h
+ $(INSTALL_DATA) $(srcdir)/krb5/kdcpolicy_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)kdcpolicy_plugin.h
$(INSTALL_DATA) $(srcdir)/krb5/kdcpreauth_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)kdcpreauth_plugin.h
$(INSTALL_DATA) $(srcdir)/krb5/localauth_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)localauth_plugin.h
$(INSTALL_DATA) $(srcdir)/krb5/locate_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)locate_plugin.h
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index ed9c7bf75..39ffb9568 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -1157,7 +1157,9 @@ struct plugin_interface {
#define PLUGIN_INTERFACE_TLS 8
#define PLUGIN_INTERFACE_KDCAUTHDATA 9
#define PLUGIN_INTERFACE_CERTAUTH 10
-#define PLUGIN_NUM_INTERFACES 11
+#define PLUGIN_INTERFACE_KADM5_AUTH 11
+#define PLUGIN_INTERFACE_KDCPOLICY 12
+#define PLUGIN_NUM_INTERFACES 13
/* Retrieve the plugin module of type interface_id and name modname,
* storing the result into module. */
diff --git a/src/include/k5-trace.h b/src/include/k5-trace.h
index c75e264e0..2885408a2 100644
--- a/src/include/k5-trace.h
+++ b/src/include/k5-trace.h
@@ -454,4 +454,9 @@ void krb5int_trace(krb5_context context, const char *fmt, ...);
#define TRACE_GET_CRED_VIA_TKT_EXT_RETURN(c, ret) \
TRACE(c, "Got cred; {kerr}", ret)
+#define TRACE_KDCPOLICY_VTINIT_FAIL(c, ret) \
+ TRACE(c, "KDC policy module failed to init vtable: {kerr}", ret)
+#define TRACE_KDCPOLICY_INIT_SKIP(c, name) \
+ TRACE(c, "kadm5_auth module {str} declined to initialize", name)
+
#endif /* K5_TRACE_H */
diff --git a/src/include/krb5/kdcpolicy_plugin.h b/src/include/krb5/kdcpolicy_plugin.h
new file mode 100644
index 000000000..c7592c5db
--- /dev/null
+++ b/src/include/krb5/kdcpolicy_plugin.h
@@ -0,0 +1,128 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* include/krb5/kdcpolicy_plugin.h - KDC policy plugin interface */
+/*
+ * Copyright (C) 2017 by 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.
+ *
+ * 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 HOLDER 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.
+ */
+
+/*
+ * Declarations for kdcpolicy plugin module implementors.
+ *
+ * The kdcpolicy pluggable interface currently has only one supported major
+ * version, which is 1. Major version 1 has a current minor version number of
+ * 1.
+ *
+ * kdcpolicy plugin modules should define a function named
+ * kdcpolicy_<modulename>_initvt, matching the signature:
+ *
+ * krb5_error_code
+ * kdcpolicy_modname_initvt(krb5_context context, int maj_ver, int min_ver,
+ * krb5_plugin_vtable vtable);
+ *
+ * The initvt function should:
+ *
+ * - Check that the supplied maj_ver number is supported by the module, or
+ * return KRB5_PLUGIN_VER_NOTSUPP if it is not.
+ *
+ * - Cast the vtable pointer as appropriate for maj_ver:
+ * maj_ver == 1: Cast to krb5_kdcpolicy_vtable
+ *
+ * - Initialize the methods of the vtable, stopping as appropriate for the
+ * supplied min_ver. Optional methods may be left uninitialized.
+ *
+ * Memory for the vtable is allocated by the caller, not by the module.
+ */
+
+#ifndef KRB5_POLICY_PLUGIN_H
+#define KRB5_POLICY_PLUGIN_H
+
+#include <krb5/krb5.h>
+
+/* Abstract module datatype. */
+typedef struct krb5_kdcpolicy_moddata_st *krb5_kdcpolicy_moddata;
+
+/* A module can optionally include kdb.h to inspect principal entries when
+ * authorizing requests. */
+struct _krb5_db_entry_new;
+
+/*
+ * Optional: Initialize module data. Return 0 on success,
+ * KRB5_PLUGIN_NO_HANDLE if the module is inoperable (due to configuration, for
+ * example), and any other error code to abort KDC startup. Optionally set
+ * *data_out to a module data object to be passed to future calls.
+ */
+typedef krb5_error_code
+(*krb5_kdcpolicy_init_fn)(krb5_context context,
+ krb5_kdcpolicy_moddata *data_out);
+
+/* Optional: Clean up module data. */
+typedef krb5_error_code
+(*krb5_kdcpolicy_fini_fn)(krb5_context context,
+ krb5_kdcpolicy_moddata moddata);
+
+/*
+ * Optional: return an error code and set status to an appropriate string
+ * literal to deny an AS request; otherwise return 0. lifetime_out, if set,
+ * restricts the ticket lifetime. renew_lifetime_out, if set, restricts the
+ * ticket renewable lifetime.
+ */
+typedef krb5_error_code
+(*krb5_kdcpolicy_check_as_fn)(krb5_context context,
+ krb5_kdcpolicy_moddata moddata,
+ const krb5_kdc_req *request,
+ const struct _krb5_db_entry_new *client,
+ const struct _krb5_db_entry_new *server,
+ const char *const *auth_indicators,
+ const char **status, krb5_deltat *lifetime_out,
+ krb5_deltat *renew_lifetime_out);
+
+/*
+ * Optional: return an error code and set status to an appropriate string
+ * literal to deny a TGS request; otherwise return 0. lifetime_out, if set,
+ * restricts the ticket lifetime. renew_lifetime_out, if set, restricts the
+ * ticket renewable lifetime.
+ */
+typedef krb5_error_code
+(*krb5_kdcpolicy_check_tgs_fn)(krb5_context context,
+ krb5_kdcpolicy_moddata moddata,
+ const krb5_kdc_req *request,
+ const struct _krb5_db_entry_new *server,
+ const krb5_ticket *ticket,
+ const char *const *auth_indicators,
+ const char **status, krb5_deltat *lifetime_out,
+ krb5_deltat *renew_lifetime_out);
+
+typedef struct krb5_kdcpolicy_vtable_st {
+ const char *name;
+ krb5_kdcpolicy_init_fn init;
+ krb5_kdcpolicy_fini_fn fini;
+ krb5_kdcpolicy_check_as_fn check_as;
+ krb5_kdcpolicy_check_tgs_fn check_tgs;
+} *krb5_kdcpolicy_vtable;
+
+#endif /* KRB5_POLICY_PLUGIN_H */
diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c
index f85da6da6..f5cf8ad89 100644
--- a/src/kdc/do_as_req.c
+++ b/src/kdc/do_as_req.c
@@ -207,6 +207,13 @@ finish_process_as_req(struct as_req_state *state, krb5_error_code errcode)
state->ticket_reply.enc_part2 = &state->enc_tkt_reply;
+ errcode = check_kdcpolicy_as(kdc_context, state->request, state->client,
+ state->server, state->auth_indicators,
+ state->kdc_time, &state->enc_tkt_reply.times,
+ &state->status);
+ if (errcode)
+ goto egress;
+
/*
* Find the server key
*/
diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c
index ac5864603..0009a9319 100644
--- a/src/kdc/do_tgs_req.c
+++ b/src/kdc/do_tgs_req.c
@@ -518,6 +518,12 @@ process_tgs_req(struct server_handle *handle, krb5_data *pkt,
kdc_get_ticket_renewtime(kdc_active_realm, request, header_enc_tkt, client,
server, &enc_tkt_reply);
+ errcode = check_kdcpolicy_tgs(kdc_context, request, server, header_ticket,
+ auth_indicators, kdc_time,
+ &enc_tkt_reply.times, &status);
+ if (errcode)
+ goto cleanup;
+
/*
* Set authtime to be the same as header or evidence ticket's
*/
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
index b710aefe4..5455e2a67 100644
--- a/src/kdc/kdc_util.c
+++ b/src/kdc/kdc_util.c
@@ -642,7 +642,6 @@ validate_as_request(kdc_realm_t *kdc_active_realm,
krb5_db_entry server, krb5_timestamp kdc_time,
const char **status, krb5_pa_data ***e_data)
{
- int errcode;
krb5_error_code ret;
/*
@@ -750,12 +749,6 @@ validate_as_request(kdc_realm_t *kdc_active_realm,
if (ret && ret != KRB5_PLUGIN_OP_NOTSUPP)
return errcode_to_protocol(ret);
- /* Check against local policy. */
- errcode = against_local_policy_as(request, client, server,
- kdc_time, status, e_data);
- if (errcode)
- return errcode;
-
return 0;
}
diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h
index 672f94380..dcedfd538 100644
--- a/src/kdc/kdc_util.h
+++ b/src/kdc/kdc_util.h
@@ -166,17 +166,6 @@ kdc_err(krb5_context call_context, errcode_t code, const char *fmt, ...)
#endif
;
-/* policy.c */
-int
-against_local_policy_as (krb5_kdc_req *, krb5_db_entry,
- krb5_db_entry, krb5_timestamp,
- const char **, krb5_pa_data ***);
-
-int
-against_local_policy_tgs (krb5_kdc_req *, krb5_db_entry,
- krb5_ticket *, const char **,
- krb5_pa_data ***);
-
/* kdc_preauth.c */
krb5_boolean
enctype_requires_etype_info_2(krb5_enctype enctype);
diff --git a/src/kdc/main.c b/src/kdc/main.c
index a4dffb29a..ccac3a759 100644
--- a/src/kdc/main.c
+++ b/src/kdc/main.c
@@ -31,6 +31,7 @@
#include "kdc_util.h"
#include "kdc_audit.h"
#include "extern.h"
+#include "policy.h"
#include "kdc5_err.h"
#include "kdb_kt.h"
#include "net-server.h"
@@ -986,6 +987,12 @@ int main(int argc, char **argv)
load_preauth_plugins(&shandle, kcontext, ctx);
load_authdata_plugins(kcontext);
+ retval = load_kdcpolicy_plugins(kcontext);
+ if (retval) {
+ kdc_err(kcontext, retval, _("while loading KDC policy plugin"));
+ finish_realms();
+ return 1;
+ }
retval = setup_sam();
if (retval) {
@@ -1068,6 +1075,7 @@ int main(int argc, char **argv)
krb5_klog_syslog(LOG_INFO, _("shutting down"));
unload_preauth_plugins(kcontext);
unload_authdata_plugins(kcontext);
+ unload_kdcpolicy_plugins(kcontext);
unload_audit_modules(kcontext);
krb5_klog_close(kcontext);
finish_realms();
diff --git a/src/kdc/policy.c b/src/kdc/policy.c
index 6cba4303f..e49644e06 100644
--- a/src/kdc/policy.c
+++ b/src/kdc/policy.c
@@ -1,67 +1,246 @@
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/* kdc/policy.c - Policy decision routines for KDC */
/*
- * Copyright 1990 by the Massachusetts Institute of Technology.
+ * Copyright (C) 2017 by Red Hat, Inc.
+ * All rights reserved.
*
- * Export of this software from the United States of America may
- * require a specific license from the United States Government.
- * It is the responsibility of any person or organization contemplating
- * export to obtain such a license before exporting.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
*
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission. Furthermore if you modify this software you must label
- * your software as modified software and not distribute it in such a
- * fashion that it might be confused with the original M.I.T. software.
- * M.I.T. makes no representations about the suitability of
- * this software for any purpose. It is provided "as is" without express
- * or implied warranty.
+ * * 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.
+ *
+ * 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 HOLDER 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.
*/
#include "k5-int.h"
#include "kdc_util.h"
#include "extern.h"
+#include "policy.h"
+#include "adm_proto.h"
+#include <krb5/kdcpolicy_plugin.h>
+#include <syslog.h>
-int
-against_local_policy_as(register krb5_kdc_req *request, krb5_db_entry client,
- krb5_db_entry server, krb5_timestamp kdc_time,
- const char **status, krb5_pa_data ***e_data)
+typedef struct kdcpolicy_handle_st {
+ struct krb5_kdcpolicy_vtable_st vt;
+ krb5_kdcpolicy_moddata moddata;
+} *kdcpolicy_handle;
+
+static kdcpolicy_handle *handles;
+
+static void
+free_indicators(char **ais)
{
-#if 0
- /* An AS request must include the addresses field */
- if (request->addresses == 0) {
- *status = "NO ADDRESS";
- return KRB5KDC_ERR_POLICY;
- }
-#endif
+ size_t i;
- return 0; /* not against policy */
+ if (ais == NULL)
+ return;
+ for (i = 0; ais[i] != NULL; i++)
+ free(ais[i]);
+ free(ais);
+}
+
+/* Convert inds to a null-terminated list of C strings. */
+static krb5_error_code
+authind_strings(krb5_data *const *inds, char ***strs_out)
+{
+ krb5_error_code ret;
+ char **list = NULL;
+ size_t i, count;
+
+ *strs_out = NULL;
+
+ for (count = 0; inds != NULL && inds[count] != NULL; count++);
+ list = k5calloc(count + 1, sizeof(*list), &ret);
+ if (list == NULL)
+ goto error;
+
+ for (i = 0; i < count; i++) {
+ list[i] = k5memdup0(inds[i]->data, inds[i]->length, &ret);
+ if (list[i] == NULL)
+ goto error;
+ }
+
+ *strs_out = list;
+ return 0;
+
+error:
+ free_indicators(list);
+ return ret;
+}
+
+/* Constrain times->endtime to life and times->renew_till to rlife, relative to
+ * now. */
+static void
+update_ticket_times(krb5_ticket_times *times, krb5_timestamp now,
+ krb5_deltat life, krb5_deltat rlife)
+{
+ if (life)
+ times->endtime = ts_min(ts_incr(now, life), times->endtime);
+ if (rlife)
+ times->renew_till = ts_min(ts_incr(now, rlife), times->renew_till);
+}
+
+/* Check an AS request against kdcpolicy modules, updating times with any
+ * module endtime constraints. Set an appropriate status string on error. */
+krb5_error_code
+check_kdcpolicy_as(krb5_context context, const krb5_kdc_req *request,
+ const krb5_db_entry *client, const krb5_db_entry *server,
+ krb5_data *const *auth_indicators, krb5_timestamp kdc_time,
+ krb5_ticket_times *times, const char **status)
+{
+ krb5_deltat life, rlife;
+ krb5_error_code ret;
+ kdcpolicy_handle *hp, h;
+ char **ais = NULL;
+
+ *status = NULL;
+
+ ret = authind_strings(auth_indicators, &ais);
+ if (ret)
+ goto done;
+
+ for (hp = handles; *hp != NULL; hp++) {
+ h = *hp;
+ if (h->vt.check_as == NULL)
+ continue;
+
+ ret = h->vt.check_as(context, h->moddata, request, client, server,
+ (const char **)ais, status, &life, &rlife);
+ if (ret)
+ goto done;
+
+ update_ticket_times(times, kdc_time, life, rlife);
+ }
+
+done:
+ free_indicators(ais);
+ return ret;
}
/*
- * This is where local policy restrictions for the TGS should placed.
+ * Check the TGS request against the local TGS policy. Accepts an
+ * authentication indicator for the module policy decisions. Returns 0 and a
+ * NULL status string on success.
*/
krb5_error_code
-against_local_policy_tgs(register krb5_kdc_req *request, krb5_db_entry server,
- krb5_ticket *ticket, const char **status,
- krb5_pa_data ***e_data)
+check_kdcpolicy_tgs(krb5_context context, const krb5_kdc_req *request,
+ const krb5_db_entry *server, const krb5_ticket *ticket,
+ krb5_data *const *auth_indicators, krb5_timestamp kdc_time,
+ krb5_ticket_times *times, const char **status)
{
-#if 0
- /*
- * For example, if your site wants to disallow ticket forwarding,
- * you might do something like this:
- */
+ krb5_deltat life, rlife;
+ krb5_error_code ret;
+ kdcpolicy_handle *hp, h;
+ char **ais = NULL;
- if (isflagset(request->kdc_options, KDC_OPT_FORWARDED)) {
- *status = "FORWARD POLICY";
- return KRB5KDC_ERR_POLICY;
+ *status = NULL;
+
+ ret = authind_strings(auth_indicators, &ais);
+ if (ret)
+ goto done;
+
+ for (hp = handles; *hp != NULL; hp++) {
+ h = *hp;
+ if (h->vt.check_tgs == NULL)
+ continue;
+
+ ret = h->vt.check_tgs(context, h->moddata, request, server, ticket,
+ (const char **)ais, status, &life, &rlife);
+ if (ret)
+ goto done;
+
+ update_ticket_times(times, kdc_time, life, rlife);
}
-#endif
- return 0; /* not against policy */
+done:
+ free_indicators(ais);
+ return ret;
+}
+
+void
+unload_kdcpolicy_plugins(krb5_context context)
+{
+ kdcpolicy_handle *hp, h;
+
+ for (hp = handles; *hp != NULL; hp++) {
+ h = *hp;
+ if (h->vt.fini != NULL)
+ h->vt.fini(context, h->moddata);
+ free(h);
+ }
+ free(handles);
+ handles = NULL;
+}
+
+krb5_error_code
+load_kdcpolicy_plugins(krb5_context context)
+{
+ krb5_error_code ret;
+ krb5_plugin_initvt_fn *modules = NULL, *mod;
+ kdcpolicy_handle h;
+ size_t count;
+
+ ret = k5_plugin_load_all(context, PLUGIN_INTERFACE_KDCPOLICY, &modules);
+ if (ret)
+ goto cleanup;
+
+ for (count = 0; modules[count] != NULL; count++);
+ handles = k5calloc(count + 1, sizeof(*handles), &ret);
+ if (handles == NULL)
+ goto cleanup;
+
+ count = 0;
+ for (mod = modules; *mod != NULL; mod++) {
+ h = k5calloc(1, sizeof(*h), &ret);
+ if (h == NULL)
+ goto cleanup;
+
+ ret = (*mod)(context, 1, 1, (krb5_plugin_vtable)&h->vt);
+ if (ret) { /* Version mismatch. */
+ TRACE_KDCPOLICY_VTINIT_FAIL(context, ret);
+ free(h);
+ continue;
+ }
+ if (h->vt.init != NULL) {
+ ret = h->vt.init(context, &h->moddata);
+ if (ret == KRB5_PLUGIN_NO_HANDLE) {
+ TRACE_KADM5_AUTH_INIT_SKIP(context, h->vt.name);
+ free(h);
+ continue;
+ }
+ if (ret) {
+ kdc_err(context, ret, _("while loading policy module %s"),
+ h->vt.name);
+ free(h);
+ goto cleanup;
+ }
+ }
+ handles[count++] = h;
+ }
+
+ ret = 0;
+
+cleanup:
+ if (ret)
+ unload_kdcpolicy_plugins(context);
+ k5_plugin_free_modules(context, modules);
+ return ret;
}
diff --git a/src/kdc/policy.h b/src/kdc/policy.h
index 6b000dc90..2a57b0a01 100644
--- a/src/kdc/policy.h
+++ b/src/kdc/policy.h
@@ -26,11 +26,22 @@
#ifndef __KRB5_KDC_POLICY__
#define __KRB5_KDC_POLICY__
-extern int against_postdate_policy (krb5_timestamp);
+krb5_error_code
+load_kdcpolicy_plugins(krb5_context context);
-extern int against_flag_policy_as (const krb5_kdc_req *);
+void
+unload_kdcpolicy_plugins(krb5_context context);
-extern int against_flag_policy_tgs (const krb5_kdc_req *,
- const krb5_ticket *);
+krb5_error_code
+check_kdcpolicy_as(krb5_context context, const krb5_kdc_req *request,
+ const krb5_db_entry *client, const krb5_db_entry *server,
+ krb5_data *const *auth_indicators, krb5_timestamp kdc_time,
+ krb5_ticket_times *times, const char **status);
+
+krb5_error_code
+check_kdcpolicy_tgs(krb5_context context, const krb5_kdc_req *request,
+ const krb5_db_entry *server, const krb5_ticket *ticket,
+ krb5_data *const *auth_indicators, krb5_timestamp kdc_time,
+ krb5_ticket_times *times, const char **status);
#endif /* __KRB5_KDC_POLICY__ */
diff --git a/src/kdc/tgs_policy.c b/src/kdc/tgs_policy.c
index d0f25d1b7..33cfbcd81 100644
--- a/src/kdc/tgs_policy.c
+++ b/src/kdc/tgs_policy.c
@@ -375,11 +375,5 @@ validate_tgs_request(kdc_realm_t *kdc_active_realm,
if (ret && ret != KRB5_PLUGIN_OP_NOTSUPP)
return errcode_to_protocol(ret);
- /* Check local policy. */
- errcode = against_local_policy_tgs(request, server, ticket,
- status, e_data);
- if (errcode)
- return errcode;
-
return 0;
}
diff --git a/src/lib/krb5/krb/plugin.c b/src/lib/krb5/krb/plugin.c
index 17dd6bd30..31aaf661d 100644
--- a/src/lib/krb5/krb/plugin.c
+++ b/src/lib/krb5/krb/plugin.c
@@ -58,7 +58,9 @@ const char *interface_names[] = {
"audit",
"tls",
"kdcauthdata",
- "certauth"
+ "certauth",
+ "kadm5_auth",
+ "kdcpolicy",
};
/* Return the context's interface structure for id, or NULL if invalid. */
diff --git a/src/plugins/kdcpolicy/test/Makefile.in b/src/plugins/kdcpolicy/test/Makefile.in
new file mode 100644
index 000000000..b81f1a7ce
--- /dev/null
+++ b/src/plugins/kdcpolicy/test/Makefile.in
@@ -0,0 +1,20 @@
+mydir=plugins$(S)policy$(S)test
+BUILDTOP=$(REL)..$(S)..$(S)..
+
+LIBBASE=policy_test
+LIBMAJOR=0
+LIBMINOR=0
+RELDIR=../plugins/kdcpolicy/test
+SHLIB_EXPDEPS=$(KRB5_BASE_DEPLIBS)
+SHLIB_EXPLIBS=$(KRB5_BASE_LIBS)
+
+STLIBOBJS=main.o
+
+SRCS=$(srcdir)/main.c
+
+all-unix: all-libs
+install-unix:
+clean-unix:: clean-libs clean-libobjs
+
+@libnover_frag@
+@libobj_frag@
diff --git a/src/plugins/kdcpolicy/test/deps b/src/plugins/kdcpolicy/test/deps
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/plugins/kdcpolicy/test/main.c b/src/plugins/kdcpolicy/test/main.c
new file mode 100644
index 000000000..eb8fde053
--- /dev/null
+++ b/src/plugins/kdcpolicy/test/main.c
@@ -0,0 +1,111 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* include/krb5/kdcpolicy_plugin.h - KDC policy plugin interface */
+/*
+ * Copyright (C) 2017 by 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.
+ *
+ * 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 HOLDER 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.
+ */
+
+#include "k5-int.h"
+#include "kdb.h"
+#include <krb5/kdcpolicy_plugin.h>
+
+static krb5_error_code
+output_from_indicator(const char *const *auth_indicators,
+ krb5_deltat *lifetime_out,
+ krb5_deltat *renew_lifetime_out,
+ const char **status)
+{
+ if (auth_indicators[0] == NULL) {
+ *status = NULL;
+ return 0;
+ }
+
+ if (strcmp(auth_indicators[0], "ONE_HOUR") == 0) {
+ *lifetime_out = 3600;
+ *renew_lifetime_out = *lifetime_out * 2;
+ return 0;
+ } else if (strcmp(auth_indicators[0], "SEVEN_HOURS") == 0) {
+ *lifetime_out = 7 * 3600;
+ *renew_lifetime_out = *lifetime_out * 2;
+ return 0;
+ }
+
+ *status = "LOCAL_POLICY";
+ return KRB5KDC_ERR_POLICY;
+}
+
+static krb5_error_code
+test_check_as(krb5_context context, krb5_kdcpolicy_moddata moddata,
+ const krb5_kdc_req *request, const krb5_db_entry *client,
+ const krb5_db_entry *server, const char *const *auth_indicators,
+ const char **status, krb5_deltat *lifetime_out,
+ krb5_deltat *renew_lifetime_out)
+{
+ if (request->client != NULL && request->client->length >= 1 &&
+ data_eq_string(request->client->data[0], "fail")) {
+ *status = "LOCAL_POLICY";
+ return KRB5KDC_ERR_POLICY;
+ }
+ return output_from_indicator(auth_indicators, lifetime_out,
+ renew_lifetime_out, status);
+}
+
+static krb5_error_code
+test_check_tgs(krb5_context context, krb5_kdcpolicy_moddata moddata,
+ const krb5_kdc_req *request, const krb5_db_entry *server,
+ const krb5_ticket *ticket, const char *const *auth_indicators,
+ const char **status, krb5_deltat *lifetime_out,
+ krb5_deltat *renew_lifetime_out)
+{
+ if (request->server != NULL && request->server->length >= 1 &&
+ data_eq_string(request->server->data[0], "fail")) {
+ *status = "LOCAL_POLICY";
+ return KRB5KDC_ERR_POLICY;
+ }
+ return output_from_indicator(auth_indicators, lifetime_out,
+ renew_lifetime_out, status);
+}
+
+krb5_error_code
+kdcpolicy_test_initvt(krb5_context context, int maj_ver, int min_ver,
+ krb5_plugin_vtable vtable);
+krb5_error_code
+kdcpolicy_test_initvt(krb5_context context, int maj_ver, int min_ver,
+ krb5_plugin_vtable vtable)
+{
+ krb5_kdcpolicy_vtable vt;
+
+ if (maj_ver != 1)
+ return KRB5_PLUGIN_VER_NOTSUPP;
+
+ vt = (krb5_kdcpolicy_vtable)vtable;
+ vt->name = "test";
+ vt->check_as = test_check_as;
+ vt->check_tgs = test_check_tgs;
+ return 0;
+}
diff --git a/src/plugins/kdcpolicy/test/policy_test.exports b/src/plugins/kdcpolicy/test/policy_test.exports
new file mode 100644
index 000000000..9682ec74f
--- /dev/null
+++ b/src/plugins/kdcpolicy/test/policy_test.exports
@@ -0,0 +1 @@
+kdcpolicy_test_initvt
diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in
index 2b3112537..a2093108b 100644
--- a/src/tests/Makefile.in
+++ b/src/tests/Makefile.in
@@ -169,6 +169,7 @@ check-pytests: localauth plugorder rdreq responder s2p s4u2proxy unlockiter
$(RUNPYTEST) $(srcdir)/t_tabdump.py $(PYTESTFLAGS)
$(RUNPYTEST) $(srcdir)/t_certauth.py $(PYTESTFLAGS)
$(RUNPYTEST) $(srcdir)/t_y2038.py $(PYTESTFLAGS)
+ $(RUNPYTEST) $(srcdir)/t_kdcpolicy.py $(PYTESTFLAGS)
clean:
$(RM) adata etinfo forward gcred hist hooks hrealm icred kdbtest
diff --git a/src/tests/t_kdcpolicy.py b/src/tests/t_kdcpolicy.py
new file mode 100644
index 000000000..6a745b959
--- /dev/null
+++ b/src/tests/t_kdcpolicy.py
@@ -0,0 +1,57 @@
+#!/usr/bin/python
+from k5test import *
+from datetime import datetime
+import re
+
+testpreauth = os.path.join(buildtop, 'plugins', 'preauth', 'test', 'test.so')
+testpolicy = os.path.join(buildtop, 'plugins', 'kdcpolicy', 'test',
+ 'policy_test.so')
+krb5_conf = {'plugins': {'kdcpreauth': {'module': 'test:' + testpreauth},
+ 'clpreauth': {'module': 'test:' + testpreauth},
+ 'kdcpolicy': {'module': 'test:' + testpolicy}}}
+kdc_conf = {'realms': {'$realm': {'default_principal_flags': '+preauth',
+ 'max_renewable_life': '1d'}}}
+realm = K5Realm(krb5_conf=krb5_conf, kdc_conf=kdc_conf)
+
+realm.run([kadminl, 'addprinc', '-pw', password('fail'), 'fail'])
+
+def verify_time(out, target_time):
+ times = re.findall(r'\d\d/\d\d/\d\d \d\d:\d\d:\d\d', out)
+ times = [datetime.strptime(t, '%m/%d/%y %H:%M:%S') for t in times]
+ while len(times) > 0:
+ starttime = times.pop(0)
+ endtime = times.pop(0)
+ renewtime = times.pop(0)
+
+ if str(endtime - starttime) != target_time:
+ fail('unexpected lifetime value')
+ if str(renewtime - endtime) != target_time:
+ fail('unexpected renewable value')
+
+rflags = ['-r', '1d', '-l', '12h']
+
+# Test AS+TGS success path.
+realm.kinit(realm.user_princ, password('user'),
+ rflags + ['-X', 'indicators=SEVEN_HOURS'])
+realm.run([kvno, realm.host_princ])
+realm.run(['./adata', realm.host_princ], expected_msg='+97: [SEVEN_HOURS]')
+out = realm.run([klist, realm.ccache, '-e'])
+verify_time(out, '7:00:00')
+
+# Test AS+TGS success path with different values.
+realm.kinit(realm.user_princ, password('user'),
+ rflags + ['-X', 'indicators=ONE_HOUR'])
+realm.run([kvno, realm.host_princ])
+realm.run(['./adata', realm.host_princ], expected_msg='+97: [ONE_HOUR]')
+out = realm.run([klist, realm.ccache, '-e'])
+verify_time(out, '1:00:00')
+
+# Test TGS failure path (using previous creds).
+realm.run([kvno, 'fail@%s' % realm.realm], expected_code=1,
+ expected_msg='KDC policy rejects request')
+
+# Test AS failure path.
+realm.kinit('fail@%s' % realm.realm, password('fail'),
+ expected_code=1, expected_msg='KDC policy rejects request')
+
+success('kdcpolicy tests')

View file

@ -0,0 +1,101 @@
From 6ce3a9416ee73fee41d0190e3fd0fde0a097c774 Mon Sep 17 00:00:00 2001
From: Matt Rogers <mrogers@redhat.com>
Date: Fri, 9 Dec 2016 11:43:27 -0500
Subject: [PATCH] Add PKINIT UPN tests to t_pkinit.py
[ghudson@mit.edu: simplify and explain tests; add test for
id-pkinit-san match against canonicalized client principal]
ticket: 8528
(cherry picked from commit d520fd3f032121b61b22681838af96ee505fe44d)
---
src/tests/t_pkinit.py | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 57 insertions(+)
diff --git a/src/tests/t_pkinit.py b/src/tests/t_pkinit.py
index 526473b42..ac4d326b6 100755
--- a/src/tests/t_pkinit.py
+++ b/src/tests/t_pkinit.py
@@ -23,6 +23,9 @@ privkey_pem = os.path.join(certs, 'privkey.pem')
privkey_enc_pem = os.path.join(certs, 'privkey-enc.pem')
user_p12 = os.path.join(certs, 'user.p12')
user_enc_p12 = os.path.join(certs, 'user-enc.p12')
+user_upn_p12 = os.path.join(certs, 'user-upn.p12')
+user_upn2_p12 = os.path.join(certs, 'user-upn2.p12')
+user_upn3_p12 = os.path.join(certs, 'user-upn3.p12')
path = os.path.join(os.getcwd(), 'testdir', 'tmp-pkinit-certs')
path_enc = os.path.join(os.getcwd(), 'testdir', 'tmp-pkinit-certs-enc')
@@ -36,6 +39,20 @@ pkinit_kdc_conf = {'realms': {'$realm': {
restrictive_kdc_conf = {'realms': {'$realm': {
'restrict_anonymous_to_tgt': 'true' }}}
+testprincs = {'krbtgt/KRBTEST.COM': {'keys': 'aes128-cts'},
+ 'user': {'keys': 'aes128-cts', 'flags': '+preauth'},
+ 'user2': {'keys': 'aes128-cts', 'flags': '+preauth'}}
+alias_kdc_conf = {'realms': {'$realm': {
+ 'default_principal_flags': '+preauth',
+ 'pkinit_eku_checking': 'none',
+ 'pkinit_allow_upn': 'true',
+ 'pkinit_identity': 'FILE:%s,%s' % (kdc_pem, privkey_pem),
+ 'database_module': 'test'}},
+ 'dbmodules': {'test': {
+ 'db_library': 'test',
+ 'alias': {'user@krbtest.com': 'user'},
+ 'princs': testprincs}}}
+
file_identity = 'FILE:%s,%s' % (user_pem, privkey_pem)
file_enc_identity = 'FILE:%s,%s' % (user_pem, privkey_enc_pem)
dir_identity = 'DIR:%s' % path
@@ -45,11 +62,51 @@ dir_file_identity = 'FILE:%s,%s' % (os.path.join(path, 'user.crt'),
dir_file_enc_identity = 'FILE:%s,%s' % (os.path.join(path_enc, 'user.crt'),
os.path.join(path_enc, 'user.key'))
p12_identity = 'PKCS12:%s' % user_p12
+p12_upn_identity = 'PKCS12:%s' % user_upn_p12
+p12_upn2_identity = 'PKCS12:%s' % user_upn2_p12
+p12_upn3_identity = 'PKCS12:%s' % user_upn3_p12
p12_enc_identity = 'PKCS12:%s' % user_enc_p12
p11_identity = 'PKCS11:soft-pkcs11.so'
p11_token_identity = ('PKCS11:module_name=soft-pkcs11.so:'
'slotid=1:token=SoftToken (token)')
+# Start a realm with the test kdb module for the following UPN SAN tests.
+realm = K5Realm(krb5_conf=pkinit_krb5_conf, kdc_conf=alias_kdc_conf,
+ create_kdb=False)
+realm.start_kdc()
+
+# Compatibility check: cert contains UPN "user", which matches the
+# request principal user@KRBTEST.COM if parsed as a normal principal.
+realm.kinit(realm.user_princ,
+ flags=['-X', 'X509_user_identity=%s' % p12_upn2_identity])
+
+# Compatibility check: cert contains UPN "user@KRBTEST.COM", which matches
+# the request principal user@KRBTEST.COM if parsed as a normal principal.
+realm.kinit(realm.user_princ,
+ flags=['-X', 'X509_user_identity=%s' % p12_upn3_identity])
+
+# Cert contains UPN "user@krbtest.com" which is aliased to the request
+# principal.
+realm.kinit(realm.user_princ,
+ flags=['-X', 'X509_user_identity=%s' % p12_upn_identity])
+
+# Test an id-pkinit-san match to a post-canonical principal.
+realm.kinit('user@krbtest.com',
+ flags=['-E', '-X', 'X509_user_identity=%s' % p12_identity])
+
+# Test a UPN match to a post-canonical principal. (This only works
+# for the cert with the UPN containing just "user", as we don't allow
+# UPN reparsing when comparing to the canonicalized client principal.)
+realm.kinit('user@krbtest.com',
+ flags=['-E', '-X', 'X509_user_identity=%s' % p12_upn2_identity])
+
+# Test a mismatch.
+out = realm.run([kinit, '-X', 'X509_user_identity=%s' % p12_upn2_identity,
+ 'user2'], expected_code=1)
+if 'kinit: Client name mismatch while getting initial credentials' not in out:
+ fail('Wrong error for UPN SAN mismatch')
+realm.stop()
+
realm = K5Realm(krb5_conf=pkinit_krb5_conf, kdc_conf=pkinit_kdc_conf,
get_creds=False)

View file

@ -0,0 +1,51 @@
From e267849bcc3813989470c03565b22d25c71af91e Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Fri, 25 Aug 2017 12:39:14 -0400
Subject: [PATCH] Add PKINIT test case for generic client cert
In t_pkinit.py, add a test case where a client cert with no extensions
is authorized via subject and issuer using a pkinit_cert_match string
attribute.
ticket: 8562
(cherry picked from commit 8c5d50888aab554239fd51306e79c5213833c898)
[rharwood@redhat.com: backport around dbmatch module]
---
src/tests/t_pkinit.py | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/src/tests/t_pkinit.py b/src/tests/t_pkinit.py
index e943f4974..fa5c5199e 100755
--- a/src/tests/t_pkinit.py
+++ b/src/tests/t_pkinit.py
@@ -26,6 +26,7 @@ user_enc_p12 = os.path.join(certs, 'user-enc.p12')
user_upn_p12 = os.path.join(certs, 'user-upn.p12')
user_upn2_p12 = os.path.join(certs, 'user-upn2.p12')
user_upn3_p12 = os.path.join(certs, 'user-upn3.p12')
+generic_p12 = os.path.join(certs, 'generic.p12')
path = os.path.join(os.getcwd(), 'testdir', 'tmp-pkinit-certs')
path_enc = os.path.join(os.getcwd(), 'testdir', 'tmp-pkinit-certs-enc')
@@ -65,6 +66,7 @@ p12_identity = 'PKCS12:%s' % user_p12
p12_upn_identity = 'PKCS12:%s' % user_upn_p12
p12_upn2_identity = 'PKCS12:%s' % user_upn2_p12
p12_upn3_identity = 'PKCS12:%s' % user_upn3_p12
+p12_generic_identity = 'PKCS12:%s' % generic_p12
p12_enc_identity = 'PKCS12:%s' % user_enc_p12
p11_identity = 'PKCS11:soft-pkcs11.so'
p11_token_identity = ('PKCS11:module_name=soft-pkcs11.so:'
@@ -284,6 +286,14 @@ realm.run(['./responder', '-X', 'X509_user_identity=%s' % p12_enc_identity,
realm.klist(realm.user_princ)
realm.run([kvno, realm.host_princ])
+# Authorize a client cert with no PKINIT extensions using subject and
+# issuer. (Relies on EKU checking being turned off.)
+rule = '&&<SUBJECT>CN=user$<ISSUER>O=MIT,'
+realm.run([kadminl, 'setstr', realm.user_princ, 'pkinit_cert_match', rule])
+realm.kinit(realm.user_princ,
+ flags=['-X', 'X509_user_identity=%s' % p12_generic_identity])
+realm.klist(realm.user_princ)
+
if not have_soft_pkcs11:
skip_rest('PKINIT PKCS11 tests', 'soft-pkcs11.so not found')

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,293 @@
From 632575ab12fc5d6c9bdc83cb8200fb8f4f422b83 Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Wed, 23 Aug 2017 17:25:17 -0400
Subject: [PATCH] Add hostname-based ccselect module
The hostname module selects the ccache whose realm is the longest
parent domain tail of the uppercase server hostname.
[ghudson@mit.edu: minor edits]
ticket: 8613 (new)
(cherry picked from commit a4ddc6cf576b4155e6b994307902567f26f752b2)
---
doc/admin/conf_files/krb5_conf.rst | 4 +
src/lib/krb5/ccache/Makefile.in | 3 +
src/lib/krb5/ccache/cc-int.h | 4 +
src/lib/krb5/ccache/ccselect.c | 5 ++
src/lib/krb5/ccache/ccselect_hostname.c | 146 ++++++++++++++++++++++++++++++++
src/tests/gssapi/t_ccselect.py | 9 ++
6 files changed, 171 insertions(+)
create mode 100644 src/lib/krb5/ccache/ccselect_hostname.c
diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
index 1d9bc9e34..9c1ee94a4 100644
--- a/doc/admin/conf_files/krb5_conf.rst
+++ b/doc/admin/conf_files/krb5_conf.rst
@@ -745,6 +745,10 @@ disabled with the disable tag):
Uses the service realm to guess an appropriate cache from the
collection
+**hostname**
+ If the service principal is host-based, uses the service hostname
+ to guess an appropriate cache from the collection
+
.. _pwqual:
pwqual interface
diff --git a/src/lib/krb5/ccache/Makefile.in b/src/lib/krb5/ccache/Makefile.in
index 5ac870728..f84cf793e 100644
--- a/src/lib/krb5/ccache/Makefile.in
+++ b/src/lib/krb5/ccache/Makefile.in
@@ -34,6 +34,7 @@ STLIBOBJS= \
ccdefops.o \
ccmarshal.o \
ccselect.o \
+ ccselect_hostname.o \
ccselect_k5identity.o \
ccselect_realm.o \
cc_dir.o \
@@ -52,6 +53,7 @@ OBJS= $(OUTPRE)ccbase.$(OBJEXT) \
$(OUTPRE)ccdefops.$(OBJEXT) \
$(OUTPRE)ccmarshal.$(OBJEXT) \
$(OUTPRE)ccselect.$(OBJEXT) \
+ $(OUTPRE)ccselect_hostname.$(OBJEXT) \
$(OUTPRE)ccselect_k5identity.$(OBJEXT) \
$(OUTPRE)ccselect_realm.$(OBJEXT) \
$(OUTPRE)cc_dir.$(OBJEXT) \
@@ -70,6 +72,7 @@ SRCS= $(srcdir)/ccbase.c \
$(srcdir)/ccdefops.c \
$(srcdir)/ccmarshal.c \
$(srcdir)/ccselect.c \
+ $(srcdir)/ccselect_hostname.c \
$(srcdir)/ccselect_k5identity.c \
$(srcdir)/ccselect_realm.c \
$(srcdir)/cc_dir.c \
diff --git a/src/lib/krb5/ccache/cc-int.h b/src/lib/krb5/ccache/cc-int.h
index ee9b5e0e9..d920367ce 100644
--- a/src/lib/krb5/ccache/cc-int.h
+++ b/src/lib/krb5/ccache/cc-int.h
@@ -123,6 +123,10 @@ k5_cccol_force_unlock(void);
krb5_error_code
krb5int_fcc_new_unique(krb5_context context, char *template, krb5_ccache *id);
+krb5_error_code
+ccselect_hostname_initvt(krb5_context context, int maj_ver, int min_ver,
+ krb5_plugin_vtable vtable);
+
krb5_error_code
ccselect_realm_initvt(krb5_context context, int maj_ver, int min_ver,
krb5_plugin_vtable vtable);
diff --git a/src/lib/krb5/ccache/ccselect.c b/src/lib/krb5/ccache/ccselect.c
index ee4b83a9b..393d39733 100644
--- a/src/lib/krb5/ccache/ccselect.c
+++ b/src/lib/krb5/ccache/ccselect.c
@@ -71,6 +71,11 @@ load_modules(krb5_context context)
if (ret != 0)
goto cleanup;
+ ret = k5_plugin_register(context, PLUGIN_INTERFACE_CCSELECT, "hostname",
+ ccselect_hostname_initvt);
+ if (ret != 0)
+ goto cleanup;
+
ret = k5_plugin_load_all(context, PLUGIN_INTERFACE_CCSELECT, &modules);
if (ret != 0)
goto cleanup;
diff --git a/src/lib/krb5/ccache/ccselect_hostname.c b/src/lib/krb5/ccache/ccselect_hostname.c
new file mode 100644
index 000000000..475cfabae
--- /dev/null
+++ b/src/lib/krb5/ccache/ccselect_hostname.c
@@ -0,0 +1,146 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/krb5/ccache/ccselect_hostname.c - hostname ccselect module */
+/*
+ * Copyright (C) 2017 by 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.
+ *
+ * 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 HOLDER 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.
+ */
+
+#include "k5-int.h"
+#include "cc-int.h"
+#include <ctype.h>
+#include <krb5/ccselect_plugin.h>
+
+/* Swap a and b, using tmp as an intermediate. */
+#define SWAP(a, b, tmp) \
+ tmp = a; \
+ a = b; \
+ b = tmp;
+
+static krb5_error_code
+hostname_init(krb5_context context, krb5_ccselect_moddata *data_out,
+ int *priority_out)
+{
+ *data_out = NULL;
+ *priority_out = KRB5_CCSELECT_PRIORITY_HEURISTIC;
+ return 0;
+}
+
+static krb5_error_code
+hostname_choose(krb5_context context, krb5_ccselect_moddata data,
+ krb5_principal server, krb5_ccache *ccache_out,
+ krb5_principal *princ_out)
+{
+ krb5_error_code ret;
+ char *p, *host = NULL;
+ size_t hostlen;
+ krb5_cccol_cursor col_cursor;
+ krb5_ccache ccache, tmp_ccache, best_ccache = NULL;
+ krb5_principal princ, tmp_princ, best_princ = NULL;
+ krb5_data domain;
+
+ *ccache_out = NULL;
+ *princ_out = NULL;
+
+ if (server->type != KRB5_NT_SRV_HST || server->length < 2)
+ return KRB5_PLUGIN_NO_HANDLE;
+
+ /* Compute upper-case hostname. */
+ hostlen = server->data[1].length;
+ host = k5memdup0(server->data[1].data, hostlen, &ret);
+ if (host == NULL)
+ return ret;
+ for (p = host; *p != '\0'; p++) {
+ if (islower(*p))
+ *p = toupper(*p);
+ }
+
+ /* Scan the collection for a cache with a client principal whose realm is
+ * the longest tail of the server hostname. */
+ ret = krb5_cccol_cursor_new(context, &col_cursor);
+ if (ret)
+ goto done;
+
+ for (ret = krb5_cccol_cursor_next(context, col_cursor, &ccache);
+ ret == 0 && ccache != NULL;
+ ret = krb5_cccol_cursor_next(context, col_cursor, &ccache)) {
+ ret = krb5_cc_get_principal(context, ccache, &princ);
+ if (ret) {
+ krb5_cc_close(context, ccache);
+ break;
+ }
+
+ /* Check for a longer match than we have. */
+ domain = make_data(host, hostlen);
+ while (best_princ == NULL ||
+ best_princ->realm.length < domain.length) {
+ if (data_eq(princ->realm, domain)) {
+ SWAP(best_ccache, ccache, tmp_ccache);
+ SWAP(best_princ, princ, tmp_princ);
+ break;
+ }
+
+ /* Try the next parent domain. */
+ p = memchr(domain.data, '.', domain.length);
+ if (p == NULL)
+ break;
+ domain = make_data(p + 1, hostlen - (p + 1 - host));
+ }
+
+ if (ccache != NULL)
+ krb5_cc_close(context, ccache);
+ krb5_free_principal(context, princ);
+ }
+
+ krb5_cccol_cursor_free(context, &col_cursor);
+
+ if (best_ccache != NULL) {
+ *ccache_out = best_ccache;
+ *princ_out = best_princ;
+ } else {
+ ret = KRB5_PLUGIN_NO_HANDLE;
+ }
+
+done:
+ free(host);
+ return ret;
+}
+
+krb5_error_code
+ccselect_hostname_initvt(krb5_context context, int maj_ver, int min_ver,
+ krb5_plugin_vtable vtable)
+{
+ krb5_ccselect_vtable vt;
+
+ if (maj_ver != 1)
+ return KRB5_PLUGIN_VER_NOTSUPP;
+ vt = (krb5_ccselect_vtable)vtable;
+ vt->name = "hostname";
+ vt->init = hostname_init;
+ vt->choose = hostname_choose;
+ return 0;
+}
diff --git a/src/tests/gssapi/t_ccselect.py b/src/tests/gssapi/t_ccselect.py
index 668a2cc62..3503f9269 100755
--- a/src/tests/gssapi/t_ccselect.py
+++ b/src/tests/gssapi/t_ccselect.py
@@ -33,6 +33,7 @@ host1 = 'p:' + r1.host_princ
host2 = 'p:' + r2.host_princ
foo = 'foo.krbtest.com'
foo2 = 'foo.krbtest2.com'
+foobar = "foo.bar.krbtest.com"
# These strings specify the target as a GSS name. The resulting
# principal will have the host-based type, with the referral realm
@@ -42,6 +43,7 @@ foo2 = 'foo.krbtest2.com'
# single component.
gssserver = 'h:host@' + foo
gssserver2 = 'h:host@' + foo2
+gssserver_bar = 'h:host@' + foobar
gsslocal = 'h:host@localhost'
# refserver specifies the target as a principal in the referral realm.
@@ -77,10 +79,12 @@ r1.addprinc('host/localhost')
r2.addprinc('host/localhost')
r1.addprinc('host/' + foo)
r2.addprinc('host/' + foo2)
+r1.addprinc('host/' + foobar)
r1.extract_keytab('host/localhost', r1.keytab)
r2.extract_keytab('host/localhost', r2.keytab)
r1.extract_keytab('host/' + foo, r1.keytab)
r2.extract_keytab('host/' + foo2, r2.keytab)
+r1.extract_keytab('host/' + foobar, r1.keytab)
# Get tickets for one user in each realm (zaphod will be primary).
r1.kinit(alice, password('alice'))
@@ -128,6 +132,11 @@ output = r2.run(['./t_ccselect', gsslocal])
if output != (zaphod + '\n'):
fail('zaphod not chosen via default realm fallback')
+# Check that realm ccselect fallback works correctly
+r1.run(['./t_ccselect', gssserver_bar], expected_msg=alice)
+r2.kinit(zaphod, password('zaphod'))
+r1.run(['./t_ccselect', gssserver_bar], expected_msg=alice)
+
# Get a second cred in r1 (bob will be primary).
r1.kinit(bob, password('bob'))

View file

@ -0,0 +1,96 @@
From 9c6f61e30e11eca5c04daa3f0dce398602ef5801 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Tue, 17 Jan 2017 11:24:41 -0500
Subject: [PATCH] Add k5test expected_msg, expected_trace
In k5test.py, add the optional keyword argument "expected_msg" to
methods that run commands, to make it easier to look for substrings in
the command output. Add the optional keyword "expected_trace" to run
the command with KRB5_TRACE enabled and look for an ordered series of
substrings in the trace output.
(cherry picked from commit 8bb5fce69a4aa6c3082fa7def66a93974e10e17a)
[rharwood@redhat.com: Removed .gitignore change]
---
src/config/post.in | 2 +-
src/util/k5test.py | 37 ++++++++++++++++++++++++++++++++++---
2 files changed, 35 insertions(+), 4 deletions(-)
diff --git a/src/config/post.in b/src/config/post.in
index 7c7d86dc9..3643abad1 100644
--- a/src/config/post.in
+++ b/src/config/post.in
@@ -156,7 +156,7 @@ clean: clean-$(WHAT)
clean-unix::
$(RM) $(OBJS) $(DEPTARGETS_CLEAN) $(EXTRA_FILES)
- $(RM) et-[ch]-*.et et-[ch]-*.[ch] testlog
+ $(RM) et-[ch]-*.et et-[ch]-*.[ch] testlog testtrace
-$(RM) -r testdir
clean-windows::
diff --git a/src/util/k5test.py b/src/util/k5test.py
index c3d026377..4d30baf40 100644
--- a/src/util/k5test.py
+++ b/src/util/k5test.py
@@ -223,8 +223,11 @@ Scripts may use the following realm methods and attributes:
command-line debugging options. Fail if the command does not return
0. Log the command output appropriately, and return it as a single
multi-line string. Keyword arguments can contain input='string' to
- send an input string to the command, and expected_code=N to expect a
- return code other than 0.
+ send an input string to the command, expected_code=N to expect a
+ return code other than 0, expected_msg=MSG to expect a substring in
+ the command output, and expected_trace=('a', 'b', ...) to expect an
+ ordered series of line substrings in the command's KRB5_TRACE
+ output.
* realm.kprop_port(): Returns a port number based on realm.portbase
intended for use by kprop and kpropd.
@@ -647,10 +650,31 @@ def _stop_or_shell(stop, shell, env, ind):
subprocess.call(os.getenv('SHELL'), env=env)
-def _run_cmd(args, env, input=None, expected_code=0):
+# Read tracefile and look for the expected strings in successive lines.
+def _check_trace(tracefile, expected):
+ output('*** Trace output for previous command:\n')
+ i = 0
+ with open(tracefile, 'r') as f:
+ for line in f:
+ output(line)
+ if i < len(expected) and expected[i] in line:
+ i += 1
+ if i < len(expected):
+ fail('Expected string not found in trace output: ' + expected[i])
+
+
+def _run_cmd(args, env, input=None, expected_code=0, expected_msg=None,
+ expected_trace=None):
global null_input, _cmd_index, _last_cmd, _last_cmd_output, _debug
global _stop_before, _stop_after, _shell_before, _shell_after
+ if expected_trace is not None:
+ tracefile = 'testtrace'
+ if os.path.exists(tracefile):
+ os.remove(tracefile)
+ env = env.copy()
+ env['KRB5_TRACE'] = tracefile
+
if (_match_cmdnum(_debug, _cmd_index)):
return _debug_cmd(args, env, input)
@@ -679,6 +703,13 @@ def _run_cmd(args, env, input=None, expected_code=0):
# Check the return code and return the output.
if code != expected_code:
fail('%s failed with code %d.' % (args[0], code))
+
+ if expected_msg is not None and expected_msg not in outdata:
+ fail('Expected string not found in command output: ' + expected_msg)
+
+ if expected_trace is not None:
+ _check_trace(tracefile, expected_trace)
+
return outdata

View file

@ -0,0 +1,419 @@
From a3408731e3d73f99028f20c3f33caa5a411b430c Mon Sep 17 00:00:00 2001
From: Simo Sorce <simo@redhat.com>
Date: Thu, 30 Mar 2017 11:27:09 -0400
Subject: [PATCH] Add support to query the SSF of a GSS context
Cyrus SASL provides a Security Strength Factor number to assess the
relative "strength" of the negotiated mechanism, and applications
sometimes make access control decisions based on it.
Add a call that allows us to query the mechanism that established the
GSS security context to ask what is the current SSF, based on the
enctype of the session key.
ticket: 8569 (new)
(cherry picked from commit 7feb7da54c0321b5a3eeb6c3797846a3cf7eda28)
[rharwood@redhat.com: hide GSS_KRB5_GET_CRED_IMPERSONATOR symbol]
---
src/include/k5-int.h | 1 +
src/lib/crypto/krb/crypto_int.h | 1 +
src/lib/crypto/krb/enctype_util.c | 16 ++++++++++++++++
src/lib/crypto/krb/etypes.c | 33 ++++++++++++++++++---------------
src/lib/crypto/libk5crypto.exports | 1 +
src/lib/gssapi/generic/gssapi_ext.h | 11 +++++++++++
src/lib/gssapi/generic/gssapi_generic.c | 9 +++++++++
src/lib/gssapi/krb5/gssapiP_krb5.h | 6 ++++++
src/lib/gssapi/krb5/gssapi_krb5.c | 4 ++++
src/lib/gssapi/krb5/inq_context.c | 27 +++++++++++++++++++++++++++
src/lib/gssapi/libgssapi_krb5.exports | 1 +
src/lib/gssapi32.def | 3 +++
src/lib/krb5_32.def | 3 +++
src/tests/gssapi/t_enctypes.c | 14 ++++++++++++++
14 files changed, 115 insertions(+), 15 deletions(-)
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index cea644d0a..06ca2b66d 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -2114,6 +2114,7 @@ krb5_get_tgs_ktypes(krb5_context, krb5_const_principal, krb5_enctype **);
krb5_boolean krb5_is_permitted_enctype(krb5_context, krb5_enctype);
krb5_boolean KRB5_CALLCONV krb5int_c_weak_enctype(krb5_enctype);
+krb5_error_code k5_enctype_to_ssf(krb5_enctype enctype, unsigned int *ssf_out);
krb5_error_code krb5_kdc_rep_decrypt_proc(krb5_context, const krb5_keyblock *,
krb5_const_pointer, krb5_kdc_rep *);
diff --git a/src/lib/crypto/krb/crypto_int.h b/src/lib/crypto/krb/crypto_int.h
index d75b49c69..e5099291e 100644
--- a/src/lib/crypto/krb/crypto_int.h
+++ b/src/lib/crypto/krb/crypto_int.h
@@ -111,6 +111,7 @@ struct krb5_keytypes {
prf_func prf;
krb5_cksumtype required_ctype;
krb5_flags flags;
+ unsigned int ssf;
};
#define ETYPE_WEAK 1
diff --git a/src/lib/crypto/krb/enctype_util.c b/src/lib/crypto/krb/enctype_util.c
index 0ed74bd6e..b1b40e7ec 100644
--- a/src/lib/crypto/krb/enctype_util.c
+++ b/src/lib/crypto/krb/enctype_util.c
@@ -131,3 +131,19 @@ krb5_enctype_to_name(krb5_enctype enctype, krb5_boolean shortest,
return ENOMEM;
return 0;
}
+
+/* The security of a mechanism cannot be summarized with a simple integer
+ * value, but we provide a per-enctype value for Cyrus SASL's SSF. */
+krb5_error_code
+k5_enctype_to_ssf(krb5_enctype enctype, unsigned int *ssf_out)
+{
+ const struct krb5_keytypes *ktp;
+
+ *ssf_out = 0;
+
+ ktp = find_enctype(enctype);
+ if (ktp == NULL)
+ return EINVAL;
+ *ssf_out = ktp->ssf;
+ return 0;
+}
diff --git a/src/lib/crypto/krb/etypes.c b/src/lib/crypto/krb/etypes.c
index 0e5e977d4..53d4a5c79 100644
--- a/src/lib/crypto/krb/etypes.c
+++ b/src/lib/crypto/krb/etypes.c
@@ -42,7 +42,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
krb5int_des_string_to_key, k5_rand2key_des,
krb5int_des_prf,
CKSUMTYPE_RSA_MD5_DES,
- ETYPE_WEAK },
+ ETYPE_WEAK, 56 },
{ ENCTYPE_DES_CBC_MD4,
"des-cbc-md4", { 0 }, "DES cbc mode with RSA-MD4",
&krb5int_enc_des, &krb5int_hash_md4,
@@ -51,7 +51,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
krb5int_des_string_to_key, k5_rand2key_des,
krb5int_des_prf,
CKSUMTYPE_RSA_MD4_DES,
- ETYPE_WEAK },
+ ETYPE_WEAK, 56 },
{ ENCTYPE_DES_CBC_MD5,
"des-cbc-md5", { "des" }, "DES cbc mode with RSA-MD5",
&krb5int_enc_des, &krb5int_hash_md5,
@@ -60,7 +60,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
krb5int_des_string_to_key, k5_rand2key_des,
krb5int_des_prf,
CKSUMTYPE_RSA_MD5_DES,
- ETYPE_WEAK },
+ ETYPE_WEAK, 56 },
{ ENCTYPE_DES_CBC_RAW,
"des-cbc-raw", { 0 }, "DES cbc mode raw",
&krb5int_enc_des, NULL,
@@ -69,7 +69,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
krb5int_des_string_to_key, k5_rand2key_des,
krb5int_des_prf,
0,
- ETYPE_WEAK },
+ ETYPE_WEAK, 56 },
{ ENCTYPE_DES3_CBC_RAW,
"des3-cbc-raw", { 0 }, "Triple DES cbc mode raw",
&krb5int_enc_des3, NULL,
@@ -78,7 +78,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
krb5int_dk_string_to_key, k5_rand2key_des3,
NULL, /*PRF*/
0,
- ETYPE_WEAK },
+ ETYPE_WEAK, 112 },
{ ENCTYPE_DES3_CBC_SHA1,
"des3-cbc-sha1", { "des3-hmac-sha1", "des3-cbc-sha1-kd" },
@@ -89,7 +89,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
krb5int_dk_string_to_key, k5_rand2key_des3,
krb5int_dk_prf,
CKSUMTYPE_HMAC_SHA1_DES3,
- 0 /*flags*/ },
+ 0 /*flags*/, 112 },
{ ENCTYPE_DES_HMAC_SHA1,
"des-hmac-sha1", { 0 }, "DES with HMAC/sha1",
@@ -99,7 +99,10 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
krb5int_dk_string_to_key, k5_rand2key_des,
NULL, /*PRF*/
0,
- ETYPE_WEAK },
+ ETYPE_WEAK, 56 },
+
+ /* rc4-hmac uses a 128-bit key, but due to weaknesses in the RC4 cipher, we
+ * consider its strength degraded and assign it an SSF value of 64. */
{ ENCTYPE_ARCFOUR_HMAC,
"arcfour-hmac", { "rc4-hmac", "arcfour-hmac-md5" },
"ArcFour with HMAC/md5",
@@ -110,7 +113,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
krb5int_arcfour_decrypt, krb5int_arcfour_string_to_key,
k5_rand2key_direct, krb5int_arcfour_prf,
CKSUMTYPE_HMAC_MD5_ARCFOUR,
- 0 /*flags*/ },
+ 0 /*flags*/, 64 },
{ ENCTYPE_ARCFOUR_HMAC_EXP,
"arcfour-hmac-exp", { "rc4-hmac-exp", "arcfour-hmac-md5-exp" },
"Exportable ArcFour with HMAC/md5",
@@ -121,7 +124,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
krb5int_arcfour_decrypt, krb5int_arcfour_string_to_key,
k5_rand2key_direct, krb5int_arcfour_prf,
CKSUMTYPE_HMAC_MD5_ARCFOUR,
- ETYPE_WEAK
+ ETYPE_WEAK, 40
},
{ ENCTYPE_AES128_CTS_HMAC_SHA1_96,
@@ -133,7 +136,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
krb5int_aes_string_to_key, k5_rand2key_direct,
krb5int_dk_prf,
CKSUMTYPE_HMAC_SHA1_96_AES128,
- 0 /*flags*/ },
+ 0 /*flags*/, 128 },
{ ENCTYPE_AES256_CTS_HMAC_SHA1_96,
"aes256-cts-hmac-sha1-96", { "aes256-cts", "aes256-sha1" },
"AES-256 CTS mode with 96-bit SHA-1 HMAC",
@@ -143,7 +146,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
krb5int_aes_string_to_key, k5_rand2key_direct,
krb5int_dk_prf,
CKSUMTYPE_HMAC_SHA1_96_AES256,
- 0 /*flags*/ },
+ 0 /*flags*/, 256 },
{ ENCTYPE_CAMELLIA128_CTS_CMAC,
"camellia128-cts-cmac", { "camellia128-cts" },
@@ -155,7 +158,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
krb5int_camellia_string_to_key, k5_rand2key_direct,
krb5int_dk_cmac_prf,
CKSUMTYPE_CMAC_CAMELLIA128,
- 0 /*flags*/ },
+ 0 /*flags*/, 128 },
{ ENCTYPE_CAMELLIA256_CTS_CMAC,
"camellia256-cts-cmac", { "camellia256-cts" },
"Camellia-256 CTS mode with CMAC",
@@ -166,7 +169,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
krb5int_camellia_string_to_key, k5_rand2key_direct,
krb5int_dk_cmac_prf,
CKSUMTYPE_CMAC_CAMELLIA256,
- 0 /*flags */ },
+ 0 /*flags */, 256 },
{ ENCTYPE_AES128_CTS_HMAC_SHA256_128,
"aes128-cts-hmac-sha256-128", { "aes128-sha2" },
@@ -177,7 +180,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
krb5int_aes2_string_to_key, k5_rand2key_direct,
krb5int_aes2_prf,
CKSUMTYPE_HMAC_SHA256_128_AES128,
- 0 /*flags*/ },
+ 0 /*flags*/, 128 },
{ ENCTYPE_AES256_CTS_HMAC_SHA384_192,
"aes256-cts-hmac-sha384-192", { "aes256-sha2" },
"AES-256 CTS mode with 192-bit SHA-384 HMAC",
@@ -187,7 +190,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
krb5int_aes2_string_to_key, k5_rand2key_direct,
krb5int_aes2_prf,
CKSUMTYPE_HMAC_SHA384_192_AES256,
- 0 /*flags*/ },
+ 0 /*flags*/, 256 },
};
const int krb5int_enctypes_length =
diff --git a/src/lib/crypto/libk5crypto.exports b/src/lib/crypto/libk5crypto.exports
index 447e45644..82eb5f30c 100644
--- a/src/lib/crypto/libk5crypto.exports
+++ b/src/lib/crypto/libk5crypto.exports
@@ -108,3 +108,4 @@ krb5int_nfold
k5_allow_weak_pbkdf2iter
krb5_c_prfplus
krb5_c_derive_prfplus
+k5_enctype_to_ssf
diff --git a/src/lib/gssapi/generic/gssapi_ext.h b/src/lib/gssapi/generic/gssapi_ext.h
index 9ad44216d..9d3a7e736 100644
--- a/src/lib/gssapi/generic/gssapi_ext.h
+++ b/src/lib/gssapi/generic/gssapi_ext.h
@@ -575,4 +575,15 @@ gss_import_cred(
}
#endif
+/*
+ * When used with gss_inquire_sec_context_by_oid(), return a buffer set with
+ * the first member containing an unsigned 32-bit integer in network byte
+ * order. This is the Security Strength Factor (SSF) associated with the
+ * secure channel established by the security context. NOTE: This value is
+ * made available solely as an indication for use by APIs like Cyrus SASL that
+ * classify the strength of a secure channel via this number. The strength of
+ * a channel cannot necessarily be represented by a simple number.
+ */
+GSS_DLLIMP extern gss_OID GSS_C_SEC_CONTEXT_SASL_SSF;
+
#endif /* GSSAPI_EXT_H_ */
diff --git a/src/lib/gssapi/generic/gssapi_generic.c b/src/lib/gssapi/generic/gssapi_generic.c
index 5496aa335..fa144c2bf 100644
--- a/src/lib/gssapi/generic/gssapi_generic.c
+++ b/src/lib/gssapi/generic/gssapi_generic.c
@@ -157,6 +157,13 @@ static const gss_OID_desc const_oids[] = {
{7, (void *)"\x2b\x06\x01\x05\x05\x0d\x19"},
{7, (void *)"\x2b\x06\x01\x05\x05\x0d\x1a"},
{7, (void *)"\x2b\x06\x01\x05\x05\x0d\x1b"},
+
+ /*
+ * GSS_SEC_CONTEXT_SASL_SSF_OID 1.2.840.113554.1.2.2.5.15
+ * iso(1) member-body(2) United States(840) mit(113554)
+ * infosys(1) gssapi(2) krb5(2) krb5-gssapi-ext(5) sasl-ssf(15)
+ */
+ {11, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0f"},
};
/* Here are the constants which point to the static structure above.
@@ -218,6 +225,8 @@ GSS_DLLIMP gss_const_OID GSS_C_MA_PFS = oids+33;
GSS_DLLIMP gss_const_OID GSS_C_MA_COMPRESS = oids+34;
GSS_DLLIMP gss_const_OID GSS_C_MA_CTX_TRANS = oids+35;
+GSS_DLLIMP gss_OID GSS_C_SEC_CONTEXT_SASL_SSF = oids+36;
+
static gss_OID_set_desc gss_ma_known_attrs_desc = { 27, oids+9 };
gss_OID_set gss_ma_known_attrs = &gss_ma_known_attrs_desc;
diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h
index d7bdef7e2..ef030707e 100644
--- a/src/lib/gssapi/krb5/gssapiP_krb5.h
+++ b/src/lib/gssapi/krb5/gssapiP_krb5.h
@@ -1144,6 +1144,12 @@ gss_krb5int_extract_authtime_from_sec_context(OM_uint32 *,
const gss_OID,
gss_buffer_set_t *);
+#define GET_SEC_CONTEXT_SASL_SSF_OID_LENGTH 11
+#define GET_SEC_CONTEXT_SASL_SSF_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0f"
+OM_uint32
+gss_krb5int_sec_context_sasl_ssf(OM_uint32 *, const gss_ctx_id_t,
+ const gss_OID, gss_buffer_set_t *);
+
#define GSS_KRB5_IMPORT_CRED_OID_LENGTH 11
#define GSS_KRB5_IMPORT_CRED_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0d"
diff --git a/src/lib/gssapi/krb5/gssapi_krb5.c b/src/lib/gssapi/krb5/gssapi_krb5.c
index 99092ccab..de4131980 100644
--- a/src/lib/gssapi/krb5/gssapi_krb5.c
+++ b/src/lib/gssapi/krb5/gssapi_krb5.c
@@ -352,6 +352,10 @@ static struct {
{
{GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID_LENGTH, GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID},
gss_krb5int_extract_authtime_from_sec_context
+ },
+ {
+ {GET_SEC_CONTEXT_SASL_SSF_OID_LENGTH, GET_SEC_CONTEXT_SASL_SSF_OID},
+ gss_krb5int_sec_context_sasl_ssf
}
};
diff --git a/src/lib/gssapi/krb5/inq_context.c b/src/lib/gssapi/krb5/inq_context.c
index 9024b3c7e..d2e466e60 100644
--- a/src/lib/gssapi/krb5/inq_context.c
+++ b/src/lib/gssapi/krb5/inq_context.c
@@ -310,3 +310,30 @@ gss_krb5int_extract_authtime_from_sec_context(OM_uint32 *minor_status,
return generic_gss_add_buffer_set_member(minor_status, &rep, data_set);
}
+
+OM_uint32
+gss_krb5int_sec_context_sasl_ssf(OM_uint32 *minor_status,
+ const gss_ctx_id_t context_handle,
+ const gss_OID desired_object,
+ gss_buffer_set_t *data_set)
+{
+ krb5_gss_ctx_id_rec *ctx;
+ krb5_key key;
+ krb5_error_code code;
+ gss_buffer_desc ssfbuf;
+ unsigned int ssf;
+ uint8_t buf[4];
+
+ ctx = (krb5_gss_ctx_id_rec *)context_handle;
+ key = ctx->have_acceptor_subkey ? ctx->acceptor_subkey : ctx->subkey;
+
+ code = k5_enctype_to_ssf(key->keyblock.enctype, &ssf);
+ if (code)
+ return GSS_S_FAILURE;
+
+ store_32_be(ssf, buf);
+ ssfbuf.value = buf;
+ ssfbuf.length = sizeof(buf);
+
+ return generic_gss_add_buffer_set_member(minor_status, &ssfbuf, data_set);
+}
diff --git a/src/lib/gssapi/libgssapi_krb5.exports b/src/lib/gssapi/libgssapi_krb5.exports
index 9facb3f42..936540e41 100644
--- a/src/lib/gssapi/libgssapi_krb5.exports
+++ b/src/lib/gssapi/libgssapi_krb5.exports
@@ -37,6 +37,7 @@ GSS_C_MA_CBINDINGS
GSS_C_MA_PFS
GSS_C_MA_COMPRESS
GSS_C_MA_CTX_TRANS
+GSS_C_SEC_CONTEXT_SASL_SSF
gss_accept_sec_context
gss_acquire_cred
gss_acquire_cred_with_password
diff --git a/src/lib/gssapi32.def b/src/lib/gssapi32.def
index 362b9bce8..dff057754 100644
--- a/src/lib/gssapi32.def
+++ b/src/lib/gssapi32.def
@@ -182,3 +182,6 @@ EXPORTS
gss_verify_mic_iov @146
; Added in 1.14
GSS_KRB5_CRED_NO_CI_FLAGS_X @147 DATA
+; Added in 1.16
+; GSS_KRB5_GET_CRED_IMPERSONATOR @148 DATA
+ GSS_C_SEC_CONTEXT_SASL_SSF @149 DATA
diff --git a/src/lib/krb5_32.def b/src/lib/krb5_32.def
index e5b560dfc..f7b428e16 100644
--- a/src/lib/krb5_32.def
+++ b/src/lib/krb5_32.def
@@ -470,3 +470,6 @@ EXPORTS
krb5_get_init_creds_opt_set_pac_request @435
krb5int_trace @436 ; PRIVATE GSSAPI
krb5_expand_hostname @437
+
+; new in 1.16
+ k5_enctype_to_ssf @438 ; PRIVATE GSSAPI
diff --git a/src/tests/gssapi/t_enctypes.c b/src/tests/gssapi/t_enctypes.c
index a2ad18f47..3fd31e2f8 100644
--- a/src/tests/gssapi/t_enctypes.c
+++ b/src/tests/gssapi/t_enctypes.c
@@ -32,6 +32,7 @@
#include "k5-int.h"
#include "common.h"
+#include "gssapi_ext.h"
/*
* This test program establishes contexts with the krb5 mech, the default
@@ -86,6 +87,9 @@ main(int argc, char *argv[])
gss_krb5_lucid_context_v1_t *ilucid, *alucid;
gss_krb5_rfc1964_keydata_t *i1964, *a1964;
gss_krb5_cfx_keydata_t *icfx, *acfx;
+ gss_buffer_set_t bufset = GSS_C_NO_BUFFER_SET;
+ gss_OID ssf_oid = GSS_C_SEC_CONTEXT_SASL_SSF;
+ unsigned int ssf;
size_t count;
void *lptr;
int c;
@@ -139,6 +143,16 @@ main(int argc, char *argv[])
establish_contexts(&mech_krb5, icred, acred, tname, flags, &ictx, &actx,
NULL, NULL, NULL);
+ /* Query the SSF value and range-check the result. */
+ major = gss_inquire_sec_context_by_oid(&minor, ictx, ssf_oid, &bufset);
+ check_gsserr("gss_inquire_sec_context_by_oid(ssf)", major, minor);
+ if (bufset->elements[0].length != 4)
+ errout("SSF buffer has unexpected length");
+ ssf = load_32_be(bufset->elements[0].value);
+ if (ssf < 56 || ssf > 256)
+ errout("SSF value not within acceptable range (56-256)");
+ (void)gss_release_buffer_set(&minor, &bufset);
+
/* Export to lucid contexts. */
major = gss_krb5_export_lucid_sec_context(&minor, &ictx, 1, &lptr);
check_gsserr("gss_export_lucid_sec_context(initiator)", major, minor);

View file

@ -0,0 +1,45 @@
From 5faadd66bb278bcc1c618e199444e3012eeec215 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Wed, 11 Jan 2017 10:49:30 -0500
Subject: [PATCH] Add test case for PKINIT DH renegotiation
In t_pkinit.py, add a PKINIT test case where the KDC sends
KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED and the client retries with the
KDC's TD_DH_PARAMETERS value, using the clpreauth tryagain method.
Use the trace log to verify that the renegotiation actually takes
place.
(cherry picked from commit 7ad7eb7fd591e6c789ea24b94eccbf74ee4d79f8)
---
src/tests/t_pkinit.py | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/src/tests/t_pkinit.py b/src/tests/t_pkinit.py
index ac4d326b6..183977750 100755
--- a/src/tests/t_pkinit.py
+++ b/src/tests/t_pkinit.py
@@ -174,6 +174,24 @@ realm.kinit(realm.user_princ,
'-X', 'flag_RSA_PROTOCOL=yes'])
realm.klist(realm.user_princ)
+# Test a DH parameter renegotiation by temporarily setting a 4096-bit
+# minimum on the KDC.
+tracefile = os.path.join(realm.testdir, 'trace')
+minbits_kdc_conf = {'realms': {'$realm': {'pkinit_dh_min_bits': '4096'}}}
+minbits_env = realm.special_env('restrict', True, kdc_conf=minbits_kdc_conf)
+realm.stop_kdc()
+realm.start_kdc(env=minbits_env)
+realm.run(['env', 'KRB5_TRACE=' + tracefile, kinit, '-X',
+ 'X509_user_identity=' + file_identity, realm.user_princ])
+with open(tracefile, 'r') as f:
+ trace = f.read()
+if ('Key parameters not accepted' not in trace or
+ 'Preauth tryagain input types' not in trace or
+ 'trying again with KDC-provided parameters' not in trace):
+ fail('DH renegotiation steps not found in kinit trace log')
+realm.stop_kdc()
+realm.start_kdc()
+
# Run the basic test - PKINIT with FILE: identity, with a password on the key,
# supplied by the prompter.
# Expect failure if the responder does nothing, and we have no prompter.

View file

@ -0,0 +1,968 @@
From 5e3885e9d7c7cd2a19a291cdb1e54312ca7f7e1f Mon Sep 17 00:00:00 2001
From: Matt Rogers <mrogers@redhat.com>
Date: Mon, 5 Dec 2016 12:22:45 -0500
Subject: [PATCH] Add test cert generation to make-certs.sh
Add additional test certificates for UPN matching. Run make-certs.sh
to regenerate certs.
ticket: 8528
(cherry picked from commit 5a1d0388ba2e4ec510ed715ce5fbc7f748941425)
---
src/tests/dejagnu/pkinit-certs/ca.pem | 54 ++++++++++++------------
src/tests/dejagnu/pkinit-certs/kdc.pem | 50 ++++++++++++----------
src/tests/dejagnu/pkinit-certs/make-certs.sh | 53 ++++++++++++++++++++++-
src/tests/dejagnu/pkinit-certs/privkey-enc.pem | 52 +++++++++++------------
src/tests/dejagnu/pkinit-certs/privkey.pem | 50 +++++++++++-----------
src/tests/dejagnu/pkinit-certs/user-enc.p12 | Bin 3029 -> 2837 bytes
src/tests/dejagnu/pkinit-certs/user-upn.p12 | Bin 0 -> 2829 bytes
src/tests/dejagnu/pkinit-certs/user-upn.pem | 28 +++++++++++++
src/tests/dejagnu/pkinit-certs/user-upn2.p12 | Bin 0 -> 2813 bytes
src/tests/dejagnu/pkinit-certs/user-upn2.pem | 28 +++++++++++++
src/tests/dejagnu/pkinit-certs/user-upn3.csr | 16 +++++++
src/tests/dejagnu/pkinit-certs/user-upn3.p12 | Bin 0 -> 2829 bytes
src/tests/dejagnu/pkinit-certs/user-upn3.pem | 28 +++++++++++++
src/tests/dejagnu/pkinit-certs/user.p12 | Bin 3104 -> 2837 bytes
src/tests/dejagnu/pkinit-certs/user.pem | 56 ++++++++++++-------------
15 files changed, 283 insertions(+), 132 deletions(-)
create mode 100644 src/tests/dejagnu/pkinit-certs/user-upn.p12
create mode 100644 src/tests/dejagnu/pkinit-certs/user-upn.pem
create mode 100644 src/tests/dejagnu/pkinit-certs/user-upn2.p12
create mode 100644 src/tests/dejagnu/pkinit-certs/user-upn2.pem
create mode 100644 src/tests/dejagnu/pkinit-certs/user-upn3.csr
create mode 100644 src/tests/dejagnu/pkinit-certs/user-upn3.p12
create mode 100644 src/tests/dejagnu/pkinit-certs/user-upn3.pem
diff --git a/src/tests/dejagnu/pkinit-certs/ca.pem b/src/tests/dejagnu/pkinit-certs/ca.pem
index 55fe02c92..44c917687 100644
--- a/src/tests/dejagnu/pkinit-certs/ca.pem
+++ b/src/tests/dejagnu/pkinit-certs/ca.pem
@@ -1,29 +1,29 @@
-----BEGIN CERTIFICATE-----
-MIIE5TCCA82gAwIBAgIJANsFDWp1HgAaMA0GCSqGSIb3DQEBBQUAMIGnMQswCQYD
-VQQGEwJVUzEWMBQGA1UECBMNTWFzc2FjaHVzZXR0czESMBAGA1UEBxMJQ2FtYnJp
-ZGdlMQwwCgYDVQQKEwNNSVQxKTAnBgNVBAsTIEluc2VjdXJlIFBraW5pdCBLZXJi
-ZXJvcyB0ZXN0IENBMTMwMQYDVQQDFCpwa2luaXQgdGVzdCBzdWl0ZSBDQTsgZG8g
-bm90IHVzZSBvdGhlcndpc2UwHhcNMTAwMTA2MTQ1MTI3WhcNMjMwOTE1MTQ1MTI3
-WjCBpzELMAkGA1UEBhMCVVMxFjAUBgNVBAgTDU1hc3NhY2h1c2V0dHMxEjAQBgNV
-BAcTCUNhbWJyaWRnZTEMMAoGA1UEChMDTUlUMSkwJwYDVQQLEyBJbnNlY3VyZSBQ
-a2luaXQgS2VyYmVyb3MgdGVzdCBDQTEzMDEGA1UEAxQqcGtpbml0IHRlc3Qgc3Vp
-dGUgQ0E7IGRvIG5vdCB1c2Ugb3RoZXJ3aXNlMIIBIjANBgkqhkiG9w0BAQEFAAOC
-AQ8AMIIBCgKCAQEAnYLMe58ny00MgskJP7tZ3PIQRpQkXGLJZKI0HfntCRbIuvmn
-ZejPSKdNMyejzRIyjdw1FDJUAnpXYcic3TD5817G5H63UrllAGuy+lhQWNzE6c6K
-ueerevR3pMaqHXonaflVasUu5e2AAWVnFbz4x04uLlQejqPwm5sR1xTeLUnVfSY7
-5NbXGIE488iDV0wW8nqGoVWn/TsRd+7KuQUIkJpt8+V6Jk6hPIcPqe6h7mXNGsgc
-5dBSqBwVcjU9DbeT4xxxEmgQdLt7qdNwV1ZPLQnTQpogNrT5uf3oSbOTsyM02GOW
-riIRmsqq81sfMrpviTRRDwoqTUEhoCSor0UmcwIDAQABo4IBEDCCAQwwHQYDVR0O
-BBYEFFn82RUKgTvkFn0cgwyCQpNeWCxYMIHcBgNVHSMEgdQwgdGAFFn82RUKgTvk
-Fn0cgwyCQpNeWCxYoYGtpIGqMIGnMQswCQYDVQQGEwJVUzEWMBQGA1UECBMNTWFz
-c2FjaHVzZXR0czESMBAGA1UEBxMJQ2FtYnJpZGdlMQwwCgYDVQQKEwNNSVQxKTAn
-BgNVBAsTIEluc2VjdXJlIFBraW5pdCBLZXJiZXJvcyB0ZXN0IENBMTMwMQYDVQQD
-FCpwa2luaXQgdGVzdCBzdWl0ZSBDQTsgZG8gbm90IHVzZSBvdGhlcndpc2WCCQDb
-BQ1qdR4AGjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQBVL2Q6Xubs
-gm881cAy6esku17/BSTZur7hCLHTGof1ZKNcCXALjmwNYNC3tl6owqpX8CSdBdsD
-Bw/Vs9p3mqnaVEoZc8uW8zS6LoAQbcqiYdQHdEXMh3ec8uvAfmdlQsIsm5Ux8q8L
-NM6bKnUOqOFOHme+RC4FGOLb8JqnnuQdwyIZaUyQP6hXbw4zyDphfgo1ZlZn20xh
-I555kPfAZKEi/d3WY0oN4k+sfCs9tWRNjmqZfKkH1OqRpjCFGG0b0vY77MFRMuPz
-YtN2iD3plgla7KkUMljp9th/Z8Ok79uA1TNLYKzoBjlAX0vToxfa8rrSNo1dHFKT
-e5Tj7+29DE4I
+MIIE5TCCA82gAwIBAgIBATANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx
+FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG
+A1UECgwDTUlUMSkwJwYDVQQLDCBJbnNlY3VyZSBQS0lOSVQgS2VyYmVyb3MgdGVz
+dCBDQTEzMDEGA1UEAwwqcGtpbml0IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ug
+b3RoZXJ3aXNlMB4XDTE2MTIxMjE0NDYzOVoXDTI3MTEyNTE0NDYzOVowgacxCzAJ
+BgNVBAYTAlVTMRYwFAYDVQQIDA1NYXNzYWNodXNldHRzMRIwEAYDVQQHDAlDYW1i
+cmlkZ2UxDDAKBgNVBAoMA01JVDEpMCcGA1UECwwgSW5zZWN1cmUgUEtJTklUIEtl
+cmJlcm9zIHRlc3QgQ0ExMzAxBgNVBAMMKnBraW5pdCB0ZXN0IHN1aXRlIENBOyBk
+byBub3QgdXNlIG90aGVyd2lzZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBANOWvXDyubZ/Kf8QYdPSRk/rsogzqS0rycNEJp/6rPpTS40UxGae5MyLHfmN
+l2mSevRoHSqhb7cfT6n9kR2kb3HB0qhhhecHey4sGwd+m7WMhBQgVtYaiWkuEQDC
+7/SWkRYzmYX8J41vrQulXU2/2pOQCmG4NKPsNo+vcKoT2SHl6qr3lflUaIG0wDu4
+bFrWszkxcuSkU7SSXDf2xTTTJ8QftO6WQY3g0+dAhbjZFKxRO5uipxURez5EemVs
+Re86vXEILka85tiVS4maCn3l3FWMqcBHRFNa+/osTb0J/OmvvdQ3bzvscG7KDRtM
+bRUnpWClr5R+AbGVvKocj5I1+G0CAwEAAaOCARgwggEUMB0GA1UdDgQWBBRrwMkO
+fMoN3ofjotSWjK0c27fYYjCB1AYDVR0jBIHMMIHJgBRrwMkOfMoN3ofjotSWjK0c
+27fYYqGBraSBqjCBpzELMAkGA1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0
+dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoGA1UECgwDTUlUMSkwJwYDVQQLDCBJ
+bnNlY3VyZSBQS0lOSVQgS2VyYmVyb3MgdGVzdCBDQTEzMDEGA1UEAwwqcGtpbml0
+IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ugb3RoZXJ3aXNlggEBMAsGA1UdDwQE
+AwIB/jAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAN82zurZwM
+TugUG6b1symxXxOdDqwinwIlQjzXJ8mTRv31q+YwNdYvdWn1aex8v44qjFDjEP80
+83y18CjjBHznwxsHll80QmFHjpy6xtRrUC/Ak7jfKnDiTKQYBdgmF4/UiVQu354e
+QI6jPMQlrWZXThlRuBjM55hs4tgRYeTgbd4VSZzVQXdm2ViZkg8SGqw0R2ZRnG91
+dfXkhu/tTruguPAT3MQ2pTK/CoHHA4W2piQbBDqIl83fphRhYxyW/cCF2mvZZUhE
+AfWhgYDeTDxHKG3Jfmm+ujMo5HscgeUpJ7XjZdobNhkQjD1piyuGzFkUfo2XzA6m
+kMz4Jq4cnvpz
-----END CERTIFICATE-----
diff --git a/src/tests/dejagnu/pkinit-certs/kdc.pem b/src/tests/dejagnu/pkinit-certs/kdc.pem
index 5575ab579..8820ad447 100644
--- a/src/tests/dejagnu/pkinit-certs/kdc.pem
+++ b/src/tests/dejagnu/pkinit-certs/kdc.pem
@@ -1,25 +1,29 @@
-----BEGIN CERTIFICATE-----
-MIIEMjCCAxqgAwIBAgIBAjANBgkqhkiG9w0BAQUFADCBpzELMAkGA1UEBhMCVVMx
-FjAUBgNVBAgTDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcTCUNhbWJyaWRnZTEMMAoG
-A1UEChMDTUlUMSkwJwYDVQQLEyBJbnNlY3VyZSBQa2luaXQgS2VyYmVyb3MgdGVz
-dCBDQTEzMDEGA1UEAxQqcGtpbml0IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ug
-b3RoZXJ3aXNlMB4XDTEwMDEwNjE0NTgwOFoXDTIzMDkxNTE0NTgwOFowSjELMAkG
-A1UEBhMCVVMxFjAUBgNVBAgTDU1hc3NhY2h1c2V0dHMxFTATBgNVBAoTDEtSQlRF
-U1QuQ09NIDEMMAoGA1UECxMDS0RDMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
-CgKCAQEAnYLMe58ny00MgskJP7tZ3PIQRpQkXGLJZKI0HfntCRbIuvmnZejPSKdN
-MyejzRIyjdw1FDJUAnpXYcic3TD5817G5H63UrllAGuy+lhQWNzE6c6KueerevR3
-pMaqHXonaflVasUu5e2AAWVnFbz4x04uLlQejqPwm5sR1xTeLUnVfSY75NbXGIE4
-88iDV0wW8nqGoVWn/TsRd+7KuQUIkJpt8+V6Jk6hPIcPqe6h7mXNGsgc5dBSqBwV
-cjU9DbeT4xxxEmgQdLt7qdNwV1ZPLQnTQpogNrT5uf3oSbOTsyM02GOWriIRmsqq
-81sfMrpviTRRDwoqTUEhoCSor0UmcwIDAQABo4HEMIHBMAkGA1UdEwQCMAAwCwYD
-VR0PBAQDAgPoMBIGA1UdJQQLMAkGBysGAQUCAwUwHQYDVR0OBBYEFFn82RUKgTvk
-Fn0cgwyCQpNeWCxYMB8GA1UdIwQYMBaAFFn82RUKgTvkFn0cgwyCQpNeWCxYMAkG
-A1UdEgQCMAAwSAYDVR0RBEEwP6A9BgYrBgEFAgKgMzAxoA0bC0tSQlRFU1QuQ09N
-oSAwHqADAgEBoRcwFRsGa3JidGd0GwtLUkJURVNULkNPTTANBgkqhkiG9w0BAQUF
-AAOCAQEAP0byILHLWPyGlv/1HN34DfIpLdVkgGar2yceMtZ2v/7UjeA5PlZc8DFM
-20bTq/vIN0eWDTPLI57e+MzQTMxs2UHsic4su0m5DG0cvQTsBXRK51CW/qUF+4n0
-qSEORULiDF6LNoo8akoLukNBhzBh+aqYt4aB46hhsmDmNZTDP1CXsNGHQI9/L52l
-oqpUGx8tBpKIFos95PSajXrQn2u66rSMMi4aawitM2igurHPDMbC+XvEYMtXpOS5
-3PEzXEYiSV3TWLTzIE9ytswHeZyHCbp7XHx0LVZFxzqtIe4qmwJJOGhlbH21Izr4
-feF5h5e2ZrOVREY4cKkJmJhEwsqBVA==
+MIIE4TCCA8mgAwIBAgIBAjANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx
+FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG
+A1UECgwDTUlUMSkwJwYDVQQLDCBJbnNlY3VyZSBQS0lOSVQgS2VyYmVyb3MgdGVz
+dCBDQTEzMDEGA1UEAwwqcGtpbml0IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ug
+b3RoZXJ3aXNlMB4XDTE2MTIxMjE0NDYzOVoXDTI3MTEyNTE0NDYzOVowSTELMAkG
+A1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxFDASBgNVBAoMC0tSQlRF
+U1QuQ09NMQwwCgYDVQQDDANLREMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQDTlr1w8rm2fyn/EGHT0kZP67KIM6ktK8nDRCaf+qz6U0uNFMRmnuTMix35
+jZdpknr0aB0qoW+3H0+p/ZEdpG9xwdKoYYXnB3suLBsHfpu1jIQUIFbWGolpLhEA
+wu/0lpEWM5mF/CeNb60LpV1Nv9qTkAphuDSj7DaPr3CqE9kh5eqq95X5VGiBtMA7
+uGxa1rM5MXLkpFO0klw39sU00yfEH7TulkGN4NPnQIW42RSsUTuboqcVEXs+RHpl
+bEXvOr1xCC5GvObYlUuJmgp95dxVjKnAR0RTWvv6LE29Cfzpr73UN2877HBuyg0b
+TG0VJ6Vgpa+UfgGxlbyqHI+SNfhtAgMBAAGjggFzMIIBbzAdBgNVHQ4EFgQUa8DJ
+DnzKDd6H46LUloytHNu32GIwgdQGA1UdIwSBzDCByYAUa8DJDnzKDd6H46LUloyt
+HNu32GKhga2kgaowgacxCzAJBgNVBAYTAlVTMRYwFAYDVQQIDA1NYXNzYWNodXNl
+dHRzMRIwEAYDVQQHDAlDYW1icmlkZ2UxDDAKBgNVBAoMA01JVDEpMCcGA1UECwwg
+SW5zZWN1cmUgUEtJTklUIEtlcmJlcm9zIHRlc3QgQ0ExMzAxBgNVBAMMKnBraW5p
+dCB0ZXN0IHN1aXRlIENBOyBkbyBub3QgdXNlIG90aGVyd2lzZYIBATALBgNVHQ8E
+BAMCA+gwDAYDVR0TAQH/BAIwADBIBgNVHREEQTA/oD0GBisGAQUCAqAzMDGgDRsL
+S1JCVEVTVC5DT02hIDAeoAMCAQGhFzAVGwZrcmJ0Z3QbC0tSQlRFU1QuQ09NMBIG
+A1UdJQQLMAkGBysGAQUCAwUwDQYJKoZIhvcNAQELBQADggEBABJpKRfoFxyOUp9i
+Z/fWql5anJuZElgBSbEC5sL2mMcmL/1vqkiYF3uF6/Z9g4X1LX4QDuvaXCJSdQ+b
+JpmhklSyFN+E/agxZtSim+AjTgYJ0y+jwNvX6kZQ8fW3VLNJZ+zbb4n4txfgSROn
+7ub+02mo4DYajyD9TE/qLzmVaiKLEKW0osjxX3fB1RN/d7zm//NDPsezzUzmKkgz
+u0ML7HGYUNY3+/SC4ShF/But1IoY3/I46lB6BMrIn9X6fsVKlipqrRFniUk0qDlJ
+fbKVB+MvGEFoqFNlMoGiufmDjnJl4PQZCVEmXO8wAVGeK8NpTBCjltAAsoVJVnjq
+AC5jSAM=
-----END CERTIFICATE-----
diff --git a/src/tests/dejagnu/pkinit-certs/make-certs.sh b/src/tests/dejagnu/pkinit-certs/make-certs.sh
index b82ef6f83..0f07709b0 100755
--- a/src/tests/dejagnu/pkinit-certs/make-certs.sh
+++ b/src/tests/dejagnu/pkinit-certs/make-certs.sh
@@ -4,7 +4,9 @@ NAMETYPE=1
KEYSIZE=2048
DAYS=4000
REALM=KRBTEST.COM
+LOWREALM=krbtest.com
KRB5_PRINCIPAL_SAN=1.3.6.1.5.2.2
+KRB5_UPN_SAN=1.3.6.1.4.1.311.20.2.3
PKINIT_KDC_EKU=1.3.6.1.5.2.3.5
PKINIT_CLIENT_EKU=1.3.6.1.5.2.3.4
TLS_SERVER_EKU=1.3.6.1.5.5.7.3.1
@@ -85,6 +87,30 @@ keyUsage = nonRepudiation,digitalSignature,keyEncipherment,keyAgreement
basicConstraints = critical,CA:FALSE
subjectAltName = otherName:$KRB5_PRINCIPAL_SAN;SEQUENCE:krb5princ_client
extendedKeyUsage = $CLIENT_EKU_LIST
+
+[exts_upn_client]
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid:always,issuer:always
+keyUsage = nonRepudiation,digitalSignature,keyEncipherment,keyAgreement
+basicConstraints = critical,CA:FALSE
+subjectAltName = otherName:$KRB5_UPN_SAN;UTF8:user@$LOWREALM
+extendedKeyUsage = $CLIENT_EKU_LIST
+
+[exts_upn2_client]
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid:always,issuer:always
+keyUsage = nonRepudiation,digitalSignature,keyEncipherment,keyAgreement
+basicConstraints = critical,CA:FALSE
+subjectAltName = otherName:$KRB5_UPN_SAN;UTF8:user
+extendedKeyUsage = $CLIENT_EKU_LIST
+
+[exts_upn3_client]
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid:always,issuer:always
+keyUsage = nonRepudiation,digitalSignature,keyEncipherment,keyAgreement
+basicConstraints = critical,CA:FALSE
+subjectAltName = otherName:$KRB5_UPN_SAN;UTF8:user@$REALM
+extendedKeyUsage = $CLIENT_EKU_LIST
EOF
# Generate a private key.
@@ -113,5 +139,30 @@ openssl pkcs12 -export -in user.pem -inkey privkey.pem -out user.p12 \
openssl pkcs12 -export -in user.pem -inkey privkey.pem -out user-enc.p12 \
-passout pass:encrypted
+# Generate a client certificate and PKCS#12 bundles with a UPN SAN.
+SUBJECT=user openssl req -config openssl.cnf -new -subj /CN=user \
+ -key privkey.pem -out user-upn.csr
+SUBJECT=user openssl x509 -extfile openssl.cnf -extensions exts_upn_client \
+ -set_serial 4 -days $DAYS -req -CA ca.pem -CAkey privkey.pem \
+ -out user-upn.pem -in user-upn.csr
+openssl pkcs12 -export -in user-upn.pem -inkey privkey.pem -out user-upn.p12 \
+ -passout pass:
+
+SUBJECT=user openssl req -config openssl.cnf -new -subj /CN=user \
+ -key privkey.pem -out user-upn2.csr
+SUBJECT=user openssl x509 -extfile openssl.cnf -extensions exts_upn2_client \
+ -set_serial 5 -days $DAYS -req -CA ca.pem -CAkey privkey.pem \
+ -out user-upn2.pem -in user-upn2.csr
+openssl pkcs12 -export -in user-upn2.pem -inkey privkey.pem \
+ -out user-upn2.p12 -passout pass:
+
+SUBJECT=user openssl req -config openssl.cnf -new -subj /CN=user \
+ -key privkey.pem -out user-upn3.csr
+SUBJECT=user openssl x509 -extfile openssl.cnf -extensions exts_upn3_client \
+ -set_serial 6 -days $DAYS -req -CA ca.pem -CAkey privkey.pem \
+ -out user-upn3.pem -in user-upn3.csr
+openssl pkcs12 -export -in user-upn3.pem -inkey privkey.pem \
+ -out user-upn3.p12 -passout pass:
+
# Clean up.
-rm -f openssl.cnf kdc.csr user.csr
+rm -f openssl.cnf kdc.csr user.csr user-upn.csr user-upn2.csr user-upn3.csr
diff --git a/src/tests/dejagnu/pkinit-certs/privkey-enc.pem b/src/tests/dejagnu/pkinit-certs/privkey-enc.pem
index 9f7816f17..837fd0b01 100644
--- a/src/tests/dejagnu/pkinit-certs/privkey-enc.pem
+++ b/src/tests/dejagnu/pkinit-certs/privkey-enc.pem
@@ -1,30 +1,30 @@
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
-DEK-Info: DES-EDE3-CBC,91CA660D6286E453
+DEK-Info: DES-EDE3-CBC,19FEC334A4D4391D
-DpJ5bo/AN37NcxTNv0Z4d5YomWqyryqYhuA43FlzWWKubld4Gp+owAv5BUd4VLx7
-Efq23ODfuiuh5zna/ZXnY+9m8RHS5AxDd2Kr1s/fVsn+m2Lw9qS69DLjxTjEuDLU
-AwmVADqQUbvocZEt0Byn9oY4ku2lGOY/ax7tZ1WegLInnoCqT2xGC6TLw7Gwr3mX
-z6xFB2Yv4PbvVU8y4V+ka0p5manxptYkrbAkC+vrC4LPUACdbonmpeXUxAfVV9hL
-EMzY74IqY2QS1xFMhbLh2HunfjjC3HZ1wXMf1/LtLl1nnodiOk5o+MTLEHO+npaO
-rJn2z3V/eQsr93M8/K5ONQcPAKZGOCmNpNQUj1UHnUHEubhpI+nqRYe3vqem5GaH
-8gn+uc1/N6c/Bs037iSLWvkgk8mvHgH/26JobZ8qg9yYgVUl3AIVkkGwLGhE5+Kn
-593/p4E5Mb6ttv3ZJ4f3Mz/1b84guhTENY67zxnQEGnpEjfRKoEN1vmHi6mIuWld
-rrUCJ/x1Yvy2tN9eyuTNsGCcfvPeY22RrKgl7Wi0EIvBlLPKBQxqXOA7Mi9Acapd
-+n5pW2Ka2FABSifZ36owa7SJEJ0GLMtdHmZPirolgIjOZVOMbSj2UuR/kXVZjZUM
-LcRcVI1z8NgKF3RKs653HqkphcyRQMMQrL/A38t+v0zFA2P3HPoNWcD+BfKg0H37
-bHPjXdlvAD5yiFXKb1XN99utW5G/qCq5CdzAirm7drxR0bs4ZIV4SwTulvWLW644
-RYes8x7WKg3WUxtair++c1eTwTPhMLz/SxERYXxSUqpxJiRgYTQhwwbE22P6FCWT
-H9pso5IMi6AJp35CGaYHi78NPLWVmrxgkkv2uBoDFd/iIQTac60aG/F86aozQD7V
-DmHINEcsN3lVUmHinoNTcIfc5EZVEbLQIBhy3XI0UDxWuLnchVlU3ad1OKqknbbi
-Ik3lmeLz07JFbpCcMk+xDlQsZYbxcRzyRh0NsWvHXuG77Hbcrnk3ndxT8wADsfOn
-foXf1/R/gf7PDmte3nFlpEcJCHyeY1haIqgk4WsnUUKP56O75cGF1ylkaBrDPlLw
-WaN2Li537ALo6TyB0jspdCzPqIRt8Gr4muoX0tqFjSfKaWmRb3Y7i6jbVrh8d6KV
-xqLse0Vkaip4Lgf/VUWOTvlfHz9nLD0xR6OUPeQ3jxGdhLxmcYec1oRj1aVMlp6f
-PyC6TN+NlPEtv6KWWB9OMc420DGOWllvS5+zsm7Ff7/5TkXlWmlhfhrkyQVy8NOe
-/3ygPbpSfCFjJMwdbEX+ic/Qjk04f3CluP3FYiIG/Pd6ny6rclrhPHg08X6+sciU
-Rj7QtoFpVsDvde2QO0depdoysAG1j1a+sas2lYNPG8hdzbPe20xIJCmF0fWfdxOy
-BxxtKzpq46S8xKLfxAMvKrZNuZy5xhs3JMUjpxTIam7ZiQXd752LdzGx2s4CII6d
-mkeQ/d32TDACAxyEK8es4Mcm3IoCAq/NjIU/ICwGDeOmfDUpsV2TMrg+aKMKcwUE
-UK4bMXercw7Cs0C3o6mdCTFrTtsihHNTrbb7yyN83XK76niSc+LREbuJ8T0vp1Yh
+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
-----END RSA PRIVATE KEY-----
diff --git a/src/tests/dejagnu/pkinit-certs/privkey.pem b/src/tests/dejagnu/pkinit-certs/privkey.pem
index 1825dec4e..7e9beb09a 100644
--- a/src/tests/dejagnu/pkinit-certs/privkey.pem
+++ b/src/tests/dejagnu/pkinit-certs/privkey.pem
@@ -1,27 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
-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
+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
-----END RSA PRIVATE KEY-----
diff --git a/src/tests/dejagnu/pkinit-certs/user-enc.p12 b/src/tests/dejagnu/pkinit-certs/user-enc.p12
index 107480c6d2564a2e60655f29a9984f3009c35a11..049602939def4be1fa9164649b39a801f417e74e 100644
GIT binary patch
delta 2772
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
ahH{=a^W;wfxC97gAc%ero&l@^0tf)CvO~uJ
delta 2966
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
M3X5P3IRXL*0PAOtl>h($
diff --git a/src/tests/dejagnu/pkinit-certs/user-upn.p12 b/src/tests/dejagnu/pkinit-certs/user-upn.p12
new file mode 100644
index 0000000000000000000000000000000000000000..7a184f651e50d1443e5fe907b5a11455d69bc0d1
GIT binary patch
literal 2829
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
literal 0
HcmV?d00001
diff --git a/src/tests/dejagnu/pkinit-certs/user-upn.pem b/src/tests/dejagnu/pkinit-certs/user-upn.pem
new file mode 100644
index 000000000..6ce095692
--- /dev/null
+++ b/src/tests/dejagnu/pkinit-certs/user-upn.pem
@@ -0,0 +1,28 @@
+-----BEGIN CERTIFICATE-----
+MIIExTCCA62gAwIBAgIBBDANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx
+FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG
+A1UECgwDTUlUMSkwJwYDVQQLDCBJbnNlY3VyZSBQS0lOSVQgS2VyYmVyb3MgdGVz
+dCBDQTEzMDEGA1UEAwwqcGtpbml0IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ug
+b3RoZXJ3aXNlMB4XDTE2MTIxMjE0NDYzOVoXDTI3MTEyNTE0NDYzOVowSjELMAkG
+A1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxFDASBgNVBAoMC0tSQlRF
+U1QuQ09NMQ0wCwYDVQQDDAR1c2VyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEA05a9cPK5tn8p/xBh09JGT+uyiDOpLSvJw0Qmn/qs+lNLjRTEZp7kzIsd
++Y2XaZJ69GgdKqFvtx9Pqf2RHaRvccHSqGGF5wd7LiwbB36btYyEFCBW1hqJaS4R
+AMLv9JaRFjOZhfwnjW+tC6VdTb/ak5AKYbg0o+w2j69wqhPZIeXqqveV+VRogbTA
+O7hsWtazOTFy5KRTtJJcN/bFNNMnxB+07pZBjeDT50CFuNkUrFE7m6KnFRF7PkR6
+ZWxF7zq9cQguRrzm2JVLiZoKfeXcVYypwEdEU1r7+ixNvQn86a+91DdvO+xwbsoN
+G0xtFSelYKWvlH4BsZW8qhyPkjX4bQIDAQABo4IBVjCCAVIwHQYDVR0OBBYEFGvA
+yQ58yg3eh+Oi1JaMrRzbt9hiMIHUBgNVHSMEgcwwgcmAFGvAyQ58yg3eh+Oi1JaM
+rRzbt9hioYGtpIGqMIGnMQswCQYDVQQGEwJVUzEWMBQGA1UECAwNTWFzc2FjaHVz
+ZXR0czESMBAGA1UEBwwJQ2FtYnJpZGdlMQwwCgYDVQQKDANNSVQxKTAnBgNVBAsM
+IEluc2VjdXJlIFBLSU5JVCBLZXJiZXJvcyB0ZXN0IENBMTMwMQYDVQQDDCpwa2lu
+aXQgdGVzdCBzdWl0ZSBDQTsgZG8gbm90IHVzZSBvdGhlcndpc2WCAQEwCwYDVR0P
+BAQDAgPoMAwGA1UdEwEB/wQCMAAwKwYDVR0RBCQwIqAgBgorBgEEAYI3FAIDoBIM
+EHVzZXJAa3JidGVzdC5jb20wEgYDVR0lBAswCQYHKwYBBQIDBDANBgkqhkiG9w0B
+AQsFAAOCAQEADpj2VeHFvGVzb2o+qUL00+1RfpNsGRxrkXpolkjGn8LNIHoMfxAR
+utnL41Jd1wQQ0FpbgR1fIXgCDfdMNWWIE0SPO6WVHVUVaDb2kjgYZ2bvR3FvTIaQ
+thj3jyG5Qn/hJZ2WZdJ1kavUQzCcGKxcIQHObcX0x2wXWPKlO1S8XDS8olsi9KPj
+y1nWUvLgxhtp4vwRuVwKtgFusgaTJOOaJ+yKS8SHr1v89GRPmff/tQzMgf/nqRNP
+lmQ5uHLeo35DvS5akdw0Izi0m5zwMvOAGBY8lyHgpx8jshourr078Swy/SNdaMGd
+fwDCc7tFD2dw3jRC1O5jWBxOuDTmUL0cVw==
+-----END CERTIFICATE-----
diff --git a/src/tests/dejagnu/pkinit-certs/user-upn2.p12 b/src/tests/dejagnu/pkinit-certs/user-upn2.p12
new file mode 100644
index 0000000000000000000000000000000000000000..6691b8c72aa60d647c4993d3972a7bc39865901f
GIT binary patch
literal 2813
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
NjEEGCzWl$H{1*d>HH`oO
literal 0
HcmV?d00001
diff --git a/src/tests/dejagnu/pkinit-certs/user-upn2.pem b/src/tests/dejagnu/pkinit-certs/user-upn2.pem
new file mode 100644
index 000000000..3a5094c84
--- /dev/null
+++ b/src/tests/dejagnu/pkinit-certs/user-upn2.pem
@@ -0,0 +1,28 @@
+-----BEGIN CERTIFICATE-----
+MIIEuTCCA6GgAwIBAgIBBTANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx
+FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG
+A1UECgwDTUlUMSkwJwYDVQQLDCBJbnNlY3VyZSBQS0lOSVQgS2VyYmVyb3MgdGVz
+dCBDQTEzMDEGA1UEAwwqcGtpbml0IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ug
+b3RoZXJ3aXNlMB4XDTE2MTIxMjE0NDYzOVoXDTI3MTEyNTE0NDYzOVowSjELMAkG
+A1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxFDASBgNVBAoMC0tSQlRF
+U1QuQ09NMQ0wCwYDVQQDDAR1c2VyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEA05a9cPK5tn8p/xBh09JGT+uyiDOpLSvJw0Qmn/qs+lNLjRTEZp7kzIsd
++Y2XaZJ69GgdKqFvtx9Pqf2RHaRvccHSqGGF5wd7LiwbB36btYyEFCBW1hqJaS4R
+AMLv9JaRFjOZhfwnjW+tC6VdTb/ak5AKYbg0o+w2j69wqhPZIeXqqveV+VRogbTA
+O7hsWtazOTFy5KRTtJJcN/bFNNMnxB+07pZBjeDT50CFuNkUrFE7m6KnFRF7PkR6
+ZWxF7zq9cQguRrzm2JVLiZoKfeXcVYypwEdEU1r7+ixNvQn86a+91DdvO+xwbsoN
+G0xtFSelYKWvlH4BsZW8qhyPkjX4bQIDAQABo4IBSjCCAUYwHQYDVR0OBBYEFGvA
+yQ58yg3eh+Oi1JaMrRzbt9hiMIHUBgNVHSMEgcwwgcmAFGvAyQ58yg3eh+Oi1JaM
+rRzbt9hioYGtpIGqMIGnMQswCQYDVQQGEwJVUzEWMBQGA1UECAwNTWFzc2FjaHVz
+ZXR0czESMBAGA1UEBwwJQ2FtYnJpZGdlMQwwCgYDVQQKDANNSVQxKTAnBgNVBAsM
+IEluc2VjdXJlIFBLSU5JVCBLZXJiZXJvcyB0ZXN0IENBMTMwMQYDVQQDDCpwa2lu
+aXQgdGVzdCBzdWl0ZSBDQTsgZG8gbm90IHVzZSBvdGhlcndpc2WCAQEwCwYDVR0P
+BAQDAgPoMAwGA1UdEwEB/wQCMAAwHwYDVR0RBBgwFqAUBgorBgEEAYI3FAIDoAYM
+BHVzZXIwEgYDVR0lBAswCQYHKwYBBQIDBDANBgkqhkiG9w0BAQsFAAOCAQEAElYM
+786mUr91z82s6QC0TwP380ze8yJQiaWifHYXiqIPay19M+QG91PvSm7LLZw+ersC
+gEl/mPKrC89XlAFp8b+hJnGq6t6YmeC7OI+FapEMxpxX/X8eqAOQLrGnoq7Pm9/8
+QtWaKgo09i7rmyykKl3xSU1VktBsmlhNPPNh3x+N4bxea9OIbZonPdDtr5/Yt87/
+6kBPsGgvUUoIxLw03OmLu8AmKAwJja0FWyu93uCUP4UZWLEGpUhSYC1uUCpAZDNy
+2AtPnxfGUDtvI9eMmyeXVGYXTfkfGZyvB3m9lyIj3VVmhbvr7qLAGQn00dbOHz16
+r6w2aye0Me0GcU0grg==
+-----END CERTIFICATE-----
diff --git a/src/tests/dejagnu/pkinit-certs/user-upn3.csr b/src/tests/dejagnu/pkinit-certs/user-upn3.csr
new file mode 100644
index 000000000..958c1e043
--- /dev/null
+++ b/src/tests/dejagnu/pkinit-certs/user-upn3.csr
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIICjzCCAXcCAQAwSjELMAkGA1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0
+dHMxFDASBgNVBAoMC0tSQlRFU1QuQ09NMQ0wCwYDVQQDDAR1c2VyMIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA05a9cPK5tn8p/xBh09JGT+uyiDOpLSvJ
+w0Qmn/qs+lNLjRTEZp7kzIsd+Y2XaZJ69GgdKqFvtx9Pqf2RHaRvccHSqGGF5wd7
+LiwbB36btYyEFCBW1hqJaS4RAMLv9JaRFjOZhfwnjW+tC6VdTb/ak5AKYbg0o+w2
+j69wqhPZIeXqqveV+VRogbTAO7hsWtazOTFy5KRTtJJcN/bFNNMnxB+07pZBjeDT
+50CFuNkUrFE7m6KnFRF7PkR6ZWxF7zq9cQguRrzm2JVLiZoKfeXcVYypwEdEU1r7
++ixNvQn86a+91DdvO+xwbsoNG0xtFSelYKWvlH4BsZW8qhyPkjX4bQIDAQABoAAw
+DQYJKoZIhvcNAQELBQADggEBAEMxNp5md+jV5dFC1iSKh2CYl3P4g3UMQ9NjLcyq
+upjJmFiEGkEg/LpH4CoXI03BaD885S7akKPA1J/sG2YIrbl3TpjUJKZoJ8BjNT0L
+tYc+JIODZJEONR34Fh6/1uRU7UkRcJ8Crc83+ML+71O2SRZRJDEOS3tVbdzjEOTj
+HIed6Ia3cu0XeAvhoqRSjh8J0ufoIv3CRRCtRU8ChkmMD64p3kOTlORxWspAF8sm
+Xa53bWIpyuyz/vWwpWfr+fL+Q+BQ1TU39xvy+46AYuQIIKzK9vKZdCElQwFXZs26
+f53OyZpFjcsT9jJAM54XUxLv5rE3fqZQiBhatPZa2ThHt08=
+-----END CERTIFICATE REQUEST-----
diff --git a/src/tests/dejagnu/pkinit-certs/user-upn3.p12 b/src/tests/dejagnu/pkinit-certs/user-upn3.p12
new file mode 100644
index 0000000000000000000000000000000000000000..a9d4780c47d33cd4d409d6ee657a7911381fe753
GIT binary patch
literal 2829
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
literal 0
HcmV?d00001
diff --git a/src/tests/dejagnu/pkinit-certs/user-upn3.pem b/src/tests/dejagnu/pkinit-certs/user-upn3.pem
new file mode 100644
index 000000000..ffedb0d1a
--- /dev/null
+++ b/src/tests/dejagnu/pkinit-certs/user-upn3.pem
@@ -0,0 +1,28 @@
+-----BEGIN CERTIFICATE-----
+MIIExTCCA62gAwIBAgIBBjANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx
+FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG
+A1UECgwDTUlUMSkwJwYDVQQLDCBJbnNlY3VyZSBQS0lOSVQgS2VyYmVyb3MgdGVz
+dCBDQTEzMDEGA1UEAwwqcGtpbml0IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ug
+b3RoZXJ3aXNlMB4XDTE2MTIxMjE0NDYzOVoXDTI3MTEyNTE0NDYzOVowSjELMAkG
+A1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxFDASBgNVBAoMC0tSQlRF
+U1QuQ09NMQ0wCwYDVQQDDAR1c2VyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEA05a9cPK5tn8p/xBh09JGT+uyiDOpLSvJw0Qmn/qs+lNLjRTEZp7kzIsd
++Y2XaZJ69GgdKqFvtx9Pqf2RHaRvccHSqGGF5wd7LiwbB36btYyEFCBW1hqJaS4R
+AMLv9JaRFjOZhfwnjW+tC6VdTb/ak5AKYbg0o+w2j69wqhPZIeXqqveV+VRogbTA
+O7hsWtazOTFy5KRTtJJcN/bFNNMnxB+07pZBjeDT50CFuNkUrFE7m6KnFRF7PkR6
+ZWxF7zq9cQguRrzm2JVLiZoKfeXcVYypwEdEU1r7+ixNvQn86a+91DdvO+xwbsoN
+G0xtFSelYKWvlH4BsZW8qhyPkjX4bQIDAQABo4IBVjCCAVIwHQYDVR0OBBYEFGvA
+yQ58yg3eh+Oi1JaMrRzbt9hiMIHUBgNVHSMEgcwwgcmAFGvAyQ58yg3eh+Oi1JaM
+rRzbt9hioYGtpIGqMIGnMQswCQYDVQQGEwJVUzEWMBQGA1UECAwNTWFzc2FjaHVz
+ZXR0czESMBAGA1UEBwwJQ2FtYnJpZGdlMQwwCgYDVQQKDANNSVQxKTAnBgNVBAsM
+IEluc2VjdXJlIFBLSU5JVCBLZXJiZXJvcyB0ZXN0IENBMTMwMQYDVQQDDCpwa2lu
+aXQgdGVzdCBzdWl0ZSBDQTsgZG8gbm90IHVzZSBvdGhlcndpc2WCAQEwCwYDVR0P
+BAQDAgPoMAwGA1UdEwEB/wQCMAAwKwYDVR0RBCQwIqAgBgorBgEEAYI3FAIDoBIM
+EHVzZXJAS1JCVEVTVC5DT00wEgYDVR0lBAswCQYHKwYBBQIDBDANBgkqhkiG9w0B
+AQsFAAOCAQEARVeLPouequn86P3LgOZQ9LpP6IHpY2ZQwvNviiA8Zk0hsqFXnmwx
+wr3JtESim3EPuwQtJ3jXp0rxQB02r5r8sg21OjCeAB+vOz3IoF/y6WEYlz67LjMB
+XCB6Fuq80IHhVXWRi7w8dVI8xcADwIOh6fgzwbbk8qV2Lgn2Giivstp+76PnRtEn
+tavWlWW7bQlXkiROYh6u3Y8IvYYoIdlDsXQBFSRE80Rc2jR2XGKAz5CDEZNC7RAH
+Z7ON9HH6IRBOX1ijmXhBl/39QQ5t+ZYgKk8OJpL1RAZlJZtGMBwJtA1aGiAFvqTr
+aCREHZfn9NAFE/szItH7hxWJv9RISUXYmA==
+-----END CERTIFICATE-----
diff --git a/src/tests/dejagnu/pkinit-certs/user.p12 b/src/tests/dejagnu/pkinit-certs/user.p12
index a7c2baddf67f5a8c6ad97b661f6ff285ecd5bf37..67c3fa2eb01c9fdd543af9172dc63a3955987ed6 100644
GIT binary patch
delta 2825
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
by5{;I{o2EAUPuH8o2f}+U#knW0s;sCTvk7E
delta 3072
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
OZhODsvxM#f0tf(M+PpOY
diff --git a/src/tests/dejagnu/pkinit-certs/user.pem b/src/tests/dejagnu/pkinit-certs/user.pem
index e6beefcde..f6d35f370 100644
--- a/src/tests/dejagnu/pkinit-certs/user.pem
+++ b/src/tests/dejagnu/pkinit-certs/user.pem
@@ -1,32 +1,28 @@
-----BEGIN CERTIFICATE-----
-MIIFkjCCBHqgAwIBAgIIYo5oQQ6iySowDQYJKoZIhvcNAQEFBQAwgacxCzAJBgNV
-BAYTAlVTMRYwFAYDVQQIEw1NYXNzYWNodXNldHRzMRIwEAYDVQQHEwlDYW1icmlk
-Z2UxDDAKBgNVBAoTA01JVDEpMCcGA1UECxMgSW5zZWN1cmUgUGtpbml0IEtlcmJl
-cm9zIHRlc3QgQ0ExMzAxBgNVBAMUKnBraW5pdCB0ZXN0IHN1aXRlIENBOyBkbyBu
-b3QgdXNlIG90aGVyd2lzZTAeFw0xMzAxMTcxODU5MDVaFw0yMzEyMzExODU5MDVa
-MIGhMQswCQYDVQQGEwJVUzEWMBQGA1UECBMNTWFzc2FjaHVzZXR0czESMBAGA1UE
-BxMJQ2FtYnJpZGdlMQwwCgYDVQQKEwNNSVQxKTAnBgNVBAsTIEluc2VjdXJlIFBr
-aW5pdCBLZXJiZXJvcyB0ZXN0IENBMS0wKwYDVQQDFCRwa2luaXQgdGVzdCBzdWl0
-ZSBjbGllbnQ7IGRvIG5vdCB1c2UwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
-AoIBAQCdgsx7nyfLTQyCyQk/u1nc8hBGlCRcYslkojQd+e0JFsi6+adl6M9Ip00z
-J6PNEjKN3DUUMlQCeldhyJzdMPnzXsbkfrdSuWUAa7L6WFBY3MTpzoq556t69Hek
-xqodeidp+VVqxS7l7YABZWcVvPjHTi4uVB6Oo/CbmxHXFN4tSdV9Jjvk1tcYgTjz
-yINXTBbyeoahVaf9OxF37sq5BQiQmm3z5XomTqE8hw+p7qHuZc0ayBzl0FKoHBVy
-NT0Nt5PjHHESaBB0u3up03BXVk8tCdNCmiA2tPm5/ehJs5OzIzTYY5auIhGayqrz
-Wx8yum+JNFEPCipNQSGgJKivRSZzAgMBAAGjggHEMIIBwDAdBgNVHQ4EFgQUWfzZ
-FQqBO+QWfRyDDIJCk15YLFgwgdwGA1UdIwSB1DCB0YAUWfzZFQqBO+QWfRyDDIJC
-k15YLFihga2kgaowgacxCzAJBgNVBAYTAlVTMRYwFAYDVQQIEw1NYXNzYWNodXNl
-dHRzMRIwEAYDVQQHEwlDYW1icmlkZ2UxDDAKBgNVBAoTA01JVDEpMCcGA1UECxMg
-SW5zZWN1cmUgUGtpbml0IEtlcmJlcm9zIHRlc3QgQ0ExMzAxBgNVBAMUKnBraW5p
-dCB0ZXN0IHN1aXRlIENBOyBkbyBub3QgdXNlIG90aGVyd2lzZYIJANsFDWp1HgAa
-MA4GA1UdDwEB/wQEAwIE8DB9BgNVHREEdjB0oC4GBisGAQUCAqAkMCKgDRsLS1JC
-VEVTVC5DT02hETAPoAMCAQGhCDAGGwR1c2VyoCAGCisGAQQBgjcUAgOgEgwQdXNl
-ckBrcmJ0ZXN0LmNvbaAgBgorBgEEAYI3FAIDoBIMEHVzZXJAS1JCVEVTVC5DT00w
-JgYDVR0lBB8wHQYHKwYBBQIDBAYIKwYBBQUHAwQGCCsGAQUFBwMCMAkGA1UdEwQC
-MAAwDQYJKoZIhvcNAQEFBQADggEBAJZ+5CMbEj9anyH/b/jxUT8yGgYB3KGj7qL+
-RdU2zjgsQUMSdnlqQzpuEcY3z1wK94dYQVsPaYBv+zHl0rXFMfKlm97nVdCJi0ep
-vplNAaUlhkma3D8rkPN5LmIdHslpJD6pwbV+o69aCEsrwm38flmEnBX0OUynULod
-icDvxOxhmYG2kXmUmF7wZXI+XWX8b/TloDNLAnYfjKytMa3SQdp6wtj76BCk+ZZQ
-GAF3D0BS36lkNQ/8buHFhVv/tC/rFvql8DRbFzk6W02Ymq2OhcP0uz67rFZ2KjZ5
-Z0WP1REC8Cv7yoqOKPk8S+1FK+8RdKHjT1n/n+Mws72F72bxQWQ=
+MIIE0zCCA7ugAwIBAgIBAzANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx
+FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG
+A1UECgwDTUlUMSkwJwYDVQQLDCBJbnNlY3VyZSBQS0lOSVQgS2VyYmVyb3MgdGVz
+dCBDQTEzMDEGA1UEAwwqcGtpbml0IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ug
+b3RoZXJ3aXNlMB4XDTE2MTIxMjE0NDYzOVoXDTI3MTEyNTE0NDYzOVowSjELMAkG
+A1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxFDASBgNVBAoMC0tSQlRF
+U1QuQ09NMQ0wCwYDVQQDDAR1c2VyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEA05a9cPK5tn8p/xBh09JGT+uyiDOpLSvJw0Qmn/qs+lNLjRTEZp7kzIsd
++Y2XaZJ69GgdKqFvtx9Pqf2RHaRvccHSqGGF5wd7LiwbB36btYyEFCBW1hqJaS4R
+AMLv9JaRFjOZhfwnjW+tC6VdTb/ak5AKYbg0o+w2j69wqhPZIeXqqveV+VRogbTA
+O7hsWtazOTFy5KRTtJJcN/bFNNMnxB+07pZBjeDT50CFuNkUrFE7m6KnFRF7PkR6
+ZWxF7zq9cQguRrzm2JVLiZoKfeXcVYypwEdEU1r7+ixNvQn86a+91DdvO+xwbsoN
+G0xtFSelYKWvlH4BsZW8qhyPkjX4bQIDAQABo4IBZDCCAWAwHQYDVR0OBBYEFGvA
+yQ58yg3eh+Oi1JaMrRzbt9hiMIHUBgNVHSMEgcwwgcmAFGvAyQ58yg3eh+Oi1JaM
+rRzbt9hioYGtpIGqMIGnMQswCQYDVQQGEwJVUzEWMBQGA1UECAwNTWFzc2FjaHVz
+ZXR0czESMBAGA1UEBwwJQ2FtYnJpZGdlMQwwCgYDVQQKDANNSVQxKTAnBgNVBAsM
+IEluc2VjdXJlIFBLSU5JVCBLZXJiZXJvcyB0ZXN0IENBMTMwMQYDVQQDDCpwa2lu
+aXQgdGVzdCBzdWl0ZSBDQTsgZG8gbm90IHVzZSBvdGhlcndpc2WCAQEwCwYDVR0P
+BAQDAgPoMAwGA1UdEwEB/wQCMAAwOQYDVR0RBDIwMKAuBgYrBgEFAgKgJDAioA0b
+C0tSQlRFU1QuQ09NoREwD6ADAgEBoQgwBhsEdXNlcjASBgNVHSUECzAJBgcrBgEF
+AgMEMA0GCSqGSIb3DQEBCwUAA4IBAQAzbpwzIFJk3a1BsrL7KT3B6aYNs5Z4bnwm
+9dG3D2S1OFSQAbQt/ap5Tjz1RWabqWaSb6ufAKudQ6Ab2uKT8QhtmVByQYKDLYvn
+bIGgoSeAcvWHWsTeReSADr2b0E9+UT8znvBDQGED39C1AgiVUWHgIExYU0kBrP3G
+1CgWQLb7nZC5rKOkcK/Nm4XL7Oe+neiCr4j9adbGxeNHmt8HPuLuNL9TWkMAkcFo
+5INHHFzNmW2aHdvO+7lDbK8/E0QwiES6UbBvQOkTyhC4W5u2Yy7qbpsQleu6jOEz
+l8b05sf4FxhHevHtYUVuyhMOg8DPmfclnGX0Dms7aLf0s3oeSVt+
-----END CERTIFICATE-----

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,58 @@
From 42469712239d3eb0e47d9aa306567464dd1f392a Mon Sep 17 00:00:00 2001
From: Matt Rogers <mrogers@redhat.com>
Date: Tue, 4 Apr 2017 16:54:56 -0400
Subject: [PATCH] Add the client_name() kdcpreauth callback
Add a kdcpreauth callback to returns the canonicalized client principal.
ticket: 8570 (new)
(cherry picked from commit a84f39ec30f3deeda7836da6e8b3d8dcf7a045b1)
---
src/include/krb5/kdcpreauth_plugin.h | 6 ++++++
src/kdc/kdc_preauth.c | 9 ++++++++-
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/src/include/krb5/kdcpreauth_plugin.h b/src/include/krb5/kdcpreauth_plugin.h
index 92aa5a5a5..fa4436b83 100644
--- a/src/include/krb5/kdcpreauth_plugin.h
+++ b/src/include/krb5/kdcpreauth_plugin.h
@@ -232,6 +232,12 @@ typedef struct krb5_kdcpreauth_callbacks_st {
krb5_kdcpreauth_rock rock,
krb5_principal princ);
+ /*
+ * Get an alias to the client DB entry principal (possibly canonicalized).
+ */
+ krb5_principal (*client_name)(krb5_context context,
+ krb5_kdcpreauth_rock rock);
+
/* End of version 4 kdcpreauth callbacks. */
} *krb5_kdcpreauth_callbacks;
diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c
index 0ce79c667..81d0b8cff 100644
--- a/src/kdc/kdc_preauth.c
+++ b/src/kdc/kdc_preauth.c
@@ -591,6 +591,12 @@ match_client(krb5_context context, krb5_kdcpreauth_rock rock,
return match;
}
+static krb5_principal
+client_name(krb5_context context, krb5_kdcpreauth_rock rock)
+{
+ return rock->client->princ;
+}
+
static struct krb5_kdcpreauth_callbacks_st callbacks = {
4,
max_time_skew,
@@ -607,7 +613,8 @@ static struct krb5_kdcpreauth_callbacks_st callbacks = {
add_auth_indicator,
get_cookie,
set_cookie,
- match_client
+ match_client,
+ client_name
};
static krb5_error_code

View file

@ -0,0 +1,80 @@
From 9b50a75e97cbe9cc8c0a4e37158b56b58e966f25 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Sat, 22 Apr 2017 09:49:12 -0400
Subject: [PATCH] Add timestamp helper functions
Add k5-int.h helper functions to manipulate krb5_timestamp values,
avoiding undefined behavior and treating negative timestamp values as
times between 2038 and 2106. Add a doxygen comment for krb5_timestamp
indicating how third-party code should use it safely.
ticket: 8352
(cherry picked from commit 58e9155060cd93b1a7557e37fbc9b077b76465c2)
---
src/include/k5-int.h | 31 +++++++++++++++++++++++++++++++
src/include/krb5/krb5.hin | 9 +++++++++
2 files changed, 40 insertions(+)
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index 06ca2b66d..82ee20760 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -2353,6 +2353,37 @@ k5memdup0(const void *in, size_t len, krb5_error_code *code)
return ptr;
}
+/* Convert a krb5_timestamp to a time_t value, treating the negative range of
+ * krb5_timestamp as times between 2038 and 2106 (if time_t is 64-bit). */
+static inline time_t
+ts2tt(krb5_timestamp timestamp)
+{
+ return (time_t)(uint32_t)timestamp;
+}
+
+/* Return the delta between two timestamps (a - b) as a signed 32-bit value,
+ * without relying on undefined behavior. */
+static inline krb5_deltat
+ts_delta(krb5_timestamp a, krb5_timestamp b)
+{
+ return (krb5_deltat)((uint32_t)a - (uint32_t)b);
+}
+
+/* Increment a timestamp by a signed 32-bit interval, without relying on
+ * undefined behavior. */
+static inline krb5_timestamp
+ts_incr(krb5_timestamp ts, krb5_deltat delta)
+{
+ return (krb5_timestamp)((uint32_t)ts + (uint32_t)delta);
+}
+
+/* Return true if a comes after b. */
+static inline krb5_boolean
+ts_after(krb5_timestamp a, krb5_timestamp b)
+{
+ return (uint32_t)a > (uint32_t)b;
+}
+
krb5_error_code KRB5_CALLCONV
krb5_get_credentials_for_user(krb5_context context, krb5_flags options,
krb5_ccache ccache,
diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
index cf60d6c41..53ad85384 100644
--- a/src/include/krb5/krb5.hin
+++ b/src/include/krb5/krb5.hin
@@ -187,7 +187,16 @@ typedef krb5_int32 krb5_cryptotype;
typedef krb5_int32 krb5_preauthtype; /* This may change, later on */
typedef krb5_int32 krb5_flags;
+
+/**
+ * Represents a timestamp in seconds since the POSIX epoch. This legacy type
+ * is used frequently in the ABI, but cannot represent timestamps after 2038 as
+ * a positive number. Code which uses this type should cast values of it to
+ * uint32_t so that negative values are treated as timestamps between 2038 and
+ * 2106 on platforms with 64-bit time_t.
+ */
typedef krb5_int32 krb5_timestamp;
+
typedef krb5_int32 krb5_deltat;
/**

599
Add-timestamp-tests.patch Normal file
View file

@ -0,0 +1,599 @@
From 3a06f6a3cfad62da6dd8878d3446003f8293c3ae Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Sat, 29 Apr 2017 17:30:36 -0400
Subject: [PATCH] Add timestamp tests
Add a test program for krb5int_validate_times() covering cases before
and across the y2038 boundary. Add a GSSAPI test program to exercise
lifetime queries, and tests using it in t_gssapi.py for ticket end
times after y2038. Add a new test script t_y2038.py which only runs
on platforms with 64-bit time_t to exercise end-user operations across
and after y2038. Add an LDAP test case to test storage of post-y2038
timestamps.
ticket: 8352
(cherry picked from commit 8ca62e54e89e2fbd6a089e8ab20b4e374a486003)
[rharwood@redhat.com: prune gitignore]
---
src/Makefile.in | 1 +
src/config/pre.in | 2 +
src/configure.in | 3 +
src/lib/krb5/krb/Makefile.in | 14 ++--
src/lib/krb5/krb/t_valid_times.c | 109 ++++++++++++++++++++++++++++++
src/tests/Makefile.in | 1 +
src/tests/gssapi/Makefile.in | 27 ++++----
src/tests/gssapi/t_gssapi.py | 32 +++++++++
src/tests/gssapi/t_lifetime.c | 140 +++++++++++++++++++++++++++++++++++++++
src/tests/t_kdb.py | 7 ++
src/tests/t_y2038.py | 75 +++++++++++++++++++++
11 files changed, 395 insertions(+), 16 deletions(-)
create mode 100644 src/lib/krb5/krb/t_valid_times.c
create mode 100644 src/tests/gssapi/t_lifetime.c
create mode 100644 src/tests/t_y2038.py
diff --git a/src/Makefile.in b/src/Makefile.in
index b0249778c..ad8565056 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -521,6 +521,7 @@ pyrunenv.vals: Makefile
done > $@
echo "tls_impl = '$(TLS_IMPL)'" >> $@
echo "have_sasl = '$(HAVE_SASL)'" >> $@
+ echo "sizeof_time_t = $(SIZEOF_TIME_T)" >> $@
runenv.py: pyrunenv.vals
echo 'env = {}' > $@
diff --git a/src/config/pre.in b/src/config/pre.in
index d961b5621..f23c07d9d 100644
--- a/src/config/pre.in
+++ b/src/config/pre.in
@@ -452,6 +452,8 @@ HAVE_SASL = @HAVE_SASL@
# Whether we have libresolv 1.1.5 for URI discovery tests
HAVE_RESOLV_WRAPPER = @HAVE_RESOLV_WRAPPER@
+SIZEOF_TIME_T = @SIZEOF_TIME_T@
+
# error table rules
#
### /* these are invoked as $(...) foo.et, which works, but could be better */
diff --git a/src/configure.in b/src/configure.in
index 24f653f0d..4ae2c07d5 100644
--- a/src/configure.in
+++ b/src/configure.in
@@ -744,6 +744,9 @@ fi
AC_HEADER_TIME
AC_CHECK_TYPE(time_t, long)
+AC_CHECK_SIZEOF(time_t)
+SIZEOF_TIME_T=$ac_cv_sizeof_time_t
+AC_SUBST(SIZEOF_TIME_T)
# Determine where to put the replay cache.
diff --git a/src/lib/krb5/krb/Makefile.in b/src/lib/krb5/krb/Makefile.in
index 0fe02a95d..55f82b147 100644
--- a/src/lib/krb5/krb/Makefile.in
+++ b/src/lib/krb5/krb/Makefile.in
@@ -364,6 +364,7 @@ SRCS= $(srcdir)/addr_comp.c \
$(srcdir)/t_in_ccache.c \
$(srcdir)/t_response_items.c \
$(srcdir)/t_sname_match.c \
+ $(srcdir)/t_valid_times.c \
$(srcdir)/t_vfy_increds.c
# Someday, when we have a "maintainer mode", do this right:
@@ -457,9 +458,12 @@ t_response_items: t_response_items.o response_items.o $(KRB5_BASE_DEPLIBS)
t_sname_match: t_sname_match.o sname_match.o $(KRB5_BASE_DEPLIBS)
$(CC_LINK) -o $@ t_sname_match.o sname_match.o $(KRB5_BASE_LIBS)
+t_valid_times: t_valid_times.o valid_times.o $(KRB5_BASE_DEPLIBS)
+ $(CC_LINK) -o $@ t_valid_times.o valid_times.o $(KRB5_BASE_LIBS)
+
TEST_PROGS= t_walk_rtree t_kerb t_ser t_deltat t_expand t_authdata t_pac \
- t_in_ccache t_cc_config t_copy_context \
- t_princ t_etypes t_vfy_increds t_response_items t_sname_match
+ t_in_ccache t_cc_config t_copy_context t_princ t_etypes t_vfy_increds \
+ t_response_items t_sname_match t_valid_times
check-unix: $(TEST_PROGS)
$(RUN_TEST_LOCAL_CONF) ./t_kerb \
@@ -496,6 +500,7 @@ check-unix: $(TEST_PROGS)
$(RUN_TEST) ./t_response_items
$(RUN_TEST) ./t_copy_context
$(RUN_TEST) ./t_sname_match
+ $(RUN_TEST) ./t_valid_times
check-pytests: t_expire_warn t_vfy_increds
$(RUNPYTEST) $(srcdir)/t_expire_warn.py $(PYTESTFLAGS)
@@ -522,8 +527,9 @@ clean:
$(OUTPRE)t_ad_fx_armor$(EXEEXT) $(OUTPRE)t_ad_fx_armor.$(OBJEXT) \
$(OUTPRE)t_vfy_increds$(EXEEXT) $(OUTPRE)t_vfy_increds.$(OBJEXT) \
$(OUTPRE)t_response_items$(EXEEXT) \
- $(OUTPRE)t_response_items.$(OBJEXT) $(OUTPRE)t_sname_match$(EXEEXT) \
- $(OUTPRE)t_sname_match.$(OBJEXT) \
+ $(OUTPRE)t_response_items.$(OBJEXT) \
+ $(OUTPRE)t_sname_match$(EXEEXT) $(OUTPRE)t_sname_match.$(OBJEXT) \
+ $(OUTPRE)t_valid_times$(EXEEXT) $(OUTPRE)t_valid_times.$(OBJECT) \
$(OUTPRE)t_parse_host_string$(EXEEXT) \
$(OUTPRE)t_parse_host_string.$(OBJEXT)
diff --git a/src/lib/krb5/krb/t_valid_times.c b/src/lib/krb5/krb/t_valid_times.c
new file mode 100644
index 000000000..1b469ffc2
--- /dev/null
+++ b/src/lib/krb5/krb/t_valid_times.c
@@ -0,0 +1,109 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/krb5/krb/t_valid_times.c - test program for krb5int_validate_times() */
+/*
+ * Copyright (C) 2017 by the Massachusetts Institute of Technology.
+ * 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.
+ *
+ * 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 HOLDER 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.
+ */
+
+#include "k5-int.h"
+#include "int-proto.h"
+
+#define BOUNDARY (uint32_t)INT32_MIN
+
+int
+main()
+{
+ krb5_error_code ret;
+ krb5_context context;
+ krb5_ticket_times times = { 0, 0, 0, 0 };
+
+ ret = krb5_init_context(&context);
+ assert(!ret);
+
+ /* Current time is within authtime and end time. */
+ ret = krb5_set_debugging_time(context, 1000, 0);
+ times.authtime = 500;
+ times.endtime = 1500;
+ ret = krb5int_validate_times(context, &times);
+ assert(!ret);
+
+ /* Current time is before starttime, but within clock skew. */
+ times.starttime = 1100;
+ ret = krb5int_validate_times(context, &times);
+ assert(!ret);
+
+ /* Current time is before starttime by more than clock skew. */
+ times.starttime = 1400;
+ ret = krb5int_validate_times(context, &times);
+ assert(ret == KRB5KRB_AP_ERR_TKT_NYV);
+
+ /* Current time is after end time, but within clock skew. */
+ times.starttime = 500;
+ times.endtime = 800;
+ ret = krb5int_validate_times(context, &times);
+ assert(!ret);
+
+ /* Current time is after end time by more than clock skew. */
+ times.endtime = 600;
+ ret = krb5int_validate_times(context, &times);
+ assert(ret == KRB5KRB_AP_ERR_TKT_EXPIRED);
+
+ /* Current time is within starttime and endtime; current time and
+ * endtime are across y2038 boundary. */
+ ret = krb5_set_debugging_time(context, BOUNDARY - 100, 0);
+ assert(!ret);
+ times.starttime = BOUNDARY - 200;
+ times.endtime = BOUNDARY + 500;
+ ret = krb5int_validate_times(context, &times);
+ assert(!ret);
+
+ /* Current time is before starttime, but by less than clock skew. */
+ times.starttime = BOUNDARY + 100;
+ ret = krb5int_validate_times(context, &times);
+ assert(!ret);
+
+ /* Current time is before starttime by more than clock skew. */
+ times.starttime = BOUNDARY + 250;
+ ret = krb5int_validate_times(context, &times);
+ assert(ret == KRB5KRB_AP_ERR_TKT_NYV);
+
+ /* Current time is after endtime, but by less than clock skew. */
+ ret = krb5_set_debugging_time(context, BOUNDARY + 100, 0);
+ assert(!ret);
+ times.starttime = BOUNDARY - 1000;
+ times.endtime = BOUNDARY - 100;
+ ret = krb5int_validate_times(context, &times);
+ assert(!ret);
+
+ /* Current time is after endtime by more than clock skew. */
+ times.endtime = BOUNDARY - 300;
+ ret = krb5int_validate_times(context, &times);
+ assert(ret == KRB5KRB_AP_ERR_TKT_EXPIRED);
+
+ return 0;
+}
diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in
index 0e93d6b59..2b3112537 100644
--- a/src/tests/Makefile.in
+++ b/src/tests/Makefile.in
@@ -168,6 +168,7 @@ check-pytests: localauth plugorder rdreq responder s2p s4u2proxy unlockiter
$(RUNPYTEST) $(srcdir)/t_princflags.py $(PYTESTFLAGS)
$(RUNPYTEST) $(srcdir)/t_tabdump.py $(PYTESTFLAGS)
$(RUNPYTEST) $(srcdir)/t_certauth.py $(PYTESTFLAGS)
+ $(RUNPYTEST) $(srcdir)/t_y2038.py $(PYTESTFLAGS)
clean:
$(RM) adata etinfo forward gcred hist hooks hrealm icred kdbtest
diff --git a/src/tests/gssapi/Makefile.in b/src/tests/gssapi/Makefile.in
index 6c1464297..604f926de 100644
--- a/src/tests/gssapi/Makefile.in
+++ b/src/tests/gssapi/Makefile.in
@@ -15,15 +15,16 @@ SRCS= $(srcdir)/ccinit.c $(srcdir)/ccrefresh.c $(srcdir)/common.c \
$(srcdir)/t_gssexts.c $(srcdir)/t_imp_cred.c $(srcdir)/t_imp_name.c \
$(srcdir)/t_invalid.c $(srcdir)/t_inq_cred.c $(srcdir)/t_inq_ctx.c \
$(srcdir)/t_inq_mechs_name.c $(srcdir)/t_iov.c \
- $(srcdir)/t_namingexts.c $(srcdir)/t_oid.c $(srcdir)/t_pcontok.c \
- $(srcdir)/t_prf.c $(srcdir)/t_s4u.c $(srcdir)/t_s4u2proxy_krb5.c \
- $(srcdir)/t_saslname.c $(srcdir)/t_spnego.c $(srcdir)/t_srcattrs.c
+ $(srcdir)/t_lifetime.c $(srcdir)/t_namingexts.c $(srcdir)/t_oid.c \
+ $(srcdir)/t_pcontok.c $(srcdir)/t_prf.c $(srcdir)/t_s4u.c \
+ $(srcdir)/t_s4u2proxy_krb5.c $(srcdir)/t_saslname.c \
+ $(srcdir)/t_spnego.c $(srcdir)/t_srcattrs.c
OBJS= ccinit.o ccrefresh.o common.o t_accname.o t_ccselect.o t_ciflags.o \
t_credstore.o t_enctypes.o t_err.o t_export_cred.o t_export_name.o \
t_gssexts.o t_imp_cred.o t_imp_name.o t_invalid.o t_inq_cred.o \
- t_inq_ctx.o t_inq_mechs_name.o t_iov.o t_namingexts.o t_oid.o \
- t_pcontok.o t_prf.o t_s4u.o t_s4u2proxy_krb5.o t_saslname.o \
+ t_inq_ctx.o t_inq_mechs_name.o t_iov.o t_lifetime.o t_namingexts.o \
+ t_oid.o t_pcontok.o t_prf.o t_s4u.o t_s4u2proxy_krb5.o t_saslname.o \
t_spnego.o t_srcattrs.o
COMMON_DEPS= common.o $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS)
@@ -31,9 +32,9 @@ COMMON_LIBS= common.o $(GSS_LIBS) $(KRB5_BASE_LIBS)
all: ccinit ccrefresh t_accname t_ccselect t_ciflags t_credstore t_enctypes \
t_err t_export_cred t_export_name t_gssexts t_imp_cred t_imp_name \
- t_invalid t_inq_cred t_inq_ctx t_inq_mechs_name t_iov t_namingexts \
- t_oid t_pcontok t_prf t_s4u t_s4u2proxy_krb5 t_saslname t_spnego \
- t_srcattrs
+ t_invalid t_inq_cred t_inq_ctx t_inq_mechs_name t_iov t_lifetime \
+ t_namingexts t_oid t_pcontok t_prf t_s4u t_s4u2proxy_krb5 t_saslname \
+ t_spnego t_srcattrs
check-unix: t_oid
$(RUN_TEST) ./t_invalid
@@ -42,8 +43,8 @@ check-unix: t_oid
check-pytests: ccinit ccrefresh t_accname t_ccselect t_ciflags t_credstore \
t_enctypes t_err t_export_cred t_export_name t_imp_cred t_inq_cred \
- t_inq_ctx t_inq_mechs_name t_iov t_pcontok t_s4u t_s4u2proxy_krb5 \
- t_spnego t_srcattrs
+ t_inq_ctx t_inq_mechs_name t_iov t_lifetime t_pcontok t_s4u \
+ t_s4u2proxy_krb5 t_spnego t_srcattrs
$(RUNPYTEST) $(srcdir)/t_gssapi.py $(PYTESTFLAGS)
$(RUNPYTEST) $(srcdir)/t_ccselect.py $(PYTESTFLAGS)
$(RUNPYTEST) $(srcdir)/t_client_keytab.py $(PYTESTFLAGS)
@@ -88,6 +89,8 @@ t_inq_mechs_name: t_inq_mechs_name.o $(COMMON_DEPS)
$(CC_LINK) -o $@ t_inq_mechs_name.o $(COMMON_LIBS)
t_iov: t_iov.o $(COMMON_DEPS)
$(CC_LINK) -o $@ t_iov.o $(COMMON_LIBS)
+t_lifetime: t_lifetime.o $(COMMON_DEPS)
+ $(CC_LINK) -o $@ t_lifetime.o $(COMMON_LIBS)
t_namingexts: t_namingexts.o $(COMMON_DEPS)
$(CC_LINK) -o $@ t_namingexts.o $(COMMON_LIBS)
t_pcontok: t_pcontok.o $(COMMON_DEPS)
@@ -111,5 +114,5 @@ clean:
$(RM) ccinit ccrefresh t_accname t_ccselect t_ciflags t_credstore
$(RM) t_enctypes t_err t_export_cred t_export_name t_gssexts t_imp_cred
$(RM) t_imp_name t_invalid t_inq_cred t_inq_ctx t_inq_mechs_name t_iov
- $(RM) t_namingexts t_oid t_pcontok t_prf t_s4u t_s4u2proxy_krb5
- $(RM) t_saslname t_spnego t_srcattrs
+ $(RM) t_lifetime t_namingexts t_oid t_pcontok t_prf t_s4u
+ $(RM) t_s4u2proxy_krb5 t_saslname t_spnego t_srcattrs
diff --git a/src/tests/gssapi/t_gssapi.py b/src/tests/gssapi/t_gssapi.py
index 397e58962..98c8df25c 100755
--- a/src/tests/gssapi/t_gssapi.py
+++ b/src/tests/gssapi/t_gssapi.py
@@ -185,4 +185,36 @@ realm.run(['./t_ciflags', 'p:' + realm.host_princ])
# contexts.
realm.run(['./t_inq_ctx', 'user', password('user'), 'p:%s' % realm.host_princ])
+# Test lifetime results, using a realm with a large maximum lifetime
+# so that we can test ticket end dates after y2038. There are no
+# time_t conversions involved, so we can run these tests on platforms
+# with 32-bit time_t.
+realm.stop()
+conf = {'realms': {'$realm': {'max_life': '9000d'}}}
+realm = K5Realm(kdc_conf=conf, get_creds=False)
+
+# Check a lifetime string result against an expected number value (or None).
+# Allow some variance due to time elapsed during the tests.
+def check_lifetime(msg, val, expected):
+ if expected is None and val != 'indefinite':
+ fail('%s: expected indefinite, got %s' % (msg, val))
+ if expected is not None and val == 'indefinite':
+ fail('%s: expected %d, got indefinite' % (msg, expected))
+ if expected is not None and abs(int(val) - expected) > 100:
+ fail('%s: expected %d, got %s' % (msg, expected, val))
+
+realm.kinit(realm.user_princ, password('user'), flags=['-l', '8500d'])
+out = realm.run(['./t_lifetime', 'p:' + realm.host_princ, str(8000 * 86400)])
+ln = out.split('\n')
+check_lifetime('icred gss_acquire_cred', ln[0], 8500 * 86400)
+check_lifetime('icred gss_inquire_cred', ln[1], 8500 * 86400)
+check_lifetime('acred gss_acquire_cred', ln[2], None)
+check_lifetime('acred gss_inquire_cred', ln[3], None)
+check_lifetime('ictx gss_init_sec_context', ln[4], 8000 * 86400)
+check_lifetime('ictx gss_inquire_context', ln[5], 8000 * 86400)
+check_lifetime('ictx gss_context_time', ln[6], 8000 * 86400)
+check_lifetime('actx gss_accept_sec_context', ln[7], 8000 * 86400 + 300)
+check_lifetime('actx gss_inquire_context', ln[8], 8000 * 86400 + 300)
+check_lifetime('actx gss_context_time', ln[9], 8000 * 86400 + 300)
+
success('GSSAPI tests')
diff --git a/src/tests/gssapi/t_lifetime.c b/src/tests/gssapi/t_lifetime.c
new file mode 100644
index 000000000..8dcf18621
--- /dev/null
+++ b/src/tests/gssapi/t_lifetime.c
@@ -0,0 +1,140 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* tests/gssapi/t_lifetime.c - display cred and context lifetimes */
+/*
+ * Copyright (C) 2017 by the Massachusetts Institute of Technology.
+ * 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.
+ *
+ * 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 HOLDER 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "common.h"
+
+/*
+ * Using the default credential, exercise the GSS functions which accept or
+ * produce lifetimes. Display the following results, one per line, as ASCII
+ * integers or the string "indefinite":
+ *
+ * initiator cred lifetime according to gss_acquire_cred()
+ * initiator cred lifetime according to gss_inquire_cred()
+ * acceptor cred lifetime according to gss_acquire_cred()
+ * acceptor cred lifetime according to gss_inquire_cred()
+ * initiator context lifetime according to gss_init_sec_context()
+ * initiator context lifetime according to gss_inquire_context()
+ * initiator context lifetime according to gss_context_time()
+ * acceptor context lifetime according to gss_init_sec_context()
+ * acceptor context lifetime according to gss_inquire_context()
+ * acceptor context lifetime according to gss_context_time()
+ */
+
+static void
+display_time(OM_uint32 tval)
+{
+ if (tval == GSS_C_INDEFINITE)
+ puts("indefinite");
+ else
+ printf("%u\n", (unsigned int)tval);
+}
+
+int
+main(int argc, char *argv[])
+{
+ OM_uint32 minor, major;
+ gss_cred_id_t icred, acred;
+ gss_name_t tname;
+ gss_ctx_id_t ictx = GSS_C_NO_CONTEXT, actx = GSS_C_NO_CONTEXT;
+ gss_buffer_desc itok = GSS_C_EMPTY_BUFFER, atok = GSS_C_EMPTY_BUFFER;
+ OM_uint32 time_req = GSS_C_INDEFINITE, time_rec;
+
+ if (argc < 2 || argc > 3) {
+ fprintf(stderr, "Usage: %s targetname [time_req]\n", argv[0]);
+ return 1;
+ }
+ tname = import_name(argv[1]);
+ if (argc >= 3)
+ time_req = atoll(argv[2]);
+
+ /* Get initiator cred and display its lifetime according to
+ * gss_acquire_cred and gss_inquire_cred. */
+ major = gss_acquire_cred(&minor, GSS_C_NO_NAME, time_req, &mechset_krb5,
+ GSS_C_INITIATE, &icred, NULL, &time_rec);
+ check_gsserr("gss_acquire_cred(initiate)", major, minor);
+ display_time(time_rec);
+ major = gss_inquire_cred(&minor, icred, NULL, &time_rec, NULL, NULL);
+ check_gsserr("gss_inquire_cred(initiate)", major, minor);
+ display_time(time_rec);
+
+ /* Get acceptor cred and display its lifetime according to gss_acquire_cred
+ * and gss_inquire_cred. */
+ major = gss_acquire_cred(&minor, GSS_C_NO_NAME, time_req, &mechset_krb5,
+ GSS_C_ACCEPT, &acred, NULL, &time_rec);
+ check_gsserr("gss_acquire_cred(accept)", major, minor);
+ display_time(time_rec);
+ major = gss_inquire_cred(&minor, acred, NULL, &time_rec, NULL, NULL);
+ check_gsserr("gss_inquire_cred(accept)", major, minor);
+ display_time(time_rec);
+
+ /* Make an initiator context and display its lifetime according to
+ * gss_init_sec_context, gss_inquire_context, and gss_context_time. */
+ major = gss_init_sec_context(&minor, icred, &ictx, tname, &mech_krb5, 0,
+ time_req, GSS_C_NO_CHANNEL_BINDINGS, &atok,
+ NULL, &itok, NULL, &time_rec);
+ check_gsserr("gss_init_sec_context", major, minor);
+ assert(major == GSS_S_COMPLETE);
+ display_time(time_rec);
+ major = gss_inquire_context(&minor, ictx, NULL, NULL, &time_rec, NULL,
+ NULL, NULL, NULL);
+ check_gsserr("gss_inquire_context(initiate)", major, minor);
+ display_time(time_rec);
+ major = gss_context_time(&minor, ictx, &time_rec);
+ check_gsserr("gss_context_time(initiate)", major, minor);
+ display_time(time_rec);
+
+ major = gss_accept_sec_context(&minor, &actx, acred, &itok,
+ GSS_C_NO_CHANNEL_BINDINGS, NULL,
+ NULL, &atok, NULL, &time_rec, NULL);
+ check_gsserr("gss_accept_sec_context", major, minor);
+ assert(major == GSS_S_COMPLETE);
+ display_time(time_rec);
+ major = gss_inquire_context(&minor, actx, NULL, NULL, &time_rec, NULL,
+ NULL, NULL, NULL);
+ check_gsserr("gss_inquire_context(accept)", major, minor);
+ display_time(time_rec);
+ major = gss_context_time(&minor, actx, &time_rec);
+ check_gsserr("gss_context_time(accept)", major, minor);
+ display_time(time_rec);
+
+ (void)gss_release_buffer(&minor, &itok);
+ (void)gss_release_buffer(&minor, &atok);
+ (void)gss_release_name(&minor, &tname);
+ (void)gss_release_cred(&minor, &icred);
+ (void)gss_release_cred(&minor, &acred);
+ (void)gss_delete_sec_context(&minor, &ictx, NULL);
+ (void)gss_delete_sec_context(&minor, &actx, NULL);
+ return 0;
+}
diff --git a/src/tests/t_kdb.py b/src/tests/t_kdb.py
index 44635b089..ffc043709 100755
--- a/src/tests/t_kdb.py
+++ b/src/tests/t_kdb.py
@@ -414,6 +414,13 @@ realm.run([kadminl, 'addprinc', '-policy', 'keepoldpasspol', '-pw', 'aaaa',
for p in ('bbbb', 'cccc', 'aaaa'):
realm.run([kadminl, 'cpw', '-keepold', '-pw', p, 'keepoldpassprinc'])
+if runenv.sizeof_time_t <= 4:
+ skipped('y2038 LDAP test', 'platform has 32-bit time_t')
+else:
+ # Test storage of timestamps after y2038.
+ realm.run([kadminl, 'modprinc', '-pwexpire', '2040-02-03', 'user'])
+ realm.run([kadminl, 'getprinc', 'user'], expected_msg=' 2040\n')
+
realm.stop()
# Briefly test dump and load.
diff --git a/src/tests/t_y2038.py b/src/tests/t_y2038.py
new file mode 100644
index 000000000..02e946df4
--- /dev/null
+++ b/src/tests/t_y2038.py
@@ -0,0 +1,75 @@
+#!/usr/bin/python
+from k5test import *
+
+# These tests will become much less important after the y2038 boundary
+# has elapsed, and may start exhibiting problems around the year 2075.
+
+if runenv.sizeof_time_t <= 4:
+ skip_rest('y2038 timestamp tests', 'platform has 32-bit time_t')
+
+# Start a KDC running roughly 21 years in the future, after the y2038
+# boundary. Set long maximum lifetimes for later tests.
+conf = {'realms': {'$realm': {'max_life': '9000d',
+ 'max_renewable_life': '9000d'}}}
+realm = K5Realm(start_kdc=False, kdc_conf=conf)
+realm.start_kdc(['-T', '662256000'])
+
+# kinit without preauth should succeed with clock skew correction, but
+# will result in an expired ticket, because we sent an absolute end
+# time and didn't get a chance to correct it..
+realm.kinit(realm.user_princ, password('user'))
+realm.run([kvno, realm.host_princ], expected_code=1,
+ expected_msg='Ticket expired')
+
+# kinit with preauth should succeed and result in a valid ticket, as
+# we get a chance to correct the end time based on the KDC time. Try
+# with encrypted timestamp and encrypted challenge.
+realm.run([kadminl, 'modprinc', '+requires_preauth', 'user'])
+realm.kinit(realm.user_princ, password('user'))
+realm.run([kvno, realm.host_princ])
+realm.kinit(realm.user_princ, password('user'), flags=['-T', realm.ccache])
+realm.run([kvno, realm.host_princ])
+
+# Test that expiration warning works after y2038, by setting a
+# password expiration time ten minutes after the KDC time.
+realm.run([kadminl, 'modprinc', '-pwexpire', '662256600 seconds', 'user'])
+out = realm.kinit(realm.user_princ, password('user'))
+if 'will expire in less than one hour' not in out:
+ fail('password expiration message')
+year = int(out.split()[-1])
+if year < 2038 or year > 9999:
+ fail('password expiration year')
+
+realm.stop_kdc()
+realm.start_kdc()
+realm.start_kadmind()
+realm.prep_kadmin()
+
+# Test getdate parsing of absolute timestamps after 2038 and
+# marshalling over the kadmin protocol. The local time zone will
+# affect the display time by a little bit, so just look for the year.
+realm.run_kadmin(['modprinc', '-pwexpire', '2040-02-03', realm.host_princ])
+realm.run_kadmin(['getprinc', realm.host_princ], expected_msg=' 2040\n')
+
+# Get a ticket whose lifetime crosses the y2038 boundary and
+# range-check the expiration year as reported by klist.
+realm.kinit(realm.user_princ, password('user'),
+ flags=['-l', '8000d', '-r', '8500d'])
+realm.run([kvno, realm.host_princ])
+out = realm.run([klist])
+if int(out.split('\n')[4].split()[2].split('/')[2]) < 39:
+ fail('unexpected tgt expiration year')
+if int(out.split('\n')[5].split()[2].split('/')[2]) < 40:
+ fail('unexpected tgt rtill year')
+if int(out.split('\n')[6].split()[2].split('/')[2]) < 39:
+ fail('unexpected service ticket expiration year')
+if int(out.split('\n')[7].split()[2].split('/')[2]) < 40:
+ fail('unexpected service ticket rtill year')
+realm.kinit(realm.user_princ, None, ['-R'])
+out = realm.run([klist])
+if int(out.split('\n')[4].split()[2].split('/')[2]) < 39:
+ fail('unexpected renewed tgt expiration year')
+if int(out.split('\n')[5].split()[2].split('/')[2]) < 40:
+ fail('unexpected renewed tgt rtill year')
+
+success('y2038 tests')

View file

@ -0,0 +1,59 @@
From 69ca5ff168f24792924b3cab0a9f27ada3eb4c4b Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Thu, 4 May 2017 17:03:35 -0400
Subject: [PATCH] Add y2038 documentation
ticket: 8352
(cherry picked from commit 85d64c43dbf7a7faa56a1999494cdfa49e8bd2c9)
---
doc/appdev/index.rst | 1 +
doc/appdev/y2038.rst | 28 ++++++++++++++++++++++++++++
2 files changed, 29 insertions(+)
create mode 100644 doc/appdev/y2038.rst
diff --git a/doc/appdev/index.rst b/doc/appdev/index.rst
index 3d62045ca..961bb1e9e 100644
--- a/doc/appdev/index.rst
+++ b/doc/appdev/index.rst
@@ -5,6 +5,7 @@ For application developers
:maxdepth: 1
gssapi.rst
+ y2038.rst
h5l_mit_apidiff.rst
init_creds.rst
princ_handle.rst
diff --git a/doc/appdev/y2038.rst b/doc/appdev/y2038.rst
new file mode 100644
index 000000000..bc4122dad
--- /dev/null
+++ b/doc/appdev/y2038.rst
@@ -0,0 +1,28 @@
+Year 2038 considerations for uses of krb5_timestamp
+===================================================
+
+POSIX time values, which measure the number of seconds since January 1
+1970, will exceed the maximum value representable in a signed 32-bit
+integer in January 2038. This documentation describes considerations
+for consumers of the MIT krb5 libraries.
+
+Applications or libraries which use libkrb5 and consume the timestamps
+included in credentials or other structures make use of the
+:c:type:`krb5_timestamp` type. For historical reasons, krb5_timestamp
+is a signed 32-bit integer, even on platforms where a larger type is
+natively used to represent time values. To behave properly for time
+values after January 2038, calling code should cast krb5_timestamp
+values to uint32_t, and then to time_t::
+
+ (time_t)(uint32_t)timestamp
+
+Used in this way, krb5_timestamp values can represent time values up
+until February 2106, provided that the platform uses a 64-bit or
+larger time_t type. This usage will also remain safe if a later
+version of MIT krb5 changes krb5_timestamp to an unsigned 32-bit
+integer.
+
+The GSSAPI only uses representations of time intervals, not absolute
+times. Callers of the GSSAPI should require no changes to behave
+correctly after January 2038, provided that they use MIT krb5 release
+1.16 or later.

View file

@ -0,0 +1,23 @@
From 5f2ea38f7ecd60184e510558bdb551d0153432e0 Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Thu, 10 Nov 2016 13:20:49 -0500
Subject: [PATCH] Build with -Werror-implicit-int where supported
(cherry picked from commit 873d864230c9c64c65ff12a24199bac3adf3bc2f)
---
src/aclocal.m4 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/aclocal.m4 b/src/aclocal.m4
index 2bfb99496..da1d6d8b4 100644
--- a/src/aclocal.m4
+++ b/src/aclocal.m4
@@ -529,7 +529,7 @@ if test "$GCC" = yes ; then
TRY_WARN_CC_FLAG(-Wno-format-zero-length)
# Other flags here may not be supported on some versions of
# gcc that people want to use.
- for flag in overflow strict-overflow missing-format-attribute missing-prototypes return-type missing-braces parentheses switch unused-function unused-label unused-variable unused-value unknown-pragmas sign-compare newline-eof error=uninitialized error=pointer-arith error=int-conversion error=incompatible-pointer-types error=discarded-qualifiers ; do
+ for flag in overflow strict-overflow missing-format-attribute missing-prototypes return-type missing-braces parentheses switch unused-function unused-label unused-variable unused-value unknown-pragmas sign-compare newline-eof error=uninitialized error=pointer-arith error=int-conversion error=incompatible-pointer-types error=discarded-qualifiers error=implicit-int ; do
TRY_WARN_CC_FLAG(-W$flag)
done
# old-style-definition? generates many, many warnings

View file

@ -0,0 +1,43 @@
From bc42112fbc232c2afba602672affc3e92ae1491e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <fidencio@redhat.com>
Date: Wed, 28 Mar 2018 18:27:06 +0200
Subject: [PATCH] Continue after KRB5_CC_END in KCM cache iteration
The KCM server returns KRB5_CC_END in response to a GET_CACHE_BY_UUID
request to indicate that the specified ccache uuid no longer exists.
In krb5_ptcursor_next(), ignore this error and continue the iteration,
as the Heimdal KCM client code does.
In addition to addressing the case where a third party deletes a cache
between the GET_CACHE_UUID_LIST request and when we reach that uuid in
the iteration, this change also fixes a bug in kdestroy -A where the
caller deletes the primary cache and we later request it by uuid when
iterating over the list.
[ghudson@mit.edu: rewrote commit message; edited comment]
ticket: 8658 (new)
tags: pullup
target_version: 1.16-next
target_version: 1.15-next
(cherry picked from commit 49087f5e6309f298f8898c35af6f4ade418ced60)
(cherry picked from commit 3001200ba4598aeb14511353a72dc746034280b1)
---
src/lib/krb5/ccache/cc_kcm.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/lib/krb5/ccache/cc_kcm.c b/src/lib/krb5/ccache/cc_kcm.c
index a889e67b4..a3afd7056 100644
--- a/src/lib/krb5/ccache/cc_kcm.c
+++ b/src/lib/krb5/ccache/cc_kcm.c
@@ -966,6 +966,9 @@ kcm_ptcursor_next(krb5_context context, krb5_cc_ptcursor cursor,
kcmreq_init(&req, KCM_OP_GET_CACHE_BY_UUID, NULL);
k5_buf_add_len(&req.reqbuf, id, KCM_UUID_LEN);
ret = kcmio_call(context, data->io, &req);
+ /* Continue if the cache has been deleted. */
+ if (ret == KRB5_CC_END)
+ continue;
if (ret)
goto cleanup;
ret = kcmreq_get_name(&req, &name);

View file

@ -0,0 +1,422 @@
From 686fa6476eb759532d566794fa8d430774d44cf7 Mon Sep 17 00:00:00 2001
From: Matt Rogers <mrogers@redhat.com>
Date: Wed, 29 Mar 2017 10:35:13 -0400
Subject: [PATCH] Convert some pkiDebug messages to TRACE macros
ticket: 8568 (new)
(cherry picked from commit 9852862a83952a94300adfafa3e333f43396ec33)
---
src/plugins/preauth/pkinit/pkinit_crypto_openssl.c | 46 ++++++---------
src/plugins/preauth/pkinit/pkinit_identity.c | 3 -
src/plugins/preauth/pkinit/pkinit_matching.c | 1 +
src/plugins/preauth/pkinit/pkinit_srv.c | 24 ++++----
src/plugins/preauth/pkinit/pkinit_trace.h | 68 +++++++++++++++++++++-
5 files changed, 97 insertions(+), 45 deletions(-)
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
index 90c30dbf5..70e230ec2 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
@@ -2320,7 +2320,6 @@ crypto_check_cert_eku(krb5_context context,
X509_NAME_oneline(X509_get_subject_name(reqctx->received_cert),
buf, sizeof(buf));
- pkiDebug("%s: looking for EKUs in cert = %s\n", __FUNCTION__, buf);
if ((i = X509_get_ext_by_NID(reqctx->received_cert,
NID_ext_key_usage, -1)) >= 0) {
@@ -2354,7 +2353,6 @@ crypto_check_cert_eku(krb5_context context,
if (found_eku) {
ASN1_BIT_STRING *usage = NULL;
- pkiDebug("%s: found acceptable EKU, checking for digitalSignature\n", __FUNCTION__);
/* check that digitalSignature KeyUsage is present */
X509_check_ca(reqctx->received_cert);
@@ -2363,12 +2361,10 @@ crypto_check_cert_eku(krb5_context context,
if (!ku_reject(reqctx->received_cert,
X509v3_KU_DIGITAL_SIGNATURE)) {
- pkiDebug("%s: found digitalSignature KU\n",
- __FUNCTION__);
+ TRACE_PKINIT_EKU(context);
*valid_eku = 1;
} else
- pkiDebug("%s: didn't find digitalSignature KU\n",
- __FUNCTION__);
+ TRACE_PKINIT_EKU_NO_KU(context);
}
ASN1_BIT_STRING_free(usage);
}
@@ -4317,8 +4313,7 @@ pkinit_get_certs_pkcs12(krb5_context context,
fp = fopen(idopts->cert_filename, "rb");
if (fp == NULL) {
- pkiDebug("Failed to open PKCS12 file '%s', error %d\n",
- idopts->cert_filename, errno);
+ TRACE_PKINIT_PKCS_OPEN_FAIL(context, idopts->cert_filename, errno);
goto cleanup;
}
set_cloexec_file(fp);
@@ -4326,8 +4321,7 @@ pkinit_get_certs_pkcs12(krb5_context context,
p12 = d2i_PKCS12_fp(fp, NULL);
fclose(fp);
if (p12 == NULL) {
- pkiDebug("Failed to decode PKCS12 file '%s' contents\n",
- idopts->cert_filename);
+ TRACE_PKINIT_PKCS_DECODE_FAIL(context, idopts->cert_filename);
goto cleanup;
}
/*
@@ -4345,7 +4339,7 @@ pkinit_get_certs_pkcs12(krb5_context context,
char *p12name = reassemble_pkcs12_name(idopts->cert_filename);
const char *tmp;
- pkiDebug("Initial PKCS12_parse with no password failed\n");
+ TRACE_PKINIT_PKCS_PARSE_FAIL_FIRST(context);
if (id_cryptoctx->defer_id_prompt) {
/* Supply the identity name to be passed to the responder. */
@@ -4386,14 +4380,14 @@ pkinit_get_certs_pkcs12(krb5_context context,
NULL, NULL, 1, &kprompt);
k5int_set_prompt_types(context, 0);
if (r) {
- pkiDebug("Failed to prompt for PKCS12 password");
+ TRACE_PKINIT_PKCS_PROMPT_FAIL(context);
goto cleanup;
}
}
ret = PKCS12_parse(p12, rdat.data, &y, &x, NULL);
if (ret == 0) {
- pkiDebug("Second PKCS12_parse with password failed\n");
+ TRACE_PKINIT_PKCS_PARSE_FAIL_SECOND(context);
goto cleanup;
}
}
@@ -4516,8 +4510,7 @@ pkinit_get_certs_fs(krb5_context context,
}
if (idopts->key_filename == NULL) {
- pkiDebug("%s: failed to get user's private key location\n",
- __FUNCTION__);
+ TRACE_PKINIT_NO_PRIVKEY(context);
goto cleanup;
}
@@ -4545,8 +4538,7 @@ pkinit_get_certs_dir(krb5_context context,
char *dirname, *suf;
if (idopts->cert_filename == NULL) {
- pkiDebug("%s: failed to get user's certificate directory location\n",
- __FUNCTION__);
+ TRACE_PKINIT_NO_CERT(context);
return ENOENT;
}
@@ -4590,8 +4582,7 @@ pkinit_get_certs_dir(krb5_context context,
retval = pkinit_load_fs_cert_and_key(context, id_cryptoctx,
certname, keyname, i);
if (retval == 0) {
- pkiDebug("%s: Successfully loaded cert (and key) for %s\n",
- __FUNCTION__, dentry->d_name);
+ TRACE_PKINIT_LOADED_CERT(context, dentry->d_name);
i++;
}
else
@@ -4599,8 +4590,7 @@ pkinit_get_certs_dir(krb5_context context,
}
if (!id_cryptoctx->defer_id_prompt && i == 0) {
- pkiDebug("%s: No cert/key pairs found in directory '%s'\n",
- __FUNCTION__, idopts->cert_filename);
+ TRACE_PKINIT_NO_CERT_AND_KEY(context, idopts->cert_filename);
retval = ENOENT;
goto cleanup;
}
@@ -5370,9 +5360,7 @@ crypto_cert_select_default(krb5_context context,
goto errout;
}
if (cert_count != 1) {
- pkiDebug("%s: ERROR: There are %d certs to choose from, "
- "but there must be exactly one.\n",
- __FUNCTION__, cert_count);
+ TRACE_PKINIT_NO_DEFAULT_CERT(context, cert_count);
retval = EINVAL;
goto errout;
}
@@ -5520,7 +5508,7 @@ load_cas_and_crls(krb5_context context,
switch(catype) {
case CATYPE_ANCHORS:
if (sk_X509_num(ca_certs) == 0) {
- pkiDebug("no anchors in file, %s\n", filename);
+ TRACE_PKINIT_NO_CA_ANCHOR(context, filename);
if (id_cryptoctx->trustedCAs == NULL)
sk_X509_free(ca_certs);
} else {
@@ -5530,7 +5518,7 @@ load_cas_and_crls(krb5_context context,
break;
case CATYPE_INTERMEDIATES:
if (sk_X509_num(ca_certs) == 0) {
- pkiDebug("no intermediates in file, %s\n", filename);
+ TRACE_PKINIT_NO_CA_INTERMEDIATE(context, filename);
if (id_cryptoctx->intermediateCAs == NULL)
sk_X509_free(ca_certs);
} else {
@@ -5540,7 +5528,7 @@ load_cas_and_crls(krb5_context context,
break;
case CATYPE_CRLS:
if (sk_X509_CRL_num(ca_crls) == 0) {
- pkiDebug("no crls in file, %s\n", filename);
+ TRACE_PKINIT_NO_CRL(context, filename);
if (id_cryptoctx->revoked == NULL)
sk_X509_CRL_free(ca_crls);
} else {
@@ -5626,14 +5614,14 @@ crypto_load_cas_and_crls(krb5_context context,
int catype,
char *id)
{
- pkiDebug("%s: called with idtype %s and catype %s\n",
- __FUNCTION__, idtype2string(idtype), catype2string(catype));
switch (idtype) {
case IDTYPE_FILE:
+ TRACE_PKINIT_LOAD_FROM_FILE(context);
return load_cas_and_crls(context, plg_cryptoctx, req_cryptoctx,
id_cryptoctx, catype, id);
break;
case IDTYPE_DIR:
+ TRACE_PKINIT_LOAD_FROM_DIR(context);
return load_cas_and_crls_dir(context, plg_cryptoctx, req_cryptoctx,
id_cryptoctx, catype, id);
break;
diff --git a/src/plugins/preauth/pkinit/pkinit_identity.c b/src/plugins/preauth/pkinit/pkinit_identity.c
index a897efa25..737552e85 100644
--- a/src/plugins/preauth/pkinit/pkinit_identity.c
+++ b/src/plugins/preauth/pkinit/pkinit_identity.c
@@ -608,7 +608,6 @@ pkinit_identity_prompt(krb5_context context,
retval = pkinit_cert_matching(context, plg_cryptoctx,
req_cryptoctx, id_cryptoctx, princ);
if (retval) {
- pkiDebug("%s: No matching certificate found\n", __FUNCTION__);
crypto_free_cert_info(context, plg_cryptoctx, req_cryptoctx,
id_cryptoctx);
goto errout;
@@ -621,8 +620,6 @@ pkinit_identity_prompt(krb5_context context,
retval = crypto_cert_select_default(context, plg_cryptoctx,
req_cryptoctx, id_cryptoctx);
if (retval) {
- pkiDebug("%s: Failed while selecting default certificate\n",
- __FUNCTION__);
crypto_free_cert_info(context, plg_cryptoctx, req_cryptoctx,
id_cryptoctx);
goto errout;
diff --git a/src/plugins/preauth/pkinit/pkinit_matching.c b/src/plugins/preauth/pkinit/pkinit_matching.c
index a50c50c8d..cad4c2b9a 100644
--- a/src/plugins/preauth/pkinit/pkinit_matching.c
+++ b/src/plugins/preauth/pkinit/pkinit_matching.c
@@ -812,6 +812,7 @@ pkinit_cert_matching(krb5_context context,
goto cleanup;
}
} else {
+ TRACE_PKINIT_NO_MATCHING_CERT(context);
retval = ENOENT; /* XXX */
goto cleanup;
}
diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c
index 32ca122f2..9c6e96c9e 100644
--- a/src/plugins/preauth/pkinit/pkinit_srv.c
+++ b/src/plugins/preauth/pkinit/pkinit_srv.c
@@ -188,6 +188,7 @@ verify_client_san(krb5_context context,
plgctx->opts->allow_upn ? &upns : NULL,
NULL);
if (retval == ENOENT) {
+ TRACE_PKINIT_SERVER_NO_SAN(context);
goto out;
} else if (retval) {
pkiDebug("%s: error from retrieve_certificate_sans()\n", __FUNCTION__);
@@ -224,7 +225,7 @@ verify_client_san(krb5_context context,
krb5_free_unparsed_name(context, san_string);
#endif
if (cb->match_client(context, rock, princs[i])) {
- pkiDebug("%s: pkinit san match found\n", __FUNCTION__);
+ TRACE_PKINIT_SERVER_MATCHING_SAN_FOUND(context);
*valid_san = 1;
retval = 0;
goto out;
@@ -252,7 +253,7 @@ verify_client_san(krb5_context context,
krb5_free_unparsed_name(context, san_string);
#endif
if (cb->match_client(context, rock, upns[i])) {
- pkiDebug("%s: upn san match found\n", __FUNCTION__);
+ TRACE_PKINIT_SERVER_MATCHING_UPN_FOUND(context);
*valid_san = 1;
retval = 0;
goto out;
@@ -300,7 +301,7 @@ verify_client_eku(krb5_context context,
*eku_accepted = 0;
if (plgctx->opts->require_eku == 0) {
- pkiDebug("%s: configuration requests no EKU checking\n", __FUNCTION__);
+ TRACE_PKINIT_SERVER_EKU_SKIP(context);
*eku_accepted = 1;
retval = 0;
goto out;
@@ -364,6 +365,7 @@ authorize_cert(krb5_context context, certauth_handle *certauth_modules,
ret = KRB5_PLUGIN_NO_HANDLE;
for (i = 0; certauth_modules != NULL && certauth_modules[i] != NULL; i++) {
h = certauth_modules[i];
+ TRACE_PKINIT_SERVER_CERT_AUTH(context, h->vt.name);
ret = h->vt.authorize(context, h->moddata, cert, cert_len, client,
&opts, db_ent, &ais);
if (ret == 0)
@@ -449,7 +451,7 @@ pkinit_server_verify_padata(krb5_context context,
switch ((int)data->pa_type) {
case KRB5_PADATA_PK_AS_REQ:
- pkiDebug("processing KRB5_PADATA_PK_AS_REQ\n");
+ TRACE_PKINIT_SERVER_PADATA_VERIFY(context);
retval = k5int_decode_krb5_pa_pk_as_req(&k5data, &reqp);
if (retval) {
pkiDebug("decode_krb5_pa_pk_as_req failed\n");
@@ -472,7 +474,7 @@ pkinit_server_verify_padata(krb5_context context,
break;
case KRB5_PADATA_PK_AS_REP_OLD:
case KRB5_PADATA_PK_AS_REQ_OLD:
- pkiDebug("processing KRB5_PADATA_PK_AS_REQ_OLD\n");
+ TRACE_PKINIT_SERVER_PADATA_VERIFY_OLD(context);
retval = k5int_decode_krb5_pa_pk_as_req_draft9(&k5data, &reqp9);
if (retval) {
pkiDebug("decode_krb5_pa_pk_as_req_draft9 failed\n");
@@ -500,7 +502,7 @@ pkinit_server_verify_padata(krb5_context context,
goto cleanup;
}
if (retval) {
- pkiDebug("pkcs7_signeddata_verify failed\n");
+ TRACE_PKINIT_SERVER_PADATA_VERIFY_FAIL(context);
goto cleanup;
}
if (is_signed) {
@@ -830,7 +832,7 @@ pkinit_server_return_padata(krb5_context context,
return ENOENT;
}
- pkiDebug("pkinit_return_padata: entered!\n");
+ TRACE_PKINIT_SERVER_RETURN_PADATA(context);
reqctx = (pkinit_kdc_req_context)modreq;
if (encrypting_key->contents) {
@@ -1463,8 +1465,7 @@ pkinit_san_authorize(krb5_context context, krb5_certauth_moddata moddata,
return ret;
if (!valid_san) {
- pkiDebug("%s: did not find an acceptable SAN in user certificate\n",
- __FUNCTION__);
+ TRACE_PKINIT_SERVER_SAN_REJECT(context);
return KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
}
@@ -1490,8 +1491,7 @@ pkinit_eku_authorize(krb5_context context, krb5_certauth_moddata moddata,
return ret;
if (!valid_eku) {
- pkiDebug("%s: did not find an acceptable EKU in user certificate\n",
- __FUNCTION__);
+ TRACE_PKINIT_SERVER_EKU_REJECT(context);
return KRB5KDC_ERR_INCONSISTENT_KEY_PURPOSE;
}
@@ -1617,7 +1617,7 @@ pkinit_server_plugin_init(krb5_context context,
return ENOMEM;
for (i = 0, j = 0; i < numrealms; i++) {
- pkiDebug("%s: processing realm '%s'\n", __FUNCTION__, realmnames[i]);
+ TRACE_PKINIT_SERVER_INIT_REALM(context, realmnames[i]);
retval = pkinit_server_plugin_init_realm(context, realmnames[i], &plgctx);
if (retval == 0 && plgctx != NULL)
realm_contexts[j++] = plgctx;
diff --git a/src/plugins/preauth/pkinit/pkinit_trace.h b/src/plugins/preauth/pkinit/pkinit_trace.h
index 458d0961e..6abe28c0c 100644
--- a/src/plugins/preauth/pkinit/pkinit_trace.h
+++ b/src/plugins/preauth/pkinit/pkinit_trace.h
@@ -52,7 +52,7 @@
#define TRACE_PKINIT_CLIENT_REP_CHECKSUM_FAIL(c, expected, received) \
TRACE(c, "PKINIT client checksum mismatch: expected {cksum}, " \
"received {cksum}", expected, received)
-#define TRACE_PKINIT_CLIENT_REP_DH(c) \
+#define TRACE_PKINIT_CLIENT_REP_DH(c) \
TRACE(c, "PKINIT client verified DH reply")
#define TRACE_PKINIT_CLIENT_REP_DH_FAIL(c) \
TRACE(c, "PKINIT client could not verify DH reply")
@@ -91,6 +91,72 @@
#define TRACE_PKINIT_OPENSSL_ERROR(c, msg) \
TRACE(c, "PKINIT OpenSSL error: {str}", msg)
+#define TRACE_PKINIT_SERVER_CERT_AUTH(c, modname) \
+ TRACE(c, "PKINIT server authorizing cert with module {str}", \
+ modname)
+#define TRACE_PKINIT_SERVER_EKU_REJECT(c) \
+ TRACE(c, "PKINIT server found no acceptable EKU in client cert")
+#define TRACE_PKINIT_SERVER_EKU_SKIP(c) \
+ TRACE(c, "PKINIT server skipping EKU check due to configuration")
+#define TRACE_PKINIT_SERVER_INIT_REALM(c, realm) \
+ TRACE(c, "PKINIT server initializing realm {str}", realm)
+#define TRACE_PKINIT_SERVER_MATCHING_UPN_FOUND(c) \
+ TRACE(c, "PKINIT server found a matching UPN SAN in client cert")
+#define TRACE_PKINIT_SERVER_MATCHING_SAN_FOUND(c) \
+ TRACE(c, "PKINIT server found a matching SAN in client cert")
+#define TRACE_PKINIT_SERVER_NO_SAN(c) \
+ TRACE(c, "PKINIT server found no SAN in client cert")
+#define TRACE_PKINIT_SERVER_PADATA_VERIFY(c) \
+ TRACE(c, "PKINIT server verifying KRB5_PADATA_PK_AS_REQ")
+#define TRACE_PKINIT_SERVER_PADATA_VERIFY_OLD(c) \
+ TRACE(c, "PKINIT server verifying KRB5_PADATA_PK_AS_REQ_OLD")
+#define TRACE_PKINIT_SERVER_PADATA_VERIFY_FAIL(c) \
+ TRACE(c, "PKINIT server failed to verify PA data")
+#define TRACE_PKINIT_SERVER_RETURN_PADATA(c) \
+ TRACE(c, "PKINIT server returning PA data")
+#define TRACE_PKINIT_SERVER_SAN_REJECT(c) \
+ TRACE(c, "PKINIT server found no acceptable SAN in client cert")
+
+#define TRACE_PKINIT_EKU(c) \
+ TRACE(c, "PKINIT found acceptable EKU and digitalSignature KU")
+#define TRACE_PKINIT_EKU_NO_KU(c) \
+ TRACE(c, "PKINIT found acceptable EKU but no digitalSignature KU")
+#define TRACE_PKINIT_LOADED_CERT(c, name) \
+ TRACE(c, "PKINIT loaded cert and key for {str}", name)
+#define TRACE_PKINIT_LOAD_FROM_FILE(c) \
+ TRACE(c, "PKINIT loading CA certs and CRLs from FILE")
+#define TRACE_PKINIT_LOAD_FROM_DIR(c) \
+ TRACE(c, "PKINIT loading CA certs and CRLs from DIR")
+#define TRACE_PKINIT_NO_CA_ANCHOR(c, file) \
+ TRACE(c, "PKINIT no anchor CA in file {str}", file)
+#define TRACE_PKINIT_NO_CA_INTERMEDIATE(c, file) \
+ TRACE(c, "PKINIT no intermediate CA in file {str}", file)
+#define TRACE_PKINIT_NO_CERT(c) \
+ TRACE(c, "PKINIT no certificate provided")
+#define TRACE_PKINIT_NO_CERT_AND_KEY(c, dirname) \
+ TRACE(c, "PKINIT no cert and key pair found in directory {str}", \
+ dirname)
+#define TRACE_PKINIT_NO_CRL(c, file) \
+ TRACE(c, "PKINIT no CRL in file {str}", file)
+#define TRACE_PKINIT_NO_DEFAULT_CERT(c, count) \
+ TRACE(c, "PKINIT error: There are {int} certs, but there must " \
+ "be exactly one.", count)
+#define TRACE_PKINIT_NO_MATCHING_CERT(c) \
+ TRACE(c, "PKINIT no matching certificate found")
+#define TRACE_PKINIT_NO_PRIVKEY(c) \
+ TRACE(c, "PKINIT no private key provided")
+#define TRACE_PKINIT_PKCS_DECODE_FAIL(c, name) \
+ TRACE(c, "PKINIT failed to decode PKCS12 file {str} contents", name)
+#define TRACE_PKINIT_PKCS_OPEN_FAIL(c, name, err) \
+ TRACE(c, "PKINIT failed to open PKCS12 file {str}: err {errno}", \
+ name, err)
+#define TRACE_PKINIT_PKCS_PARSE_FAIL_FIRST(c) \
+ TRACE(c, "PKINIT initial PKCS12_parse with no password failed")
+#define TRACE_PKINIT_PKCS_PARSE_FAIL_SECOND(c) \
+ TRACE(c, "PKINIT second PKCS12_parse with password failed")
+#define TRACE_PKINIT_PKCS_PROMPT_FAIL(c) \
+ TRACE(c, "PKINIT failed to prompt for PKCS12 password")
+
#define TRACE_CERTAUTH_VTINIT_FAIL(c, ret) \
TRACE(c, "certauth module failed to init vtable: {kerr}", ret)
#define TRACE_CERTAUTH_INIT_FAIL(c, name, ret) \

View file

@ -0,0 +1,32 @@
From 08d995aaf48e75c174525ae0b47e12c3170b3f5f Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Thu, 23 Mar 2017 13:42:55 -0400
Subject: [PATCH] Correct error handling bug in prior commit
In crypto_encode_der_cert(), if the second i2d_X509() invocation
fails, make sure to free the allocated pointer and not the
possibly-modified alias.
ticket: 8561
(cherry picked from commit 7fdaef7c3280c86b5df25ae061fb04cc56d8620c)
---
src/plugins/preauth/pkinit/pkinit_crypto_openssl.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
index a5b010b26..90c30dbf5 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
@@ -6196,10 +6196,10 @@ crypto_encode_der_cert(krb5_context context, pkinit_req_crypto_context reqctx,
if (len <= 0)
return EINVAL;
p = der = malloc(len);
- if (p == NULL)
+ if (der == NULL)
return ENOMEM;
if (i2d_X509(reqctx->received_cert, &p) <= 0) {
- free(p);
+ free(der);
return EINVAL;
}
*der_out = der;

View file

@ -0,0 +1,263 @@
From d5462c96c9918ffa7d3f05de310c5aed34181941 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Wed, 4 Jan 2017 11:33:57 -0500
Subject: [PATCH] Deindent crypto_retrieve_X509_sans()
Fix some long lines in crypto_retrieve_X509_sans() by returning early
if X509_get_ext_by_NID() returns a negative result. Also ensure that
return parameters are always initialized.
(cherry picked from commit c6b772523db9d7791ee1c56eb512c4626556a4e7)
---
src/plugins/preauth/pkinit/pkinit_crypto_openssl.c | 224 +++++++++++----------
1 file changed, 114 insertions(+), 110 deletions(-)
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
index bc6e7662e..8def8c542 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
@@ -2101,11 +2101,21 @@ crypto_retrieve_X509_sans(krb5_context context,
{
krb5_error_code retval = EINVAL;
char buf[DN_BUF_LEN];
- int p = 0, u = 0, d = 0, l;
+ int p = 0, u = 0, d = 0, ret = 0, l;
krb5_principal *princs = NULL;
krb5_principal *upns = NULL;
unsigned char **dnss = NULL;
- unsigned int i, num_found = 0;
+ unsigned int i, num_found = 0, num_sans = 0;
+ X509_EXTENSION *ext = NULL;
+ GENERAL_NAMES *ialt = NULL;
+ GENERAL_NAME *gen = NULL;
+
+ if (princs_ret != NULL)
+ *princs_ret = NULL;
+ if (upn_ret != NULL)
+ *upn_ret = NULL;
+ if (dns_ret != NULL)
+ *dns_ret = NULL;
if (princs_ret == NULL && upn_ret == NULL && dns_ret == NULL) {
pkiDebug("%s: nowhere to return any values!\n", __FUNCTION__);
@@ -2121,118 +2131,112 @@ crypto_retrieve_X509_sans(krb5_context context,
buf, sizeof(buf));
pkiDebug("%s: looking for SANs in cert = %s\n", __FUNCTION__, buf);
- if ((l = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1)) >= 0) {
- X509_EXTENSION *ext = NULL;
- GENERAL_NAMES *ialt = NULL;
- GENERAL_NAME *gen = NULL;
- int ret = 0;
- unsigned int num_sans = 0;
+ l = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
+ if (l < 0)
+ return 0;
- if (!(ext = X509_get_ext(cert, l)) || !(ialt = X509V3_EXT_d2i(ext))) {
- pkiDebug("%s: found no subject alt name extensions\n",
- __FUNCTION__);
+ if (!(ext = X509_get_ext(cert, l)) || !(ialt = X509V3_EXT_d2i(ext))) {
+ pkiDebug("%s: found no subject alt name extensions\n", __FUNCTION__);
+ goto cleanup;
+ }
+ num_sans = sk_GENERAL_NAME_num(ialt);
+
+ pkiDebug("%s: found %d subject alt name extension(s)\n", __FUNCTION__,
+ num_sans);
+
+ /* OK, we're likely returning something. Allocate return values */
+ if (princs_ret != NULL) {
+ princs = calloc(num_sans + 1, sizeof(krb5_principal));
+ if (princs == NULL) {
+ retval = ENOMEM;
goto cleanup;
}
- num_sans = sk_GENERAL_NAME_num(ialt);
-
- pkiDebug("%s: found %d subject alt name extension(s)\n",
- __FUNCTION__, num_sans);
-
- /* OK, we're likely returning something. Allocate return values */
- if (princs_ret != NULL) {
- princs = calloc(num_sans + 1, sizeof(krb5_principal));
- if (princs == NULL) {
- retval = ENOMEM;
- goto cleanup;
- }
- }
- if (upn_ret != NULL) {
- upns = calloc(num_sans + 1, sizeof(krb5_principal));
- if (upns == NULL) {
- retval = ENOMEM;
- goto cleanup;
- }
- }
- if (dns_ret != NULL) {
- dnss = calloc(num_sans + 1, sizeof(*dnss));
- if (dnss == NULL) {
- retval = ENOMEM;
- goto cleanup;
- }
- }
-
- for (i = 0; i < num_sans; i++) {
- krb5_data name = { 0, 0, NULL };
-
- gen = sk_GENERAL_NAME_value(ialt, i);
- switch (gen->type) {
- case GEN_OTHERNAME:
- name.length = gen->d.otherName->value->value.sequence->length;
- name.data = (char *)gen->d.otherName->value->value.sequence->data;
- if (princs != NULL
- && OBJ_cmp(plgctx->id_pkinit_san,
- gen->d.otherName->type_id) == 0) {
-#ifdef DEBUG_ASN1
- print_buffer_bin((unsigned char *)name.data, name.length,
- "/tmp/pkinit_san");
-#endif
- ret = k5int_decode_krb5_principal_name(&name, &princs[p]);
- if (ret) {
- pkiDebug("%s: failed decoding pkinit san value\n",
- __FUNCTION__);
- } else {
- p++;
- num_found++;
- }
- } else if (upns != NULL
- && OBJ_cmp(plgctx->id_ms_san_upn,
- gen->d.otherName->type_id) == 0) {
- /* Prevent abuse of embedded null characters. */
- if (memchr(name.data, '\0', name.length))
- break;
- ret = krb5_parse_name_flags(context, name.data,
- KRB5_PRINCIPAL_PARSE_ENTERPRISE,
- &upns[u]);
- if (ret) {
- pkiDebug("%s: failed parsing ms-upn san value\n",
- __FUNCTION__);
- } else {
- u++;
- num_found++;
- }
- } else {
- pkiDebug("%s: unrecognized othername oid in SAN\n",
- __FUNCTION__);
- continue;
- }
-
- break;
- case GEN_DNS:
- if (dnss != NULL) {
- /* Prevent abuse of embedded null characters. */
- if (memchr(gen->d.dNSName->data, '\0',
- gen->d.dNSName->length))
- break;
- pkiDebug("%s: found dns name = %s\n",
- __FUNCTION__, gen->d.dNSName->data);
- dnss[d] = (unsigned char *)
- strdup((char *)gen->d.dNSName->data);
- if (dnss[d] == NULL) {
- pkiDebug("%s: failed to duplicate dns name\n",
- __FUNCTION__);
- } else {
- d++;
- num_found++;
- }
- }
- break;
- default:
- pkiDebug("%s: SAN type = %d expecting %d\n",
- __FUNCTION__, gen->type, GEN_OTHERNAME);
- }
- }
- sk_GENERAL_NAME_pop_free(ialt, GENERAL_NAME_free);
}
+ if (upn_ret != NULL) {
+ upns = calloc(num_sans + 1, sizeof(krb5_principal));
+ if (upns == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ }
+ if (dns_ret != NULL) {
+ dnss = calloc(num_sans + 1, sizeof(*dnss));
+ if (dnss == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ }
+
+ for (i = 0; i < num_sans; i++) {
+ krb5_data name = { 0, 0, NULL };
+
+ gen = sk_GENERAL_NAME_value(ialt, i);
+ switch (gen->type) {
+ case GEN_OTHERNAME:
+ name.length = gen->d.otherName->value->value.sequence->length;
+ name.data = (char *)gen->d.otherName->value->value.sequence->data;
+ if (princs != NULL &&
+ OBJ_cmp(plgctx->id_pkinit_san,
+ gen->d.otherName->type_id) == 0) {
+#ifdef DEBUG_ASN1
+ print_buffer_bin((unsigned char *)name.data, name.length,
+ "/tmp/pkinit_san");
+#endif
+ ret = k5int_decode_krb5_principal_name(&name, &princs[p]);
+ if (ret) {
+ pkiDebug("%s: failed decoding pkinit san value\n",
+ __FUNCTION__);
+ } else {
+ p++;
+ num_found++;
+ }
+ } else if (upns != NULL &&
+ OBJ_cmp(plgctx->id_ms_san_upn,
+ gen->d.otherName->type_id) == 0) {
+ /* Prevent abuse of embedded null characters. */
+ if (memchr(name.data, '\0', name.length))
+ break;
+ ret = krb5_parse_name_flags(context, name.data,
+ KRB5_PRINCIPAL_PARSE_ENTERPRISE,
+ &upns[u]);
+ if (ret) {
+ pkiDebug("%s: failed parsing ms-upn san value\n",
+ __FUNCTION__);
+ } else {
+ u++;
+ num_found++;
+ }
+ } else {
+ pkiDebug("%s: unrecognized othername oid in SAN\n",
+ __FUNCTION__);
+ continue;
+ }
+
+ break;
+ case GEN_DNS:
+ if (dnss != NULL) {
+ /* Prevent abuse of embedded null characters. */
+ if (memchr(gen->d.dNSName->data, '\0', gen->d.dNSName->length))
+ break;
+ pkiDebug("%s: found dns name = %s\n", __FUNCTION__,
+ gen->d.dNSName->data);
+ dnss[d] = (unsigned char *)
+ strdup((char *)gen->d.dNSName->data);
+ if (dnss[d] == NULL) {
+ pkiDebug("%s: failed to duplicate dns name\n",
+ __FUNCTION__);
+ } else {
+ d++;
+ num_found++;
+ }
+ }
+ break;
+ default:
+ pkiDebug("%s: SAN type = %d expecting %d\n", __FUNCTION__,
+ gen->type, GEN_OTHERNAME);
+ }
+ }
+ sk_GENERAL_NAME_pop_free(ialt, GENERAL_NAME_free);
retval = 0;
if (princs)

View file

@ -0,0 +1,105 @@
From 3fe07aaa6d8b6115aa19e2c04087352a5c87a568 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Tue, 24 Oct 2017 15:33:37 -0400
Subject: [PATCH] Fix PKINIT cert matching data construction
Rewrite X509_NAME_oneline_ex() and its call sites to use dynamic
allocation and to perform proper error checking.
(cherry picked from commit 1d8fb334a6256b9ddd3d4377a92c2441407d8a12)
---
src/plugins/preauth/pkinit/pkinit_crypto_openssl.c | 63 ++++++++--------------
1 file changed, 21 insertions(+), 42 deletions(-)
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
index 7fa2efd21..336102656 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
@@ -5139,33 +5139,23 @@ out:
return retval;
}
-/*
- * Return a string format of an X509_NAME in buf where
- * size is an in/out parameter. On input it is the size
- * of the buffer, and on output it is the actual length
- * of the name.
- * If buf is NULL, returns the length req'd to hold name
- */
-static char *
-X509_NAME_oneline_ex(X509_NAME * a,
- char *buf,
- unsigned int *size,
- unsigned long flag)
+static krb5_error_code
+rfc2253_name(X509_NAME *name, char **str_out)
{
- BIO *out = NULL;
+ BIO *b = NULL;
+ char *str;
- out = BIO_new(BIO_s_mem ());
- if (X509_NAME_print_ex(out, a, 0, flag) > 0) {
- if (buf != NULL && (*size) > (unsigned int) BIO_number_written(out)) {
- memset(buf, 0, *size);
- BIO_read(out, buf, (int) BIO_number_written(out));
- }
- else {
- *size = BIO_number_written(out);
- }
- }
- BIO_free(out);
- return (buf);
+ *str_out = NULL;
+ b = BIO_new(BIO_s_mem());
+ if (X509_NAME_print_ex(b, name, 0, XN_FLAG_SEP_COMMA_PLUS) < 0)
+ return ENOMEM;
+ str = calloc(BIO_number_written(b) + 1, 1);
+ if (str == NULL)
+ return ENOMEM;
+ BIO_read(b, str, BIO_number_written(b));
+ BIO_free(b);
+ *str_out = str;
+ return 0;
}
/*
@@ -5181,8 +5171,6 @@ crypto_cert_get_matching_data(krb5_context context,
krb5_principal *pkinit_sans =NULL, *upn_sans = NULL;
struct _pkinit_cert_data *cd = (struct _pkinit_cert_data *)ch;
unsigned int i, j;
- char buf[DN_BUF_LEN];
- unsigned int bufsize = sizeof(buf);
if (cd == NULL || cd->magic != CERT_MAGIC)
return EINVAL;
@@ -5195,23 +5183,14 @@ crypto_cert_get_matching_data(krb5_context context,
md->ch = ch;
- /* get the subject name (in rfc2253 format) */
- X509_NAME_oneline_ex(X509_get_subject_name(cd->cred->cert),
- buf, &bufsize, XN_FLAG_SEP_COMMA_PLUS);
- md->subject_dn = strdup(buf);
- if (md->subject_dn == NULL) {
- retval = ENOMEM;
+ retval = rfc2253_name(X509_get_subject_name(cd->cred->cert),
+ &md->subject_dn);
+ if (retval)
goto cleanup;
- }
-
- /* get the issuer name (in rfc2253 format) */
- X509_NAME_oneline_ex(X509_get_issuer_name(cd->cred->cert),
- buf, &bufsize, XN_FLAG_SEP_COMMA_PLUS);
- md->issuer_dn = strdup(buf);
- if (md->issuer_dn == NULL) {
- retval = ENOMEM;
+ retval = rfc2253_name(X509_get_issuer_name(cd->cred->cert),
+ &md->issuer_dn);
+ if (retval)
goto cleanup;
- }
/* get the san data */
retval = crypto_retrieve_X509_sans(context, cd->plgctx, cd->reqctx,

View file

@ -0,0 +1,130 @@
From c8c704cdaaa15a0908024f0917344048c0df5940 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Sat, 19 Aug 2017 19:09:24 -0400
Subject: [PATCH] Fix bugs in kdcpolicy commit
Commit d0969f6a8170344031ef58fd2a161190f1edfb96 added tests using
"klist ccachname -e", which does not work with a POSIX-conformant
getopt() implementation such as the one in Solaris. Fix
t_kdcpolicy.py to use "klist -e ccachename" instead.
The tests could fail if the clock second rolled over between kinit and
kvno. Divide service ticket maximum lifetimes by 2 in the test module
to correctly exercise TGS policy restrictions and ensure that service
tickets are not constrained by the TGT end time.
Also use the correct trace macro when a kdcpolicy module declines to
initialize (my mistake when revising the commit, noted by rharwood).
ticket: 8606
(cherry picked from commit 09acbd91efc6df54e1572285ffc94c6acb3a9113)
---
src/kdc/policy.c | 2 +-
src/plugins/kdcpolicy/test/main.c | 10 +++++-----
src/tests/t_kdcpolicy.py | 13 +++++++++----
3 files changed, 15 insertions(+), 10 deletions(-)
diff --git a/src/kdc/policy.c b/src/kdc/policy.c
index e49644e06..26c16f97c 100644
--- a/src/kdc/policy.c
+++ b/src/kdc/policy.c
@@ -222,7 +222,7 @@ load_kdcpolicy_plugins(krb5_context context)
if (h->vt.init != NULL) {
ret = h->vt.init(context, &h->moddata);
if (ret == KRB5_PLUGIN_NO_HANDLE) {
- TRACE_KADM5_AUTH_INIT_SKIP(context, h->vt.name);
+ TRACE_KDCPOLICY_INIT_SKIP(context, h->vt.name);
free(h);
continue;
}
diff --git a/src/plugins/kdcpolicy/test/main.c b/src/plugins/kdcpolicy/test/main.c
index eb8fde053..86c808958 100644
--- a/src/plugins/kdcpolicy/test/main.c
+++ b/src/plugins/kdcpolicy/test/main.c
@@ -35,7 +35,7 @@
#include <krb5/kdcpolicy_plugin.h>
static krb5_error_code
-output_from_indicator(const char *const *auth_indicators,
+output_from_indicator(const char *const *auth_indicators, int divisor,
krb5_deltat *lifetime_out,
krb5_deltat *renew_lifetime_out,
const char **status)
@@ -46,11 +46,11 @@ output_from_indicator(const char *const *auth_indicators,
}
if (strcmp(auth_indicators[0], "ONE_HOUR") == 0) {
- *lifetime_out = 3600;
+ *lifetime_out = 3600 / divisor;
*renew_lifetime_out = *lifetime_out * 2;
return 0;
} else if (strcmp(auth_indicators[0], "SEVEN_HOURS") == 0) {
- *lifetime_out = 7 * 3600;
+ *lifetime_out = 7 * 3600 / divisor;
*renew_lifetime_out = *lifetime_out * 2;
return 0;
}
@@ -71,7 +71,7 @@ test_check_as(krb5_context context, krb5_kdcpolicy_moddata moddata,
*status = "LOCAL_POLICY";
return KRB5KDC_ERR_POLICY;
}
- return output_from_indicator(auth_indicators, lifetime_out,
+ return output_from_indicator(auth_indicators, 1, lifetime_out,
renew_lifetime_out, status);
}
@@ -87,7 +87,7 @@ test_check_tgs(krb5_context context, krb5_kdcpolicy_moddata moddata,
*status = "LOCAL_POLICY";
return KRB5KDC_ERR_POLICY;
}
- return output_from_indicator(auth_indicators, lifetime_out,
+ return output_from_indicator(auth_indicators, 2, lifetime_out,
renew_lifetime_out, status);
}
diff --git a/src/tests/t_kdcpolicy.py b/src/tests/t_kdcpolicy.py
index 6a745b959..b5d308461 100644
--- a/src/tests/t_kdcpolicy.py
+++ b/src/tests/t_kdcpolicy.py
@@ -18,16 +18,21 @@ realm.run([kadminl, 'addprinc', '-pw', password('fail'), 'fail'])
def verify_time(out, target_time):
times = re.findall(r'\d\d/\d\d/\d\d \d\d:\d\d:\d\d', out)
times = [datetime.strptime(t, '%m/%d/%y %H:%M:%S') for t in times]
+ divisor = 1
while len(times) > 0:
starttime = times.pop(0)
endtime = times.pop(0)
renewtime = times.pop(0)
- if str(endtime - starttime) != target_time:
+ if str((endtime - starttime) * divisor) != target_time:
fail('unexpected lifetime value')
- if str(renewtime - endtime) != target_time:
+ if str((renewtime - endtime) * divisor) != target_time:
fail('unexpected renewable value')
+ # Service tickets should have half the lifetime of initial
+ # tickets.
+ divisor = 2
+
rflags = ['-r', '1d', '-l', '12h']
# Test AS+TGS success path.
@@ -35,7 +40,7 @@ realm.kinit(realm.user_princ, password('user'),
rflags + ['-X', 'indicators=SEVEN_HOURS'])
realm.run([kvno, realm.host_princ])
realm.run(['./adata', realm.host_princ], expected_msg='+97: [SEVEN_HOURS]')
-out = realm.run([klist, realm.ccache, '-e'])
+out = realm.run([klist, '-e', realm.ccache])
verify_time(out, '7:00:00')
# Test AS+TGS success path with different values.
@@ -43,7 +48,7 @@ realm.kinit(realm.user_princ, password('user'),
rflags + ['-X', 'indicators=ONE_HOUR'])
realm.run([kvno, realm.host_princ])
realm.run(['./adata', realm.host_princ], expected_msg='+97: [ONE_HOUR]')
-out = realm.run([klist, realm.ccache, '-e'])
+out = realm.run([klist, '-e', realm.ccache])
verify_time(out, '1:00:00')
# Test TGS failure path (using previous creds).

View file

@ -0,0 +1,124 @@
From 0d93e336e2cb8319bfd3e0fa096e5ee8ea3bbbbf Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Thu, 24 Aug 2017 11:11:46 -0400
Subject: [PATCH] Fix certauth built-in module returns
The PKINIT certauth eku module should never authoritatively authorize
a certificate, because an extended key usage does not establish a
relationship between the certificate and any specific user; it only
establishes that the certificate was created for PKINIT client
authentication. Therefore, pkinit_eku_authorize() should return
KRB5_PLUGIN_NO_HANDLE on success, not 0.
The certauth san module should pass if it does not find any SANs of
the types it can match against; the presence of other types of SANs
should not cause it to explicitly deny a certificate. Check for an
empty result from crypto_retrieve_cert_sans() in verify_client_san(),
instead of returning ENOENT from crypto_retrieve_cert_sans() when
there are no SANs at all.
ticket: 8561
(cherry picked from commit 07243f85a760fb37f0622d7ff0177db3f19ab025)
---
src/plugins/preauth/pkinit/pkinit_crypto_openssl.c | 39 ++++++++++------------
src/plugins/preauth/pkinit/pkinit_srv.c | 14 +++++---
2 files changed, 27 insertions(+), 26 deletions(-)
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
index 70e230ec2..7fa2efd21 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
@@ -2137,7 +2137,6 @@ crypto_retrieve_X509_sans(krb5_context context,
if (!(ext = X509_get_ext(cert, l)) || !(ialt = X509V3_EXT_d2i(ext))) {
pkiDebug("%s: found no subject alt name extensions\n", __FUNCTION__);
- retval = ENOENT;
goto cleanup;
}
num_sans = sk_GENERAL_NAME_num(ialt);
@@ -2240,31 +2239,29 @@ crypto_retrieve_X509_sans(krb5_context context,
sk_GENERAL_NAME_pop_free(ialt, GENERAL_NAME_free);
retval = 0;
- if (princs)
+ if (princs != NULL && *princs != NULL) {
*princs_ret = princs;
- if (upns)
+ princs = NULL;
+ }
+ if (upns != NULL && *upns != NULL) {
*upn_ret = upns;
- if (dnss)
+ upns = NULL;
+ }
+ if (dnss != NULL && *dnss != NULL) {
*dns_ret = dnss;
+ dnss = NULL;
+ }
cleanup:
- if (retval) {
- if (princs != NULL) {
- for (i = 0; princs[i] != NULL; i++)
- krb5_free_principal(context, princs[i]);
- free(princs);
- }
- if (upns != NULL) {
- for (i = 0; upns[i] != NULL; i++)
- krb5_free_principal(context, upns[i]);
- free(upns);
- }
- if (dnss != NULL) {
- for (i = 0; dnss[i] != NULL; i++)
- free(dnss[i]);
- free(dnss);
- }
- }
+ for (i = 0; princs != NULL && princs[i] != NULL; i++)
+ krb5_free_principal(context, princs[i]);
+ free(princs);
+ for (i = 0; upns != NULL && upns[i] != NULL; i++)
+ krb5_free_principal(context, upns[i]);
+ free(upns);
+ for (i = 0; dnss != NULL && dnss[i] != NULL; i++)
+ free(dnss[i]);
+ free(dnss);
return retval;
}
diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c
index 9c6e96c9e..8e77606f8 100644
--- a/src/plugins/preauth/pkinit/pkinit_srv.c
+++ b/src/plugins/preauth/pkinit/pkinit_srv.c
@@ -187,14 +187,18 @@ verify_client_san(krb5_context context,
&princs,
plgctx->opts->allow_upn ? &upns : NULL,
NULL);
- if (retval == ENOENT) {
- TRACE_PKINIT_SERVER_NO_SAN(context);
- goto out;
- } else if (retval) {
+ if (retval) {
pkiDebug("%s: error from retrieve_certificate_sans()\n", __FUNCTION__);
retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
goto out;
}
+
+ if (princs == NULL && upns == NULL) {
+ TRACE_PKINIT_SERVER_NO_SAN(context);
+ retval = ENOENT;
+ goto out;
+ }
+
/* XXX Verify this is consistent with client side XXX */
#if 0
retval = call_san_checking_plugins(context, plgctx, reqctx, princs,
@@ -1495,7 +1499,7 @@ pkinit_eku_authorize(krb5_context context, krb5_certauth_moddata moddata,
return KRB5KDC_ERR_INCONSISTENT_KEY_PURPOSE;
}
- return 0;
+ return KRB5_PLUGIN_NO_HANDLE;
}
static krb5_error_code

View file

@ -0,0 +1,58 @@
From e2d34698687c00504b83e1c0deb56dc6232bef42 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Mon, 24 Apr 2017 02:02:36 -0400
Subject: [PATCH] Fix in_clock_skew() and use it in AS client code
Add a context parameter to the in_clock_skew() macro so that it isn't
implicitly relying on a local variable. Use it in
get_in_tkt.c:verify_as_reply().
(cherry picked from commit 28a07a6461bb443b7fa75cc5cb859ad0db4cbb5a)
---
src/lib/krb5/krb/gc_via_tkt.c | 2 +-
src/lib/krb5/krb/get_in_tkt.c | 4 ++--
src/lib/krb5/krb/int-proto.h | 3 ++-
3 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/src/lib/krb5/krb/gc_via_tkt.c b/src/lib/krb5/krb/gc_via_tkt.c
index 4c0a1a461..c85d8b8d8 100644
--- a/src/lib/krb5/krb/gc_via_tkt.c
+++ b/src/lib/krb5/krb/gc_via_tkt.c
@@ -305,7 +305,7 @@ krb5int_process_tgs_reply(krb5_context context,
goto cleanup;
if (!in_cred->times.starttime &&
- !in_clock_skew(dec_rep->enc_part2->times.starttime,
+ !in_clock_skew(context, dec_rep->enc_part2->times.starttime,
timestamp)) {
retval = KRB5_KDCREP_SKEW;
goto cleanup;
diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
index 54badbbc3..a058f5bd7 100644
--- a/src/lib/krb5/krb/get_in_tkt.c
+++ b/src/lib/krb5/krb/get_in_tkt.c
@@ -287,8 +287,8 @@ verify_as_reply(krb5_context context,
return retval;
} else {
if ((request->from == 0) &&
- (labs(as_reply->enc_part2->times.starttime - time_now)
- > context->clockskew))
+ !in_clock_skew(context, as_reply->enc_part2->times.starttime,
+ time_now))
return (KRB5_KDCREP_SKEW);
}
return 0;
diff --git a/src/lib/krb5/krb/int-proto.h b/src/lib/krb5/krb/int-proto.h
index 6da74858e..44eca359f 100644
--- a/src/lib/krb5/krb/int-proto.h
+++ b/src/lib/krb5/krb/int-proto.h
@@ -83,7 +83,8 @@ krb5int_construct_matching_creds(krb5_context context, krb5_flags options,
krb5_creds *in_creds, krb5_creds *mcreds,
krb5_flags *fields);
-#define in_clock_skew(date, now) (labs((date)-(now)) < context->clockskew)
+#define in_clock_skew(context, date, now) \
+ (labs((date) - (now)) < (context)->clockskew)
#define IS_TGS_PRINC(p) ((p)->length == 2 && \
data_eq_string((p)->data[0], KRB5_TGS_NAME))

View file

@ -0,0 +1,83 @@
From 7b28a408650c58d0ea98fddab5034642af32fdaf Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Wed, 17 May 2017 14:52:09 -0400
Subject: [PATCH] Fix more time manipulations for y2038
Use timestamp helper functions to ensure that more operations are safe
after y2038, and display the current timestamp as unsigned in
krb5int_trace().
ticket: 8352
(cherry picked from commit a60db180211a383bd382afe729e9309acb8dcf53)
---
src/kadmin/server/misc.c | 2 +-
src/kdc/dispatch.c | 2 +-
src/lib/krb5/os/c_ustime.c | 8 ++++----
src/lib/krb5/os/trace.c | 2 +-
4 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/kadmin/server/misc.c b/src/kadmin/server/misc.c
index 27a6376af..a75b65a26 100644
--- a/src/kadmin/server/misc.c
+++ b/src/kadmin/server/misc.c
@@ -184,7 +184,7 @@ check_min_life(void *server_handle, krb5_principal principal,
(void) kadm5_free_principal_ent(handle->lhandle, &princ);
return (ret == KADM5_UNK_POLICY) ? 0 : ret;
}
- if((now - princ.last_pwd_change) < pol.pw_min_life &&
+ if(ts_delta(now, princ.last_pwd_change) < pol.pw_min_life &&
!(princ.attributes & KRB5_KDB_REQUIRES_PWCHANGE)) {
if (msg_ret != NULL) {
time_t until;
diff --git a/src/kdc/dispatch.c b/src/kdc/dispatch.c
index 3a169ebc7..16a35d2be 100644
--- a/src/kdc/dispatch.c
+++ b/src/kdc/dispatch.c
@@ -104,7 +104,7 @@ reseed_random(krb5_context kdc_err_context)
if (last_os_random == 0)
last_os_random = now;
/* Grab random data from OS every hour*/
- if (now-last_os_random >= 60 * 60) {
+ if (ts_delta(now, last_os_random) >= 60 * 60) {
krb5_c_random_os_entropy(kdc_err_context, 0, NULL);
last_os_random = now;
}
diff --git a/src/lib/krb5/os/c_ustime.c b/src/lib/krb5/os/c_ustime.c
index 871d72183..68fb381f4 100644
--- a/src/lib/krb5/os/c_ustime.c
+++ b/src/lib/krb5/os/c_ustime.c
@@ -102,17 +102,17 @@ krb5_crypto_us_timeofday(krb5_int32 *seconds, krb5_int32 *microseconds)
putting now.sec in the past. But don't just use '<' because we
need to properly handle the case where the administrator intentionally
adjusted time backwards. */
- if ((now.sec == last_time.sec-1) ||
- ((now.sec == last_time.sec) && (now.usec <= last_time.usec))) {
+ if (now.sec == ts_incr(last_time.sec, -1) ||
+ (now.sec == last_time.sec && !ts_after(last_time.usec, now.usec))) {
/* Correct 'now' to be exactly one microsecond later than 'last_time'.
Note that _because_ we perform this hack, 'now' may be _earlier_
than 'last_time', even though the system time is monotonically
increasing. */
now.sec = last_time.sec;
- now.usec = ++last_time.usec;
+ now.usec = ts_incr(last_time.usec, 1);
if (now.usec >= 1000000) {
- ++now.sec;
+ now.sec = ts_incr(now.sec, 1);
now.usec = 0;
}
}
diff --git a/src/lib/krb5/os/trace.c b/src/lib/krb5/os/trace.c
index a19246128..74c315c90 100644
--- a/src/lib/krb5/os/trace.c
+++ b/src/lib/krb5/os/trace.c
@@ -350,7 +350,7 @@ krb5int_trace(krb5_context context, const char *fmt, ...)
goto cleanup;
if (krb5_crypto_us_timeofday(&sec, &usec) != 0)
goto cleanup;
- if (asprintf(&msg, "[%d] %d.%d: %s\n", (int) getpid(), (int) sec,
+ if (asprintf(&msg, "[%d] %u.%d: %s\n", (int) getpid(), (unsigned int) sec,
(int) usec, str) < 0)
goto cleanup;
info.message = msg;

View file

@ -0,0 +1,151 @@
From 03265620488b84238c31170356b5f41c80f0e9d9 Mon Sep 17 00:00:00 2001
From: Matt Rogers <mrogers@redhat.com>
Date: Mon, 5 Dec 2016 12:17:59 -0500
Subject: [PATCH] Improve PKINIT UPN SAN matching
Add the match_client() kdcpreauth callback and use it in
verify_client_san(). match_client() preserves the direct UPN to
request principal comparison and adds a direct comparison to the
client principal, falling back to an alias DB search and comparison
against the client principal. Change crypto_retreive_X509_sans() to
parse UPN values as enterprise principals.
[ghudson@mit.edu: use match_client for both kinds of SANs]
ticket: 8528 (new)
(cherry picked from commit 46ff765e1fb8cbec2bb602b43311269e695dbedc)
---
src/include/krb5/kdcpreauth_plugin.h | 13 ++++++++++
src/kdc/kdc_preauth.c | 28 ++++++++++++++++++++--
src/plugins/preauth/pkinit/pkinit_crypto_openssl.c | 4 +++-
src/plugins/preauth/pkinit/pkinit_srv.c | 10 ++++----
4 files changed, 48 insertions(+), 7 deletions(-)
diff --git a/src/include/krb5/kdcpreauth_plugin.h b/src/include/krb5/kdcpreauth_plugin.h
index f455effae..92aa5a5a5 100644
--- a/src/include/krb5/kdcpreauth_plugin.h
+++ b/src/include/krb5/kdcpreauth_plugin.h
@@ -221,6 +221,19 @@ typedef struct krb5_kdcpreauth_callbacks_st {
/* End of version 3 kdcpreauth callbacks. */
+ /*
+ * Return true if princ matches the principal named in the request or the
+ * client principal (possibly canonicalized). If princ does not match,
+ * attempt a database lookup of princ with aliases allowed and compare the
+ * result to the client principal, returning true if it matches.
+ * Otherwise, return false.
+ */
+ krb5_boolean (*match_client)(krb5_context context,
+ krb5_kdcpreauth_rock rock,
+ krb5_principal princ);
+
+ /* End of version 4 kdcpreauth callbacks. */
+
} *krb5_kdcpreauth_callbacks;
/* Optional: preauth plugin initialization function. */
diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c
index 605fcb7ad..0ce79c667 100644
--- a/src/kdc/kdc_preauth.c
+++ b/src/kdc/kdc_preauth.c
@@ -568,8 +568,31 @@ set_cookie(krb5_context context, krb5_kdcpreauth_rock rock,
return kdc_fast_set_cookie(rock->rstate, pa_type, data);
}
+static krb5_boolean
+match_client(krb5_context context, krb5_kdcpreauth_rock rock,
+ krb5_principal princ)
+{
+ krb5_db_entry *ent;
+ krb5_boolean match = FALSE;
+ krb5_principal req_client = rock->request->client;
+ krb5_principal client = rock->client->princ;
+
+ /* Check for a direct match against the request principal or
+ * the post-canon client principal. */
+ if (krb5_principal_compare_flags(context, princ, req_client,
+ KRB5_PRINCIPAL_COMPARE_ENTERPRISE) ||
+ krb5_principal_compare(context, princ, client))
+ return TRUE;
+
+ if (krb5_db_get_principal(context, princ, KRB5_KDB_FLAG_ALIAS_OK, &ent))
+ return FALSE;
+ match = krb5_principal_compare(context, ent->princ, client);
+ krb5_db_free_principal(context, ent);
+ return match;
+}
+
static struct krb5_kdcpreauth_callbacks_st callbacks = {
- 3,
+ 4,
max_time_skew,
client_keys,
free_keys,
@@ -583,7 +606,8 @@ static struct krb5_kdcpreauth_callbacks_st callbacks = {
client_keyblock,
add_auth_indicator,
get_cookie,
- set_cookie
+ set_cookie,
+ match_client
};
static krb5_error_code
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
index 74fffbf32..bc6e7662e 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
@@ -2190,7 +2190,9 @@ crypto_retrieve_X509_sans(krb5_context context,
/* Prevent abuse of embedded null characters. */
if (memchr(name.data, '\0', name.length))
break;
- ret = krb5_parse_name(context, name.data, &upns[u]);
+ ret = krb5_parse_name_flags(context, name.data,
+ KRB5_PRINCIPAL_PARSE_ENTERPRISE,
+ &upns[u]);
if (ret) {
pkiDebug("%s: failed parsing ms-upn san value\n",
__FUNCTION__);
diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c
index 295be25e1..b5638a367 100644
--- a/src/plugins/preauth/pkinit/pkinit_srv.c
+++ b/src/plugins/preauth/pkinit/pkinit_srv.c
@@ -121,6 +121,8 @@ static krb5_error_code
verify_client_san(krb5_context context,
pkinit_kdc_context plgctx,
pkinit_kdc_req_context reqctx,
+ krb5_kdcpreauth_callbacks cb,
+ krb5_kdcpreauth_rock rock,
krb5_principal client,
int *valid_san)
{
@@ -171,7 +173,7 @@ verify_client_san(krb5_context context,
__FUNCTION__, client_string, san_string);
krb5_free_unparsed_name(context, san_string);
#endif
- if (krb5_principal_compare(context, princs[i], client)) {
+ if (cb->match_client(context, rock, princs[i])) {
pkiDebug("%s: pkinit san match found\n", __FUNCTION__);
*valid_san = 1;
retval = 0;
@@ -199,7 +201,7 @@ verify_client_san(krb5_context context,
__FUNCTION__, client_string, san_string);
krb5_free_unparsed_name(context, san_string);
#endif
- if (krb5_principal_compare(context, upns[i], client)) {
+ if (cb->match_client(context, rock, upns[i])) {
pkiDebug("%s: upn san match found\n", __FUNCTION__);
*valid_san = 1;
retval = 0;
@@ -387,8 +389,8 @@ pkinit_server_verify_padata(krb5_context context,
}
if (is_signed) {
- retval = verify_client_san(context, plgctx, reqctx, request->client,
- &valid_san);
+ retval = verify_client_san(context, plgctx, reqctx, cb, rock,
+ request->client, &valid_san);
if (retval)
goto cleanup;
if (!valid_san) {

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,134 @@
From 466d09c9b2c456d663672cb6d5f661ef86e8536e Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Mon, 31 Jul 2017 16:03:41 -0400
Subject: [PATCH] Remove incomplete PKINIT OCSP support
pkinit_kdc_ocsp is non-functional in the PKINIT OpenSSL crypto
implementation, so remove most traces of it, including its man page
entry. If it is present in kdc.conf, error out of PKINIT
initialization instead of silently ignoring the realm entirely.
ticket: 8603 (new)
(cherry picked from commit 3ff426b9048a8024e5c175256c63cd0ad0572320)
---
doc/admin/conf_files/kdc_conf.rst | 3 ---
src/man/kdc.conf.man | 3 ---
src/plugins/preauth/pkinit/pkinit.h | 2 +-
src/plugins/preauth/pkinit/pkinit_identity.c | 11 -----------
src/plugins/preauth/pkinit/pkinit_srv.c | 12 ++++++++++--
5 files changed, 11 insertions(+), 20 deletions(-)
diff --git a/doc/admin/conf_files/kdc_conf.rst b/doc/admin/conf_files/kdc_conf.rst
index 4e54f7e1d..d00e7926c 100644
--- a/doc/admin/conf_files/kdc_conf.rst
+++ b/doc/admin/conf_files/kdc_conf.rst
@@ -765,9 +765,6 @@ For information about the syntax of some of these options, see
pkinit is used to authenticate. This option may be specified
multiple times. (New in release 1.14.)
-**pkinit_kdc_ocsp**
- Specifies the location of the KDC's OCSP.
-
**pkinit_pool**
Specifies the location of intermediate certificates which may be
used by the KDC to complete the trust chain between a client's
diff --git a/src/man/kdc.conf.man b/src/man/kdc.conf.man
index d207ebd7f..c47da0117 100644
--- a/src/man/kdc.conf.man
+++ b/src/man/kdc.conf.man
@@ -886,9 +886,6 @@ Specifies an authentication indicator to include in the ticket if
pkinit is used to authenticate. This option may be specified
multiple times. (New in release 1.14.)
.TP
-.B \fBpkinit_kdc_ocsp\fP
-Specifies the location of the KDC\(aqs OCSP.
-.TP
.B \fBpkinit_pool\fP
Specifies the location of intermediate certificates which may be
used by the KDC to complete the trust chain between a client\(aqs
diff --git a/src/plugins/preauth/pkinit/pkinit.h b/src/plugins/preauth/pkinit/pkinit.h
index 876db94c3..a49f3078e 100644
--- a/src/plugins/preauth/pkinit/pkinit.h
+++ b/src/plugins/preauth/pkinit/pkinit.h
@@ -73,6 +73,7 @@
#define KRB5_CONF_PKINIT_IDENTITIES "pkinit_identities"
#define KRB5_CONF_PKINIT_IDENTITY "pkinit_identity"
#define KRB5_CONF_PKINIT_KDC_HOSTNAME "pkinit_kdc_hostname"
+/* pkinit_kdc_ocsp has been removed */
#define KRB5_CONF_PKINIT_KDC_OCSP "pkinit_kdc_ocsp"
#define KRB5_CONF_PKINIT_POOL "pkinit_pool"
#define KRB5_CONF_PKINIT_REQUIRE_CRL_CHECKING "pkinit_require_crl_checking"
@@ -173,7 +174,6 @@ typedef struct _pkinit_identity_opts {
char **anchors;
char **intermediates;
char **crls;
- char *ocsp;
int idtype;
char *cert_filename;
char *key_filename;
diff --git a/src/plugins/preauth/pkinit/pkinit_identity.c b/src/plugins/preauth/pkinit/pkinit_identity.c
index 177a2cad8..a897efa25 100644
--- a/src/plugins/preauth/pkinit/pkinit_identity.c
+++ b/src/plugins/preauth/pkinit/pkinit_identity.c
@@ -125,7 +125,6 @@ pkinit_init_identity_opts(pkinit_identity_opts **idopts)
opts->anchors = NULL;
opts->intermediates = NULL;
opts->crls = NULL;
- opts->ocsp = NULL;
opts->cert_filename = NULL;
opts->key_filename = NULL;
@@ -174,12 +173,6 @@ pkinit_dup_identity_opts(pkinit_identity_opts *src_opts,
if (retval)
goto cleanup;
- if (src_opts->ocsp != NULL) {
- newopts->ocsp = strdup(src_opts->ocsp);
- if (newopts->ocsp == NULL)
- goto cleanup;
- }
-
if (src_opts->cert_filename != NULL) {
newopts->cert_filename = strdup(src_opts->cert_filename);
if (newopts->cert_filename == NULL)
@@ -674,10 +667,6 @@ pkinit_identity_prompt(krb5_context context,
if (retval)
goto errout;
}
- if (idopts->ocsp != NULL) {
- retval = ENOTSUP;
- goto errout;
- }
errout:
return retval;
diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c
index 731d14eb8..32ca122f2 100644
--- a/src/plugins/preauth/pkinit/pkinit_srv.c
+++ b/src/plugins/preauth/pkinit/pkinit_srv.c
@@ -1252,7 +1252,7 @@ static krb5_error_code
pkinit_init_kdc_profile(krb5_context context, pkinit_kdc_context plgctx)
{
krb5_error_code retval;
- char *eku_string = NULL;
+ char *eku_string = NULL, *ocsp_check = NULL;
pkiDebug("%s: entered for realm %s\n", __FUNCTION__, plgctx->realmname);
retval = pkinit_kdcdefault_string(context, plgctx->realmname,
@@ -1287,7 +1287,15 @@ pkinit_init_kdc_profile(krb5_context context, pkinit_kdc_context plgctx)
pkinit_kdcdefault_string(context, plgctx->realmname,
KRB5_CONF_PKINIT_KDC_OCSP,
- &plgctx->idopts->ocsp);
+ &ocsp_check);
+ if (ocsp_check != NULL) {
+ free(ocsp_check);
+ retval = ENOTSUP;
+ krb5_set_error_message(context, retval,
+ _("OCSP is not supported: (realm: %s)"),
+ plgctx->realmname);
+ goto errout;
+ }
pkinit_kdcdefault_integer(context, plgctx->realmname,
KRB5_CONF_PKINIT_DH_MIN_BITS,

View file

@ -0,0 +1,35 @@
From 6d0b40b26e7fea1cd394618c1ab6d5e366bbc069 Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Wed, 1 Mar 2017 17:46:22 -0500
Subject: [PATCH] Use GSSAPI fallback skiptest
Also-authored-by: Matt Rogers <mrogers@redhat.com>
[rharwood@redhat.com: Adjusted patch to apply]
---
src/appl/gss-sample/Makefile.in | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/appl/gss-sample/Makefile.in b/src/appl/gss-sample/Makefile.in
index 28e59f90f..9806fd327 100644
--- a/src/appl/gss-sample/Makefile.in
+++ b/src/appl/gss-sample/Makefile.in
@@ -6,6 +6,8 @@ SRCS= $(srcdir)/gss-client.c $(srcdir)/gss-misc.c $(srcdir)/gss-server.c
OBJS= gss-client.o gss-misc.o gss-server.o
+LBITS = $(shell /usr/bin/getconf LONG_BIT)
+
all-unix: gss-server gss-client
##WIN32##VERSIONRC = $(BUILDTOP)\windows\version.rc
@@ -43,7 +45,9 @@ clean-unix::
$(RM) gss-server gss-client
check-pytests:
- $(RUNPYTEST) $(srcdir)/t_gss_sample.py $(PYTESTFLAGS)
+ if ! [ $(LBITS) -eq 32 ]; then \
+ $(RUNPYTEST) $(srcdir)/t_gss_sample.py $(PYTESTFLAGS); \
+ fi
install-unix:
$(INSTALL_PROGRAM) gss-client $(DESTDIR)$(CLIENT_BINDIR)/gss-client

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,75 @@
From 35a00879008457d21ccc6e623835976a21f5000b Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Tue, 17 Jan 2017 11:25:22 -0500
Subject: [PATCH] Use expected_trace in test scripts
(cherry picked from commit 7b7e5d964e5d020fdda3fb9843d9b8cf8b29a6f8)
---
src/tests/t_general.py | 24 ++++++++----------------
src/tests/t_pkinit.py | 15 ++++++---------
2 files changed, 14 insertions(+), 25 deletions(-)
diff --git a/src/tests/t_general.py b/src/tests/t_general.py
index 6d523fe45..16bf6c5e3 100755
--- a/src/tests/t_general.py
+++ b/src/tests/t_general.py
@@ -47,21 +47,13 @@ if 'not found in Kerberos database' not in out:
fail('Expected error message not seen in kinit -C output')
# Spot-check KRB5_TRACE output
-tracefile = os.path.join(realm.testdir, 'trace')
-realm.run(['env', 'KRB5_TRACE=' + tracefile, kinit, realm.user_princ],
- input=(password('user') + "\n"))
-f = open(tracefile, 'r')
-trace = f.read()
-f.close()
-expected = ('Sending initial UDP request',
- 'Received answer',
- 'Selected etype info',
- 'AS key obtained',
- 'Decrypted AS reply',
- 'FAST negotiation: available',
- 'Storing user@KRBTEST.COM')
-for e in expected:
- if e not in trace:
- fail('Expected output not in kinit trace log')
+expected_trace = ('Sending initial UDP request',
+ 'Received answer',
+ 'Selected etype info',
+ 'AS key obtained',
+ 'Decrypted AS reply',
+ 'FAST negotiation: available',
+ 'Storing user@KRBTEST.COM')
+realm.kinit(realm.user_princ, password('user'), expected_trace=expected_trace)
success('FAST kinit, trace logging')
diff --git a/src/tests/t_pkinit.py b/src/tests/t_pkinit.py
index 183977750..f56141564 100755
--- a/src/tests/t_pkinit.py
+++ b/src/tests/t_pkinit.py
@@ -176,19 +176,16 @@ realm.klist(realm.user_princ)
# Test a DH parameter renegotiation by temporarily setting a 4096-bit
# minimum on the KDC.
-tracefile = os.path.join(realm.testdir, 'trace')
minbits_kdc_conf = {'realms': {'$realm': {'pkinit_dh_min_bits': '4096'}}}
minbits_env = realm.special_env('restrict', True, kdc_conf=minbits_kdc_conf)
realm.stop_kdc()
realm.start_kdc(env=minbits_env)
-realm.run(['env', 'KRB5_TRACE=' + tracefile, kinit, '-X',
- 'X509_user_identity=' + file_identity, realm.user_princ])
-with open(tracefile, 'r') as f:
- trace = f.read()
-if ('Key parameters not accepted' not in trace or
- 'Preauth tryagain input types' not in trace or
- 'trying again with KDC-provided parameters' not in trace):
- fail('DH renegotiation steps not found in kinit trace log')
+expected_trace = ('Key parameters not accepted',
+ 'Preauth tryagain input types',
+ 'trying again with KDC-provided parameters')
+realm.kinit(realm.user_princ,
+ flags=['-X', 'X509_user_identity=%s' % file_identity],
+ expected_trace=expected_trace)
realm.stop_kdc()
realm.start_kdc()

View file

@ -0,0 +1,185 @@
From feee4c633a7db348ef99f1f0c99a5c2e6cb70f92 Mon Sep 17 00:00:00 2001
From: Matt Rogers <mrogers@redhat.com>
Date: Fri, 10 Feb 2017 12:53:42 -0500
Subject: [PATCH] Use fallback realm for GSSAPI ccache selection
In krb5_cc_select(), if the server principal has an empty realm, use
krb5_get_fallback_host_realm() and set the server realm to the first
fallback found. This helps with the selection of a non-default ccache
when there is no [domain_realms] configuration for the server domain.
Modify t_ccselect.py tests to account for fallback behavior.
ticket: 8549 (new)
(cherry picked from commit 234b64bd6139d5b75dadd5abbd5bef5a162e298a)
---
src/lib/krb5/ccache/ccselect.c | 37 ++++++++++++++++++++++++++-----
src/tests/gssapi/t_ccselect.py | 50 +++++++++++++++++++++++++++++++++---------
2 files changed, 72 insertions(+), 15 deletions(-)
diff --git a/src/lib/krb5/ccache/ccselect.c b/src/lib/krb5/ccache/ccselect.c
index 2f3071a27..ee4b83a9b 100644
--- a/src/lib/krb5/ccache/ccselect.c
+++ b/src/lib/krb5/ccache/ccselect.c
@@ -132,6 +132,8 @@ krb5_cc_select(krb5_context context, krb5_principal server,
struct ccselect_module_handle **hp, *h;
krb5_ccache cache;
krb5_principal princ;
+ krb5_principal srvcp = NULL;
+ char **fbrealms = NULL;
*cache_out = NULL;
*princ_out = NULL;
@@ -139,7 +141,27 @@ krb5_cc_select(krb5_context context, krb5_principal server,
if (context->ccselect_handles == NULL) {
ret = load_modules(context);
if (ret)
- return ret;
+ goto cleanup;
+ }
+
+ /* Try to use the fallback host realm for the server if there is no
+ * authoritative realm. */
+ if (krb5_is_referral_realm(&server->realm) &&
+ server->type == KRB5_NT_SRV_HST && server->length == 2) {
+ ret = krb5_get_fallback_host_realm(context, &server->data[1],
+ &fbrealms);
+ if (ret)
+ goto cleanup;
+
+ /* Make a copy with the first fallback realm. */
+ ret = krb5_copy_principal(context, server, &srvcp);
+ if (ret)
+ goto cleanup;
+ ret = krb5_set_principal_realm(context, srvcp, fbrealms[0]);
+ if (ret)
+ goto cleanup;
+
+ server = srvcp;
}
/* Consult authoritative modules first, then heuristic ones. */
@@ -155,20 +177,25 @@ krb5_cc_select(krb5_context context, krb5_principal server,
princ);
*cache_out = cache;
*princ_out = princ;
- return 0;
+ goto cleanup;
} else if (ret == KRB5_CC_NOTFOUND) {
TRACE_CCSELECT_MODNOTFOUND(context, h->vt.name, server, princ);
*princ_out = princ;
- return ret;
+ goto cleanup;
} else if (ret != KRB5_PLUGIN_NO_HANDLE) {
TRACE_CCSELECT_MODFAIL(context, h->vt.name, ret, server);
- return ret;
+ goto cleanup;
}
}
}
TRACE_CCSELECT_NOTFOUND(context, server);
- return KRB5_CC_NOTFOUND;
+ ret = KRB5_CC_NOTFOUND;
+
+cleanup:
+ krb5_free_principal(context, srvcp);
+ krb5_free_host_realm(context, fbrealms);
+ return ret;
}
void
diff --git a/src/tests/gssapi/t_ccselect.py b/src/tests/gssapi/t_ccselect.py
index 1ea614d30..668a2cc62 100755
--- a/src/tests/gssapi/t_ccselect.py
+++ b/src/tests/gssapi/t_ccselect.py
@@ -31,12 +31,18 @@ r2 = K5Realm(create_user=False, realm='KRBTEST2.COM', portbase=62000,
host1 = 'p:' + r1.host_princ
host2 = 'p:' + r2.host_princ
+foo = 'foo.krbtest.com'
+foo2 = 'foo.krbtest2.com'
-# gsserver specifies the target as a GSS name. The resulting
-# principal will have the host-based type, but the realm won't be
-# known before the client cache is selected (since k5test realms have
-# no domain-realm mapping by default).
-gssserver = 'h:host@' + hostname
+# These strings specify the target as a GSS name. The resulting
+# principal will have the host-based type, with the referral realm
+# (since k5test realms have no domain-realm mapping by default).
+# krb5_cc_select() will use the fallback realm, which is either the
+# uppercased parent domain, or the default realm if the hostname is a
+# single component.
+gssserver = 'h:host@' + foo
+gssserver2 = 'h:host@' + foo2
+gsslocal = 'h:host@localhost'
# refserver specifies the target as a principal in the referral realm.
# The principal won't be treated as a host principal by the
@@ -66,6 +72,16 @@ r1.addprinc(alice, password('alice'))
r1.addprinc(bob, password('bob'))
r2.addprinc(zaphod, password('zaphod'))
+# Create host principals and keytabs for fallback realm tests.
+r1.addprinc('host/localhost')
+r2.addprinc('host/localhost')
+r1.addprinc('host/' + foo)
+r2.addprinc('host/' + foo2)
+r1.extract_keytab('host/localhost', r1.keytab)
+r2.extract_keytab('host/localhost', r2.keytab)
+r1.extract_keytab('host/' + foo, r1.keytab)
+r2.extract_keytab('host/' + foo2, r2.keytab)
+
# Get tickets for one user in each realm (zaphod will be primary).
r1.kinit(alice, password('alice'))
r2.kinit(zaphod, password('zaphod'))
@@ -93,10 +109,24 @@ if output != (zaphod + '\n'):
fail('zaphod not chosen as default initiator name for server in r1')
# Check that primary cache is used if server realm is unknown.
-output = r2.run(['./t_ccselect', gssserver])
+output = r2.run(['./t_ccselect', refserver])
if output != (zaphod + '\n'):
fail('zaphod not chosen via primary cache for unknown server realm')
-r1.run(['./t_ccselect', gssserver], expected_code=1)
+r1.run(['./t_ccselect', gssserver2], expected_code=1)
+# Check ccache selection using a fallback realm.
+output = r1.run(['./t_ccselect', gssserver])
+if output != (alice + '\n'):
+ fail('alice not chosen via parent domain fallback')
+output = r2.run(['./t_ccselect', gssserver2])
+if output != (zaphod + '\n'):
+ fail('zaphod not chosen via parent domain fallback')
+# Check ccache selection using a fallback realm (default realm).
+output = r1.run(['./t_ccselect', gsslocal])
+if output != (alice + '\n'):
+ fail('alice not chosen via default realm fallback')
+output = r2.run(['./t_ccselect', gsslocal])
+if output != (zaphod + '\n'):
+ fail('zaphod not chosen via default realm fallback')
# Get a second cred in r1 (bob will be primary).
r1.kinit(bob, password('bob'))
@@ -104,19 +134,19 @@ r1.kinit(bob, password('bob'))
# Try some cache selections using .k5identity.
k5id = open(os.path.join(r1.testdir, '.k5identity'), 'w')
k5id.write('%s realm=%s\n' % (alice, r1.realm))
-k5id.write('%s service=ho*t host=%s\n' % (zaphod, hostname))
+k5id.write('%s service=ho*t host=localhost\n' % zaphod)
k5id.write('noprinc service=bogus')
k5id.close()
output = r1.run(['./t_ccselect', host1])
if output != (alice + '\n'):
fail('alice not chosen via .k5identity realm line.')
-output = r2.run(['./t_ccselect', gssserver])
+output = r2.run(['./t_ccselect', gsslocal])
if output != (zaphod + '\n'):
fail('zaphod not chosen via .k5identity service/host line.')
output = r1.run(['./t_ccselect', refserver])
if output != (bob + '\n'):
fail('bob not chosen via primary cache when no .k5identity line matches.')
-r1.run(['./t_ccselect', 'h:bogus@' + hostname], expected_code=1,
+r1.run(['./t_ccselect', 'h:bogus@' + foo2], expected_code=1,
expected_msg="Can't find client principal noprinc")
success('GSSAPI credential selection tests')

View file

@ -0,0 +1,327 @@
From 0ae9141d53a8d9fe048542f89d17760990bd5bc4 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Wed, 17 May 2017 15:14:15 -0400
Subject: [PATCH] Use krb5_timestamp where appropriate
Where krb5_int32 is used to hold the number of seconds since the
epoch, use krb5_timestamp instead.
(cherry picked from commit ae25f6ec5558140a546db34fea389412d81c0631)
---
src/clients/klist/klist.c | 2 +-
src/include/k5-int.h | 2 +-
src/kadmin/server/misc.c | 2 +-
src/kdc/dispatch.c | 4 ++--
src/lib/kadm5/srv/server_acl.c | 2 +-
src/lib/kadm5/srv/server_kdb.c | 2 +-
src/lib/kadm5/srv/svr_principal.c | 10 +++++-----
src/lib/krb5/krb/gen_save_subkey.c | 3 ++-
src/lib/krb5/krb/get_in_tkt.c | 2 +-
src/lib/krb5/krb/init_ctx.c | 3 ++-
src/lib/krb5/os/c_ustime.c | 7 +++++--
src/lib/krb5/os/toffset.c | 3 ++-
src/lib/krb5/os/trace.c | 3 ++-
src/lib/krb5/os/ustime.c | 3 ++-
src/lib/krb5/rcache/rc_dfl.c | 10 +++++-----
src/tests/create/kdb5_mkdums.c | 2 +-
16 files changed, 34 insertions(+), 26 deletions(-)
diff --git a/src/clients/klist/klist.c b/src/clients/klist/klist.c
index ffeecc394..4334415be 100644
--- a/src/clients/klist/klist.c
+++ b/src/clients/klist/klist.c
@@ -56,7 +56,7 @@ int show_adtype = 0, show_all = 0, list_all = 0, use_client_keytab = 0;
int show_config = 0;
char *defname;
char *progname;
-krb5_int32 now;
+krb5_timestamp now;
unsigned int timestamp_width;
krb5_context kcontext;
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index 82ee20760..ed9c7bf75 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -721,7 +721,7 @@ krb5_error_code krb5int_c_copy_keyblock_contents(krb5_context context,
const krb5_keyblock *from,
krb5_keyblock *to);
-krb5_error_code krb5_crypto_us_timeofday(krb5_int32 *, krb5_int32 *);
+krb5_error_code krb5_crypto_us_timeofday(krb5_timestamp *, krb5_int32 *);
/*
* End "los-proto.h"
diff --git a/src/kadmin/server/misc.c b/src/kadmin/server/misc.c
index a75b65a26..ba672d714 100644
--- a/src/kadmin/server/misc.c
+++ b/src/kadmin/server/misc.c
@@ -159,7 +159,7 @@ kadm5_ret_t
check_min_life(void *server_handle, krb5_principal principal,
char *msg_ret, unsigned int msg_len)
{
- krb5_int32 now;
+ krb5_timestamp now;
kadm5_ret_t ret;
kadm5_policy_ent_rec pol;
kadm5_principal_ent_rec princ;
diff --git a/src/kdc/dispatch.c b/src/kdc/dispatch.c
index 16a35d2be..4ecc23481 100644
--- a/src/kdc/dispatch.c
+++ b/src/kdc/dispatch.c
@@ -94,8 +94,8 @@ static void
reseed_random(krb5_context kdc_err_context)
{
krb5_error_code retval;
- krb5_int32 now, now_usec;
- krb5_int32 usec_difference;
+ krb5_timestamp now;
+ krb5_int32 now_usec, usec_difference;
krb5_data data;
retval = krb5_crypto_us_timeofday(&now, &now_usec);
diff --git a/src/lib/kadm5/srv/server_acl.c b/src/lib/kadm5/srv/server_acl.c
index c4bb16dc7..679fc7c41 100644
--- a/src/lib/kadm5/srv/server_acl.c
+++ b/src/lib/kadm5/srv/server_acl.c
@@ -375,7 +375,7 @@ kadm5int_acl_impose_restrictions(kcontext, recp, maskp, rp)
restriction_t *rp;
{
krb5_error_code code;
- krb5_int32 now;
+ krb5_timestamp now;
DPRINT(DEBUG_CALLS, acl_debug_level,
("* kadm5int_acl_impose_restrictions(..., *maskp=0x%08x, rp=0x%08x)\n",
diff --git a/src/lib/kadm5/srv/server_kdb.c b/src/lib/kadm5/srv/server_kdb.c
index 612553ba3..f4b8aef2b 100644
--- a/src/lib/kadm5/srv/server_kdb.c
+++ b/src/lib/kadm5/srv/server_kdb.c
@@ -365,7 +365,7 @@ kdb_put_entry(kadm5_server_handle_t handle,
krb5_db_entry *kdb, osa_princ_ent_rec *adb)
{
krb5_error_code ret;
- krb5_int32 now;
+ krb5_timestamp now;
XDR xdrs;
krb5_tl_data tl_data;
diff --git a/src/lib/kadm5/srv/svr_principal.c b/src/lib/kadm5/srv/svr_principal.c
index 137e1fb64..89f34482b 100644
--- a/src/lib/kadm5/srv/svr_principal.c
+++ b/src/lib/kadm5/srv/svr_principal.c
@@ -296,7 +296,7 @@ kadm5_create_principal_3(void *server_handle,
osa_princ_ent_rec adb;
kadm5_policy_ent_rec polent;
krb5_boolean have_polent = FALSE;
- krb5_int32 now;
+ krb5_timestamp now;
krb5_tl_data *tl_data_tail;
unsigned int ret;
kadm5_server_handle_t handle = server_handle;
@@ -1322,7 +1322,7 @@ kadm5_chpass_principal_3(void *server_handle,
int n_ks_tuple, krb5_key_salt_tuple *ks_tuple,
char *password)
{
- krb5_int32 now;
+ krb5_timestamp now;
kadm5_policy_ent_rec pol;
osa_princ_ent_rec adb;
krb5_db_entry *kdb;
@@ -1544,7 +1544,7 @@ kadm5_randkey_principal_3(void *server_handle,
{
krb5_db_entry *kdb;
osa_princ_ent_rec adb;
- krb5_int32 now;
+ krb5_timestamp now;
kadm5_policy_ent_rec pol;
int ret, last_pwd, n_new_keys;
krb5_boolean have_pol = FALSE;
@@ -1686,7 +1686,7 @@ kadm5_setv4key_principal(void *server_handle,
{
krb5_db_entry *kdb;
osa_princ_ent_rec adb;
- krb5_int32 now;
+ krb5_timestamp now;
kadm5_policy_ent_rec pol;
krb5_keysalt keysalt;
int i, kvno, ret;
@@ -1891,7 +1891,7 @@ kadm5_setkey_principal_4(void *server_handle, krb5_principal principal,
{
krb5_db_entry *kdb;
osa_princ_ent_rec adb;
- krb5_int32 now;
+ krb5_timestamp now;
kadm5_policy_ent_rec pol;
krb5_key_data *new_key_data = NULL;
int i, j, ret, n_new_key_data = 0;
diff --git a/src/lib/krb5/krb/gen_save_subkey.c b/src/lib/krb5/krb/gen_save_subkey.c
index 61f36aa36..bc2c46d30 100644
--- a/src/lib/krb5/krb/gen_save_subkey.c
+++ b/src/lib/krb5/krb/gen_save_subkey.c
@@ -38,7 +38,8 @@ k5_generate_and_save_subkey(krb5_context context,
to guarantee randomness, but to make it less likely that multiple
sessions could pick the same subkey. */
struct {
- krb5_int32 sec, usec;
+ krb5_timestamp sec;
+ krb5_int32 usec;
} rnd_data;
krb5_data d;
krb5_error_code retval;
diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
index 40aba1905..7178bd87b 100644
--- a/src/lib/krb5/krb/get_in_tkt.c
+++ b/src/lib/krb5/krb/get_in_tkt.c
@@ -1788,7 +1788,7 @@ k5_populate_gic_opt(krb5_context context, krb5_get_init_creds_opt **out,
krb5_creds *creds)
{
int i;
- krb5_int32 starttime;
+ krb5_timestamp starttime;
krb5_deltat lifetime;
krb5_get_init_creds_opt *opt;
krb5_error_code retval;
diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c
index cf226fdba..4246c5dd2 100644
--- a/src/lib/krb5/krb/init_ctx.c
+++ b/src/lib/krb5/krb/init_ctx.c
@@ -139,7 +139,8 @@ krb5_init_context_profile(profile_t profile, krb5_flags flags,
krb5_context ctx = 0;
krb5_error_code retval;
struct {
- krb5_int32 now, now_usec;
+ krb5_timestamp now;
+ krb5_int32 now_usec;
long pid;
} seed_data;
krb5_data seed;
diff --git a/src/lib/krb5/os/c_ustime.c b/src/lib/krb5/os/c_ustime.c
index 68fb381f4..f69f2ea4c 100644
--- a/src/lib/krb5/os/c_ustime.c
+++ b/src/lib/krb5/os/c_ustime.c
@@ -29,7 +29,10 @@
k5_mutex_t krb5int_us_time_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
-struct time_now { krb5_int32 sec, usec; };
+struct time_now {
+ krb5_timestamp sec;
+ krb5_int32 usec;
+};
#if defined(_WIN32)
@@ -73,7 +76,7 @@ get_time_now(struct time_now *n)
static struct time_now last_time;
krb5_error_code
-krb5_crypto_us_timeofday(krb5_int32 *seconds, krb5_int32 *microseconds)
+krb5_crypto_us_timeofday(krb5_timestamp *seconds, krb5_int32 *microseconds)
{
struct time_now now;
krb5_error_code err;
diff --git a/src/lib/krb5/os/toffset.c b/src/lib/krb5/os/toffset.c
index 37bc69f49..4bbcdde52 100644
--- a/src/lib/krb5/os/toffset.c
+++ b/src/lib/krb5/os/toffset.c
@@ -40,7 +40,8 @@ krb5_error_code KRB5_CALLCONV
krb5_set_real_time(krb5_context context, krb5_timestamp seconds, krb5_int32 microseconds)
{
krb5_os_context os_ctx = &context->os_context;
- krb5_int32 sec, usec;
+ krb5_timestamp sec;
+ krb5_int32 usec;
krb5_error_code retval;
retval = krb5_crypto_us_timeofday(&sec, &usec);
diff --git a/src/lib/krb5/os/trace.c b/src/lib/krb5/os/trace.c
index 74c315c90..8750b7650 100644
--- a/src/lib/krb5/os/trace.c
+++ b/src/lib/krb5/os/trace.c
@@ -340,7 +340,8 @@ krb5int_trace(krb5_context context, const char *fmt, ...)
va_list ap;
krb5_trace_info info;
char *str = NULL, *msg = NULL;
- krb5_int32 sec, usec;
+ krb5_timestamp sec;
+ krb5_int32 usec;
if (context == NULL || context->trace_callback == NULL)
return;
diff --git a/src/lib/krb5/os/ustime.c b/src/lib/krb5/os/ustime.c
index 1c1b571eb..a80fdf68c 100644
--- a/src/lib/krb5/os/ustime.c
+++ b/src/lib/krb5/os/ustime.c
@@ -40,7 +40,8 @@ krb5_error_code
k5_time_with_offset(krb5_timestamp offset, krb5_int32 offset_usec,
krb5_timestamp *time_out, krb5_int32 *usec_out)
{
- krb5_int32 sec, usec;
+ krb5_timestamp sec;
+ krb5_int32 usec;
krb5_error_code retval;
retval = krb5_crypto_us_timeofday(&sec, &usec);
diff --git a/src/lib/krb5/rcache/rc_dfl.c b/src/lib/krb5/rcache/rc_dfl.c
index 6b043844d..41ebf94da 100644
--- a/src/lib/krb5/rcache/rc_dfl.c
+++ b/src/lib/krb5/rcache/rc_dfl.c
@@ -93,7 +93,7 @@ cmp(krb5_donot_replay *old, krb5_donot_replay *new1, krb5_deltat t)
}
static int
-alive(krb5_int32 mytime, krb5_donot_replay *new1, krb5_deltat t)
+alive(krb5_timestamp mytime, krb5_donot_replay *new1, krb5_deltat t)
{
if (mytime == 0)
return CMP_HOHUM; /* who cares? */
@@ -129,7 +129,7 @@ struct authlist
static int
rc_store(krb5_context context, krb5_rcache id, krb5_donot_replay *rep,
- krb5_int32 now, krb5_boolean fromfile)
+ krb5_timestamp now, krb5_boolean fromfile)
{
struct dfl_data *t = (struct dfl_data *)id->data;
unsigned int rephash;
@@ -536,7 +536,7 @@ krb5_rc_dfl_recover_locked(krb5_context context, krb5_rcache id)
krb5_error_code retval;
long max_size;
int expired_entries = 0;
- krb5_int32 now;
+ krb5_timestamp now;
if ((retval = krb5_rc_io_open(context, &t->d, t->name))) {
return retval;
@@ -706,7 +706,7 @@ krb5_rc_dfl_store(krb5_context context, krb5_rcache id, krb5_donot_replay *rep)
{
krb5_error_code ret;
struct dfl_data *t;
- krb5_int32 now;
+ krb5_timestamp now;
ret = krb5_timeofday(context, &now);
if (ret)
@@ -762,7 +762,7 @@ krb5_rc_dfl_expunge_locked(krb5_context context, krb5_rcache id)
struct authlist **qt;
struct authlist *r;
struct authlist *rt;
- krb5_int32 now;
+ krb5_timestamp now;
if (krb5_timestamp(context, &now))
now = 0;
diff --git a/src/tests/create/kdb5_mkdums.c b/src/tests/create/kdb5_mkdums.c
index 622f549f9..7c0666601 100644
--- a/src/tests/create/kdb5_mkdums.c
+++ b/src/tests/create/kdb5_mkdums.c
@@ -247,7 +247,7 @@ add_princ(context, str_newprinc)
{
/* Add mod princ to db entry */
- krb5_int32 now;
+ krb5_timestamp now;
retval = krb5_timeofday(context, &now);
if (retval) {

View file

@ -0,0 +1,28 @@
From 7998de0b9ccd0c8813159cc3f1d49fe107e3e0ba Mon Sep 17 00:00:00 2001
From: Matt Rogers <mrogers@redhat.com>
Date: Wed, 5 Apr 2017 16:48:55 -0400
Subject: [PATCH] Use the canonical client principal name for OTP
In the OTP module, when constructing the RADIUS request, use the
canonicalized client principal (using the new client_name kdcpreauth
callback) instead of the request client principal.
ticket: 8571 (new)
---
src/plugins/preauth/otp/main.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/plugins/preauth/otp/main.c b/src/plugins/preauth/otp/main.c
index 2649e9a90..a1b681682 100644
--- a/src/plugins/preauth/otp/main.c
+++ b/src/plugins/preauth/otp/main.c
@@ -331,7 +331,8 @@ otp_verify(krb5_context context, krb5_data *req_pkt, krb5_kdc_req *request,
/* Send the request. */
otp_state_verify((otp_state *)moddata, cb->event_context(context, rock),
- request->client, config, req, on_response, rs);
+ cb->client_name(context, rock), config, req, on_response,
+ rs);
cb->free_string(context, rock, config);
k5_free_pa_otp_req(context, req);

1
ci.fmf
View file

@ -1 +0,0 @@
resultsdb-testcase: separate

View file

@ -1,8 +0,0 @@
--- !Policy
product_versions:
- fedora-*
decision_contexts:
- bodhi_update_push_stable
subject_type: koji_build
rules:
- !PassingTestCaseRule {test_case_name: fedora-ci.koji-build./plans/tests.functional}

View file

@ -1,14 +1,13 @@
[Unit]
Description=Kerberos 5 Password-changing and Administration
Wants=network-online.target
After=syslog.target network.target network-online.target
After=syslog.target network.target
AssertPathExists=!/var/kerberos/krb5kdc/kpropd.acl
[Service]
Type=forking
PIDFile=/run/kadmind.pid
PIDFile=/var/run/kadmind.pid
EnvironmentFile=-/etc/sysconfig/kadmin
ExecStart=/usr/sbin/kadmind -P /run/kadmind.pid $KADMIND_ARGS
ExecStart=/usr/sbin/kadmind -P /var/run/kadmind.pid $KADMIND_ARGS
ExecReload=/bin/kill -HUP $MAINPID
[Install]

View file

@ -4,6 +4,6 @@
monthly
rotate 12
postrotate
systemctl reload kadmin.service || true
/bin/kill -HUP `cat /var/run/kadmind.pid 2>/dev/null` 2> /dev/null || true
endscript
}

View file

@ -1,20 +1,12 @@
[libdefaults]
# Allow RC4 HMAC-MD5 for session keys (see CVE-2022-37966)
#allow_rc4 = true
[kdcdefaults]
kdc_ports = 88
kdc_tcp_ports = 88
spake_preauth_kdc_challenge = edwards25519
kdc_ports = 88
kdc_tcp_ports = 88
[realms]
EXAMPLE.COM = {
master_key_type = aes256-cts-hmac-sha384-192
acl_file = /var/kerberos/krb5kdc/kadm5.acl
dict_file = /usr/share/dict/words
default_principal_flags = +preauth
admin_keytab = /var/kerberos/krb5kdc/kadm5.keytab
supported_enctypes = aes256-cts-hmac-sha384-192:normal aes128-cts-hmac-sha256-128:normal aes256-cts-hmac-sha1-96:normal aes128-cts-hmac-sha1-96:normal camellia256-cts-cmac:normal camellia128-cts-cmac:normal arcfour-hmac-md5:normal
# Supported encryption types for FIPS mode:
#supported_enctypes = aes256-cts-hmac-sha384-192:normal aes128-cts-hmac-sha256-128:normal
}
EXAMPLE.COM = {
#master_key_type = aes256-cts
acl_file = /var/kerberos/krb5kdc/kadm5.acl
dict_file = /usr/share/dict/words
admin_keytab = /var/kerberos/krb5kdc/kadm5.keytab
supported_enctypes = aes256-cts:normal aes128-cts:normal des3-hmac-sha1:normal arcfour-hmac:normal camellia256-cts:normal camellia128-cts:normal des-hmac-sha1:normal des-cbc-md5:normal des-cbc-crc:normal
}

View file

@ -1,7 +1,6 @@
[Unit]
Description=Kerberos 5 Propagation
Wants=network-online.target
After=syslog.target network.target network-online.target
After=syslog.target network.target
AssertPathExists=/var/kerberos/krb5kdc/kpropd.acl
[Service]

View file

@ -0,0 +1,21 @@
From fb8f32ebdf3293d8a6bdb9478fe1f902a399ba7a Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Tue, 23 Aug 2016 16:52:01 -0400
Subject: [PATCH] krb5-1.11-kpasswdtest.patch
---
src/kadmin/testing/proto/krb5.conf.proto | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/kadmin/testing/proto/krb5.conf.proto b/src/kadmin/testing/proto/krb5.conf.proto
index 00c442978..9c4bc1de7 100644
--- a/src/kadmin/testing/proto/krb5.conf.proto
+++ b/src/kadmin/testing/proto/krb5.conf.proto
@@ -9,6 +9,7 @@
__REALM__ = {
kdc = __KDCHOST__:1750
admin_server = __KDCHOST__:1751
+ kpasswd_server = __KDCHOST__:1752
database_module = foobar_db2_module_blah
}

View file

@ -0,0 +1,44 @@
From 9c45f66fbc6afb472589dbeb5166f46ad266d319 Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Tue, 23 Aug 2016 16:49:57 -0400
Subject: [PATCH] krb5-1.11-run_user_0.patch
A hack: if we're looking at creating a ccache directory directly below
the /run/user/0 directory, and /run/user/0 doesn't exist, try to create
it, too.
---
src/lib/krb5/ccache/cc_dir.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/src/lib/krb5/ccache/cc_dir.c b/src/lib/krb5/ccache/cc_dir.c
index 73f0fe62d..4850c0d07 100644
--- a/src/lib/krb5/ccache/cc_dir.c
+++ b/src/lib/krb5/ccache/cc_dir.c
@@ -61,6 +61,8 @@
#include <dirent.h>
+#define ROOT_SPECIAL_DCC_PARENT "/run/user/0"
+
extern const krb5_cc_ops krb5_dcc_ops;
extern const krb5_cc_ops krb5_fcc_ops;
@@ -237,6 +239,18 @@ verify_dir(krb5_context context, const char *dirname)
if (stat(dirname, &st) < 0) {
if (errno == ENOENT) {
+ if (strncmp(dirname, ROOT_SPECIAL_DCC_PARENT "/",
+ sizeof(ROOT_SPECIAL_DCC_PARENT)) == 0 &&
+ stat(ROOT_SPECIAL_DCC_PARENT, &st) < 0 &&
+ errno == ENOENT) {
+#ifdef USE_SELINUX
+ selabel = krb5int_push_fscreatecon_for(ROOT_SPECIAL_DCC_PARENT);
+#endif
+ status = mkdir(ROOT_SPECIAL_DCC_PARENT, S_IRWXU);
+#ifdef USE_SELINUX
+ krb5int_pop_fscreatecon(selabel);
+#endif
+ }
#ifdef USE_SELINUX
selabel = krb5int_push_fscreatecon_for(dirname);
#endif

37
krb5-1.12-api.patch Normal file
View file

@ -0,0 +1,37 @@
From 107a2b8728f1b76feb16df9201919444482e3981 Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Tue, 23 Aug 2016 16:47:00 -0400
Subject: [PATCH] krb5-1.12-api.patch
Reference docs don't define what happens if you call krb5_realm_compare() with
malformed krb5_principal structures. Define a behavior which keeps it from
crashing if applications don't check ahead of time.
---
src/lib/krb5/krb/princ_comp.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/lib/krb5/krb/princ_comp.c b/src/lib/krb5/krb/princ_comp.c
index a6936107d..0ed78833b 100644
--- a/src/lib/krb5/krb/princ_comp.c
+++ b/src/lib/krb5/krb/princ_comp.c
@@ -36,6 +36,10 @@ realm_compare_flags(krb5_context context,
const krb5_data *realm1 = &princ1->realm;
const krb5_data *realm2 = &princ2->realm;
+ if (princ1 == NULL || princ2 == NULL)
+ return FALSE;
+ if (realm1 == NULL || realm2 == NULL)
+ return FALSE;
if (realm1->length != realm2->length)
return FALSE;
if (realm1->length == 0)
@@ -88,6 +92,9 @@ krb5_principal_compare_flags(krb5_context context,
krb5_principal upn2 = NULL;
krb5_boolean ret = FALSE;
+ if (princ1 == NULL || princ2 == NULL)
+ return FALSE;
+
if (flags & KRB5_PRINCIPAL_COMPARE_ENTERPRISE) {
/* Treat UPNs as if they were real principals */
if (princ1->type == KRB5_NT_ENTERPRISE_PRINCIPAL) {

22
krb5-1.12-ksu-path.patch Normal file
View file

@ -0,0 +1,22 @@
From 93b86d94b871aed49b14d7fc1a2a9f23c16cbe0f Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Tue, 23 Aug 2016 16:32:09 -0400
Subject: [PATCH] krb5-1.12-ksu-path.patch
Set the default PATH to the one set by login.
---
src/clients/ksu/Makefile.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/clients/ksu/Makefile.in b/src/clients/ksu/Makefile.in
index 5755bb58a..9d58f29b5 100644
--- a/src/clients/ksu/Makefile.in
+++ b/src/clients/ksu/Makefile.in
@@ -1,6 +1,6 @@
mydir=clients$(S)ksu
BUILDTOP=$(REL)..$(S)..
-DEFINES = -DGET_TGT_VIA_PASSWD -DPRINC_LOOK_AHEAD -DCMD_PATH='"/bin /local/bin"'
+DEFINES = -DGET_TGT_VIA_PASSWD -DPRINC_LOOK_AHEAD -DCMD_PATH='"/usr/local/sbin /usr/local/bin /sbin /bin /usr/sbin /usr/bin"'
KSU_LIBS=@KSU_LIBS@
PAM_LIBS=@PAM_LIBS@

366
krb5-1.12-ktany.patch Normal file
View file

@ -0,0 +1,366 @@
From efee9f8598ba84f2be0983fc1d07a9a72d0ff1b7 Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Tue, 23 Aug 2016 16:33:53 -0400
Subject: [PATCH] krb5-1.12-ktany.patch
Adds an "ANY" keytab type which is a list of other keytab locations to search
when searching for a specific entry. When iterated through, it only presents
the contents of the first keytab.
---
src/lib/krb5/keytab/Makefile.in | 3 +
src/lib/krb5/keytab/kt_any.c | 292 ++++++++++++++++++++++++++++++++++++++++
src/lib/krb5/keytab/ktbase.c | 7 +-
3 files changed, 301 insertions(+), 1 deletion(-)
create mode 100644 src/lib/krb5/keytab/kt_any.c
diff --git a/src/lib/krb5/keytab/Makefile.in b/src/lib/krb5/keytab/Makefile.in
index 2a8fceb00..ffd179fb2 100644
--- a/src/lib/krb5/keytab/Makefile.in
+++ b/src/lib/krb5/keytab/Makefile.in
@@ -12,6 +12,7 @@ STLIBOBJS= \
ktfr_entry.o \
ktremove.o \
ktfns.o \
+ kt_any.o \
kt_file.o \
kt_memory.o \
kt_srvtab.o \
@@ -24,6 +25,7 @@ OBJS= \
$(OUTPRE)ktfr_entry.$(OBJEXT) \
$(OUTPRE)ktremove.$(OBJEXT) \
$(OUTPRE)ktfns.$(OBJEXT) \
+ $(OUTPRE)kt_any.$(OBJEXT) \
$(OUTPRE)kt_file.$(OBJEXT) \
$(OUTPRE)kt_memory.$(OBJEXT) \
$(OUTPRE)kt_srvtab.$(OBJEXT) \
@@ -36,6 +38,7 @@ SRCS= \
$(srcdir)/ktfr_entry.c \
$(srcdir)/ktremove.c \
$(srcdir)/ktfns.c \
+ $(srcdir)/kt_any.c \
$(srcdir)/kt_file.c \
$(srcdir)/kt_memory.c \
$(srcdir)/kt_srvtab.c \
diff --git a/src/lib/krb5/keytab/kt_any.c b/src/lib/krb5/keytab/kt_any.c
new file mode 100644
index 000000000..1b9b7765b
--- /dev/null
+++ b/src/lib/krb5/keytab/kt_any.c
@@ -0,0 +1,292 @@
+/*
+ * lib/krb5/keytab/kt_any.c
+ *
+ * Copyright 1998, 1999 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ *
+ * krb5_kta_ops
+ */
+
+#include "k5-int.h"
+
+typedef struct _krb5_ktany_data {
+ char *name;
+ krb5_keytab *choices;
+ int nchoices;
+} krb5_ktany_data;
+
+typedef struct _krb5_ktany_cursor_data {
+ int which;
+ krb5_kt_cursor cursor;
+} krb5_ktany_cursor_data;
+
+static krb5_error_code krb5_ktany_resolve
+ (krb5_context,
+ const char *,
+ krb5_keytab *);
+static krb5_error_code krb5_ktany_get_name
+ (krb5_context context,
+ krb5_keytab id,
+ char *name,
+ unsigned int len);
+static krb5_error_code krb5_ktany_close
+ (krb5_context context,
+ krb5_keytab id);
+static krb5_error_code krb5_ktany_get_entry
+ (krb5_context context,
+ krb5_keytab id,
+ krb5_const_principal principal,
+ krb5_kvno kvno,
+ krb5_enctype enctype,
+ krb5_keytab_entry *entry);
+static krb5_error_code krb5_ktany_start_seq_get
+ (krb5_context context,
+ krb5_keytab id,
+ krb5_kt_cursor *cursorp);
+static krb5_error_code krb5_ktany_next_entry
+ (krb5_context context,
+ krb5_keytab id,
+ krb5_keytab_entry *entry,
+ krb5_kt_cursor *cursor);
+static krb5_error_code krb5_ktany_end_seq_get
+ (krb5_context context,
+ krb5_keytab id,
+ krb5_kt_cursor *cursor);
+static void cleanup
+ (krb5_context context,
+ krb5_ktany_data *data,
+ int nchoices);
+
+struct _krb5_kt_ops krb5_kta_ops = {
+ 0,
+ "ANY", /* Prefix -- this string should not appear anywhere else! */
+ krb5_ktany_resolve,
+ krb5_ktany_get_name,
+ krb5_ktany_close,
+ krb5_ktany_get_entry,
+ krb5_ktany_start_seq_get,
+ krb5_ktany_next_entry,
+ krb5_ktany_end_seq_get,
+ NULL,
+ NULL,
+ NULL,
+};
+
+static krb5_error_code
+krb5_ktany_resolve(context, name, id)
+ krb5_context context;
+ const char *name;
+ krb5_keytab *id;
+{
+ const char *p, *q;
+ char *copy;
+ krb5_error_code kerror;
+ krb5_ktany_data *data;
+ int i;
+
+ /* Allocate space for our data and remember a copy of the name. */
+ if ((data = (krb5_ktany_data *)malloc(sizeof(krb5_ktany_data))) == NULL)
+ return(ENOMEM);
+ if ((data->name = (char *)malloc(strlen(name) + 1)) == NULL) {
+ free(data);
+ return(ENOMEM);
+ }
+ strcpy(data->name, name);
+
+ /* Count the number of choices and allocate memory for them. */
+ data->nchoices = 1;
+ for (p = name; (q = strchr(p, ',')) != NULL; p = q + 1)
+ data->nchoices++;
+ if ((data->choices = (krb5_keytab *)
+ malloc(data->nchoices * sizeof(krb5_keytab))) == NULL) {
+ free(data->name);
+ free(data);
+ return(ENOMEM);
+ }
+
+ /* Resolve each of the choices. */
+ i = 0;
+ for (p = name; (q = strchr(p, ',')) != NULL; p = q + 1) {
+ /* Make a copy of the choice name so we can terminate it. */
+ if ((copy = (char *)malloc(q - p + 1)) == NULL) {
+ cleanup(context, data, i);
+ return(ENOMEM);
+ }
+ memcpy(copy, p, q - p);
+ copy[q - p] = 0;
+
+ /* Try resolving the choice name. */
+ kerror = krb5_kt_resolve(context, copy, &data->choices[i]);
+ free(copy);
+ if (kerror) {
+ cleanup(context, data, i);
+ return(kerror);
+ }
+ i++;
+ }
+ if ((kerror = krb5_kt_resolve(context, p, &data->choices[i]))) {
+ cleanup(context, data, i);
+ return(kerror);
+ }
+
+ /* Allocate and fill in an ID for the caller. */
+ if ((*id = (krb5_keytab)malloc(sizeof(**id))) == NULL) {
+ cleanup(context, data, i);
+ return(ENOMEM);
+ }
+ (*id)->ops = &krb5_kta_ops;
+ (*id)->data = (krb5_pointer)data;
+ (*id)->magic = KV5M_KEYTAB;
+
+ return(0);
+}
+
+static krb5_error_code
+krb5_ktany_get_name(context, id, name, len)
+ krb5_context context;
+ krb5_keytab id;
+ char *name;
+ unsigned int len;
+{
+ krb5_ktany_data *data = (krb5_ktany_data *)id->data;
+
+ if (len < strlen(data->name) + 1)
+ return(KRB5_KT_NAME_TOOLONG);
+ strcpy(name, data->name);
+ return(0);
+}
+
+static krb5_error_code
+krb5_ktany_close(context, id)
+ krb5_context context;
+ krb5_keytab id;
+{
+ krb5_ktany_data *data = (krb5_ktany_data *)id->data;
+
+ cleanup(context, data, data->nchoices);
+ id->ops = 0;
+ free(id);
+ return(0);
+}
+
+static krb5_error_code
+krb5_ktany_get_entry(context, id, principal, kvno, enctype, entry)
+ krb5_context context;
+ krb5_keytab id;
+ krb5_const_principal principal;
+ krb5_kvno kvno;
+ krb5_enctype enctype;
+ krb5_keytab_entry *entry;
+{
+ krb5_ktany_data *data = (krb5_ktany_data *)id->data;
+ krb5_error_code kerror = KRB5_KT_NOTFOUND;
+ int i;
+
+ for (i = 0; i < data->nchoices; i++) {
+ if ((kerror = krb5_kt_get_entry(context, data->choices[i], principal,
+ kvno, enctype, entry)) != ENOENT)
+ return kerror;
+ }
+ return kerror;
+}
+
+static krb5_error_code
+krb5_ktany_start_seq_get(context, id, cursorp)
+ krb5_context context;
+ krb5_keytab id;
+ krb5_kt_cursor *cursorp;
+{
+ krb5_ktany_data *data = (krb5_ktany_data *)id->data;
+ krb5_ktany_cursor_data *cdata;
+ krb5_error_code kerror = ENOENT;
+ int i;
+
+ if ((cdata = (krb5_ktany_cursor_data *)
+ malloc(sizeof(krb5_ktany_cursor_data))) == NULL)
+ return(ENOMEM);
+
+ /* Find a choice which can handle the serialization request. */
+ for (i = 0; i < data->nchoices; i++) {
+ if ((kerror = krb5_kt_start_seq_get(context, data->choices[i],
+ &cdata->cursor)) == 0)
+ break;
+ else if (kerror != ENOENT) {
+ free(cdata);
+ return(kerror);
+ }
+ }
+
+ if (i == data->nchoices) {
+ /* Everyone returned ENOENT, so no go. */
+ free(cdata);
+ return(kerror);
+ }
+
+ cdata->which = i;
+ *cursorp = (krb5_kt_cursor)cdata;
+ return(0);
+}
+
+static krb5_error_code
+krb5_ktany_next_entry(context, id, entry, cursor)
+ krb5_context context;
+ krb5_keytab id;
+ krb5_keytab_entry *entry;
+ krb5_kt_cursor *cursor;
+{
+ krb5_ktany_data *data = (krb5_ktany_data *)id->data;
+ krb5_ktany_cursor_data *cdata = (krb5_ktany_cursor_data *)*cursor;
+ krb5_keytab choice_id;
+
+ choice_id = data->choices[cdata->which];
+ return(krb5_kt_next_entry(context, choice_id, entry, &cdata->cursor));
+}
+
+static krb5_error_code
+krb5_ktany_end_seq_get(context, id, cursor)
+ krb5_context context;
+ krb5_keytab id;
+ krb5_kt_cursor *cursor;
+{
+ krb5_ktany_data *data = (krb5_ktany_data *)id->data;
+ krb5_ktany_cursor_data *cdata = (krb5_ktany_cursor_data *)*cursor;
+ krb5_keytab choice_id;
+ krb5_error_code kerror;
+
+ choice_id = data->choices[cdata->which];
+ kerror = krb5_kt_end_seq_get(context, choice_id, &cdata->cursor);
+ free(cdata);
+ return(kerror);
+}
+
+static void
+cleanup(context, data, nchoices)
+ krb5_context context;
+ krb5_ktany_data *data;
+ int nchoices;
+{
+ int i;
+
+ free(data->name);
+ for (i = 0; i < nchoices; i++)
+ krb5_kt_close(context, data->choices[i]);
+ free(data->choices);
+ free(data);
+}
diff --git a/src/lib/krb5/keytab/ktbase.c b/src/lib/krb5/keytab/ktbase.c
index 0d39b2940..6534d7c52 100644
--- a/src/lib/krb5/keytab/ktbase.c
+++ b/src/lib/krb5/keytab/ktbase.c
@@ -57,14 +57,19 @@ extern const krb5_kt_ops krb5_ktf_ops;
extern const krb5_kt_ops krb5_ktf_writable_ops;
extern const krb5_kt_ops krb5_kts_ops;
extern const krb5_kt_ops krb5_mkt_ops;
+extern const krb5_kt_ops krb5_kta_ops;
struct krb5_kt_typelist {
const krb5_kt_ops *ops;
const struct krb5_kt_typelist *next;
};
+static struct krb5_kt_typelist krb5_kt_typelist_any = {
+ &krb5_kta_ops,
+ NULL
+};
const static struct krb5_kt_typelist krb5_kt_typelist_srvtab = {
&krb5_kts_ops,
- NULL
+ &krb5_kt_typelist_any
};
const static struct krb5_kt_typelist krb5_kt_typelist_memory = {
&krb5_mkt_ops,

View file

@ -1,7 +1,7 @@
From de4205c45e310ceaaa7cd7958af7293322fa43a6 Mon Sep 17 00:00:00 2001
From e0924e10dd431a898c9c95faa04b51edbe59c5ef 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
Subject: [PATCH] krb5-1.12.1-pam.patch
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
@ -16,28 +16,25 @@ 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/aclocal.m4 | 67 ++++++++
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(-)
src/clients/ksu/main.c | 88 +++++++++-
src/clients/ksu/pam.c | 389 ++++++++++++++++++++++++++++++++++++++++++++
src/clients/ksu/pam.h | 57 +++++++
src/configure.in | 2 +
6 files changed, 608 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
index 9c46da4b5..508e5fe90 100644
--- a/src/aclocal.m4
+++ b/src/aclocal.m4
@@ -1458,3 +1458,72 @@ if test "$with_ldap" = yes; then
OPENLDAP_PLUGIN=yes
fi
@@ -1675,3 +1675,70 @@ AC_DEFUN(KRB5_AC_PERSISTENT_KEYRING,[
]))
])dnl
+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
@ -105,13 +102,12 @@ index 3d66a876b3..ce3c5a9bac 100644
+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
index b2fcbf240..5755bb58a 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"'
DEFINES = -DGET_TGT_VIA_PASSWD -DPRINC_LOOK_AHEAD -DCMD_PATH='"/bin /local/bin"'
KSU_LIBS=@KSU_LIBS@
+PAM_LIBS=@PAM_LIBS@
@ -145,11 +141,11 @@ index 8b4edce4d8..9d58f29b5d 100644
clean:
$(RM) ksu
diff --git a/src/clients/ksu/main.c b/src/clients/ksu/main.c
index af12861729..931f054041 100644
index 28342c2d7..cab0c1806 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
* KSU was writen by: Ari Medvinsky, ari@isi.edu
*/
+#include "autoconf.h"
@ -175,7 +171,7 @@ index af12861729..931f054041 100644
/***********/
#define KS_TEMPORARY_CACHE "MEMORY:_ksu"
@@ -536,6 +542,23 @@ main (argc, argv)
@@ -515,6 +521,23 @@ main (argc, argv)
prog_name,target_user,client_name,
source_user,ontty());
@ -199,7 +195,7 @@ index af12861729..931f054041 100644
/* 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)
@@ -575,6 +598,24 @@ main (argc, argv)
exit(1);
}
@ -224,7 +220,7 @@ index af12861729..931f054041 100644
}
if( some_rest_copy){
@@ -653,6 +694,30 @@ main (argc, argv)
@@ -632,6 +673,30 @@ main (argc, argv)
exit(1);
}
@ -255,7 +251,7 @@ index af12861729..931f054041 100644
/* set permissions */
if (setgid(target_pwd->pw_gid) < 0) {
perror("ksu: setgid");
@@ -750,7 +815,7 @@ main (argc, argv)
@@ -729,7 +794,7 @@ main (argc, argv)
fprintf(stderr, "program to be execed %s\n",params[0]);
}
@ -264,7 +260,7 @@ index af12861729..931f054041 100644
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)
@@ -759,16 +824,35 @@ main (argc, argv)
if (ret_pid == -1) {
com_err(prog_name, errno, _("while calling waitpid"));
}
@ -303,7 +299,7 @@ index af12861729..931f054041 100644
}
diff --git a/src/clients/ksu/pam.c b/src/clients/ksu/pam.c
new file mode 100644
index 0000000000..cbfe487047
index 000000000..cbfe48704
--- /dev/null
+++ b/src/clients/ksu/pam.c
@@ -0,0 +1,389 @@
@ -698,7 +694,7 @@ index 0000000000..cbfe487047
+#endif
diff --git a/src/clients/ksu/pam.h b/src/clients/ksu/pam.h
new file mode 100644
index 0000000000..0ab76569cb
index 000000000..0ab76569c
--- /dev/null
+++ b/src/clients/ksu/pam.h
@@ -0,0 +1,57 @@
@ -759,11 +755,11 @@ index 0000000000..0ab76569cb
+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])
diff --git a/src/configure.in b/src/configure.in
index 037c9f316..daabd12c8 100644
--- a/src/configure.in
+++ b/src/configure.in
@@ -1336,6 +1336,8 @@ AC_SUBST([VERTO_VERSION])
AC_PATH_PROG(GROFF, groff)
@ -772,6 +768,3 @@ index 77be7a2025..587221936e 100644
# Make localedir work in autoconf 2.5x.
if test "${localedir+set}" != set; then
localedir='$(datadir)/locale'
--
2.45.1

View file

@ -0,0 +1,75 @@
From f2df0b75dfbc9796bf8e1477f4661dfb7cdcf8d4 Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Tue, 23 Aug 2016 16:47:44 -0400
Subject: [PATCH] krb5-1.13-dirsrv-accountlock.patch
Treat 'nsAccountLock: true' the same as 'loginDisabled: true'. Updated from
original version filed as RT#5891.
---
src/aclocal.m4 | 9 +++++++++
src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c | 17 +++++++++++++++++
src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c | 3 +++
3 files changed, 29 insertions(+)
diff --git a/src/aclocal.m4 b/src/aclocal.m4
index f5667c35f..2bfb99496 100644
--- a/src/aclocal.m4
+++ b/src/aclocal.m4
@@ -1656,6 +1656,15 @@ if test "$with_ldap" = yes; then
AC_MSG_NOTICE(enabling OpenLDAP database backend module support)
OPENLDAP_PLUGIN=yes
fi
+AC_ARG_WITH([dirsrv-account-locking],
+[ --with-dirsrv-account-locking compile 389/Red Hat/Fedora/Netscape Directory Server database backend module],
+[case "$withval" in
+ yes | no) ;;
+ *) AC_MSG_ERROR(Invalid option value --with-dirsrv-account-locking="$withval") ;;
+esac], with_dirsrv_account_locking=no)
+if test $with_dirsrv_account_locking = yes; then
+ AC_DEFINE(HAVE_DIRSRV_ACCOUNT_LOCKING,1,[Define if LDAP KDB interface should heed 389 DS's nsAccountLock attribute.])
+fi
])dnl
dnl
dnl If libkeyutils exists (on Linux) include it and use keyring ccache
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c
index 32efc4f54..af8b2db7b 100644
--- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c
@@ -1674,6 +1674,23 @@ populate_krb5_db_entry(krb5_context context, krb5_ldap_context *ldap_context,
ret = krb5_dbe_update_tl_data(context, entry, &userinfo_tl_data);
if (ret)
goto cleanup;
+#ifdef HAVE_DIRSRV_ACCOUNT_LOCKING
+ {
+ krb5_timestamp expiretime=0;
+ char *is_login_disabled=NULL;
+
+ /* LOGIN DISABLED */
+ ret = krb5_ldap_get_string(ld, ent, "nsAccountLock", &is_login_disabled,
+ &attr_present);
+ if (ret)
+ goto cleanup;
+ if (attr_present == TRUE) {
+ if (strcasecmp(is_login_disabled, "TRUE")== 0)
+ entry->attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
+ free (is_login_disabled);
+ }
+ }
+#endif
ret = krb5_read_tkt_policy(context, ldap_context, entry, tktpolname);
if (ret)
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c
index d722dbfa6..5e8e9a897 100644
--- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c
@@ -54,6 +54,9 @@ char *principal_attributes[] = { "krbprincipalname",
"krbLastFailedAuth",
"krbLoginFailedCount",
"krbLastSuccessfulAuth",
+#ifdef HAVE_DIRSRV_ACCOUNT_LOCKING
+ "nsAccountLock",
+#endif
"krbLastPwdChange",
"krbLastAdminUnlock",
"krbPrincipalAuthInd",

View file

@ -0,0 +1,70 @@
From ae5bb11c0f06fdf92f51d237e94c1d410c59aa04 Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Tue, 23 Aug 2016 16:45:26 -0400
Subject: [PATCH] krb5-1.15-beta1-buildconf.patch
Build binaries in this package as RELRO PIEs, libraries as partial RELRO,
and install shared libraries with the execute bit set on them. Prune out
the -L/usr/lib* and PIE flags where they might leak out and affect
apps which just want to link with the libraries. FIXME: needs to check and
not just assume that the compiler supports using these flags.
---
src/build-tools/krb5-config.in | 7 +++++++
src/config/pre.in | 2 +-
src/config/shlib.conf | 5 +++--
3 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/src/build-tools/krb5-config.in b/src/build-tools/krb5-config.in
index c17cb5eb5..1891dea99 100755
--- a/src/build-tools/krb5-config.in
+++ b/src/build-tools/krb5-config.in
@@ -226,6 +226,13 @@ if test -n "$do_libs"; then
-e 's#\$(PTHREAD_CFLAGS)#'"$PTHREAD_CFLAGS"'#' \
-e 's#\$(CFLAGS)##'`
+ if test `dirname $libdir` = /usr ; then
+ lib_flags=`echo $lib_flags | sed -e "s#-L$libdir##" -e "s#$RPATH_FLAG$libdir##"`
+ fi
+ lib_flags=`echo $lib_flags | sed -e "s#-fPIE##g" -e "s#-pie##g"`
+ lib_flags=`echo $lib_flags | sed -e "s#-Wl,-z,relro##g"`
+ lib_flags=`echo $lib_flags | sed -e "s#-Wl,-z,now##g"`
+
if test $library = 'kdb'; then
lib_flags="$lib_flags -lkdb5 $KDB5_DB_LIB"
library=krb5
diff --git a/src/config/pre.in b/src/config/pre.in
index fcea229bd..d961b5621 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) $(INSTALL_STRIP) -m 4755
## This is needed because autoconf will sometimes define @exec_prefix@ to be
## ${prefix}.
prefix=@prefix@
diff --git a/src/config/shlib.conf b/src/config/shlib.conf
index 3e4af6c02..2b20c3fda 100644
--- a/src/config/shlib.conf
+++ b/src/config/shlib.conf
@@ -423,7 +423,7 @@ mips-*-netbsd*)
# Linux ld doesn't default to stuffing the SONAME field...
# Use objdump -x to examine the fields of the library
# UNDEF_CHECK is suppressed by --enable-asan
- LDCOMBINE='$(CC) -shared -fPIC -Wl,-h,$(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT) $(UNDEF_CHECK)'
+ LDCOMBINE='$(CC) -shared -fPIC -Wl,-h,$(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT) $(UNDEF_CHECK) -Wl,-z,relro -Wl,--warn-shared-textrel'
UNDEF_CHECK='-Wl,--no-undefined'
# $(EXPORT_CHECK) runs export-check.pl when in maintainer mode.
LDCOMBINE_TAIL='-Wl,--version-script binutils.versions $(EXPORT_CHECK)'
@@ -435,7 +435,8 @@ mips-*-netbsd*)
SHLIB_EXPFLAGS='$(SHLIB_RPATH_FLAGS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)'
PROFFLAGS=-pg
PROG_RPATH_FLAGS='$(RPATH_FLAG)$(PROG_RPATH)'
- CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) $(LDFLAGS)'
+ CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) -pie -Wl,-z,relro -Wl,-z,now $(LDFLAGS)'
+ INSTALL_SHLIB='${INSTALL} -m755'
CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)'
CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CXXFLAGS) $(LDFLAGS)'
CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(LDFLAGS)'

View file

@ -1,7 +1,7 @@
From 30ff501e4b519396f5aea25e24919be817863e7c Mon Sep 17 00:00:00 2001
From aaf74b66a51cbda90ba40f73eb8def9b192ab262 Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Tue, 23 Aug 2016 16:30:53 -0400
Subject: [PATCH] [downstream] SELinux integration
Subject: [PATCH] krb5-1.15.1-selinux-label.patch
SELinux bases access to files on the domain of the requesting process,
the operation being performed, and the context applied to the file.
@ -35,44 +35,41 @@ stomp all over us.
The selabel APIs for looking up the context should be thread-safe (per
Red Hat #273081), so switching to using them instead of matchpathcon(),
which we used earlier, is some improvement.
Last-updated: krb5-1.20.1
[jrische@redhat.com: Replace deprecated security_context_t by char *:
- src/util/support/selinux.c]
---
src/aclocal.m4 | 48 +++
src/build-tools/krb5-config.in | 3 +-
src/config/pre.in | 3 +-
src/configure.ac | 2 +
src/include/k5-int.h | 1 +
src/include/k5-label.h | 32 ++
src/include/krb5/krb5.hin | 6 +
src/kadmin/dbutil/dump.c | 11 +-
src/kdc/main.c | 2 +-
src/kprop/kpropd.c | 9 +
src/lib/kadm5/logger.c | 4 +-
src/lib/kdb/kdb_log.c | 2 +-
src/lib/krb5/ccache/cc_dir.c | 26 +-
src/lib/krb5/keytab/kt_file.c | 4 +-
src/lib/krb5/os/trace.c | 2 +-
src/plugins/kdb/db2/adb_openclose.c | 2 +-
src/plugins/kdb/db2/kdb_db2.c | 4 +-
src/plugins/kdb/db2/libdb2/btree/bt_open.c | 3 +-
src/plugins/kdb/db2/libdb2/hash/hash.c | 3 +-
src/plugins/kdb/db2/libdb2/recno/rec_open.c | 4 +-
.../kdb/ldap/ldap_util/kdb5_ldap_services.c | 11 +-
src/util/profile/prof_file.c | 3 +-
src/util/support/Makefile.in | 3 +-
src/util/support/selinux.c | 405 ++++++++++++++++++
24 files changed, 572 insertions(+), 21 deletions(-)
src/aclocal.m4 | 49 +++
src/build-tools/krb5-config.in | 3 +-
src/config/pre.in | 3 +-
src/configure.in | 2 +
src/include/k5-int.h | 1 +
src/include/k5-label.h | 32 ++
src/include/krb5/krb5.hin | 6 +
src/kadmin/dbutil/dump.c | 11 +-
src/kdc/main.c | 2 +-
src/lib/kadm5/logger.c | 4 +-
src/lib/kdb/kdb_log.c | 2 +-
src/lib/krb5/ccache/cc_dir.c | 26 +-
src/lib/krb5/keytab/kt_file.c | 4 +-
src/lib/krb5/os/trace.c | 2 +-
src/lib/krb5/rcache/rc_dfl.c | 13 +
src/plugins/kdb/db2/adb_openclose.c | 2 +-
src/plugins/kdb/db2/kdb_db2.c | 4 +-
src/plugins/kdb/db2/libdb2/btree/bt_open.c | 3 +-
src/plugins/kdb/db2/libdb2/hash/hash.c | 3 +-
src/plugins/kdb/db2/libdb2/recno/rec_open.c | 4 +-
.../kdb/ldap/ldap_util/kdb5_ldap_services.c | 11 +-
src/slave/kpropd.c | 9 +
src/util/profile/prof_file.c | 3 +-
src/util/support/Makefile.in | 3 +-
src/util/support/selinux.c | 406 +++++++++++++++++++++
25 files changed, 587 insertions(+), 21 deletions(-)
create mode 100644 src/include/k5-label.h
create mode 100644 src/util/support/selinux.c
diff --git a/src/aclocal.m4 b/src/aclocal.m4
index ce3c5a9bac..3331970930 100644
index 508e5fe90..607859f17 100644
--- a/src/aclocal.m4
+++ b/src/aclocal.m4
@@ -85,6 +85,7 @@ AC_SUBST_FILE(libnodeps_frag)
@@ -89,6 +89,7 @@ AC_SUBST_FILE(libnodeps_frag)
dnl
KRB5_AC_PRAGMA_WEAK_REF
WITH_LDAP
@ -80,7 +77,7 @@ index ce3c5a9bac..3331970930 100644
KRB5_LIB_PARAMS
KRB5_AC_INITFINI
KRB5_AC_ENABLE_THREADS
@@ -1526,4 +1527,51 @@ AC_SUBST(PAM_LIBS)
@@ -1742,3 +1743,51 @@ AC_SUBST(PAM_LIBS)
AC_SUBST(PAM_MAN)
AC_SUBST(NON_PAM_MAN)
])dnl
@ -103,7 +100,7 @@ index ce3c5a9bac..3331970930 100644
+ AC_MSG_ERROR([Unable to locate selinux/selinux.h.])
+ fi
+ fi
+
+ LIBS=
+ unset ac_cv_func_setfscreatecon
+ AC_CHECK_FUNCS(setfscreatecon selabel_open)
@ -133,10 +130,10 @@ index ce3c5a9bac..3331970930 100644
+AC_SUBST(SELINUX_LIBS)
+])dnl
diff --git a/src/build-tools/krb5-config.in b/src/build-tools/krb5-config.in
index 8e6eb86601..7677f37359 100755
index f6184da3f..c17cb5eb5 100755
--- a/src/build-tools/krb5-config.in
+++ b/src/build-tools/krb5-config.in
@@ -40,6 +40,7 @@ DL_LIB='@DL_LIB@'
@@ -41,6 +41,7 @@ DL_LIB='@DL_LIB@'
DEFCCNAME='@DEFCCNAME@'
DEFKTNAME='@DEFKTNAME@'
DEFCKTNAME='@DEFCKTNAME@'
@ -144,7 +141,7 @@ index 8e6eb86601..7677f37359 100755
LIBS='@LIBS@'
GEN_LIB=@GEN_LIB@
@@ -253,7 +254,7 @@ if test -n "$do_libs"; then
@@ -255,7 +256,7 @@ if test -n "$do_libs"; then
fi
# If we ever support a flag to generate output suitable for static
@ -154,7 +151,7 @@ index 8e6eb86601..7677f37359 100755
echo $lib_flags
diff --git a/src/config/pre.in b/src/config/pre.in
index a0c60c70b3..7eaa2f351c 100644
index e0626320c..fcea229bd 100644
--- a/src/config/pre.in
+++ b/src/config/pre.in
@@ -177,6 +177,7 @@ LD = $(PURE) @LD@
@ -165,7 +162,7 @@ index a0c60c70b3..7eaa2f351c 100644
INSTALL=@INSTALL@
INSTALL_STRIP=
@@ -379,7 +380,7 @@ SUPPORT_LIB = -l$(SUPPORT_LIBNAME)
@@ -399,7 +400,7 @@ SUPPORT_LIB = -l$(SUPPORT_LIBNAME)
# HESIOD_LIBS is -lhesiod...
HESIOD_LIBS = @HESIOD_LIBS@
@ -173,12 +170,12 @@ index a0c60c70b3..7eaa2f351c 100644
+KRB5_BASE_LIBS = $(KRB5_LIB) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB) $(GEN_LIB) $(LIBS) $(SELINUX_LIBS) $(DL_LIB)
KDB5_LIBS = $(KDB5_LIB) $(GSSRPC_LIBS)
GSS_LIBS = $(GSS_KRB5_LIB)
# needs fixing if ever used on macOS!
diff --git a/src/configure.ac b/src/configure.ac
index 587221936e..69be9030f8 100644
--- a/src/configure.ac
+++ b/src/configure.ac
@@ -1401,6 +1401,8 @@ AC_PATH_PROG(GROFF, groff)
# needs fixing if ever used on Mac OS X!
diff --git a/src/configure.in b/src/configure.in
index daabd12c8..acf3a458b 100644
--- a/src/configure.in
+++ b/src/configure.in
@@ -1338,6 +1338,8 @@ AC_PATH_PROG(GROFF, groff)
KRB5_WITH_PAM
@ -188,7 +185,7 @@ index 587221936e..69be9030f8 100644
if test "${localedir+set}" != set; then
localedir='$(datadir)/locale'
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index 1d1c8293f4..768110e5ef 100644
index 64991738a..173cb0264 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -128,6 +128,7 @@ typedef unsigned char u_char;
@ -201,7 +198,7 @@ index 1d1c8293f4..768110e5ef 100644
#define KRB5_KDB_MAX_RLIFE (60*60*24*7) /* one week */
diff --git a/src/include/k5-label.h b/src/include/k5-label.h
new file mode 100644
index 0000000000..dfaaa847cb
index 000000000..dfaaa847c
--- /dev/null
+++ b/src/include/k5-label.h
@@ -0,0 +1,32 @@
@ -238,10 +235,10 @@ index 0000000000..dfaaa847cb
+#endif
+#endif
diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
index 4e09ed345d..09f800be52 100644
index ac22f4c55..cf60d6c41 100644
--- a/src/include/krb5/krb5.hin
+++ b/src/include/krb5/krb5.hin
@@ -83,6 +83,12 @@
@@ -87,6 +87,12 @@
#define THREEPARAMOPEN(x,y,z) open(x,y,z)
#endif
@ -255,7 +252,7 @@ index 4e09ed345d..09f800be52 100644
#include <stdlib.h>
diff --git a/src/kadmin/dbutil/dump.c b/src/kadmin/dbutil/dump.c
index a89b5144f6..4d6cc0bdf9 100644
index f7889bd23..cad53cfbf 100644
--- a/src/kadmin/dbutil/dump.c
+++ b/src/kadmin/dbutil/dump.c
@@ -148,12 +148,21 @@ create_ofile(char *ofile, char **tmpname)
@ -280,20 +277,20 @@ index a89b5144f6..4d6cc0bdf9 100644
if (fd == -1)
goto error;
@@ -197,7 +206,7 @@ prep_ok_file(krb5_context context, char *file_name, int *fd_out)
goto cleanup;
@@ -194,7 +203,7 @@ prep_ok_file(krb5_context context, char *file_name, int *fd)
return 0;
}
- fd = open(file_ok, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+ fd = THREEPARAMOPEN(file_ok, O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (fd == -1) {
- *fd = open(file_ok, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+ *fd = THREEPARAMOPEN(file_ok, O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (*fd == -1) {
com_err(progname, errno, _("while creating 'ok' file, '%s'"), file_ok);
goto cleanup;
exit_status++;
diff --git a/src/kdc/main.c b/src/kdc/main.c
index bfdfef5c48..b43fe9a082 100644
index ebc852bba..a4dffb29a 100644
--- a/src/kdc/main.c
+++ b/src/kdc/main.c
@@ -844,7 +844,7 @@ write_pid_file(const char *path)
@@ -872,7 +872,7 @@ write_pid_file(const char *path)
FILE *file;
unsigned long pid;
@ -302,41 +299,11 @@ index bfdfef5c48..b43fe9a082 100644
if (file == NULL)
return errno;
pid = (unsigned long) getpid();
diff --git a/src/kprop/kpropd.c b/src/kprop/kpropd.c
index aa3c81ea30..cb9785aaeb 100644
--- a/src/kprop/kpropd.c
+++ b/src/kprop/kpropd.c
@@ -488,6 +488,9 @@ doit(int fd)
krb5_enctype etype;
int database_fd;
char host[INET6_ADDRSTRLEN + 1];
+#ifdef USE_SELINUX
+ void *selabel;
+#endif
signal_wrapper(SIGALRM, alarm_handler);
alarm(params.iprop_resync_timeout);
@@ -543,9 +546,15 @@ doit(int fd)
free(name);
exit(1);
}
+#ifdef USE_SELINUX
+ selabel = krb5int_push_fscreatecon_for(file);
+#endif
omask = umask(077);
lock_fd = open(temp_file_name, O_RDWR | O_CREAT, 0600);
(void)umask(omask);
+#ifdef USE_SELINUX
+ krb5int_pop_fscreatecon(selabel);
+#endif
retval = krb5_lock_file(kpropd_context, lock_fd,
KRB5_LOCKMODE_EXCLUSIVE | KRB5_LOCKMODE_DONTBLOCK);
if (retval) {
diff --git a/src/lib/kadm5/logger.c b/src/lib/kadm5/logger.c
index e14da53790..b879a4049b 100644
index ce79fabf7..c53a5743f 100644
--- a/src/lib/kadm5/logger.c
+++ b/src/lib/kadm5/logger.c
@@ -310,7 +310,7 @@ krb5_klog_init(krb5_context kcontext, char *ename, char *whoami, krb5_boolean do
@@ -414,7 +414,7 @@ krb5_klog_init(krb5_context kcontext, char *ename, char *whoami, krb5_boolean do
*/
append = (cp[4] == ':') ? O_APPEND : 0;
if (append || cp[4] == '=') {
@ -345,7 +312,7 @@ index e14da53790..b879a4049b 100644
S_IRUSR | S_IWUSR | S_IRGRP);
if (fd != -1)
f = fdopen(fd, append ? "a" : "w");
@@ -777,7 +777,7 @@ krb5_klog_reopen(krb5_context kcontext)
@@ -918,7 +918,7 @@ krb5_klog_reopen(krb5_context kcontext)
* In case the old logfile did not get moved out of the
* way, open for append to prevent squashing the old logs.
*/
@ -355,20 +322,20 @@ index e14da53790..b879a4049b 100644
set_cloexec_file(f);
log_control.log_entries[lindex].lfu_filep = f;
diff --git a/src/lib/kdb/kdb_log.c b/src/lib/kdb/kdb_log.c
index 2659a25018..e9b95fce59 100644
index 766d3002a..6466417b7 100644
--- a/src/lib/kdb/kdb_log.c
+++ b/src/lib/kdb/kdb_log.c
@@ -480,7 +480,7 @@ ulog_map(krb5_context context, const char *logname, uint32_t ulogentries)
return ENOMEM;
@@ -476,7 +476,7 @@ ulog_map(krb5_context context, const char *logname, uint32_t ulogentries)
int ulogfd = -1;
if (stat(logname, &st) == -1) {
- log_ctx->ulogfd = open(logname, O_RDWR | O_CREAT, 0600);
+ log_ctx->ulogfd = THREEPARAMOPEN(logname, O_RDWR | O_CREAT, 0600);
if (log_ctx->ulogfd == -1) {
retval = errno;
goto cleanup;
- ulogfd = open(logname, O_RDWR | O_CREAT, 0600);
+ ulogfd = THREEPARAMOPEN(logname, O_RDWR | O_CREAT, 0600);
if (ulogfd == -1)
return errno;
diff --git a/src/lib/krb5/ccache/cc_dir.c b/src/lib/krb5/ccache/cc_dir.c
index 1da40b51d0..f3ab7340a6 100644
index bba64e516..73f0fe62d 100644
--- a/src/lib/krb5/ccache/cc_dir.c
+++ b/src/lib/krb5/ccache/cc_dir.c
@@ -183,10 +183,19 @@ write_primary_file(const char *primary_path, const char *contents)
@ -418,10 +385,10 @@ index 1da40b51d0..f3ab7340a6 100644
_("Credential cache directory %s does not exist"),
dirname);
diff --git a/src/lib/krb5/keytab/kt_file.c b/src/lib/krb5/keytab/kt_file.c
index e510211fc5..f3ea28c8ec 100644
index 6a42f267d..674d88bab 100644
--- a/src/lib/krb5/keytab/kt_file.c
+++ b/src/lib/krb5/keytab/kt_file.c
@@ -735,14 +735,14 @@ krb5_ktfileint_open(krb5_context context, krb5_keytab id, int mode)
@@ -1022,14 +1022,14 @@ krb5_ktfileint_open(krb5_context context, krb5_keytab id, int mode)
KTCHECKLOCK(id);
errno = 0;
@ -439,10 +406,10 @@ index e510211fc5..f3ea28c8ec 100644
goto report_errno;
writevno = 1;
diff --git a/src/lib/krb5/os/trace.c b/src/lib/krb5/os/trace.c
index 4cbbbb270a..c4058ddc96 100644
index 83c8d4db8..a19246128 100644
--- a/src/lib/krb5/os/trace.c
+++ b/src/lib/krb5/os/trace.c
@@ -460,7 +460,7 @@ krb5_set_trace_filename(krb5_context context, const char *filename)
@@ -397,7 +397,7 @@ krb5_set_trace_filename(krb5_context context, const char *filename)
fd = malloc(sizeof(*fd));
if (fd == NULL)
return ENOMEM;
@ -451,8 +418,40 @@ index 4cbbbb270a..c4058ddc96 100644
if (*fd == -1) {
free(fd);
return errno;
diff --git a/src/lib/krb5/rcache/rc_dfl.c b/src/lib/krb5/rcache/rc_dfl.c
index c4d2c744d..c0f12ed9d 100644
--- a/src/lib/krb5/rcache/rc_dfl.c
+++ b/src/lib/krb5/rcache/rc_dfl.c
@@ -794,6 +794,9 @@ krb5_rc_dfl_expunge_locked(krb5_context context, krb5_rcache id)
krb5_error_code retval = 0;
krb5_rcache tmp;
krb5_deltat lifespan = t->lifespan; /* save original lifespan */
+#ifdef USE_SELINUX
+ void *selabel;
+#endif
if (! t->recovering) {
name = t->name;
@@ -815,7 +818,17 @@ krb5_rc_dfl_expunge_locked(krb5_context context, krb5_rcache id)
retval = krb5_rc_resolve(context, tmp, 0);
if (retval)
goto cleanup;
+#ifdef USE_SELINUX
+ if (t->d.fn != NULL)
+ selabel = krb5int_push_fscreatecon_for(t->d.fn);
+ else
+ selabel = NULL;
+#endif
retval = krb5_rc_initialize(context, tmp, lifespan);
+#ifdef USE_SELINUX
+ if (selabel != NULL)
+ krb5int_pop_fscreatecon(selabel);
+#endif
if (retval)
goto cleanup;
for (q = t->a; q; q = q->na) {
diff --git a/src/plugins/kdb/db2/adb_openclose.c b/src/plugins/kdb/db2/adb_openclose.c
index 9a506e9d44..f92ab47143 100644
index 7db30a33b..2b9d01921 100644
--- a/src/plugins/kdb/db2/adb_openclose.c
+++ b/src/plugins/kdb/db2/adb_openclose.c
@@ -152,7 +152,7 @@ osa_adb_init_db(osa_adb_db_t *dbp, char *filename, char *lockfilename,
@ -465,7 +464,7 @@ index 9a506e9d44..f92ab47143 100644
* maybe someone took away write permission so we could only
* get shared locks?
diff --git a/src/plugins/kdb/db2/kdb_db2.c b/src/plugins/kdb/db2/kdb_db2.c
index 2c163d91cc..9a344a603e 100644
index 4c4036eb4..d90bdeaba 100644
--- a/src/plugins/kdb/db2/kdb_db2.c
+++ b/src/plugins/kdb/db2/kdb_db2.c
@@ -694,8 +694,8 @@ ctx_create_db(krb5_context context, krb5_db2_context *dbc)
@ -480,7 +479,7 @@ index 2c163d91cc..9a344a603e 100644
retval = errno;
goto cleanup;
diff --git a/src/plugins/kdb/db2/libdb2/btree/bt_open.c b/src/plugins/kdb/db2/libdb2/btree/bt_open.c
index 2977b17f3a..d5809a5a93 100644
index 2977b17f3..d5809a5a9 100644
--- a/src/plugins/kdb/db2/libdb2/btree/bt_open.c
+++ b/src/plugins/kdb/db2/libdb2/btree/bt_open.c
@@ -60,6 +60,7 @@ static char sccsid[] = "@(#)bt_open.c 8.11 (Berkeley) 11/2/95";
@ -501,7 +500,7 @@ index 2977b17f3a..d5809a5a93 100644
} else {
diff --git a/src/plugins/kdb/db2/libdb2/hash/hash.c b/src/plugins/kdb/db2/libdb2/hash/hash.c
index 862dbb1640..686a960c96 100644
index 76f5d4709..1fa8b8389 100644
--- a/src/plugins/kdb/db2/libdb2/hash/hash.c
+++ b/src/plugins/kdb/db2/libdb2/hash/hash.c
@@ -51,6 +51,7 @@ static char sccsid[] = "@(#)hash.c 8.12 (Berkeley) 11/7/95";
@ -512,7 +511,7 @@ index 862dbb1640..686a960c96 100644
#include "db-int.h"
#include "hash.h"
#include "page.h"
@@ -129,7 +130,7 @@ __kdb2_hash_open(file, flags, mode, info, dflags)
@@ -140,7 +141,7 @@ __kdb2_hash_open(file, flags, mode, info, dflags)
new_table = 1;
}
if (file) {
@ -522,7 +521,7 @@ index 862dbb1640..686a960c96 100644
(void)fcntl(hashp->fp, F_SETFD, 1);
}
diff --git a/src/plugins/kdb/db2/libdb2/recno/rec_open.c b/src/plugins/kdb/db2/libdb2/recno/rec_open.c
index d8b26e7011..b0daa7c021 100644
index d8b26e701..b0daa7c02 100644
--- a/src/plugins/kdb/db2/libdb2/recno/rec_open.c
+++ b/src/plugins/kdb/db2/libdb2/recno/rec_open.c
@@ -51,6 +51,7 @@ static char sccsid[] = "@(#)rec_open.c 8.12 (Berkeley) 11/18/94";
@ -544,10 +543,10 @@ index d8b26e7011..b0daa7c021 100644
if (fname != NULL && fcntl(rfd, F_SETFD, 1) == -1) {
diff --git a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
index e87688d666..30f7c00ab5 100644
index 022156a5e..3d6994c67 100644
--- a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
@@ -190,7 +190,7 @@ kdb5_ldap_stash_service_password(int argc, char **argv)
@@ -203,7 +203,7 @@ kdb5_ldap_stash_service_password(int argc, char **argv)
/* set password in the file */
old_mode = umask(0177);
@ -556,7 +555,7 @@ index e87688d666..30f7c00ab5 100644
if (pfile == NULL) {
com_err(me, errno, _("Failed to open file %s: %s"), file_name,
strerror (errno));
@@ -231,6 +231,9 @@ kdb5_ldap_stash_service_password(int argc, char **argv)
@@ -244,6 +244,9 @@ kdb5_ldap_stash_service_password(int argc, char **argv)
* Delete the existing entry and add the new entry
*/
FILE *newfile;
@ -566,7 +565,7 @@ index e87688d666..30f7c00ab5 100644
mode_t omask;
@@ -242,7 +245,13 @@ kdb5_ldap_stash_service_password(int argc, char **argv)
@@ -255,7 +258,13 @@ kdb5_ldap_stash_service_password(int argc, char **argv)
}
omask = umask(077);
@ -580,8 +579,38 @@ index e87688d666..30f7c00ab5 100644
umask (omask);
if (newfile == NULL) {
com_err(me, errno, _("Error creating file %s"), tmp_file);
diff --git a/src/slave/kpropd.c b/src/slave/kpropd.c
index 056c31a42..b78c3d9e5 100644
--- a/src/slave/kpropd.c
+++ b/src/slave/kpropd.c
@@ -464,6 +464,9 @@ doit(int fd)
krb5_enctype etype;
int database_fd;
char host[INET6_ADDRSTRLEN + 1];
+#ifdef USE_SELINUX
+ void *selabel;
+#endif
signal_wrapper(SIGALRM, alarm_handler);
alarm(params.iprop_resync_timeout);
@@ -520,9 +523,15 @@ doit(int fd)
free(name);
exit(1);
}
+#ifdef USE_SELINUX
+ selabel = krb5int_push_fscreatecon_for(file);
+#endif
omask = umask(077);
lock_fd = open(temp_file_name, O_RDWR | O_CREAT, 0600);
(void)umask(omask);
+#ifdef USE_SELINUX
+ krb5int_pop_fscreatecon(selabel);
+#endif
retval = krb5_lock_file(kpropd_context, lock_fd,
KRB5_LOCKMODE_EXCLUSIVE | KRB5_LOCKMODE_DONTBLOCK);
if (retval) {
diff --git a/src/util/profile/prof_file.c b/src/util/profile/prof_file.c
index aa951df05f..79f9500f69 100644
index 907c119bb..0f5462aea 100644
--- a/src/util/profile/prof_file.c
+++ b/src/util/profile/prof_file.c
@@ -33,6 +33,7 @@
@ -592,7 +621,7 @@ index aa951df05f..79f9500f69 100644
struct global_shared_profile_data {
/* This is the head of the global list of shared trees */
@@ -391,7 +392,7 @@ static errcode_t write_data_to_file(prf_data_t data, const char *outfile,
@@ -423,7 +424,7 @@ static errcode_t write_data_to_file(prf_data_t data, const char *outfile,
errno = 0;
@ -602,10 +631,10 @@ index aa951df05f..79f9500f69 100644
retval = errno;
if (retval == 0)
diff --git a/src/util/support/Makefile.in b/src/util/support/Makefile.in
index 86d5a950a6..1052d53a1e 100644
index 6239e4176..17bcd2a67 100644
--- a/src/util/support/Makefile.in
+++ b/src/util/support/Makefile.in
@@ -74,6 +74,7 @@ IPC_SYMS= \
@@ -69,6 +69,7 @@ IPC_SYMS= \
STLIBOBJS= \
threads.o \
@ -613,7 +642,7 @@ index 86d5a950a6..1052d53a1e 100644
init-addrinfo.o \
plugins.o \
errors.o \
@@ -168,7 +169,7 @@ SRCS=\
@@ -148,7 +149,7 @@ SRCS=\
SHLIB_EXPDEPS =
# Add -lm if dumping thread stats, for sqrt.
@ -624,10 +653,10 @@ index 86d5a950a6..1052d53a1e 100644
diff --git a/src/util/support/selinux.c b/src/util/support/selinux.c
new file mode 100644
index 0000000000..807d039da3
index 000000000..6d41f3244
--- /dev/null
+++ b/src/util/support/selinux.c
@@ -0,0 +1,405 @@
@@ -0,0 +1,406 @@
+/*
+ * Copyright 2007,2008,2009,2011,2012,2013,2016 Red Hat, Inc. All Rights Reserved.
+ *
@ -726,16 +755,17 @@ index 0000000000..807d039da3
+ }
+}
+
+static char *
+static security_context_t
+push_fscreatecon(const char *pathname, mode_t mode)
+{
+ char *previous, *configuredsc, *currentsc, *genpath;
+ const char *derivedsc, *fullpath, *currentuser;
+ security_context_t previous, configuredsc, currentsc, derivedsc;
+ context_t current, derived;
+ const char *fullpath, *currentuser;
+ char *genpath;
+
+ previous = configuredsc = currentsc = genpath = NULL;
+ derivedsc = NULL;
+ previous = configuredsc = currentsc = derivedsc = NULL;
+ current = derived = NULL;
+ genpath = NULL;
+
+ fullpath = pathname;
+
@ -863,7 +893,7 @@ index 0000000000..807d039da3
+}
+
+static void
+pop_fscreatecon(char *previous)
+pop_fscreatecon(security_context_t previous)
+{
+ if (!is_selinux_enabled()) {
+ return;
@ -917,7 +947,7 @@ index 0000000000..807d039da3
+{
+ FILE *fp;
+ int errno_save;
+ char *ctx;
+ security_context_t ctx;
+
+ if ((strcmp(mode, "r") == 0) ||
+ (strcmp(mode, "rb") == 0)) {
@ -943,7 +973,7 @@ index 0000000000..807d039da3
+{
+ int fd;
+ int errno_save;
+ char *ctx;
+ security_context_t ctx;
+
+ k5_once(&labeled_once, label_mutex_init);
+ k5_mutex_lock(&labeled_mutex);
@ -964,7 +994,7 @@ index 0000000000..807d039da3
+{
+ int ret;
+ int errno_save;
+ char *ctx;
+ security_context_t ctx;
+
+ k5_once(&labeled_once, label_mutex_init);
+ k5_mutex_lock(&labeled_mutex);
@ -985,7 +1015,7 @@ index 0000000000..807d039da3
+{
+ int ret;
+ int errno_save;
+ char *ctx;
+ security_context_t ctx;
+
+ k5_once(&labeled_once, label_mutex_init);
+ k5_mutex_lock(&labeled_mutex);
@ -1006,7 +1036,7 @@ index 0000000000..807d039da3
+{
+ int fd;
+ int errno_save;
+ char *ctx;
+ security_context_t ctx;
+ mode_t mode;
+ va_list ap;
+
@ -1033,6 +1063,3 @@ index 0000000000..807d039da3
+}
+
+#endif /* USE_SELINUX */
--
2.45.1

22
krb5-1.3.1-dns.patch Normal file
View file

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

View file

@ -1,20 +1,18 @@
From 393830d96000ed692aa9a99ef87187d6f2863931 Mon Sep 17 00:00:00 2001
From e1d7fcf9713fe322ad5740045650dac86427e6ae 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
Subject: [PATCH] krb5-1.9-debuginfo.patch
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
index adfea6e2b..d1327e400 100644
--- a/src/kadmin/cli/Makefile.in
+++ b/src/kadmin/cli/Makefile.in
@@ -37,3 +37,8 @@ clean-unix::
@ -27,7 +25,7 @@ index adfea6e2b5..d1327e400b 100644
+ $(YACC.y) $<
+ $(CP) y.tab.c $@
diff --git a/src/plugins/kdb/ldap/ldap_util/Makefile.in b/src/plugins/kdb/ldap/ldap_util/Makefile.in
index 8669c2436c..a22f23c02c 100644
index 8669c2436..a22f23c02 100644
--- a/src/plugins/kdb/ldap/ldap_util/Makefile.in
+++ b/src/plugins/kdb/ldap/ldap_util/Makefile.in
@@ -20,7 +20,7 @@ $(PROG): $(OBJS) $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIB) $(GETDATE)
@ -39,6 +37,3 @@ index 8669c2436c..a22f23c02c 100644
install:
$(INSTALL_PROGRAM) $(PROG) ${DESTDIR}$(ADMIN_BINDIR)/$(PROG)
--
2.45.1

View file

@ -1 +1 @@
d /run/krb5kdc 0755 root root
d /var/run/krb5kdc 0755 root root

View file

@ -1,18 +0,0 @@
#!/bin/sh
set -e
export RPM_PACKAGE_NAME={{ name }}
export RPM_PACKAGE_VERSION={{ version }}
export RPM_PACKAGE_RELEASE={{ release }}
export RPM_ARCH={{ arch }}
export RPM_BUILD_NCPUS="$(getconf _NPROCESSORS_ONLN)"
testdir="$(mktemp -d)"
trap "rm -rf ${testdir}" EXIT
build_flags="$(eval "echo $(rpm --eval '%{_smp_mflags}')")"
mkdir "${testdir}/{{ name }}-tests"
cp -rp /usr/share/{{ name }}-tests/{{ arch }} "${testdir}/{{ name }}-tests/"
make -C "${testdir}/{{ name }}-tests/{{ arch }}/" $build_flags
keyctl session - make -C "${testdir}/{{ name }}-tests/{{ arch }}/" check

View file

@ -3,26 +3,22 @@
includedir /etc/krb5.conf.d/
[logging]
default = FILE:/var/log/krb5libs.log
kdc = FILE:/var/log/krb5kdc.log
admin_server = FILE:/var/log/kadmind.log
default = FILE:/var/log/krb5libs.log
kdc = FILE:/var/log/krb5kdc.log
admin_server = FILE:/var/log/kadmind.log
[libdefaults]
dns_lookup_realm = false
ticket_lifetime = 24h
renew_lifetime = 7d
forwardable = true
rdns = false
pkinit_anchors = FILE:/etc/pki/tls/certs/ca-bundle.crt
spake_preauth_groups = edwards25519
dns_canonicalize_hostname = fallback
qualify_shortname = ""
# default_realm = EXAMPLE.COM
dns_lookup_realm = false
ticket_lifetime = 24h
renew_lifetime = 7d
forwardable = true
rdns = false
# default_realm = EXAMPLE.COM
[realms]
# EXAMPLE.COM = {
# kdc = kerberos.example.com
# admin_server = kerberos.example.com
# kdc = kerberos.example.com
# admin_server = kerberos.example.com
# }
[domain_realm]

View file

@ -1,14 +0,0 @@
addFilter(r'spelling-error .* en_US (unencrypted)')
addFilter(r'hidden-file-or-dir /usr/share/man/man5/.k5identity.5.gz')
addFilter(r'non-standard-dir-in-var kerberos')
addFilter(r'explicit-lib-dependency libverto-module-base')
addFilter(r'shared-lib-calls-exit')
addFilter(r'dir-or-file-in-var-run /var/run/krb5kdc')
addFilter(r'devel-file-in-non-devel-package /usr/lib64/libkadm5(clnt|srv)_mit.so')
addFilter(r'non-readable /var/kerberos/krb5kdc')
addFilter(r'devel-file-in-non-devel-package /usr/lib64/libkdb_ldap.so')
addFilter(r'/usr/bin/ksu')
addFilter(r'no-documentation')
addFilter(r'invalid-directory-reference .*pkgconfig')
addFilter(r'incoherent-logrotate-file /etc/logrotate.d/k')
addFilter(r'library-not-linked-against-libc')

2126
krb5.spec

File diff suppressed because it is too large Load diff

View file

@ -4,6 +4,6 @@
monthly
rotate 12
postrotate
systemctl reload krb5kdc.service || true
/bin/kill -HUP `cat /var/run/krb5kdc.pid 2>/dev/null` 2> /dev/null || true
endscript
}

View file

@ -1,13 +1,12 @@
[Unit]
Description=Kerberos 5 KDC
Wants=network-online.target
After=syslog.target network.target network-online.target
After=syslog.target network.target
[Service]
Type=forking
PIDFile=/run/krb5kdc.pid
PIDFile=/var/run/krb5kdc.pid
EnvironmentFile=-/etc/sysconfig/krb5kdc
ExecStart=/usr/sbin/krb5kdc -P /run/krb5kdc.pid $KRB5KDC_ARGS
ExecStart=/usr/sbin/krb5kdc -P /var/run/krb5kdc.pid $KRB5KDC_ARGS
ExecReload=/bin/kill -HUP $MAINPID
[Install]

111
noport.c Normal file
View file

@ -0,0 +1,111 @@
#define _GNU_SOURCE
#include <sys/socket.h>
#include <dlfcn.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
static int
port_is_okay(unsigned short port)
{
char *p, *q;
long l;
p = getenv("NOPORT");
while ((p != NULL) && (*p != '\0')) {
l = strtol(p, &q, 10);
if ((q == NULL) || (q == p)) {
break;
}
if ((*q == '\0') || (*q == ',')) {
if (port == l) {
errno = ECONNREFUSED;
return -1;
}
}
p = q;
p += strspn(p, ",");
}
return 0;
}
int
connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
unsigned short port;
static int (*next_connect)(int, const struct sockaddr *, socklen_t);
if (next_connect == NULL) {
next_connect = dlsym(RTLD_NEXT, "connect");
if (next_connect == NULL) {
errno = ENOSYS;
return -1;
}
}
if (getenv("NOPORT") == NULL) {
return next_connect(sockfd, addr, addrlen);
}
switch (addr->sa_family) {
case AF_INET:
port = ntohs(((struct sockaddr_in *)addr)->sin_port);
if (port_is_okay(port) != 0) {
return -1;
}
break;
case AF_INET6:
port = ntohs(((struct sockaddr_in6 *)addr)->sin6_port);
if (port_is_okay(port) != 0) {
return -1;
}
break;
default:
break;
}
return next_connect(sockfd, addr, addrlen);
}
ssize_t
sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen)
{
unsigned short port;
static int (*next_sendto)(int, const void *, size_t, int,
const struct sockaddr *, socklen_t);
if (next_sendto == NULL) {
next_sendto = dlsym(RTLD_NEXT, "sendto");
if (next_sendto == NULL) {
errno = ENOSYS;
return -1;
}
}
if (getenv("NOPORT") == NULL) {
return next_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
}
if (dest_addr != NULL) {
switch (dest_addr->sa_family) {
case AF_INET:
port = ((struct sockaddr_in *)dest_addr)->sin_port;
port = ntohs(port);
if (port_is_okay(port) != 0) {
return -1;
}
break;
case AF_INET6:
port = ((struct sockaddr_in6 *)dest_addr)->sin6_port;
port = ntohs(port);
if (port_is_okay(port) != 0) {
return -1;
}
break;
default:
break;
}
}
return next_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
}

Some files were not shown because too many files have changed in this diff Show more