Merged update from upstream sources

This is an automated DistroBaker update from upstream sources.
If you do not know what this is about or would like to opt out,
contact the OSCI team.

Source: https://src.fedoraproject.org/rpms/krb5.git#bfdc7c0b7be1f33f451a173fb1155450fbe25690
This commit is contained in:
DistroBaker 2020-10-27 21:13:14 +01:00 committed by Petr Šabata
parent 908aeb56b2
commit 2c0634c50d
10 changed files with 1935 additions and 2 deletions

View File

@ -0,0 +1,404 @@
From 538d787aa7c10894cc0426f54db0d8248efcf7c9 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Wed, 17 Jun 2020 20:48:38 -0400
Subject: [PATCH] Add three kvno options from Heimdal kgetcred
Add the flags --cached-only and --no-store, which pass the
corresponding options to krb5_get_credentials(). Add the option
--out-cache to write the retrieved credentials to a specified output
cache.
Add a Python test script for kvno command-line options, including
tests for the new options.
ticket: 8917 (new)
(cherry picked from commit 876bab8418d7dd134c9d9db812ee2118d5ad58f0)
---
doc/user/user_commands/kvno.rst | 13 ++++
src/clients/kvno/Makefile.in | 3 +
src/clients/kvno/kvno.c | 115 +++++++++++++++++++++++---------
src/clients/kvno/t_kvno.py | 75 +++++++++++++++++++++
src/man/kvno.man | 13 ++++
5 files changed, 187 insertions(+), 32 deletions(-)
create mode 100644 src/clients/kvno/t_kvno.py
diff --git a/doc/user/user_commands/kvno.rst b/doc/user/user_commands/kvno.rst
index 3892f0ca5..718313576 100644
--- a/doc/user/user_commands/kvno.rst
+++ b/doc/user/user_commands/kvno.rst
@@ -74,6 +74,19 @@ OPTIONS
client principal with the X.509 certificate in *cert_file*. The
certificate file must be in PEM format.
+**--cached-only**
+ Only retrieve credentials already present in the cache, not from
+ the KDC.
+
+**--no-store**
+ Do not store retrieved credentials in the cache. If
+ **--out-cache** is also specified, credentials will still be
+ stored into the output credential cache.
+
+**--out-cache** *ccache*
+ Initialize *ccache* and store all retrieved credentials into it.
+ Do not store acquired credentials in the input cache.
+
**--u2u** *ccache*
Requests a user-to-user ticket. *ccache* must contain a local
krbtgt ticket for the server principal. The reported version
diff --git a/src/clients/kvno/Makefile.in b/src/clients/kvno/Makefile.in
index 1c3f79392..5ba877271 100644
--- a/src/clients/kvno/Makefile.in
+++ b/src/clients/kvno/Makefile.in
@@ -26,6 +26,9 @@ kvno: kvno.o $(KRB5_BASE_DEPLIBS)
##WIN32## link $(EXE_LINKOPTS) /out:$@ $**
##WIN32## $(_VC_MANIFEST_EMBED_EXE)
+check-pytests: kvno
+ $(RUNPYTEST) $(srcdir)/t_kvno.py $(PYTESTFLAGS)
+
clean-unix::
$(RM) kvno.o kvno
diff --git a/src/clients/kvno/kvno.c b/src/clients/kvno/kvno.c
index 2472c0cfe..9d85864f6 100644
--- a/src/clients/kvno/kvno.c
+++ b/src/clients/kvno/kvno.c
@@ -44,14 +44,17 @@ xusage()
fprintf(stderr, _("usage: %s [-C] [-u] [-c ccache] [-e etype]\n"), prog);
fprintf(stderr, _("\t[-k keytab] [-S sname] [{-I | -U} for_user | "
"[-F cert_file] [-P]]\n"));
- fprintf(stderr, _("\t[--u2u ccache] service1 service2 ...\n"));
+ fprintf(stderr, _("\t[--cached-only] [--no-store] [--out-cache ccache] "
+ "[--u2u ccache]\n"));
+ fprintf(stderr, _("\tservice1 service2 ...\n"));
exit(1);
}
static void do_v5_kvno(int argc, char *argv[], char *ccachestr, char *etypestr,
- char *keytab_name, char *sname, int canon, int unknown,
- char *for_user, int for_user_enterprise,
- char *for_user_cert_file, int proxy,
+ char *keytab_name, char *sname, int cached_only,
+ int canon, int no_store, int unknown, char *for_user,
+ int for_user_enterprise, char *for_user_cert_file,
+ int proxy, const char *out_ccname,
const char *u2u_ccname);
#include <com_err.h>
@@ -61,18 +64,21 @@ static void extended_com_err_fn(const char *myprog, errcode_t code,
int
main(int argc, char *argv[])
{
- enum { OPTION_U2U = 256 };
- struct option lopts[] = {
- { "u2u", 1, NULL, OPTION_U2U },
- { NULL, 0, NULL, 0 }
- };
+ enum { OPTION_U2U = 256, OPTION_OUT_CACHE = 257 };
const char *shopts = "uCc:e:hk:qPS:I:U:F:";
int option;
char *etypestr = NULL, *ccachestr = NULL, *keytab_name = NULL;
char *sname = NULL, *for_user = NULL, *u2u_ccname = NULL;
- char *for_user_cert_file = NULL;
+ char *for_user_cert_file = NULL, *out_ccname = NULL;
int canon = 0, unknown = 0, proxy = 0, for_user_enterprise = 0;
- int impersonate = 0;
+ int impersonate = 0, cached_only = 0, no_store = 0;
+ struct option lopts[] = {
+ { "cached-only", 0, &cached_only, 1 },
+ { "no-store", 0, &no_store, 1 },
+ { "out-cache", 1, NULL, OPTION_OUT_CACHE },
+ { "u2u", 1, NULL, OPTION_U2U },
+ { NULL, 0, NULL, 0 }
+ };
setlocale(LC_ALL, "");
set_com_err_hook(extended_com_err_fn);
@@ -135,6 +141,12 @@ main(int argc, char *argv[])
case OPTION_U2U:
u2u_ccname = optarg;
break;
+ case OPTION_OUT_CACHE:
+ out_ccname = optarg;
+ break;
+ case 0:
+ /* If this option set a flag, do nothing else now. */
+ break;
default:
xusage();
break;
@@ -159,8 +171,9 @@ main(int argc, char *argv[])
xusage();
do_v5_kvno(argc - optind, argv + optind, ccachestr, etypestr, keytab_name,
- sname, canon, unknown, for_user, for_user_enterprise,
- for_user_cert_file, proxy, u2u_ccname);
+ sname, cached_only, canon, no_store, unknown, for_user,
+ for_user_enterprise, for_user_cert_file, proxy, out_ccname,
+ u2u_ccname);
return 0;
}
@@ -274,14 +287,16 @@ static krb5_error_code
kvno(const char *name, krb5_ccache ccache, krb5_principal me,
krb5_enctype etype, krb5_keytab keytab, const char *sname,
krb5_flags options, int unknown, krb5_principal for_user_princ,
- krb5_data *for_user_cert, int proxy, krb5_data *u2u_ticket)
+ krb5_data *for_user_cert, int proxy, krb5_data *u2u_ticket,
+ krb5_creds **creds_out)
{
krb5_error_code ret;
krb5_principal server = NULL;
krb5_ticket *ticket = NULL;
- krb5_creds in_creds, *out_creds = NULL;
+ krb5_creds in_creds, *creds = NULL;
char *princ = NULL;
+ *creds_out = NULL;
memset(&in_creds, 0, sizeof(in_creds));
if (sname != NULL) {
@@ -321,13 +336,12 @@ kvno(const char *name, krb5_ccache ccache, krb5_principal me,
in_creds.client = for_user_princ;
in_creds.server = me;
ret = krb5_get_credentials_for_user(context, options, ccache,
- &in_creds, for_user_cert,
- &out_creds);
+ &in_creds, for_user_cert, &creds);
} else {
in_creds.client = me;
in_creds.server = server;
ret = krb5_get_credentials(context, options, ccache, &in_creds,
- &out_creds);
+ &creds);
}
if (ret) {
@@ -336,7 +350,7 @@ kvno(const char *name, krb5_ccache ccache, krb5_principal me,
}
/* We need a native ticket. */
- ret = krb5_decode_ticket(&out_creds->ticket, &ticket);
+ ret = krb5_decode_ticket(&creds->ticket, &ticket);
if (ret) {
com_err(prog, ret, _("while decoding ticket for %s"), princ);
goto cleanup;
@@ -362,15 +376,15 @@ kvno(const char *name, krb5_ccache ccache, krb5_principal me,
}
if (proxy) {
- in_creds.client = out_creds->client;
- out_creds->client = NULL;
- krb5_free_creds(context, out_creds);
- out_creds = NULL;
+ in_creds.client = creds->client;
+ creds->client = NULL;
+ krb5_free_creds(context, creds);
+ creds = NULL;
in_creds.server = server;
ret = krb5_get_credentials_for_proxy(context, KRB5_GC_CANONICALIZE,
ccache, &in_creds, ticket,
- &out_creds);
+ &creds);
krb5_free_principal(context, in_creds.client);
if (ret) {
com_err(prog, ret, _("%s: constrained delegation failed"),
@@ -379,10 +393,13 @@ kvno(const char *name, krb5_ccache ccache, krb5_principal me,
}
}
+ *creds_out = creds;
+ creds = NULL;
+
cleanup:
krb5_free_principal(context, server);
krb5_free_ticket(context, ticket);
- krb5_free_creds(context, out_creds);
+ krb5_free_creds(context, creds);
krb5_free_unparsed_name(context, princ);
return ret;
}
@@ -428,19 +445,28 @@ cleanup:
static void
do_v5_kvno(int count, char *names[], char * ccachestr, char *etypestr,
- char *keytab_name, char *sname, int canon, int unknown,
- char *for_user, int for_user_enterprise,
- char *for_user_cert_file, int proxy, const char *u2u_ccname)
+ char *keytab_name, char *sname, int cached_only, int canon,
+ int no_store, int unknown, char *for_user, int for_user_enterprise,
+ char *for_user_cert_file, int proxy, const char *out_ccname,
+ const char *u2u_ccname)
{
krb5_error_code ret;
- int i, errors, flags;
+ int i, errors, flags, initialized = 0;
krb5_enctype etype;
- krb5_ccache ccache;
+ krb5_ccache ccache, out_ccache = NULL;
krb5_principal me;
krb5_keytab keytab = NULL;
krb5_principal for_user_princ = NULL;
- krb5_flags options = canon ? KRB5_GC_CANONICALIZE : 0;
+ krb5_flags options = 0;
krb5_data cert_data = empty_data(), *user_cert = NULL, *u2u_ticket = NULL;
+ krb5_creds *creds;
+
+ if (canon)
+ options |= KRB5_GC_CANONICALIZE;
+ if (cached_only)
+ options |= KRB5_GC_CACHED;
+ if (no_store || out_ccname != NULL)
+ options |= KRB5_GC_NO_STORE;
ret = krb5_init_context(&context);
if (ret) {
@@ -467,6 +493,14 @@ do_v5_kvno(int count, char *names[], char * ccachestr, char *etypestr,
exit(1);
}
+ if (out_ccname != NULL) {
+ ret = krb5_cc_resolve(context, out_ccname, &out_ccache);
+ if (ret) {
+ com_err(prog, ret, _("while resolving output ccache"));
+ exit(1);
+ }
+ }
+
if (keytab_name != NULL) {
ret = krb5_kt_resolve(context, keytab_name, &keytab);
if (ret) {
@@ -513,8 +547,25 @@ do_v5_kvno(int count, char *names[], char * ccachestr, char *etypestr,
errors = 0;
for (i = 0; i < count; i++) {
if (kvno(names[i], ccache, me, etype, keytab, sname, options, unknown,
- for_user_princ, user_cert, proxy, u2u_ticket) != 0)
+ for_user_princ, user_cert, proxy, u2u_ticket, &creds) != 0) {
errors++;
+ } else if (out_ccache != NULL) {
+ if (!initialized) {
+ ret = krb5_cc_initialize(context, out_ccache, creds->client);
+ if (ret) {
+ com_err(prog, ret, _("while initializing output ccache"));
+ exit(1);
+ }
+ initialized = 1;
+ }
+ ret = krb5_cc_store_cred(context, out_ccache, creds);
+ if (ret) {
+ com_err(prog, ret, _("while storing creds in output ccache"));
+ exit(1);
+ }
+ }
+
+ krb5_free_creds(context, creds);
}
if (keytab != NULL)
diff --git a/src/clients/kvno/t_kvno.py b/src/clients/kvno/t_kvno.py
new file mode 100644
index 000000000..e98b90e8a
--- /dev/null
+++ b/src/clients/kvno/t_kvno.py
@@ -0,0 +1,75 @@
+from k5test import *
+
+realm = K5Realm()
+
+def check_cache(ccache, expected_services):
+ # Fetch the klist output and skip past the header.
+ lines = realm.run([klist, '-c', ccache]).splitlines()
+ lines = lines[4:]
+
+ # For each line not beginning with an indent, match against the
+ # expected service principals.
+ svcs = {x: True for x in expected_services}
+ for l in lines:
+ if not l.startswith('\t'):
+ svcprinc = l.split()[4]
+ if svcprinc in svcs:
+ del svcs[svcprinc]
+ else:
+ fail('unexpected service princ ' + svcprinc)
+
+ if svcs:
+ fail('services not found in klist output: ' + ' '.join(svcs.keys()))
+
+
+mark('no options')
+realm.run([kvno, realm.user_princ], expected_msg='user@KRBTEST.COM: kvno = 1')
+check_cache(realm.ccache, [realm.krbtgt_princ, realm.user_princ])
+
+mark('-e')
+msgs = ('etypes requested in TGS request: camellia128-cts',
+ '/KDC has no support for encryption type')
+realm.run([kvno, '-e', 'camellia128-cts', realm.host_princ],
+ expected_code=1, expected_trace=msgs)
+
+mark('--cached-only')
+realm.run([kvno, '--cached-only', realm.user_princ], expected_msg='kvno = 1')
+realm.run([kvno, '--cached-only', realm.host_princ],
+ expected_code=1, expected_msg='Matching credential not found')
+check_cache(realm.ccache, [realm.krbtgt_princ, realm.user_princ])
+
+mark('--no-store')
+realm.run([kvno, '--no-store', realm.host_princ], expected_msg='kvno = 1')
+check_cache(realm.ccache, [realm.krbtgt_princ, realm.user_princ])
+
+mark('--out-cache') # and multiple services
+out_ccache = os.path.join(realm.testdir, 'ccache.out')
+realm.run([kvno, '--out-cache', out_ccache,
+ realm.host_princ, realm.admin_princ])
+check_cache(realm.ccache, [realm.krbtgt_princ, realm.user_princ])
+check_cache(out_ccache, [realm.host_princ, realm.admin_princ])
+
+mark('--out-cache --cached-only') # tests out-cache overwriting, and -q
+realm.run([kvno, '--out-cache', out_ccache, '--cached-only', realm.host_princ],
+ expected_code=1, expected_msg='Matching credential not found')
+out = realm.run([kvno, '-q', '--out-cache', out_ccache, '--cached-only',
+ realm.user_princ])
+if out:
+ fail('unexpected kvno output with -q')
+check_cache(out_ccache, [realm.user_princ])
+
+mark('-U') # and -c
+svc_ccache = os.path.join(realm.testdir, 'ccache.svc')
+realm.run([kinit, '-k', '-c', svc_ccache, realm.host_princ])
+realm.run([kvno, '-c', svc_ccache, '-U', 'user', realm.host_princ])
+realm.run([klist, '-c', svc_ccache], expected_msg='for client user@')
+realm.run([kvno, '-c', svc_ccache, '-U', 'user', '--out-cache', out_ccache,
+ realm.host_princ])
+out = realm.run([klist, '-c', out_ccache])
+if ('Default principal: user@KRBTEST.COM' not in out):
+ fail('wrong default principal in klist output')
+
+# More S4U options are tested in tests/gssapi/t_s4u.py.
+# --u2u is tested in tests/t_u2u.py.
+
+success('kvno tests')
diff --git a/src/man/kvno.man b/src/man/kvno.man
index 005a2ec97..b9f6739eb 100644
--- a/src/man/kvno.man
+++ b/src/man/kvno.man
@@ -95,6 +95,19 @@ Specifies that protocol transition is to be used, identifying the
client principal with the X.509 certificate in \fIcert_file\fP\&. The
certificate file must be in PEM format.
.TP
+\fB\-\-cached\-only\fP
+Only retrieve credentials already present in the cache, not from
+the KDC.
+.TP
+\fB\-\-no\-store\fP
+Do not store retrieved credentials in the cache. If
+\fB\-\-out\-cache\fP is also specified, credentials will still be
+stored into the output credential cache.
+.TP
+\fB\-\-out\-cache\fP \fIccache\fP
+Initialize \fIccache\fP and store all retrieved credentials into it.
+Do not store acquired credentials in the input cache.
+.TP
\fB\-\-u2u\fP \fIccache\fP
Requests a user\-to\-user ticket. \fIccache\fP must contain a local
krbtgt ticket for the server principal. The reported version

View File

@ -0,0 +1,80 @@
From 758f5031fe9d6c1e3eb33818bc6d57cf8b4a3a72 Mon Sep 17 00:00:00 2001
From: Isaac Boukris <iboukris@gmail.com>
Date: Tue, 22 Sep 2020 01:11:39 +0300
Subject: [PATCH] Adjust KDC alias helper function contract
Change the name of is_client_alias() to is_client_db_alias(), and
change the contract so that the already-canonical principal name comes
from a DB entry (which is less flexible, but clearer since DB entries
always contain canonical principal names). Make the function
available outside of kdc_util.c.
[ghudson@mit.edu: clarified commit message]
(cherry picked from commit 9fb5f572dd6ce808b234cb60a573eac48136d7ca)
---
src/kdc/kdc_util.c | 14 +++++++-------
src/kdc/kdc_util.h | 4 ++++
2 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
index dcb2df8dc..6330387d0 100644
--- a/src/kdc/kdc_util.c
+++ b/src/kdc/kdc_util.c
@@ -1463,10 +1463,10 @@ cleanup:
return code;
}
-/* Return true if princ canonicalizes to the same principal as canon. */
-static krb5_boolean
-is_client_alias(krb5_context context, krb5_const_principal canon,
- krb5_const_principal princ)
+/* Return true if princ canonicalizes to the same principal as entry's. */
+krb5_boolean
+is_client_db_alias(krb5_context context, const krb5_db_entry *entry,
+ krb5_const_principal princ)
{
krb5_error_code ret;
krb5_db_entry *self;
@@ -1475,7 +1475,7 @@ is_client_alias(krb5_context context, krb5_const_principal canon,
ret = krb5_db_get_principal(context, princ,
KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY, &self);
if (!ret) {
- is_self = krb5_principal_compare(context, canon, self->princ);
+ is_self = krb5_principal_compare(context, entry->princ, self->princ);
krb5_db_free_principal(context, self);
}
@@ -1535,7 +1535,7 @@ kdc_process_s4u2self_req(kdc_realm_t *kdc_active_realm,
/* If the server is local, check that the request is for self. */
if (!isflagset(c_flags, KRB5_KDB_FLAG_ISSUING_REFERRAL) &&
- !is_client_alias(kdc_context, server->princ, client_princ)) {
+ !is_client_db_alias(kdc_context, server, client_princ)) {
*status = "INVALID_S4U2SELF_REQUEST_SERVER_MISMATCH";
return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; /* match Windows error */
}
@@ -1728,7 +1728,7 @@ kdc_process_s4u2proxy_req(kdc_realm_t *kdc_active_realm, unsigned int flags,
}
client_princ = *stkt_authdata_client;
- } else if (!is_client_alias(kdc_context, server->princ, server_princ)) {
+ } else if (!is_client_db_alias(kdc_context, server, server_princ)) {
*status = "EVIDENCE_TICKET_MISMATCH";
return KRB5KDC_ERR_SERVER_NOMATCH;
}
diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h
index 384b21ad2..2c9d8cf69 100644
--- a/src/kdc/kdc_util.h
+++ b/src/kdc/kdc_util.h
@@ -344,6 +344,10 @@ log_tgs_badtrans(krb5_context ctx, krb5_principal cprinc,
void
log_tgs_alt_tgt(krb5_context context, krb5_principal p);
+krb5_boolean
+is_client_db_alias(krb5_context context, const krb5_db_entry *entry,
+ krb5_const_principal princ);
+
/* FAST*/
enum krb5_fast_kdc_flags {
KRB5_FAST_REPLY_KEY_USED = 0x1,

View File

@ -0,0 +1,65 @@
From ccc5b9663e229f20421c01836aa5ecb06f1f2a48 Mon Sep 17 00:00:00 2001
From: Isaac Boukris <iboukris@gmail.com>
Date: Tue, 22 Sep 2020 01:17:11 +0300
Subject: [PATCH] Allow aliases when matching U2U second ticket
In process_tgs_req() when verifying the user-to-user second ticket,
compare the canonical names of the request server and the second
ticket client.
[ghudson@mit.edu: expanded commit message; trimmed tests]
ticket: 8951 (new)
(cherry picked from commit afc494ef9418e6be7fbb887364efa6606b10034a)
---
src/kdc/do_tgs_req.c | 2 +-
src/tests/t_u2u.py | 25 +++++++++++++++++++++++++
2 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c
index 463a9c0dd..74cd19e96 100644
--- a/src/kdc/do_tgs_req.c
+++ b/src/kdc/do_tgs_req.c
@@ -666,7 +666,7 @@ process_tgs_req(krb5_kdc_req *request, krb5_data *pkt,
*/
krb5_enc_tkt_part *t2enc = request->second_ticket[st_idx]->enc_part2;
krb5_principal client2 = t2enc->client;
- if (!krb5_principal_compare(kdc_context, request->server, client2)) {
+ if (!is_client_db_alias(kdc_context, server, client2)) {
altcprinc = client2;
errcode = KRB5KDC_ERR_SERVER_NOMATCH;
status = "2ND_TKT_MISMATCH";
diff --git a/src/tests/t_u2u.py b/src/tests/t_u2u.py
index 1ca6ac87e..4b8a82a2f 100644
--- a/src/tests/t_u2u.py
+++ b/src/tests/t_u2u.py
@@ -32,4 +32,29 @@ realm.run([kvno, '--u2u', realm.ccache, realm.user_princ])
realm.run([klist])
+realm.stop()
+
+# Load the test KDB module to test aliases
+testprincs = {'krbtgt/KRBTEST.COM': {'keys': 'aes128-cts'},
+ 'user': {'keys': 'aes128-cts', 'flags': '+preauth'},
+ 'WIN10': {'keys': 'aes128-cts'}}
+kdcconf = {'realms': {'$realm': {'database_module': 'test'}},
+ 'dbmodules': {'test': {'db_library': 'test',
+ 'princs': testprincs,
+ 'alias': {'HOST/win10': 'WIN10'}}}}
+
+realm = K5Realm(kdc_conf=kdcconf, create_kdb=False)
+realm.start_kdc()
+
+# Create a second user principal and get tickets for it.
+u2u_ccache = 'FILE:' + os.path.join(realm.testdir, 'ccu2u')
+realm.extract_keytab('WIN10', realm.keytab)
+realm.kinit('WIN10', None, ['-k', '-c', u2u_ccache])
+
+realm.extract_keytab(realm.user_princ, realm.keytab)
+realm.kinit(realm.user_princ, None, ['-k'])
+
+realm.run([kvno, '--u2u', u2u_ccache, 'HOST/win10'], expected_msg='kvno = 0')
+realm.run([kvno, '--u2u', u2u_ccache, 'WIN10'], expected_msg='kvno = 0')
+
success('user-to-user tests')

View File

@ -0,0 +1,298 @@
From dd8b146093d4bdf8a7d0c0eb8156b62d090448d7 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Wed, 30 Sep 2020 02:12:00 -0400
Subject: [PATCH] Avoid passing DB entry structures in KDC
When validating AS or TGS requests, pass pointers to DB entry
structures, not the structures themselves.
(cherry picked from commit 7ccc08a889b40693b2ce7f108f2cdda51bc04bff)
---
src/kdc/do_as_req.c | 4 ++--
src/kdc/do_tgs_req.c | 2 +-
src/kdc/kdc_util.c | 34 +++++++++++++++++-----------------
src/kdc/kdc_util.h | 6 +++---
src/kdc/tgs_policy.c | 35 ++++++++++++++++++-----------------
5 files changed, 41 insertions(+), 40 deletions(-)
diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c
index 9ae7b0a5e..c2dfea9b8 100644
--- a/src/kdc/do_as_req.c
+++ b/src/kdc/do_as_req.c
@@ -663,8 +663,8 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
au_state->stage = VALIDATE_POL;
if ((errcode = validate_as_request(kdc_active_realm,
- state->request, *state->client,
- *state->server, state->kdc_time,
+ state->request, state->client,
+ state->server, state->kdc_time,
&state->status, &state->e_data))) {
errcode += ERROR_TABLE_BASE_krb5;
goto errout;
diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c
index 74cd19e96..d345797c4 100644
--- a/src/kdc/do_tgs_req.c
+++ b/src/kdc/do_tgs_req.c
@@ -260,7 +260,7 @@ process_tgs_req(krb5_kdc_req *request, krb5_data *pkt,
goto cleanup;
if ((retval = validate_tgs_request(kdc_active_realm,
- request, *server, header_ticket,
+ request, server, header_ticket,
kdc_time, &status, &e_data))) {
if (retval == KDC_ERR_POLICY || retval == KDC_ERR_BADOPTION)
au_state->violation = PROT_CONSTRAINT;
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
index a4a05b9fa..b2042862a 100644
--- a/src/kdc/kdc_util.c
+++ b/src/kdc/kdc_util.c
@@ -612,8 +612,8 @@ check_anon(kdc_realm_t *kdc_active_realm,
KDC_OPT_ENC_TKT_IN_SKEY | KDC_OPT_CNAME_IN_ADDL_TKT)
int
validate_as_request(kdc_realm_t *kdc_active_realm,
- krb5_kdc_req *request, krb5_db_entry client,
- krb5_db_entry server, krb5_timestamp kdc_time,
+ krb5_kdc_req *request, krb5_db_entry *client,
+ krb5_db_entry *server, krb5_timestamp kdc_time,
const char **status, krb5_pa_data ***e_data)
{
krb5_error_code ret;
@@ -627,7 +627,7 @@ validate_as_request(kdc_realm_t *kdc_active_realm,
}
/* The client must not be expired */
- if (client.expiration && ts_after(kdc_time, client.expiration)) {
+ if (client->expiration && ts_after(kdc_time, client->expiration)) {
*status = "CLIENT EXPIRED";
if (vague_errors)
return(KRB_ERR_GENERIC);
@@ -637,8 +637,8 @@ validate_as_request(kdc_realm_t *kdc_active_realm,
/* The client's password must not be expired, unless the server is
a KRB5_KDC_PWCHANGE_SERVICE. */
- if (client.pw_expiration && ts_after(kdc_time, client.pw_expiration) &&
- !isflagset(server.attributes, KRB5_KDB_PWCHANGE_SERVICE)) {
+ if (client->pw_expiration && ts_after(kdc_time, client->pw_expiration) &&
+ !isflagset(server->attributes, KRB5_KDB_PWCHANGE_SERVICE)) {
*status = "CLIENT KEY EXPIRED";
if (vague_errors)
return(KRB_ERR_GENERIC);
@@ -647,7 +647,7 @@ validate_as_request(kdc_realm_t *kdc_active_realm,
}
/* The server must not be expired */
- if (server.expiration && ts_after(kdc_time, server.expiration)) {
+ if (server->expiration && ts_after(kdc_time, server->expiration)) {
*status = "SERVICE EXPIRED";
return(KDC_ERR_SERVICE_EXP);
}
@@ -656,8 +656,8 @@ validate_as_request(kdc_realm_t *kdc_active_realm,
* If the client requires password changing, then only allow the
* pwchange service.
*/
- if (isflagset(client.attributes, KRB5_KDB_REQUIRES_PWCHANGE) &&
- !isflagset(server.attributes, KRB5_KDB_PWCHANGE_SERVICE)) {
+ if (isflagset(client->attributes, KRB5_KDB_REQUIRES_PWCHANGE) &&
+ !isflagset(server->attributes, KRB5_KDB_PWCHANGE_SERVICE)) {
*status = "REQUIRED PWCHANGE";
return(KDC_ERR_KEY_EXP);
}
@@ -665,37 +665,37 @@ validate_as_request(kdc_realm_t *kdc_active_realm,
/* Client and server must allow postdating tickets */
if ((isflagset(request->kdc_options, KDC_OPT_ALLOW_POSTDATE) ||
isflagset(request->kdc_options, KDC_OPT_POSTDATED)) &&
- (isflagset(client.attributes, KRB5_KDB_DISALLOW_POSTDATED) ||
- isflagset(server.attributes, KRB5_KDB_DISALLOW_POSTDATED))) {
+ (isflagset(client->attributes, KRB5_KDB_DISALLOW_POSTDATED) ||
+ isflagset(server->attributes, KRB5_KDB_DISALLOW_POSTDATED))) {
*status = "POSTDATE NOT ALLOWED";
return(KDC_ERR_CANNOT_POSTDATE);
}
/* Check to see if client is locked out */
- if (isflagset(client.attributes, KRB5_KDB_DISALLOW_ALL_TIX)) {
+ if (isflagset(client->attributes, KRB5_KDB_DISALLOW_ALL_TIX)) {
*status = "CLIENT LOCKED OUT";
return(KDC_ERR_CLIENT_REVOKED);
}
/* Check to see if server is locked out */
- if (isflagset(server.attributes, KRB5_KDB_DISALLOW_ALL_TIX)) {
+ if (isflagset(server->attributes, KRB5_KDB_DISALLOW_ALL_TIX)) {
*status = "SERVICE LOCKED OUT";
return(KDC_ERR_S_PRINCIPAL_UNKNOWN);
}
/* Check to see if server is allowed to be a service */
- if (isflagset(server.attributes, KRB5_KDB_DISALLOW_SVR)) {
+ if (isflagset(server->attributes, KRB5_KDB_DISALLOW_SVR)) {
*status = "SERVICE NOT ALLOWED";
return(KDC_ERR_MUST_USE_USER2USER);
}
- if (check_anon(kdc_active_realm, client.princ, request->server) != 0) {
+ if (check_anon(kdc_active_realm, client->princ, request->server) != 0) {
*status = "ANONYMOUS NOT ALLOWED";
return(KDC_ERR_POLICY);
}
/* Perform KDB module policy checks. */
- ret = krb5_db_check_policy_as(kdc_context, request, &client, &server,
+ ret = krb5_db_check_policy_as(kdc_context, request, client, server,
kdc_time, status, e_data);
if (ret && ret != KRB5_PLUGIN_OP_NOTSUPP)
return errcode_to_protocol(ret);
@@ -1568,8 +1568,8 @@ kdc_process_s4u2self_req(kdc_realm_t *kdc_active_realm,
princ->pw_expiration = 0;
clear(princ->attributes, KRB5_KDB_REQUIRES_PWCHANGE);
- code = validate_as_request(kdc_active_realm, request, *princ,
- no_server, kdc_time, status, &e_data);
+ code = validate_as_request(kdc_active_realm, request, princ,
+ &no_server, kdc_time, status, &e_data);
if (code) {
krb5_db_free_principal(kdc_context, princ);
krb5_free_pa_data(kdc_context, e_data);
diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h
index 42b7ee208..04007a8f5 100644
--- a/src/kdc/kdc_util.h
+++ b/src/kdc/kdc_util.h
@@ -76,12 +76,12 @@ get_local_tgt(krb5_context context, const krb5_data *realm,
krb5_db_entry **storage_out, krb5_keyblock *kb_out);
int
-validate_as_request (kdc_realm_t *, krb5_kdc_req *, krb5_db_entry,
- krb5_db_entry, krb5_timestamp,
+validate_as_request (kdc_realm_t *, krb5_kdc_req *, krb5_db_entry *,
+ krb5_db_entry *, krb5_timestamp,
const char **, krb5_pa_data ***);
int
-validate_tgs_request (kdc_realm_t *, krb5_kdc_req *, krb5_db_entry,
+validate_tgs_request (kdc_realm_t *, krb5_kdc_req *, krb5_db_entry *,
krb5_ticket *, krb5_timestamp,
const char **, krb5_pa_data ***);
diff --git a/src/kdc/tgs_policy.c b/src/kdc/tgs_policy.c
index 554345ba5..3f4fa8499 100644
--- a/src/kdc/tgs_policy.c
+++ b/src/kdc/tgs_policy.c
@@ -48,7 +48,7 @@ struct tgsflagrule {
};
/* Service principal TGS policy checking functions */
-typedef int (check_tgs_svc_pol_fn)(krb5_kdc_req *, krb5_db_entry,
+typedef int (check_tgs_svc_pol_fn)(krb5_kdc_req *, krb5_db_entry *,
krb5_ticket *, krb5_timestamp,
const char **);
@@ -110,7 +110,7 @@ static const struct tgsflagrule svcdenyrules[] = {
* A service principal can forbid some TGS-REQ options.
*/
static int
-check_tgs_svc_deny_opts(krb5_kdc_req *req, krb5_db_entry server,
+check_tgs_svc_deny_opts(krb5_kdc_req *req, krb5_db_entry *server,
krb5_ticket *tkt, krb5_timestamp kdc_time,
const char **status)
{
@@ -122,7 +122,7 @@ check_tgs_svc_deny_opts(krb5_kdc_req *req, krb5_db_entry server,
r = &svcdenyrules[i];
if (!(r->reqflags & req->kdc_options))
continue;
- if (r->checkflag & server.attributes) {
+ if (r->checkflag & server->attributes) {
*status = r->status;
return r->err;
}
@@ -134,20 +134,20 @@ check_tgs_svc_deny_opts(krb5_kdc_req *req, krb5_db_entry server,
* A service principal can deny all TGS-REQs for it.
*/
static int
-check_tgs_svc_deny_all(krb5_kdc_req *req, krb5_db_entry server,
+check_tgs_svc_deny_all(krb5_kdc_req *req, krb5_db_entry *server,
krb5_ticket *tkt, krb5_timestamp kdc_time,
const char **status)
{
- if (server.attributes & KRB5_KDB_DISALLOW_ALL_TIX) {
+ if (server->attributes & KRB5_KDB_DISALLOW_ALL_TIX) {
*status = "SERVER LOCKED OUT";
return KDC_ERR_S_PRINCIPAL_UNKNOWN;
}
- if ((server.attributes & KRB5_KDB_DISALLOW_SVR) &&
+ if ((server->attributes & KRB5_KDB_DISALLOW_SVR) &&
!(req->kdc_options & KDC_OPT_ENC_TKT_IN_SKEY)) {
*status = "SERVER NOT ALLOWED";
return KDC_ERR_MUST_USE_USER2USER;
}
- if (server.attributes & KRB5_KDB_DISALLOW_TGT_BASED) {
+ if (server->attributes & KRB5_KDB_DISALLOW_TGT_BASED) {
if (krb5_is_tgs_principal(tkt->server)) {
*status = "TGT BASED NOT ALLOWED";
return KDC_ERR_POLICY;
@@ -160,17 +160,17 @@ check_tgs_svc_deny_all(krb5_kdc_req *req, krb5_db_entry server,
* A service principal can require certain TGT flags.
*/
static int
-check_tgs_svc_reqd_flags(krb5_kdc_req *req, krb5_db_entry server,
+check_tgs_svc_reqd_flags(krb5_kdc_req *req, krb5_db_entry *server,
krb5_ticket *tkt,
krb5_timestamp kdc_time, const char **status)
{
- if (server.attributes & KRB5_KDB_REQUIRES_HW_AUTH) {
+ if (server->attributes & KRB5_KDB_REQUIRES_HW_AUTH) {
if (!(tkt->enc_part2->flags & TKT_FLG_HW_AUTH)) {
*status = "NO HW PREAUTH";
return KRB_ERR_GENERIC;
}
}
- if (server.attributes & KRB5_KDB_REQUIRES_PRE_AUTH) {
+ if (server->attributes & KRB5_KDB_REQUIRES_PRE_AUTH) {
if (!(tkt->enc_part2->flags & TKT_FLG_PRE_AUTH)) {
*status = "NO PREAUTH";
return KRB_ERR_GENERIC;
@@ -180,10 +180,10 @@ check_tgs_svc_reqd_flags(krb5_kdc_req *req, krb5_db_entry server,
}
static int
-check_tgs_svc_time(krb5_kdc_req *req, krb5_db_entry server, krb5_ticket *tkt,
+check_tgs_svc_time(krb5_kdc_req *req, krb5_db_entry *server, krb5_ticket *tkt,
krb5_timestamp kdc_time, const char **status)
{
- if (server.expiration && ts_after(kdc_time, server.expiration)) {
+ if (server->expiration && ts_after(kdc_time, server->expiration)) {
*status = "SERVICE EXPIRED";
return KDC_ERR_SERVICE_EXP;
}
@@ -191,8 +191,9 @@ check_tgs_svc_time(krb5_kdc_req *req, krb5_db_entry server, krb5_ticket *tkt,
}
static int
-check_tgs_svc_policy(krb5_kdc_req *req, krb5_db_entry server, krb5_ticket *tkt,
- krb5_timestamp kdc_time, const char **status)
+check_tgs_svc_policy(krb5_kdc_req *req, krb5_db_entry *server,
+ krb5_ticket *tkt, krb5_timestamp kdc_time,
+ const char **status)
{
int errcode;
size_t i;
@@ -317,7 +318,7 @@ check_tgs_tgt(kdc_realm_t *kdc_active_realm, krb5_kdc_req *req,
int
validate_tgs_request(kdc_realm_t *kdc_active_realm,
- krb5_kdc_req *request, krb5_db_entry server,
+ krb5_kdc_req *request, krb5_db_entry *server,
krb5_ticket *ticket, krb5_timestamp kdc_time,
const char **status, krb5_pa_data ***e_data)
{
@@ -367,8 +368,8 @@ validate_tgs_request(kdc_realm_t *kdc_active_realm,
}
/* Perform KDB module policy checks. */
- ret = krb5_db_check_policy_tgs(kdc_context, request, &server,
- ticket, status, e_data);
+ ret = krb5_db_check_policy_tgs(kdc_context, request, server, ticket,
+ status, e_data);
if (ret && ret != KRB5_PLUGIN_OP_NOTSUPP)
return errcode_to_protocol(ret);

View File

@ -0,0 +1,106 @@
From c3d96fca46cb2cc3ee9f4c2e2a4ed98bad3e310a Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Thu, 15 Oct 2020 18:15:29 -0400
Subject: [PATCH] Fix minor static analysis defects
Remove an unused variable in krb5_ldap_create(). Handle the return
value from krb5_dbe_get_string() in the certauth test plugin module.
Handle the return value from k5_expand_path_tokens() in
k5_rc_default(). Remove dead assignments in
krb5_get_credentials_for_user() and kg_accept_krb5().
[ghudson@mit.edu: squashed and edited commit message; simplified
k5_rc_default() change]
(cherry picked from commit b27461141810fddd299764928649148c5d0e99f3)
---
src/lib/gssapi/krb5/accept_sec_context.c | 4 +---
src/lib/krb5/krb/s4u_creds.c | 1 -
src/lib/krb5/rcache/rc_base.c | 2 ++
src/plugins/certauth/test/main.c | 3 +++
src/plugins/kdb/ldap/libkdb_ldap/ldap_create.c | 4 ----
5 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/src/lib/gssapi/krb5/accept_sec_context.c b/src/lib/gssapi/krb5/accept_sec_context.c
index 3d5b84b15..e2c5e2b59 100644
--- a/src/lib/gssapi/krb5/accept_sec_context.c
+++ b/src/lib/gssapi/krb5/accept_sec_context.c
@@ -671,7 +671,7 @@ kg_accept_krb5(minor_status, context_handle,
krb5_auth_context auth_context = NULL;
krb5_ticket * ticket = NULL;
const gss_OID_desc *mech_used = NULL;
- OM_uint32 major_status = GSS_S_FAILURE;
+ OM_uint32 major_status;
OM_uint32 tmp_minor_status;
krb5_error krb_error_data;
krb5_data scratch;
@@ -878,8 +878,6 @@ kg_accept_krb5(minor_status, context_handle,
if (major_status != GSS_S_COMPLETE)
goto fail;
- major_status = GSS_S_FAILURE;
-
if (exts->iakerb.conv && !exts->iakerb.verified) {
major_status = GSS_S_BAD_SIG;
goto fail;
diff --git a/src/lib/krb5/krb/s4u_creds.c b/src/lib/krb5/krb/s4u_creds.c
index d8f486dc6..35a8843e5 100644
--- a/src/lib/krb5/krb/s4u_creds.c
+++ b/src/lib/krb5/krb/s4u_creds.c
@@ -714,7 +714,6 @@ krb5_get_credentials_for_user(krb5_context context, krb5_flags options,
} else if (code != KRB5_CC_NOTFOUND && code != KRB5_CC_NOT_KTYPE) {
goto cleanup;
}
- code = 0;
}
/* Note the authdata we asked for in the output creds. */
diff --git a/src/lib/krb5/rcache/rc_base.c b/src/lib/krb5/rcache/rc_base.c
index 5f456d1f3..f9a482318 100644
--- a/src/lib/krb5/rcache/rc_base.c
+++ b/src/lib/krb5/rcache/rc_base.c
@@ -56,6 +56,8 @@ k5_rc_default(krb5_context context, krb5_rcache *rc_out)
&profstr) == 0 && profstr != NULL) {
ret = k5_expand_path_tokens(context, profstr, &rcname);
profile_release_string(profstr);
+ if (ret)
+ return ret;
ret = k5_rc_resolve(context, rcname, rc_out);
free(rcname);
return ret;
diff --git a/src/plugins/certauth/test/main.c b/src/plugins/certauth/test/main.c
index d4633b8cd..7e7a3ef4c 100644
--- a/src/plugins/certauth/test/main.c
+++ b/src/plugins/certauth/test/main.c
@@ -171,6 +171,9 @@ test2_authorize(krb5_context context, krb5_certauth_moddata moddata,
ret = krb5_dbe_get_string(context, (krb5_db_entry *)db_entry, "hwauth",
&strval);
+ if (ret)
+ goto cleanup;
+
ret = (strval != NULL) ? KRB5_CERTAUTH_HWAUTH : 0;
krb5_dbe_free_string(context, strval);
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_create.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_create.c
index 5b57c799a..2d6605666 100644
--- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_create.c
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_create.c
@@ -55,7 +55,6 @@ krb5_ldap_create(krb5_context context, char *conf_section, char **db_args)
krb5_error_code status = 0;
krb5_ldap_realm_params *rparams = NULL;
krb5_ldap_context *ldap_context=NULL;
- krb5_boolean realm_obj_created = FALSE;
int mask = 0;
/* Clear the global error string */
@@ -109,9 +108,6 @@ krb5_ldap_create(krb5_context context, char *conf_section, char **db_args)
if ((status = krb5_ldap_create_realm(context, rparams, mask)))
goto cleanup;
- /* We just created the Realm container. Here starts our transaction tracking */
- realm_obj_created = TRUE;
-
/* verify realm object */
if ((status = krb5_ldap_read_realm_params(context,
rparams->realm_name,

View File

@ -0,0 +1,124 @@
From ed87237cdd70f72b309960a294a2bed26cef1579 Mon Sep 17 00:00:00 2001
From: Isaac Boukris <iboukris@gmail.com>
Date: Fri, 4 Sep 2020 14:05:50 +0300
Subject: [PATCH] Improve KDC alias checking for S4U requests
When processing an S4U2Self request, check for DB aliases when
matching the TGT client against the request server. When processing
an S4U2Proxy request, check for DB aliases when matching the TGT
client against the evidence ticket server.
[ghudson@mit.edu: minor edits; rewrote commit message]
ticket: 8946 (new)
(cherry picked from commit 05deeebfc096970b5d9aa67a48b14106cf1b9b56)
---
src/kdc/kdc_util.c | 74 ++++++++++++++++------------------------------
1 file changed, 25 insertions(+), 49 deletions(-)
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
index e3352f9cc..dcb2df8dc 100644
--- a/src/kdc/kdc_util.c
+++ b/src/kdc/kdc_util.c
@@ -1463,6 +1463,25 @@ cleanup:
return code;
}
+/* Return true if princ canonicalizes to the same principal as canon. */
+static krb5_boolean
+is_client_alias(krb5_context context, krb5_const_principal canon,
+ krb5_const_principal princ)
+{
+ krb5_error_code ret;
+ krb5_db_entry *self;
+ krb5_boolean is_self = FALSE;
+
+ ret = krb5_db_get_principal(context, princ,
+ KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY, &self);
+ if (!ret) {
+ is_self = krb5_principal_compare(context, canon, self->princ);
+ krb5_db_free_principal(context, self);
+ }
+
+ return is_self;
+}
+
/*
* Protocol transition (S4U2Self)
*/
@@ -1481,7 +1500,6 @@ kdc_process_s4u2self_req(kdc_realm_t *kdc_active_realm,
{
krb5_error_code code;
krb5_pa_data *pa_data;
- int flags;
krb5_db_entry *princ;
krb5_s4u_userid *id;
@@ -1515,51 +1533,11 @@ kdc_process_s4u2self_req(kdc_realm_t *kdc_active_realm,
}
id = &(*s4u_x509_user)->user_id;
- /*
- * We need to compare the client name in the TGT with the requested
- * server name. Supporting server name aliases without assuming a
- * global name service makes this difficult to do.
- *
- * The comparison below handles the following cases (note that the
- * term "principal name" below excludes the realm).
- *
- * (1) The requested service is a host-based service with two name
- * components, in which case we assume the principal name to
- * contain sufficient qualifying information. The realm is
- * ignored for the purpose of comparison.
- *
- * (2) The requested service name is an enterprise principal name:
- * the service principal name is compared with the unparsed
- * form of the client name (including its realm).
- *
- * (3) The requested service is some other name type: an exact
- * match is required.
- *
- * An alternative would be to look up the server once again with
- * FLAG_CANONICALIZE | FLAG_CLIENT_REFERRALS_ONLY set, do an exact
- * match between the returned name and client_princ. However, this
- * assumes that the client set FLAG_CANONICALIZE when requesting
- * the TGT and that we have a global name service.
- */
- flags = 0;
- switch (krb5_princ_type(kdc_context, request->server)) {
- case KRB5_NT_SRV_HST: /* (1) */
- if (krb5_princ_size(kdc_context, request->server) == 2)
- flags |= KRB5_PRINCIPAL_COMPARE_IGNORE_REALM;
- break;
- case KRB5_NT_ENTERPRISE_PRINCIPAL: /* (2) */
- flags |= KRB5_PRINCIPAL_COMPARE_ENTERPRISE;
- break;
- default: /* (3) */
- break;
- }
-
- if (!krb5_principal_compare_flags(kdc_context,
- request->server,
- client_princ,
- flags)) {
- *status = "INVALID_S4U2SELF_REQUEST";
- return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; /* match Windows error code */
+ /* If the server is local, check that the request is for self. */
+ if (!isflagset(c_flags, KRB5_KDB_FLAG_ISSUING_REFERRAL) &&
+ !is_client_alias(kdc_context, server->princ, client_princ)) {
+ *status = "INVALID_S4U2SELF_REQUEST_SERVER_MISMATCH";
+ return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; /* match Windows error */
}
/*
@@ -1750,9 +1728,7 @@ kdc_process_s4u2proxy_req(kdc_realm_t *kdc_active_realm, unsigned int flags,
}
client_princ = *stkt_authdata_client;
- } else if (!krb5_principal_compare(kdc_context,
- server->princ, /* after canon */
- server_princ)) {
+ } else if (!is_client_alias(kdc_context, server->princ, server_princ)) {
*status = "EVIDENCE_TICKET_MISMATCH";
return KRB5KDC_ERR_SERVER_NOMATCH;
}

View File

@ -0,0 +1,316 @@
From 5e79319edf3836d12dbc710ec1e2dd4405c9df35 Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Fri, 25 Sep 2020 11:12:34 -0400
Subject: [PATCH] Minimize usage of tgs_server in KDC
Where possible, use the realm of the request server principal
(canonicalized via KDB lookup, if available) in preference to
tgs_server. This change facilitates alias realm support and potential
future support for serving multiple realms from the same KDB.
S4U2Self local user testing currently uses the uncanonicalized request
realm after this change, which will require attention for alias realm
support.
FAST armor ticket checking is unaffected by this change (it still
compares against tgs_server). This check poses no issue for realm
aliases, as both tgs_server and the armor ticket server should have
canonical realms, but it will require attention for multi-realm KDB
support.
Remove is_local_principal() as it is no longer used. Add an
is_local_tgs_principal() helper and shorten is_cross_tgs_principal().
Move the header ticket lineage check from kdc_process_tgs_req() to
process_tgs_req(), where we have the canonical request server name and
a more natural indication of whether the request was an S4U2Self
request.
(cherry picked from commit 90fedf8188fc47aa5a476a969af34671555df389)
---
src/kdc/do_as_req.c | 21 ++++++--------
src/kdc/do_tgs_req.c | 16 ++++++++---
src/kdc/kdc_util.c | 68 ++++++++++----------------------------------
src/kdc/kdc_util.h | 3 +-
src/kdc/tgs_policy.c | 16 ++++++-----
5 files changed, 46 insertions(+), 78 deletions(-)
diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c
index c2dfea9b8..e0ac33649 100644
--- a/src/kdc/do_as_req.c
+++ b/src/kdc/do_as_req.c
@@ -620,18 +620,6 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
}
state->rock.client = state->client;
- /*
- * If the backend returned a principal that is not in the local
- * realm, then we need to refer the client to that realm.
- */
- if (!is_local_principal(kdc_active_realm, state->client->princ)) {
- /* Entry is a referral to another realm */
- state->status = "REFERRAL";
- au_state->cl_realm = &state->client->princ->realm;
- errcode = KRB5KDC_ERR_WRONG_REALM;
- goto errout;
- }
-
au_state->stage = SRVC_PRINC;
s_flags = 0;
@@ -651,6 +639,15 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
goto errout;
}
+ /* If the KDB module returned a different realm for the client and server,
+ * we need to issue a client realm referral. */
+ if (!data_eq(state->server->princ->realm, state->client->princ->realm)) {
+ state->status = "REFERRAL";
+ au_state->cl_realm = &state->client->princ->realm;
+ errcode = KRB5KDC_ERR_WRONG_REALM;
+ goto errout;
+ }
+
errcode = get_local_tgt(kdc_context, &state->request->server->realm,
state->server, &state->local_tgt,
&state->local_tgt_storage, &state->local_tgt_key);
diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c
index d345797c4..8ea418e43 100644
--- a/src/kdc/do_tgs_req.c
+++ b/src/kdc/do_tgs_req.c
@@ -268,7 +268,7 @@ process_tgs_req(krb5_kdc_req *request, krb5_data *pkt,
goto cleanup;
}
- if (!is_local_principal(kdc_active_realm, header_ticket->server))
+ if (!data_eq(header_server->princ->realm, sprinc->realm))
setflag(c_flags, KRB5_KDB_FLAG_CROSS_REALM);
if (is_referral)
setflag(c_flags, KRB5_KDB_FLAG_ISSUING_REFERRAL);
@@ -295,6 +295,15 @@ process_tgs_req(krb5_kdc_req *request, krb5_data *pkt,
au_state->s4u2self_user = NULL;
}
+ /* Aside from cross-realm S4U2Self requests, do not accept header tickets
+ * for local users issued by foreign realms. */
+ if (s4u_x509_user == NULL && data_eq(cprinc->realm, sprinc->realm) &&
+ isflagset(c_flags, KRB5_KDB_FLAG_CROSS_REALM)) {
+ krb5_klog_syslog(LOG_INFO, _("PROCESS_TGS: failed lineage check"));
+ retval = KRB5KDC_ERR_POLICY;
+ goto cleanup;
+ }
+
if (errcode)
goto cleanup;
@@ -583,13 +592,12 @@ process_tgs_req(krb5_kdc_req *request, krb5_data *pkt,
/*
* Only add the realm of the presented tgt to the transited list if
- * it is different than the local realm (cross-realm) and it is different
+ * it is different than the server realm (cross-realm) and it is different
* than the realm of the client (since the realm of the client is already
* implicitly part of the transited list and should not be explicitly
* listed).
*/
- /* realm compare is like strcmp, but knows how to deal with these args */
- if (krb5_realm_compare(kdc_context, header_ticket->server, tgs_server) ||
+ if (!isflagset(c_flags, KRB5_KDB_FLAG_CROSS_REALM) ||
krb5_realm_compare(kdc_context, header_ticket->server,
enc_tkt_reply.client)) {
/* tgt issued by local realm or issued by realm of client */
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
index b2042862a..e0b65a87c 100644
--- a/src/kdc/kdc_util.c
+++ b/src/kdc/kdc_util.c
@@ -78,12 +78,6 @@ static krb5_error_code find_server_key(krb5_context,
krb5_kvno, krb5_keyblock **,
krb5_kvno *);
-krb5_boolean
-is_local_principal(kdc_realm_t *kdc_active_realm, krb5_const_principal princ1)
-{
- return krb5_realm_compare(kdc_context, princ1, tgs_server);
-}
-
/*
* Returns TRUE if the kerberos principal is the name of a Kerberos ticket
* service.
@@ -104,13 +98,16 @@ krb5_is_tgs_principal(krb5_const_principal principal)
krb5_boolean
is_cross_tgs_principal(krb5_const_principal principal)
{
- if (!krb5_is_tgs_principal(principal))
- return FALSE;
- if (!data_eq(*krb5_princ_component(kdc_context, principal, 1),
- *krb5_princ_realm(kdc_context, principal)))
- return TRUE;
- else
- return FALSE;
+ return krb5_is_tgs_principal(principal) &&
+ !data_eq(principal->data[1], principal->realm);
+}
+
+/* Return true if princ is the name of a local TGS for any realm. */
+krb5_boolean
+is_local_tgs_principal(krb5_const_principal principal)
+{
+ return krb5_is_tgs_principal(principal) &&
+ data_eq(principal->data[1], principal->realm);
}
/*
@@ -143,17 +140,6 @@ comp_cksum(krb5_context kcontext, krb5_data *source, krb5_ticket *ticket,
return(0);
}
-/* Return true if padata contains an entry of either S4U2Self type. */
-static inline krb5_boolean
-has_s4u2self_padata(krb5_pa_data **padata)
-{
- if (krb5int_find_pa_data(NULL, padata, KRB5_PADATA_FOR_USER) != NULL)
- return TRUE;
- if (krb5int_find_pa_data(NULL, padata, KRB5_PADATA_S4U_X509_USER) != NULL)
- return TRUE;
- return FALSE;
-}
-
/* If a header ticket is decrypted, *ticket_out is filled in even on error. */
krb5_error_code
kdc_process_tgs_req(kdc_realm_t *kdc_active_realm,
@@ -170,7 +156,6 @@ kdc_process_tgs_req(kdc_realm_t *kdc_active_realm,
krb5_authdata **authdata = NULL;
krb5_data scratch1;
krb5_data * scratch = NULL;
- krb5_boolean foreign_server = FALSE;
krb5_auth_context auth_context = NULL;
krb5_authenticator * authenticator = NULL;
krb5_checksum * his_cksum = NULL;
@@ -199,19 +184,6 @@ kdc_process_tgs_req(kdc_realm_t *kdc_active_realm,
goto cleanup;
}
- /* If the "server" principal in the ticket is not something
- in the local realm, then we must refuse to service the request
- if the client claims to be from the local realm.
-
- If we don't do this, then some other realm's nasty KDC can
- claim to be authenticating a client from our realm, and we'll
- give out tickets concurring with it!
-
- we set a flag here for checking below.
- */
- foreign_server = !is_local_principal(kdc_active_realm,
- apreq->ticket->server);
-
if ((retval = krb5_auth_con_init(kdc_context, &auth_context)))
goto cleanup;
@@ -265,15 +237,6 @@ kdc_process_tgs_req(kdc_realm_t *kdc_active_realm,
goto cleanup_authenticator;
}
- /* make sure the client is of proper lineage (see above) */
- if (foreign_server && !has_s4u2self_padata(request->padata) &&
- is_local_principal(kdc_active_realm, ticket->enc_part2->client)) {
- /* someone in a foreign realm claiming to be local */
- krb5_klog_syslog(LOG_INFO, _("PROCESS_TGS: failed lineage check"));
- retval = KRB5KDC_ERR_POLICY;
- goto cleanup_authenticator;
- }
-
/*
* Check application checksum vs. tgs request
*
@@ -591,12 +554,12 @@ int
check_anon(kdc_realm_t *kdc_active_realm,
krb5_principal client, krb5_principal server)
{
- /* If restrict_anon is set, reject requests from anonymous to principals
- * other than the local TGT. */
+ /* If restrict_anon is set, reject requests from anonymous clients to
+ * server principals other than local TGTs. */
if (kdc_active_realm->realm_restrict_anon &&
krb5_principal_compare_any_realm(kdc_context, client,
krb5_anonymous_principal()) &&
- !krb5_principal_compare(kdc_context, server, tgs_server))
+ !is_local_tgs_principal(server))
return -1;
return 0;
}
@@ -1527,7 +1490,7 @@ kdc_process_s4u2self_req(kdc_realm_t *kdc_active_realm,
/*
* Do not attempt to lookup principals in foreign realms.
*/
- if (is_local_principal(kdc_active_realm, id->user)) {
+ if (data_eq(server->princ->realm, id->user->realm)) {
krb5_db_entry no_server;
krb5_pa_data **e_data = NULL;
@@ -1663,8 +1626,7 @@ kdc_process_s4u2proxy_req(kdc_realm_t *kdc_active_realm, unsigned int flags,
*/
if (isflagset(flags, KRB5_KDB_FLAG_ISSUING_REFERRAL) ||
!is_cross_tgs_principal(server->princ) ||
- !krb5_principal_compare_any_realm(kdc_context, server->princ,
- tgs_server) ||
+ !data_eq(server->princ->data[1], proxy->princ->realm) ||
!krb5_principal_compare(kdc_context, client_princ, server_princ)) {
*status = "XREALM_EVIDENCE_TICKET_MISMATCH";
return KRB5KDC_ERR_BADOPTION;
diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h
index 04007a8f5..a6bac4388 100644
--- a/src/kdc/kdc_util.h
+++ b/src/kdc/kdc_util.h
@@ -37,10 +37,9 @@
#include "reqstate.h"
krb5_error_code check_hot_list (krb5_ticket *);
-krb5_boolean is_local_principal(kdc_realm_t *kdc_active_realm,
- krb5_const_principal princ1);
krb5_boolean krb5_is_tgs_principal (krb5_const_principal);
krb5_boolean is_cross_tgs_principal(krb5_const_principal);
+krb5_boolean is_local_tgs_principal(krb5_const_principal);
krb5_error_code
add_to_transited (krb5_data *,
krb5_data *,
diff --git a/src/kdc/tgs_policy.c b/src/kdc/tgs_policy.c
index 3f4fa8499..a5a00f0cc 100644
--- a/src/kdc/tgs_policy.c
+++ b/src/kdc/tgs_policy.c
@@ -252,19 +252,21 @@ check_tgs_s4u2proxy(kdc_realm_t *kdc_active_realm,
}
static int
-check_tgs_u2u(kdc_realm_t *kdc_active_realm,
- krb5_kdc_req *req, const char **status)
+check_tgs_u2u(kdc_realm_t *kdc_active_realm, krb5_kdc_req *req,
+ krb5_const_principal server_princ, const char **status)
{
+ krb5_const_principal second_server_princ;
+
if (req->kdc_options & KDC_OPT_ENC_TKT_IN_SKEY) {
/* Check that second ticket is in request. */
if (!req->second_ticket || !req->second_ticket[0]) {
*status = "NO_2ND_TKT";
return KDC_ERR_BADOPTION;
}
- /* Check that second ticket is a TGT. */
- if (!krb5_principal_compare(kdc_context,
- req->second_ticket[0]->server,
- tgs_server)) {
+ /* Check that second ticket is a TGT to the server realm. */
+ second_server_princ = req->second_ticket[0]->server;
+ if (!is_local_tgs_principal(second_server_princ) ||
+ !data_eq(second_server_princ->data[1], server_princ->realm)) {
*status = "2ND_TKT_NOT_TGS";
return KDC_ERR_POLICY;
}
@@ -353,7 +355,7 @@ validate_tgs_request(kdc_realm_t *kdc_active_realm,
return(KRB_AP_ERR_REPEAT);
}
- errcode = check_tgs_u2u(kdc_active_realm, request, status);
+ errcode = check_tgs_u2u(kdc_active_realm, request, server->princ, status);
if (errcode != 0)
return errcode;

View File

@ -0,0 +1,335 @@
From 9335481c00cd15170adec244ccff0a00a014bbab Mon Sep 17 00:00:00 2001
From: Greg Hudson <ghudson@mit.edu>
Date: Wed, 5 Feb 2020 18:46:11 -0500
Subject: [PATCH] Refactor KDC authdata list management helpers
Remove the unused concat_authorization_data(). Split merge_authdata()
into two helpers, one to destructively merge without filtering and one
to add copied elements while filtering out KDC-only authdata types.
Remove context parameters where they aren't needed (taking advantage
of knowledge that some libkrb5 functions don't use their context
parameters).
(cherry picked from commit b2190fdc253de6024001e0f1ff9fe56c31042bb7)
---
src/kdc/kdc_authdata.c | 138 +++++++++++++++++++----------------------
src/kdc/kdc_util.c | 50 ---------------
src/kdc/kdc_util.h | 5 --
3 files changed, 64 insertions(+), 129 deletions(-)
diff --git a/src/kdc/kdc_authdata.c b/src/kdc/kdc_authdata.c
index 1ebe87246..010922c27 100644
--- a/src/kdc/kdc_authdata.c
+++ b/src/kdc/kdc_authdata.c
@@ -108,7 +108,7 @@ unload_authdata_plugins(krb5_context context)
/* Return true if authdata should be filtered when copying from untrusted
* authdata. If desired_type is non-zero, look only for that type. */
static krb5_boolean
-is_kdc_issued_authdatum(krb5_context context, krb5_authdata *authdata,
+is_kdc_issued_authdatum(krb5_authdata *authdata,
krb5_authdatatype desired_type)
{
krb5_boolean result = FALSE;
@@ -117,7 +117,7 @@ is_kdc_issued_authdatum(krb5_context context, krb5_authdata *authdata,
krb5_authdatatype *ad_types, *containee_types = NULL;
if (authdata->ad_type == KRB5_AUTHDATA_IF_RELEVANT) {
- if (krb5int_get_authdata_containee_types(context, authdata, &count,
+ if (krb5int_get_authdata_containee_types(NULL, authdata, &count,
&containee_types) != 0)
goto cleanup;
ad_types = containee_types;
@@ -152,7 +152,7 @@ cleanup:
/* Return true if authdata contains any elements which should only come from
* the KDC. If desired_type is non-zero, look only for that type. */
static krb5_boolean
-has_kdc_issued_authdata(krb5_context context, krb5_authdata **authdata,
+has_kdc_issued_authdata(krb5_authdata **authdata,
krb5_authdatatype desired_type)
{
int i;
@@ -160,7 +160,7 @@ has_kdc_issued_authdata(krb5_context context, krb5_authdata **authdata,
if (authdata == NULL)
return FALSE;
for (i = 0; authdata[i] != NULL; i++) {
- if (is_kdc_issued_authdatum(context, authdata[i], desired_type))
+ if (is_kdc_issued_authdatum(authdata[i], desired_type))
return TRUE;
}
return FALSE;
@@ -181,66 +181,71 @@ has_mandatory_for_kdc_authdata(krb5_context context, krb5_authdata **authdata)
return FALSE;
}
-/*
- * Add the elements of in_authdata to out_authdata. If copy is false,
- * in_authdata is invalid on successful return. If ignore_kdc_issued is true,
- * KDC-issued authdata is not copied.
- */
+/* Add elements from *new_elements to *existing_list, reallocating as
+ * necessary. On success, release *new_elements and set it to NULL. */
static krb5_error_code
-merge_authdata(krb5_context context, krb5_authdata **in_authdata,
- krb5_authdata ***out_authdata, krb5_boolean copy,
- krb5_boolean ignore_kdc_issued)
+merge_authdata(krb5_authdata ***existing_list, krb5_authdata ***new_elements)
{
- krb5_error_code ret;
- size_t i, j, nadata = 0;
- krb5_authdata **in_copy = NULL, **authdata = *out_authdata;
+ size_t count = 0, ncount = 0;
+ krb5_authdata **list = *existing_list, **nlist = *new_elements;
- if (in_authdata == NULL || in_authdata[0] == NULL)
+ if (nlist == NULL)
return 0;
- if (authdata != NULL) {
- for (nadata = 0; authdata[nadata] != NULL; nadata++)
- ;
- }
+ for (count = 0; list != NULL && list[count] != NULL; count++);
+ for (ncount = 0; nlist[ncount] != NULL; ncount++);
- for (i = 0; in_authdata[i] != NULL; i++)
- ;
-
- if (copy) {
- ret = krb5_copy_authdata(context, in_authdata, &in_copy);
- if (ret)
- return ret;
- in_authdata = in_copy;
- }
-
- authdata = realloc(authdata, (nadata + i + 1) * sizeof(krb5_authdata *));
- if (authdata == NULL) {
- krb5_free_authdata(context, in_copy);
+ list = realloc(list, (count + ncount + 1) * sizeof(*list));
+ if (list == NULL)
return ENOMEM;
+
+ memcpy(list + count, nlist, ncount * sizeof(*nlist));
+ list[count + ncount] = NULL;
+ free(nlist);
+
+ if (list[0] == NULL) {
+ free(list);
+ list = NULL;
}
- for (i = 0, j = 0; in_authdata[i] != NULL; i++) {
- if (ignore_kdc_issued &&
- is_kdc_issued_authdatum(context, in_authdata[i], 0)) {
- free(in_authdata[i]->contents);
- free(in_authdata[i]);
+ *new_elements = NULL;
+ *existing_list = list;
+ return 0;
+}
+
+/* Add a copy of new_elements to *existing_list, omitting KDC-issued
+ * authdata. */
+static krb5_error_code
+add_filtered_authdata(krb5_authdata ***existing_list,
+ krb5_authdata **new_elements)
+{
+ krb5_error_code ret;
+ krb5_authdata **copy;
+ size_t i, j;
+
+ if (new_elements == NULL)
+ return 0;
+
+ ret = krb5_copy_authdata(NULL, new_elements, &copy);
+ if (ret)
+ return ret;
+
+ /* Remove KDC-issued elements from copy. */
+ j = 0;
+ for (i = 0; copy[i] != NULL; i++) {
+ if (is_kdc_issued_authdatum(copy[i], 0)) {
+ free(copy[i]->contents);
+ free(copy[i]);
} else {
- authdata[nadata + j++] = in_authdata[i];
+ copy[j++] = copy[i];
}
}
+ copy[j] = NULL;
- authdata[nadata + j] = NULL;
-
- free(in_authdata);
-
- if (authdata[0] == NULL) {
- free(authdata);
- authdata = NULL;
- }
-
- *out_authdata = authdata;
-
- return 0;
+ /* Destructively merge the filtered copy into existing_list. */
+ ret = merge_authdata(existing_list, &copy);
+ krb5_free_authdata(NULL, copy);
+ return ret;
}
/* Copy TGS-REQ authorization data into the ticket authdata. */
@@ -289,10 +294,7 @@ copy_request_authdata(krb5_context context, krb5_keyblock *client_key,
goto cleanup;
}
- /* Add a copy of the requested authdata to the ticket, ignoring KDC-issued
- * types. */
- ret = merge_authdata(context, req->unenc_authdata, tkt_authdata, TRUE,
- TRUE);
+ ret = add_filtered_authdata(tkt_authdata, req->unenc_authdata);
cleanup:
free(plaintext.data);
@@ -307,9 +309,7 @@ copy_tgt_authdata(krb5_context context, krb5_kdc_req *request,
if (has_mandatory_for_kdc_authdata(context, tgt_authdata))
return KRB5KDC_ERR_POLICY;
- /* Add a copy of the TGT authdata to the ticket, ignoring KDC-issued
- * types. */
- return merge_authdata(context, tgt_authdata, tkt_authdata, TRUE, TRUE);
+ return add_filtered_authdata(tkt_authdata, tgt_authdata);
}
/* Fetch authorization data from KDB module. */
@@ -374,8 +374,7 @@ fetch_kdb_authdata(krb5_context context, unsigned int flags,
/* Put the KDB authdata first in the ticket. A successful merge places the
* combined list in db_authdata and releases the old ticket authdata. */
- ret = merge_authdata(context, enc_tkt_reply->authorization_data,
- &db_authdata, FALSE, FALSE);
+ ret = merge_authdata(&db_authdata, &enc_tkt_reply->authorization_data);
if (ret)
krb5_free_authdata(context, db_authdata);
else
@@ -404,8 +403,7 @@ make_signedpath_data(krb5_context context, krb5_const_principal client,
return ret;
for (i = 0, j = 0; authdata[i] != NULL; i++) {
- if (is_kdc_issued_authdatum(context, authdata[i],
- KRB5_AUTHDATA_SIGNTICKET))
+ if (is_kdc_issued_authdatum(authdata[i], KRB5_AUTHDATA_SIGNTICKET))
continue;
sign_authdata[j++] = authdata[i];
@@ -635,12 +633,8 @@ make_signedpath(krb5_context context, krb5_const_principal for_user_princ,
if (ret)
goto cleanup;
- /* Add the authdata to the ticket, without copying or filtering. */
- ret = merge_authdata(context, if_relevant,
- &enc_tkt_reply->authorization_data, FALSE, FALSE);
- if (ret)
- goto cleanup;
- if_relevant = NULL; /* merge_authdata() freed */
+ /* Add the signedpath authdata to the ticket. */
+ ret = merge_authdata(&enc_tkt_reply->authorization_data, &if_relevant);
cleanup:
free(sp.delegated);
@@ -665,7 +659,7 @@ free_deleg_path(krb5_context context, krb5_principal *deleg_path)
static krb5_boolean
has_pac(krb5_context context, krb5_authdata **authdata)
{
- return has_kdc_issued_authdata(context, authdata, KRB5_AUTHDATA_WIN2K_PAC);
+ return has_kdc_issued_authdata(authdata, KRB5_AUTHDATA_WIN2K_PAC);
}
/* Verify AD-SIGNTICKET authdata if we need to, and insert an AD-SIGNEDPATH
@@ -746,11 +740,7 @@ add_auth_indicators(krb5_context context, krb5_data *const *auth_indicators,
goto cleanup;
/* Add the wrapped authdata to the ticket, without copying or filtering. */
- ret = merge_authdata(context, cammac, &enc_tkt_reply->authorization_data,
- FALSE, FALSE);
- if (ret)
- goto cleanup;
- cammac = NULL; /* merge_authdata() freed */
+ ret = merge_authdata(&enc_tkt_reply->authorization_data, &cammac);
cleanup:
krb5_free_data(context, der_indicators);
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
index 6330387d0..a4a05b9fa 100644
--- a/src/kdc/kdc_util.c
+++ b/src/kdc/kdc_util.c
@@ -78,56 +78,6 @@ static krb5_error_code find_server_key(krb5_context,
krb5_kvno, krb5_keyblock **,
krb5_kvno *);
-/*
- * concatenate first two authdata arrays, returning an allocated replacement.
- * The replacement should be freed with krb5_free_authdata().
- */
-krb5_error_code
-concat_authorization_data(krb5_context context,
- krb5_authdata **first, krb5_authdata **second,
- krb5_authdata ***output)
-{
- int i, j;
- krb5_authdata **ptr, **retdata;
-
- /* count up the entries */
- i = 0;
- if (first)
- for (ptr = first; *ptr; ptr++)
- i++;
- if (second)
- for (ptr = second; *ptr; ptr++)
- i++;
-
- retdata = (krb5_authdata **)malloc((i+1)*sizeof(*retdata));
- if (!retdata)
- return ENOMEM;
- retdata[i] = 0; /* null-terminated array */
- for (i = 0, j = 0, ptr = first; j < 2 ; ptr = second, j++)
- while (ptr && *ptr) {
- /* now walk & copy */
- retdata[i] = (krb5_authdata *)malloc(sizeof(*retdata[i]));
- if (!retdata[i]) {
- krb5_free_authdata(context, retdata);
- return ENOMEM;
- }
- *retdata[i] = **ptr;
- if (!(retdata[i]->contents =
- (krb5_octet *)malloc(retdata[i]->length))) {
- free(retdata[i]);
- retdata[i] = 0;
- krb5_free_authdata(context, retdata);
- return ENOMEM;
- }
- memcpy(retdata[i]->contents, (*ptr)->contents, retdata[i]->length);
-
- ptr++;
- i++;
- }
- *output = retdata;
- return 0;
-}
-
krb5_boolean
is_local_principal(kdc_realm_t *kdc_active_realm, krb5_const_principal princ1)
{
diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h
index 2c9d8cf69..42b7ee208 100644
--- a/src/kdc/kdc_util.h
+++ b/src/kdc/kdc_util.h
@@ -52,11 +52,6 @@ compress_transited (krb5_data *,
krb5_principal,
krb5_data *);
krb5_error_code
-concat_authorization_data (krb5_context,
- krb5_authdata **,
- krb5_authdata **,
- krb5_authdata ***);
-krb5_error_code
fetch_last_req_info (krb5_db_entry *, krb5_last_req_entry ***);
krb5_error_code

View File

@ -0,0 +1,185 @@
From 52e3695cc5ef00766e12adfe8ed276c2885e71bb Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Thu, 20 Aug 2020 17:49:29 -0400
Subject: [PATCH] Unify kvno option documentation
Add missing kvno options to the kvno.rst synopsis and option
descriptions, and to the kvno usage message. Remove mention of '-h'
(help text), from kvno.rst as it is an implicit option. Note that the
three new caching options were added in release 1.19.
Indicate the two exclusions (-u/-S and --u2u with the S4U2Self options)
and dependency (-P on S4U2Self) where they are missing.
Switch xusage() to print only a single localized string, rather than
running each line of output through localization separately.
Leave kvno -C undocumented for now, as the semantics of
KRB5_GC_CANONICALIZE are minimally useful and likely to change.
[ghudson@mit.edu: edited documentation and commit message]
ticket: 7476
tags: pullup
target_version: 1.18-next
(cherry picked from commit becd1ad6830b526d08ddaf5b2b6f213154c6446c)
---
doc/user/user_commands/kvno.rst | 24 +++++++++++++-----------
src/clients/kvno/kvno.c | 15 +++++++++------
src/man/kvno.man | 24 +++++++++++++-----------
3 files changed, 35 insertions(+), 28 deletions(-)
diff --git a/doc/user/user_commands/kvno.rst b/doc/user/user_commands/kvno.rst
index 718313576..65c44e1c0 100644
--- a/doc/user/user_commands/kvno.rst
+++ b/doc/user/user_commands/kvno.rst
@@ -10,13 +10,9 @@ SYNOPSIS
[**-c** *ccache*]
[**-e** *etype*]
[**-q**]
-[**-h**]
+[**-u** | **-S** *sname*]
[**-P**]
-[**-S** *sname*]
-[**-I** *for_user*]
-[**-U** *for_user*]
-[**-F** *cert_file*]
-[**--u2u** *ccache*]
+[[{**-F** *cert_file* | {**-I** | **-U**} *for_user*} [**-P**]] | **--u2u** *ccache*]
*service1 service2* ...
@@ -39,13 +35,18 @@ OPTIONS
of all the services named on the command line. This is useful in
certain backward compatibility situations.
+**-k** *keytab*
+ Decrypt the acquired tickets using *keytab* to confirm their
+ validity.
+
**-q**
Suppress printing output when successful. If a service ticket
cannot be obtained, an error message will still be printed and
kvno will exit with nonzero status.
-**-h**
- Prints a usage statement and exits.
+**-u**
+ Use the unknown name type in requested service principal names.
+ This option Cannot be used with *-S*.
**-P**
Specifies that the *service1 service2* ... arguments are to be
@@ -76,16 +77,17 @@ OPTIONS
**--cached-only**
Only retrieve credentials already present in the cache, not from
- the KDC.
+ the KDC. (Added in release 1.19.)
**--no-store**
Do not store retrieved credentials in the cache. If
**--out-cache** is also specified, credentials will still be
- stored into the output credential cache.
+ stored into the output credential cache. (Added in release 1.19.)
**--out-cache** *ccache*
Initialize *ccache* and store all retrieved credentials into it.
- Do not store acquired credentials in the input cache.
+ Do not store acquired credentials in the input cache. (Added in
+ release 1.19.)
**--u2u** *ccache*
Requests a user-to-user ticket. *ccache* must contain a local
diff --git a/src/clients/kvno/kvno.c b/src/clients/kvno/kvno.c
index 9d85864f6..c5f6bf700 100644
--- a/src/clients/kvno/kvno.c
+++ b/src/clients/kvno/kvno.c
@@ -38,15 +38,18 @@
static char *prog;
static int quiet = 0;
+#define XUSAGE_BREAK "\n\t"
+
static void
xusage()
{
- fprintf(stderr, _("usage: %s [-C] [-u] [-c ccache] [-e etype]\n"), prog);
- fprintf(stderr, _("\t[-k keytab] [-S sname] [{-I | -U} for_user | "
- "[-F cert_file] [-P]]\n"));
- fprintf(stderr, _("\t[--cached-only] [--no-store] [--out-cache ccache] "
- "[--u2u ccache]\n"));
- fprintf(stderr, _("\tservice1 service2 ...\n"));
+ fprintf(stderr, _("usage: %s [-c ccache] [-e etype] [-k keytab] [-q] "
+ "[-u | -S sname]" XUSAGE_BREAK
+ "[[{-F cert_file | {-I | -U} for_user} [-P]] | "
+ "--u2u ccache]" XUSAGE_BREAK
+ "[--cached-only] [--no-store] [--out-cache] "
+ "service1 service2 ...\n"),
+ prog);
exit(1);
}
diff --git a/src/man/kvno.man b/src/man/kvno.man
index b9f6739eb..22318324d 100644
--- a/src/man/kvno.man
+++ b/src/man/kvno.man
@@ -36,13 +36,9 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
[\fB\-c\fP \fIccache\fP]
[\fB\-e\fP \fIetype\fP]
[\fB\-q\fP]
-[\fB\-h\fP]
+[\fB\-u\fP | \fB\-S\fP \fIsname\fP]
[\fB\-P\fP]
-[\fB\-S\fP \fIsname\fP]
-[\fB\-I\fP \fIfor_user\fP]
-[\fB\-U\fP \fIfor_user\fP]
-[\fB\-F\fP \fIcert_file\fP]
-[\fB\-\-u2u\fP \fIccache\fP]
+[[{\fB\-F\fP \fIcert_file\fP | {\fB\-I\fP | \fB\-U\fP} \fIfor_user\fP} [\fB\-P\fP]] | \fB\-\-u2u\fP \fIccache\fP]
\fIservice1 service2\fP ...
.SH DESCRIPTION
.sp
@@ -60,13 +56,18 @@ Specifies the enctype which will be requested for the session key
of all the services named on the command line. This is useful in
certain backward compatibility situations.
.TP
+\fB\-k\fP \fIkeytab\fP
+Decrypt the acquired tickets using \fIkeytab\fP to confirm their
+validity.
+.TP
\fB\-q\fP
Suppress printing output when successful. If a service ticket
cannot be obtained, an error message will still be printed and
kvno will exit with nonzero status.
.TP
-\fB\-h\fP
-Prints a usage statement and exits.
+\fB\-u\fP
+Use the unknown name type in requested service principal names.
+This option Cannot be used with \fI\-S\fP\&.
.TP
\fB\-P\fP
Specifies that the \fIservice1 service2\fP ... arguments are to be
@@ -97,16 +98,17 @@ certificate file must be in PEM format.
.TP
\fB\-\-cached\-only\fP
Only retrieve credentials already present in the cache, not from
-the KDC.
+the KDC. (Added in release 1.19.)
.TP
\fB\-\-no\-store\fP
Do not store retrieved credentials in the cache. If
\fB\-\-out\-cache\fP is also specified, credentials will still be
-stored into the output credential cache.
+stored into the output credential cache. (Added in release 1.19.)
.TP
\fB\-\-out\-cache\fP \fIccache\fP
Initialize \fIccache\fP and store all retrieved credentials into it.
-Do not store acquired credentials in the input cache.
+Do not store acquired credentials in the input cache. (Added in
+release 1.19.)
.TP
\fB\-\-u2u\fP \fIccache\fP
Requests a user\-to\-user ticket. \fIccache\fP must contain a local

View File

@ -18,7 +18,7 @@ Summary: The Kerberos network authentication system
Name: krb5
Version: 1.18.2
# for prerelease, should be e.g., 0.% {prerelease}.1% { ?dist } (without spaces)
Release: 24%{?dist}
Release: 28%{?dist}
# rharwood has trust path to signing key and verifies on check-in
Source0: https://web.mit.edu/kerberos/dist/krb5/1.18/krb5-%{version}%{prerelease}.tar.gz
@ -72,6 +72,15 @@ Patch33: Allow-gss_unwrap_iov-of-unpadded-RC4-tokens.patch
Patch34: Ignore-bad-enctypes-in-krb5_string_to_keysalts.patch
Patch35: Fix-leak-in-KERB_AP_OPTIONS_CBT-server-support.patch
Patch36: Fix-input-length-checking-in-SPNEGO-DER-decoding.patch
Patch37: Add-three-kvno-options-from-Heimdal-kgetcred.patch
Patch38: Unify-kvno-option-documentation.patch
Patch39: Improve-KDC-alias-checking-for-S4U-requests.patch
Patch40: Adjust-KDC-alias-helper-function-contract.patch
Patch41: Allow-aliases-when-matching-U2U-second-ticket.patch
Patch42: Refactor-KDC-authdata-list-management-helpers.patch
Patch43: Avoid-passing-DB-entry-structures-in-KDC.patch
Patch44: Minimize-usage-of-tgs_server-in-KDC.patch
Patch45: Fix-minor-static-analysis-defects.patch
License: MIT
URL: https://web.mit.edu/kerberos/www/
@ -127,7 +136,6 @@ to install this package.
%package libs
Summary: The non-admin shared libraries used by Kerberos 5
Requires: openssl-libs >= 1:1.1.1d-4
Requires: openssl-libs < 1:3.0.0
Requires: coreutils, gawk, grep, sed
Requires: keyutils-libs >= 1.5.8
Requires: /etc/crypto-policies/back-ends/krb5.config
@ -633,6 +641,18 @@ exit 0
%{_libdir}/libkadm5srv_mit.so.*
%changelog
* Fri Oct 23 2020 Robbie Harwood <rharwood@redhat.com> - 1.18.2-28
- Fix minor static analysis defects
* Wed Oct 21 2020 Robbie Harwood <rharwood@redhat.com> - 1.18.2-27
- Fix build of previous
* Wed Oct 21 2020 Robbie Harwood <rharwood@redhat.com> - 1.18.2-26
- Cross-realm s4u fixes for samba (#1836630)
* Thu Oct 15 2020 Robbie Harwood <rharwood@redhat.com> - 1.18.2-25
- Unify kvno option documentation
* Fri Oct 02 2020 Robbie Harwood <rharwood@redhat.com> - 1.18.2-24
- Add md5 override to krad