Compare commits

...
Sign in to create a new pull request.

22 commits

Author SHA1 Message Date
Julien Rische
ee9e3fc1e1 Try harder to avoid password change replay errors
change_set_password() was changed to prefer TCP.  However, because
UDP_LAST falls back to UDP after one second, we can still get a replay
error due to a dropped packet, before the TCP layer has a chance to
retry.

Instead, try k5_sendto() with NO_UDP, and only fall back to UDP after
TCP fails completely without reaching a server.  In sendto_kdc.c,
implement an ONLY_UDP transport strategy to allow the UDP fallback.

Resolves: rhbz#2076965

Signed-off-by: Julien Rische <jrische@redhat.com>
2022-04-20 17:17:09 +02:00
Alexander Bokovoy
114b35c436 Fix libkrad client cleanup code
Resolves: rhbz#2072059

Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
2022-04-05 22:14:44 +03:00
Alexander Bokovoy
e66c7a3a81 Allow use of larger RADIUS attributes in krad library
In kr_attrset_decode(), explicitly treat the length byte as unsigned.
    Otherwise attributes longer than 125 characters will be rejected with
    EBADMSG.

    Add a 253-character-long NAS-Identifier attribute to the tests to make
    sure that attributes with the maximal number of characters are working
    as expected.

    [ghudson@mit.edu: used uint8_t cast per current practices; edited
    commit message]

    ticket: 9036 (new)

From upstream, needed in preparation for OAuth2 support for FreeIPA and
SSSD.

Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
2022-04-05 16:55:31 +03:00
Julien Rische
2deca4e8cd Use SHA-256 instead of SHA-1 for PKINIT CMS digest
CMS digest and signature algorithm for the anonymous PKINIT is changed
from SHA-1 to SHA-256. SHA-1 hasn't been considered secure anymore for
this kind of purposes for some years already.

Resolves: rhbz#2067121

Signed-off-by: Julien Rische <jrische@redhat.com>
2022-03-23 13:16:13 +01:00
Robbie Harwood
d693d44347 Fix KDC null deref on TGS inner body null server (CVE-2021-37750) 2021-08-19 12:32:16 -04:00
Robbie Harwood
3cd2cfc1c6 Add sources 2021-08-19 12:32:16 -04:00
Robbie Harwood
f4fc3f0f46 New upstream version (1.19.2) 2021-08-19 12:32:16 -04:00
Robbie Harwood
75a24fdad1 Fix defcred leak in krb5 gss_inquire_cred() 2021-08-19 12:32:16 -04:00
Robbie Harwood
d4c49281cc Fix KDC null deref on bad encrypted challenge (CVE-2021-36222) 2021-07-12 13:12:39 -04:00
Robbie Harwood
e2cba14cf1 Fix use-after-free during krad remote_shutdown() 2021-07-12 13:12:39 -04:00
Robbie Harwood
9450abbfbc MEMORY locking fix and static analysis pullup 2021-07-12 13:12:39 -04:00
Robbie Harwood
1806554414 Add the backward-compatible parts of openssl3 support 2021-07-12 13:12:39 -04:00
Robbie Harwood
09eff6f6df Fix three canonicalization cases for fallback 2021-07-12 13:12:39 -04:00
Robbie Harwood
5bbe654d61 Fix doc build for Sphinx 4.0 2021-07-12 13:12:39 -04:00
Robbie Harwood
ee6f543041 Add all the sssd-kcm workarounds
(cherry picked from commit 72e80d67ef)
2021-05-20 17:26:40 -04:00
Robbie Harwood
e76f184909 Fix context for previous backport
(cherry picked from commit c4150c67d1)
2021-05-20 14:04:29 -04:00
Robbie Harwood
a987c5f3a2 Add KCM_OP_GET_CRED_LIST and KCM_OP_RETRIEVE support
(cherry picked from commit 904d264a41)
2021-05-20 14:04:29 -04:00
Robbie Harwood
b407176c1f Remove broken gating file
Currently the gating file prevents building:

    rharwood@eesha:~/krb5.fedora/rawhide$ fedpkg build
    Could not execute build: Found a gating.yaml file in your repo with additional Greenwave policies, but it is not valid.
    Please fix the file or skip this check using the option --skip-remote-rules-validation.
    Error response from Greenwave: YAML Parser Error: mapping values are not allowed here
      in "<unicode string>", line 2, column 18:
           product_versions:
                                ^
    rharwood@eesha:~/krb5.fedora/rawhide$

Patches to add it back will be considered if and only if they don't
break the build.

(cherry picked from commit 69e05d5e39)
2021-05-20 14:04:15 -04:00
Robbie Harwood
be7528aa8e Suppress static analyzer warning in FIPS override
(cherry picked from commit e9fb111a11)
2021-05-20 14:04:10 -04:00
Robbie Harwood
2f63f28a76 Add rpminspect configuration
(cherry picked from commit 1c2362203e)
2021-05-20 14:04:06 -04:00
Miroslav Vadkerti
3892b7fc8e Onboard krb5 to downstream gating
Because krb5 is auto-synced via DistroBaker, we need to add
downstream gating configuration in Fedora.

Signed-off-by: Miroslav Vadkerti <mvadkert@redhat.com>
2021-03-30 14:38:16 -04:00
Robbie Harwood
c22d77ba16 Fix the mess the mass rebuild made of Release 2021-03-30 09:07:45 -04:00
35 changed files with 5069 additions and 22 deletions

2
.gitignore vendored
View file

@ -197,3 +197,5 @@ krb5-1.8.3-pdf.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

View file

@ -1,4 +1,4 @@
From 4505316756e42db02b6dabe0a6b075fe52852371 Mon Sep 17 00:00:00 2001
From 3a99832252755cf7e5fef2bd824459cea3eb823e Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Thu, 14 Jan 2021 18:13:09 -0500
Subject: [PATCH] Add APIs for marshalling credentials

View file

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

View file

@ -1,4 +1,4 @@
From d898d94cef8e1a8772a91cd3a62255c33f109636 Mon Sep 17 00:00:00 2001
From e88f0319427cee7245fb05c97a25473297c9d2d6 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Fri, 15 Jan 2021 14:43:34 -0500
Subject: [PATCH] Add hostname canonicalization helper to k5test.py

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

@ -1,4 +1,4 @@
From 8c57937f3ca793fe3f8fdd636be0bc11c24069bc Mon Sep 17 00:00:00 2001
From 818a777822658d44ce647fe975011a5ea25e8250 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Fri, 15 Jan 2021 13:51:34 -0500
Subject: [PATCH] Support host-based GSS initiator names

View file

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

View file

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

View file

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

View file

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

View file

@ -1,4 +1,4 @@
From 4a62aeae7b747cd289548949f940525365fe0947 Mon Sep 17 00:00:00 2001
From 91e1d43858d90f59f5d9f45987cfca02c3175feb 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
@ -19,6 +19,8 @@ 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.17
---
doc/admin/conf_files/krb5_conf.rst | 6 +++
@ -349,7 +351,7 @@ index 03c613716..d89982a13 100644
return retval;
diff --git a/src/lib/krad/internal.h b/src/lib/krad/internal.h
index 0143d155a..223ffd730 100644
index 0143d155a..57672982f 100644
--- a/src/lib/krad/internal.h
+++ b/src/lib/krad/internal.h
@@ -39,6 +39,8 @@
@ -407,8 +409,8 @@ index 0143d155a..223ffd730 100644
+ if (!FIPS_mode())
+ return 0;
+
+ profile_get_boolean(ctx->profile, "libdefaults",
+ "radius_md5_fips_override", NULL, 0, &val);
+ (void)profile_get_boolean(ctx->profile, "libdefaults",
+ "radius_md5_fips_override", NULL, 0, &val);
+ return !val;
+}
+
@ -475,7 +477,7 @@ index c597174b6..fc2d24800 100644
}
diff --git a/src/lib/krad/remote.c b/src/lib/krad/remote.c
index c96a9b4ee..eca432424 100644
index a938665f6..7b5804b1d 100644
--- a/src/lib/krad/remote.c
+++ b/src/lib/krad/remote.c
@@ -263,7 +263,7 @@ on_io_write(krad_remote *rr)

View file

@ -1,4 +1,4 @@
From fef4e551d3d2dcb55e58cc182304254c36aa8949 Mon Sep 17 00:00:00 2001
From defa8816e26ab9f5a8f0b61e7bebad67175c433e Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Tue, 26 Mar 2019 18:51:10 -0400
Subject: [PATCH] [downstream] Remove 3des support
@ -195,7 +195,7 @@ index 1dc958d62..3a72aabef 100644
While **aes128-cts** and **aes256-cts** are supported for all Kerberos
diff --git a/doc/admin/enctypes.rst b/doc/admin/enctypes.rst
index 047185afb..b08d954d9 100644
index 694922c0d..c4d5499d3 100644
--- a/doc/admin/enctypes.rst
+++ b/doc/admin/enctypes.rst
@@ -129,7 +129,7 @@ enctype weak? krb5 Windows
@ -243,7 +243,7 @@ index ade5e1f87..e4dc54f7e 100644
.. _err_cert_chain_cert_expired:
diff --git a/doc/appdev/refs/macros/index.rst b/doc/appdev/refs/macros/index.rst
index cebb6644c..4d51e795c 100644
index 5542d9850..0cb2e81bd 100644
--- a/doc/appdev/refs/macros/index.rst
+++ b/doc/appdev/refs/macros/index.rst
@@ -36,7 +36,6 @@ Public
@ -255,10 +255,10 @@ index cebb6644c..4d51e795c 100644
CKSUMTYPE_NIST_SHA.rst
CKSUMTYPE_RSA_MD4.rst
diff --git a/doc/conf.py b/doc/conf.py
index 543202bf4..4fb6aae14 100644
index 14158ae81..a876fd633 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -271,7 +271,7 @@ else:
@@ -278,7 +278,7 @@ else:
rst_epilog += '''
.. |krb5conf| replace:: ``/etc/krb5.conf``
.. |defkeysalts| replace:: ``aes256-cts-hmac-sha1-96:normal aes128-cts-hmac-sha1-96:normal``

View file

@ -1,4 +1,4 @@
From e787771b618a344d45ac515927e914602f48946f Mon Sep 17 00:00:00 2001
From 97966ffaac6bf9f2e09ac33a16b15794b31d51de 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

View file

@ -1,4 +1,4 @@
From 687bb26cb0877fa5497e90f7d325de42b456da2a Mon Sep 17 00:00:00 2001
From 86d606e33439fd0511c5154be7f32b0df2c72e54 Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Fri, 15 Nov 2019 20:05:16 +0000
Subject: [PATCH] [downstream] Use backported version of OpenSSL-3 KDF

View file

@ -1,4 +1,4 @@
From d5ea86ef491feb38f12e6aa53b7579ac02675df6 Mon Sep 17 00:00:00 2001
From 98b50683165089bf7bd9d91f953abbd79a8b1b08 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

View file

@ -1,4 +1,4 @@
From 90ba715be48c2e1b6c7ca53cb1d75f3af2c388d6 Mon Sep 17 00:00:00 2001
From 659b3b4a654b879ce84ad8fb4621dde5ae693385 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

View file

@ -1,4 +1,4 @@
From ad123366e5fb2694cf6d9f4f292a001a761b78fa Mon Sep 17 00:00:00 2001
From 2d7e197fa88dccd3ca051f9f7cb97937c35c55a8 Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Tue, 23 Aug 2016 16:46:21 -0400
Subject: [PATCH] [downstream] netlib and dns

View file

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

209
krb5-krad-remote.patch Normal file
View file

@ -0,0 +1,209 @@
From ce160f8826bae223876a6527a731c36b6912db15 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Tue, 9 Nov 2021 13:00:43 -0500
Subject: [PATCH 1/2] Avoid use after free during libkrad cleanup
libkrad client requests contain a list of references to remotes, with
no back-references or reference counts. To prevent accesses to
dangling references during cleanup, cancel all requests on all remotes
before freeing any remotes.
Remove the code for aging out unused servers. This code was fairly
safe as all requests referencing a remote should have completed or
timed out during an hour of disuse, but in the current design we have
no way to guarantee or check that. The set of addresses we send
RADIUS requests to will generally be small, so aging out servers is
unnecessary.
ticket: 9035 (new)
---
src/lib/krad/client.c | 42 ++++++++++++++---------------------------
src/lib/krad/internal.h | 4 ++++
src/lib/krad/remote.c | 11 ++++++++---
3 files changed, 26 insertions(+), 31 deletions(-)
diff --git a/src/lib/krad/client.c b/src/lib/krad/client.c
index 6365dd1c6..810940afc 100644
--- a/src/lib/krad/client.c
+++ b/src/lib/krad/client.c
@@ -64,7 +64,6 @@ struct request_st {
struct server_st {
krad_remote *serv;
- time_t last;
K5_LIST_ENTRY(server_st) list;
};
@@ -81,15 +80,10 @@ get_server(krad_client *rc, const struct addrinfo *ai, const char *secret,
krad_remote **out)
{
krb5_error_code retval;
- time_t currtime;
server *srv;
- if (time(&currtime) == (time_t)-1)
- return errno;
-
K5_LIST_FOREACH(srv, &rc->servers, list) {
if (kr_remote_equals(srv->serv, ai, secret)) {
- srv->last = currtime;
*out = srv->serv;
return 0;
}
@@ -98,7 +92,6 @@ get_server(krad_client *rc, const struct addrinfo *ai, const char *secret,
srv = calloc(1, sizeof(server));
if (srv == NULL)
return ENOMEM;
- srv->last = currtime;
retval = kr_remote_new(rc->kctx, rc->vctx, ai, secret, &srv->serv);
if (retval != 0) {
@@ -173,28 +166,12 @@ request_new(krad_client *rc, krad_code code, const krad_attrset *attrs,
return 0;
}
-/* Close remotes that haven't been used in a while. */
-static void
-age(struct server_head *head, time_t currtime)
-{
- server *srv, *tmp;
-
- K5_LIST_FOREACH_SAFE(srv, head, list, tmp) {
- if (currtime == (time_t)-1 || currtime - srv->last > 60 * 60) {
- K5_LIST_REMOVE(srv, list);
- kr_remote_free(srv->serv);
- free(srv);
- }
- }
-}
-
/* Handle a response from a server (or related errors). */
static void
on_response(krb5_error_code retval, const krad_packet *reqp,
const krad_packet *rspp, void *data)
{
request *req = data;
- time_t currtime;
size_t i;
/* Do nothing if we are already completed. */
@@ -221,10 +198,6 @@ on_response(krb5_error_code retval, const krad_packet *reqp,
for (i = 0; req->remotes[i].remote != NULL; i++)
kr_remote_cancel(req->remotes[i].remote, req->remotes[i].packet);
- /* Age out servers that haven't been used in a while. */
- if (time(&currtime) != (time_t)-1)
- age(&req->rc->servers, currtime);
-
request_free(req);
}
@@ -247,10 +220,23 @@ krad_client_new(krb5_context kctx, verto_ctx *vctx, krad_client **out)
void
krad_client_free(krad_client *rc)
{
+ server *srv;
+
if (rc == NULL)
return;
- age(&rc->servers, -1);
+ /* Cancel all requests before freeing any remotes, since each request's
+ * callback data may contain references to multiple remotes. */
+ K5_LIST_FOREACH(srv, &rc->servers, list)
+ kr_remote_cancel_all(srv->serv);
+
+ while (!K5_LIST_EMPTY(&rc->servers)) {
+ srv = K5_LIST_FIRST(&rc->servers);
+ K5_LIST_REMOVE(srv, list);
+ kr_remote_free(srv->serv);
+ free(srv);
+ }
+
free(rc);
}
diff --git a/src/lib/krad/internal.h b/src/lib/krad/internal.h
index 0143d155a..7619563fc 100644
--- a/src/lib/krad/internal.h
+++ b/src/lib/krad/internal.h
@@ -109,6 +109,10 @@ kr_remote_send(krad_remote *rr, krad_code code, krad_attrset *attrs,
void
kr_remote_cancel(krad_remote *rr, const krad_packet *pkt);
+/* Cancel all requests awaiting responses. */
+void
+kr_remote_cancel_all(krad_remote *rr);
+
/* Determine if this remote object refers to the remote resource identified
* by the addrinfo struct and the secret. */
krb5_boolean
diff --git a/src/lib/krad/remote.c b/src/lib/krad/remote.c
index 7e491e994..06ae751bc 100644
--- a/src/lib/krad/remote.c
+++ b/src/lib/krad/remote.c
@@ -421,15 +421,20 @@ error:
return retval;
}
+void
+kr_remote_cancel_all(krad_remote *rr)
+{
+ while (!K5_TAILQ_EMPTY(&rr->list))
+ request_finish(K5_TAILQ_FIRST(&rr->list), ECANCELED, NULL);
+}
+
void
kr_remote_free(krad_remote *rr)
{
if (rr == NULL)
return;
- while (!K5_TAILQ_EMPTY(&rr->list))
- request_finish(K5_TAILQ_FIRST(&rr->list), ECANCELED, NULL);
-
+ kr_remote_cancel_all(rr);
free(rr->secret);
if (rr->info != NULL)
free(rr->info->ai_addr);
--
2.35.1
From e0084425df784952e76b3bcc8ae9d08300234733 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Mon, 8 Nov 2021 17:47:17 +0100
Subject: [PATCH 2/2] More python3 fixes for t_daemon.py
[ghudson@mit.edu: use a list comprehension instead of map()]
---
src/lib/krad/t_daemon.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/lib/krad/t_daemon.py b/src/lib/krad/t_daemon.py
index 7668cd7f8..4a3de079c 100755
--- a/src/lib/krad/t_daemon.py
+++ b/src/lib/krad/t_daemon.py
@@ -50,7 +50,7 @@ class TestServer(server.Server):
for key in pkt.keys():
if key == "User-Password":
- passwd = map(pkt.PwDecrypt, pkt[key])
+ passwd = [pkt.PwDecrypt(x) for x in pkt[key]]
reply = self.CreateReplyPacket(pkt)
if passwd == ['accept']:
@@ -61,8 +61,8 @@ class TestServer(server.Server):
srv = TestServer(addresses=["localhost"],
hosts={"127.0.0.1":
- server.RemoteHost("127.0.0.1", "foo", "localhost")},
- dict=dictionary.Dictionary(StringIO.StringIO(DICTIONARY)))
+ server.RemoteHost("127.0.0.1", b"foo", "localhost")},
+ dict=dictionary.Dictionary(StringIO(DICTIONARY)))
# Write a sentinel character to let the parent process know we're listening.
sys.stdout.write("~")
--
2.35.1

View file

@ -41,8 +41,8 @@
Summary: The Kerberos network authentication system
Name: krb5
Version: 1.19.1
Release: %{?zdpd}3%{?dist}.1
Version: 1.19.2
Release: %{?zdpd}6%{?dist}
# rharwood has trust path to signing key and verifies on check-in
Source0: https://web.mit.edu/kerberos/dist/krb5/%{version}/krb5-%{version}%{?dashpre}.tar.gz
@ -73,6 +73,27 @@ Patch7: downstream-FIPS-with-PRNG-and-RADIUS-and-MD4.patch
Patch8: Add-APIs-for-marshalling-credentials.patch
Patch9: Add-hostname-canonicalization-helper-to-k5test.py.patch
Patch10: Support-host-based-GSS-initiator-names.patch
Patch11: Add-KCM_OP_GET_CRED_LIST-for-faster-iteration.patch
Patch12: Fix-KCM-flag-transmission-for-remove_cred.patch
Patch13: Make-KCM-iteration-fallback-work-with-sssd-kcm.patch
Patch14: Use-KCM_OP_RETRIEVE-in-KCM-client.patch
Patch15: Fix-KCM-retrieval-support-for-sssd.patch
Patch17: Move-some-dejagnu-kadmin-tests-to-Python-tests.patch
Patch18: Fix-some-principal-realm-canonicalization-cases.patch
Patch19: Allow-kinit-with-keytab-to-defer-canonicalization.patch
Patch20: Fix-kadmin-k-with-fallback-or-referral-realm.patch
Patch21: Fix-softpkcs11-build-issues-with-openssl-3.0.patch
Patch22: Remove-deprecated-OpenSSL-calls-from-softpkcs11.patch
Patch23: Fix-k5tls-module-for-OpenSSL-3.patch
Patch24: Fix-leaks-on-error-in-kadm5-init-functions.patch
Patch25: Clean-up-context-after-failed-open-in-libkdb5.patch
Patch26: Use-asan-in-one-of-the-CI-builds.patch
Patch29: Clean-up-gssapi_krb5-ccache-name-functions.patch
Patch30: Fix-KDC-null-deref-on-TGS-inner-body-null-server.patch
Patch31: Use-SHA256-instead-of-SHA1-for-PKINIT-CMS-digest.patch
Patch32: krb5-krad-remote.patch
Patch33: krb5-krad-larger-attrs.patch
Patch34: Try-harder-to-avoid-password-change-replay-errors.patch
License: MIT
URL: https://web.mit.edu/kerberos/www/
@ -635,6 +656,59 @@ exit 0
%{_libdir}/libkadm5srv_mit.so.*
%changelog
* Wed Apr 20 2022 Julien Rische <jrische@redhat.com> - 1.19.2-6
- Try harder to avoid password change replay errors
- Resolves: rhbz#2076965
* Tue Apr 05 2022 Alexander Bokovoy <abokovoy@redhat.com> - 1.19.2-5
- Fix libkrad client cleanup
- Fixes rhbz#2072059
* Tue Apr 05 2022 Alexander Bokovoy <abokovoy@redhat.com> - 1.19.2-4
- Allow use of larger RADIUS attributes in krad library
* Wed Mar 23 2022 Julien Rische <jrische@redhat.com> - 1.19.2-3
- Use SHA-256 instead of SHA-1 for PKINIT CMS digest
* Thu Aug 19 2021 Robbie Harwood <rharwood@redhat.com> - 1.19.2-2
- Fix KDC null deref on TGS inner body null server (CVE-2021-37750)
* Mon Jul 26 2021 Robbie Harwood <rharwood@redhat.com> - 1.19.2-1
- New upstream version (1.19.2)
* Wed Jul 21 2021 Robbie Harwood <rharwood@redhat.com> - 1.19.1-15
- Fix defcred leak in krb5 gss_inquire_cred()
* Mon Jul 12 2021 Robbie Harwood <rharwood@redhat.com> - 1.19.1-14
- Fix KDC null deref on bad encrypted challenge (CVE-2021-36222)
* Thu Jul 01 2021 Robbie Harwood <rharwood@redhat.com> - 1.19.1-13
- Fix use-after-free during krad remote_shutdown()
* Mon Jun 28 2021 Robbie Harwood <rharwood@redhat.com> - 1.19.1-12
- MEMORY locking fix and static analysis pullup
* Mon Jun 21 2021 Robbie Harwood <rharwood@redhat.com> - 1.19.1-11
- Add the backward-compatible parts of openssl3 support
* Wed Jun 09 2021 Robbie Harwood <rharwood@redhat.com> - 1.19.1-10
- Fix three canonicalization cases for fallback
* Wed Jun 02 2021 Robbie Harwood <rharwood@redhat.com> - 1.19.1-9
- Fix doc build for Sphinx 4.0
* Thu May 20 2021 Robbie Harwood <rharwood@redhat.com> - 1.19.1-8
- Add all the sssd-kcm workarounds
* Thu May 20 2021 Robbie Harwood <rharwood@redhat.com> - 1.19.1-7
- Fix context for previous backport
* Thu May 20 2021 Robbie Harwood <rharwood@redhat.com> - 1.19.1-6
- Add KCM_OP_GET_CRED_LIST and KCM_OP_RETRIEVE support
* Tue May 04 2021 Robbie Harwood <rharwood@redhat.com> - 1.19.1-5
- Suppress static analyzer warning in FIPS override
* Tue Mar 02 2021 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 1.19.1-3.1
- Rebuilt for updated systemd-rpm-macros
See https://pagure.io/fesco/issue/2583.

17
rpminspect.yaml Normal file
View file

@ -0,0 +1,17 @@
---
inspections:
# https://bugzilla.redhat.com/show_bug.cgi?id=1956479
badfuncs: off
# Not a Java package
javabytecode: off
# I need to be able to *add* functions, and also we export internal
# functions that are not considered part of our ABI.
abidiff: off
# These just flag when things change "too much"
changedfiles: off
filesize: off
patches: off
upstream: off

View file

@ -1,2 +1,2 @@
SHA512 (krb5-1.19.1.tar.gz) = 36bf33802119ada4650a8f69f1daca95aaf882dc96bfa7061f0340a5decd588c31fc10108ddadf1042934e0e2c3bbd975deec565b0a7f0fc2baf8b8cc6d97491
SHA512 (krb5-1.19.1.tar.gz.asc) = 078924730ce441630b4ac553a76ba0ebacb09b67dd057a53e3cf42185dd80bf423e875bddd306e4e91873797a9c013a7b0cae66134976abdea2c9752028e66c7
SHA512 (krb5-1.19.2.tar.gz) = b90d6ed0e1e8a87eb5cb2c36d88b823a6a6caabf85e5d419adb8a930f7eea09a5f8491464e7e454cca7ba88be09d19415962fe0036ad2e31fc584f9fc0bbd470
SHA512 (krb5-1.19.2.tar.gz.asc) = 87c4d096dbb6821401125b8f8a315ce1aac029744ba9670a4f8a2a680e6dd5798e1c6d5d2b68b17fd9a4b3b9c6ff111cd1dcac42f934d48fb20381b3765e0f64