diff options
author | Isaac Boukris <iboukris@gmail.com> | 2019-12-12 03:20:44 +0100 |
---|---|---|
committer | Greg Hudson <ghudson@mit.edu> | 2020-01-24 21:59:07 -0500 |
commit | 8642b06696fd7fca68aae475bd4113be5a1658cb (patch) | |
tree | 627f352db6c898678edfacf3c108b9388e7d48dc | |
parent | cad856e8a51c0b22ec2c41db02c6a56c433e5b20 (diff) | |
download | krb5-8642b06696fd7fca68aae475bd4113be5a1658cb.zip krb5-8642b06696fd7fca68aae475bd4113be5a1658cb.tar.gz krb5-8642b06696fd7fca68aae475bd4113be5a1658cb.tar.bz2 |
Add tests for S4U request-authdata handling
In adata.c, look up the server in the keytab by ticket->server (which
has the canonicalized realm), to allow testing of cross-realm RBCD
(although unused for now).
In s4u2proxy.c, set KRB5_GC_CANONICALIZE to support RBCD, and add an
authdata request option. Add an s4u2self test harness with authdata
request option.
[ghudson@mit.edu: minor code simplifications; edited commit message]
(cherry picked from commit 2d039a2b4c3ba6d71da8fcf76658dc63bc659f0c)
ticket: 8866
version_fixed: 1.18
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | src/tests/Makefile.in | 11 | ||||
-rw-r--r-- | src/tests/adata.c | 4 | ||||
-rw-r--r-- | src/tests/s4u2proxy.c | 37 | ||||
-rw-r--r-- | src/tests/s4u2self.c | 128 | ||||
-rw-r--r-- | src/tests/t_authdata.py | 22 |
6 files changed, 195 insertions, 8 deletions
@@ -444,6 +444,7 @@ local.properties /src/tests/responder /src/tests/s2p /src/tests/s4u2proxy +/src/tests/s4u2self /src/tests/unlockiter /src/tests/asn.1/expected_encode.out diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in index 81ca4cb..3f88f17 100644 --- a/src/tests/Makefile.in +++ b/src/tests/Makefile.in @@ -8,10 +8,10 @@ RUN_DB_TEST = $(RUN_SETUP) KRB5_KDC_PROFILE=kdc.conf KRB5_CONFIG=krb5.conf \ OBJS= adata.o etinfo.o forward.o gcred.o hist.o hooks.o hrealm.o \ icinterleave.o icred.o kdbtest.o localauth.o plugorder.o rdreq.o \ - replay.o responder.o s2p.o s4u2proxy.o unlockiter.o + replay.o responder.o s2p.o s4u2self.o s4u2proxy.o unlockiter.o EXTRADEPSRCS= adata.c etinfo.c forward.c gcred.c hist.c hooks.c hrealm.c \ icinterleave.c icred.c kdbtest.c localauth.c plugorder.c rdreq.c \ - replay.c responder.c s2p.c s4u2proxy.c unlockiter.c + replay.c responder.c s2p.c s4u2self.c s4u2proxy.c unlockiter.c TEST_DB = ./testdb TEST_REALM = FOO.TEST.REALM @@ -72,6 +72,9 @@ responder: responder.o $(KRB5_BASE_DEPLIBS) s2p: s2p.o $(KRB5_BASE_DEPLIBS) $(CC_LINK) -o $@ s2p.o $(KRB5_BASE_LIBS) +s4u2self: s4u2self.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ s4u2self.o $(KRB5_BASE_LIBS) + s4u2proxy: s4u2proxy.o $(KRB5_BASE_DEPLIBS) $(CC_LINK) -o $@ s4u2proxy.o $(KRB5_BASE_LIBS) @@ -117,7 +120,7 @@ kdb_check: kdc.conf krb5.conf check-pytests: adata etinfo forward gcred hist hooks hrealm icinterleave icred check-pytests: kdbtest localauth plugorder rdreq replay responder s2p s4u2proxy -check-pytests: unlockiter +check-pytests: unlockiter s4u2self $(RUNPYTEST) $(srcdir)/t_general.py $(PYTESTFLAGS) $(RUNPYTEST) $(srcdir)/t_hooks.py $(PYTESTFLAGS) $(RUNPYTEST) $(srcdir)/t_dump.py $(PYTESTFLAGS) @@ -180,7 +183,7 @@ check-pytests: unlockiter clean: $(RM) adata etinfo forward gcred hist hooks hrealm icinterleave icred $(RM) kdbtest localauth plugorder rdreq replay responder s2p s4u2proxy - $(RM) unlockiter + $(RM) unlockiter s4u2self $(RM) krb5.conf kdc.conf $(RM) -rf kdc_realm/sandbox ldap $(RM) au.log diff --git a/src/tests/adata.c b/src/tests/adata.c index df77c80..d3bd08e 100644 --- a/src/tests/adata.c +++ b/src/tests/adata.c @@ -303,9 +303,11 @@ main(int argc, char **argv) check(krb5_get_credentials(ctx, KRB5_GC_NO_STORE, ccache, &in_creds, &creds)); + assert(in_creds.authdata == NULL || creds->authdata != NULL); + check(krb5_decode_ticket(&creds->ticket, &ticket)); check(krb5_kt_default(ctx, &keytab)); - check(krb5_kt_get_entry(ctx, keytab, server, ticket->enc_part.kvno, + check(krb5_kt_get_entry(ctx, keytab, ticket->server, ticket->enc_part.kvno, ticket->enc_part.enctype, &ktent)); check(krb5_decrypt_tkt_part(ctx, &ktent.key, ticket)); diff --git a/src/tests/s4u2proxy.c b/src/tests/s4u2proxy.c index 28bff61..4adf6ac 100644 --- a/src/tests/s4u2proxy.c +++ b/src/tests/s4u2proxy.c @@ -31,7 +31,7 @@ */ /* - * Usage: s4u2proxy evccname targetname + * Usage: s4u2proxy evccname targetname [ad-type ad-contents] * * evccname contains an evidence ticket. The default ccache contains a TGT for * the intermediate service. The default keytab contains a key for the @@ -57,6 +57,28 @@ check(krb5_error_code code) } } +static krb5_authdata ** +make_request_authdata(int type, const char *contents) +{ + krb5_authdata *ad; + krb5_authdata **req_authdata; + + ad = malloc(sizeof(*ad)); + assert(ad != NULL); + ad->magic = KV5M_AUTHDATA; + ad->ad_type = type; + ad->length = strlen(contents); + ad->contents = (unsigned char *)strdup(contents); + assert(ad->contents != NULL); + + req_authdata = malloc(2 * sizeof(*req_authdata)); + assert(req_authdata != NULL); + req_authdata[0] = ad; + req_authdata[1] = NULL; + + return req_authdata; +} + int main(int argc, char **argv) { @@ -66,6 +88,12 @@ main(int argc, char **argv) krb5_keytab defkt; krb5_creds mcred, ev_cred, *new_cred; krb5_ticket *ev_ticket; + krb5_authdata **req_authdata = NULL; + + if (argc == 5) { + req_authdata = make_request_authdata(atoi(argv[3]), argv[4]); + argc -= 2; + } assert(argc == 3); check(krb5_init_context(&context)); @@ -91,12 +119,16 @@ main(int argc, char **argv) /* Make an S4U2Proxy request for the target service. */ mcred.client = client_name; mcred.server = target_name; - check(krb5_get_credentials_for_proxy(context, KRB5_GC_NO_STORE, defcc, + mcred.authdata = req_authdata; + check(krb5_get_credentials_for_proxy(context, KRB5_GC_NO_STORE | + KRB5_GC_CANONICALIZE, defcc, &mcred, ev_ticket, &new_cred)); /* Store the new cred in the default ccache. */ check(krb5_cc_store_cred(context, defcc, new_cred)); + assert(req_authdata == NULL || new_cred->authdata != NULL); + krb5_cc_close(context, defcc); krb5_cc_close(context, evcc); krb5_kt_close(context, defkt); @@ -106,6 +138,7 @@ main(int argc, char **argv) krb5_free_cred_contents(context, &ev_cred); krb5_free_ticket(context, ev_ticket); krb5_free_creds(context, new_cred); + krb5_free_authdata(context, req_authdata); krb5_free_context(context); return 0; } diff --git a/src/tests/s4u2self.c b/src/tests/s4u2self.c new file mode 100644 index 0000000..c8e4822 --- /dev/null +++ b/src/tests/s4u2self.c @@ -0,0 +1,128 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2019 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Usage: s4u2self user self out_cache [ad-type ad-contents] + * + * The default ccache contains a TGT for the intermediate service self. An + * S4U2Self request is made to self. The resulting cred is stored in + * out_cache. + */ + +#include <k5-int.h> + +static krb5_context ctx; + +static void +check(krb5_error_code code) +{ + const char *errmsg; + + if (code) { + errmsg = krb5_get_error_message(ctx, code); + fprintf(stderr, "%s\n", errmsg); + krb5_free_error_message(ctx, errmsg); + exit(1); + } +} + +static krb5_authdata ** +make_request_authdata(int type, const char *contents) +{ + krb5_authdata *ad; + krb5_authdata **req_authdata; + + ad = malloc(sizeof(*ad)); + assert(ad != NULL); + ad->magic = KV5M_AUTHDATA; + ad->ad_type = type; + ad->length = strlen(contents); + ad->contents = (unsigned char *)strdup(contents); + assert(ad->contents != NULL); + + req_authdata = malloc(2 * sizeof(*req_authdata)); + assert(req_authdata != NULL); + req_authdata[0] = ad; + req_authdata[1] = NULL; + + return req_authdata; +} + +int +main(int argc, char **argv) +{ + krb5_context context; + krb5_ccache defcc, ocache; + krb5_principal client, self; + krb5_creds mcred, *new_cred; + krb5_authdata **req_authdata = NULL; + + if (argc == 6) { + req_authdata = make_request_authdata(atoi(argv[4]), argv[5]); + argc -= 2; + } + + assert(argc == 4); + check(krb5_init_context(&context)); + + /* Open the default ccache. */ + check(krb5_cc_default(context, &defcc)); + + check(krb5_parse_name(context, argv[1], &client)); + check(krb5_parse_name(context, argv[2], &self)); + + memset(&mcred, 0, sizeof(mcred)); + mcred.client = client; + mcred.server = self; + mcred.authdata = req_authdata; + check(krb5_get_credentials_for_user(context, KRB5_GC_NO_STORE | + KRB5_GC_CANONICALIZE, defcc, + &mcred, NULL, &new_cred)); + + if (strcmp(argv[3], "-") == 0) { + check(krb5_cc_store_cred(context, defcc, new_cred)); + } else { + check(krb5_cc_resolve(context, argv[3], &ocache)); + check(krb5_cc_initialize(context, ocache, new_cred->client)); + check(krb5_cc_store_cred(context, ocache, new_cred)); + krb5_cc_close(context, ocache); + } + + assert(req_authdata == NULL || new_cred->authdata != NULL); + + krb5_cc_close(context, defcc); + krb5_free_principal(context, client); + krb5_free_principal(context, self); + krb5_free_creds(context, new_cred); + krb5_free_authdata(context, req_authdata); + krb5_free_context(context); + return 0; +} diff --git a/src/tests/t_authdata.py b/src/tests/t_authdata.py index 9b41bc0..44965dd 100644 --- a/src/tests/t_authdata.py +++ b/src/tests/t_authdata.py @@ -193,7 +193,9 @@ realm2.stop() testprincs = {'krbtgt/KRBTEST.COM': {'keys': 'aes128-cts'}, 'krbtgt/FOREIGN': {'keys': 'aes128-cts'}, 'user': {'keys': 'aes128-cts', 'flags': '+preauth'}, - 'service/1': {'keys': 'aes128-cts', 'flags': '+preauth'}, + 'user2': {'keys': 'aes128-cts', 'flags': '+preauth'}, + 'service/1': {'keys': 'aes128-cts', + 'flags': '+ok_to_auth_as_delegate'}, 'service/2': {'keys': 'aes128-cts'}, 'noauthdata': {'keys': 'aes128-cts', 'flags': '+no_auth_data_required'}} @@ -219,6 +221,11 @@ out = realm.run(['./adata', '-p', realm.user_princ, 'service/1']) if '97:' in out: fail('auth-indicator present in S4U2Self response') +# Get another S4U2Self ticket with requested authdata. +realm.run(['./s4u2self', 'user', 'service/1', '-', '-2', 'self_ad']) +realm.run(['./adata', '-p', realm.user_princ, 'service/1', '-2', 'self_ad'], + expected_msg=' -2: self_ad') + # S4U2Proxy (indicators should come from evidence ticket, not TGT) mark('S4U2Proxy (auth indicators from evidence ticket expected)') realm.kinit(realm.user_princ, None, ['-k', '-f', '-X', 'indicators=indcl', @@ -228,6 +235,19 @@ out = realm.run(['./adata', '-p', realm.user_princ, 'service/2']) if '+97: [indcl]' not in out or '[inds1]' in out: fail('correct auth-indicator not seen for S4U2Proxy req') +# Get another S4U2Proxy ticket including request-authdata. +realm.run(['./s4u2proxy', usercache, 'service/2', '-2', 'proxy_ad']) +realm.run(['./adata', '-p', realm.user_princ, 'service/2', '-2', 'proxy_ad'], + expected_msg=' -2: proxy_ad') + +# Get an S4U2Proxy ticket using an evidence ticket obtained by S4U2Self, +# with request authdata in both steps. +realm.run(['./s4u2self', 'user2', 'service/1', usercache, '-2', 'self_ad']) +realm.run(['./s4u2proxy', usercache, 'service/2', '-2', 'proxy_ad']) +out = realm.run(['./adata', '-p', 'user2', 'service/2', '-2', 'proxy_ad']) +if ' -2: self_ad' not in out or ' -2: proxy_ad' not in out: + fail('expected authdata not seen in S4U2Proxy ticket') + # Test alteration of auth indicators by KDB module (AS and TGS). realm.kinit(realm.user_princ, None, ['-k', '-X', 'indicators=dummy dbincr1']) realm.run(['./adata', realm.krbtgt_princ], expected_msg='+97: [dbincr2]') |