diff options
author | Greg Hudson <ghudson@mit.edu> | 2015-03-15 15:56:34 -0400 |
---|---|---|
committer | Greg Hudson <ghudson@mit.edu> | 2015-07-22 12:22:47 -0400 |
commit | e64140aba967e3d8a785d4f83b1477ed0bdc85bd (patch) | |
tree | fddde1abf876ad9f7392d6eb115f31cf72c5a8ad | |
parent | 24dc279b9b14fe8d6674fdd2a9210c1e1fb52e37 (diff) | |
download | krb5-e64140aba967e3d8a785d4f83b1477ed0bdc85bd.zip krb5-e64140aba967e3d8a785d4f83b1477ed0bdc85bd.tar.gz krb5-e64140aba967e3d8a785d4f83b1477ed0bdc85bd.tar.bz2 |
Test auth indicator functionality
Modify adata.c to handle CAMMAC containers and display auth
indicators. Modify the test preauth module to transmit a list of
indicators (specified by a gic opt) from the clpreauth module to the
kdcpreauth module and assert them to the KDC. Add a new s4u2proxy
test harness in src/tests which can be used to exercise S4U2Proxy
without going through GSSAPI, using a second ccache containing an
existing evidence ticket.
Add tests to t_authdata.py to exercise a variety of ticket issuing
scenarios and verify that the correct auth indicators appear in each
ticket.
ticket: 8157
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | src/plugins/preauth/test/cltest.c | 66 | ||||
-rw-r--r-- | src/plugins/preauth/test/kdctest.c | 29 | ||||
-rw-r--r-- | src/tests/Makefile.in | 11 | ||||
-rw-r--r-- | src/tests/adata.c | 60 | ||||
-rw-r--r-- | src/tests/s4u2proxy.c | 110 | ||||
-rw-r--r-- | src/tests/t_authdata.py | 125 |
7 files changed, 381 insertions, 21 deletions
@@ -261,6 +261,7 @@ testlog /src/tests/rdreq /src/tests/responder /src/tests/s2p +/src/tests/s4u2proxy /src/tests/t_init_creds /src/tests/t_localauth diff --git a/src/plugins/preauth/test/cltest.c b/src/plugins/preauth/test/cltest.c index fe63ed9..d101a21 100644 --- a/src/plugins/preauth/test/cltest.c +++ b/src/plugins/preauth/test/cltest.c @@ -32,9 +32,15 @@ /* * This module is used to test preauth interface features. At this time, the - * clpreauth module decrypts a message from the initial KDC padata using the - * reply key and prints it to stdout. (The unencrypted message "no key" can - * also be displayed.) An empty padata message is then sent to the KDC. + * clpreauth module does two things: + * + * - It decrypts a message from the initial KDC padata using the reply key and + * prints it to stdout. (The unencrypted message "no key" can also be + * displayed.) + * + * - It pulls an "indicators" attribute from the gic preauth options and sends + * it to the server, instructing the kdcpreauth module to assert one or more + * space-separated authentication indicators. */ #include "k5-int.h" @@ -44,6 +50,31 @@ static krb5_preauthtype pa_types[] = { TEST_PA_TYPE, 0 }; +struct client_state { + char *indicators; +}; + +static krb5_error_code +test_init(krb5_context context, krb5_clpreauth_moddata *moddata_out) +{ + struct client_state *st; + + st = malloc(sizeof(*st)); + assert(st != NULL); + st->indicators = NULL; + *moddata_out = (krb5_clpreauth_moddata)st; + return 0; +} + +static void +test_fini(krb5_context context, krb5_clpreauth_moddata moddata) +{ + struct client_state *st = (struct client_state *)moddata; + + free(st->indicators); + free(st); +} + static krb5_error_code test_process(krb5_context context, krb5_clpreauth_moddata moddata, krb5_clpreauth_modreq modreq, krb5_get_init_creds_opt *opt, @@ -53,17 +84,21 @@ test_process(krb5_context context, krb5_clpreauth_moddata moddata, krb5_prompter_fct prompter, void *prompter_data, krb5_pa_data ***out_pa_data) { + struct client_state *st = (struct client_state *)moddata; krb5_error_code ret; krb5_pa_data **list, *pa; krb5_keyblock *k; krb5_enc_data enc; krb5_data plain; + const char *indstr; if (pa_data->length == 6 && memcmp(pa_data->contents, "no key", 6) == 0) { printf("no key\n"); } else { + /* This fails during s4u_identify_user(), so don't assert. */ ret = cb->get_as_key(context, rock, &k); - assert(!ret); + if (ret) + return ret; ret = alloc_data(&plain, pa_data->length); assert(!ret); enc.enctype = k->enctype; @@ -74,19 +109,35 @@ test_process(krb5_context context, krb5_clpreauth_moddata moddata, free(plain.data); } + indstr = (st->indicators != NULL) ? st->indicators : ""; list = k5calloc(2, sizeof(*list), &ret); assert(!ret); pa = k5alloc(sizeof(*pa), &ret); assert(!ret); pa->pa_type = TEST_PA_TYPE; - pa->contents = NULL; - pa->length = 0; + pa->contents = (uint8_t *)strdup(indstr); + assert(pa->contents != NULL); + pa->length = strlen(indstr); list[0] = pa; list[1] = NULL; *out_pa_data = list; return 0; } +static krb5_error_code +test_gic_opt(krb5_context kcontext, krb5_clpreauth_moddata moddata, + krb5_get_init_creds_opt *opt, const char *attr, const char *value) +{ + struct client_state *st = (struct client_state *)moddata; + + if (strcmp(attr, "indicators") == 0) { + free(st->indicators); + st->indicators = strdup(value); + assert(st->indicators != NULL); + } + return 0; +} + krb5_error_code clpreauth_test_initvt(krb5_context context, int maj_ver, int min_ver, krb5_plugin_vtable vtable); @@ -102,6 +153,9 @@ clpreauth_test_initvt(krb5_context context, int maj_ver, vt = (krb5_clpreauth_vtable)vtable; vt->name = "test"; vt->pa_type_list = pa_types; + vt->init = test_init; + vt->fini = test_fini; vt->process = test_process; + vt->gic_opts = test_gic_opt; return 0; } diff --git a/src/plugins/preauth/test/kdctest.c b/src/plugins/preauth/test/kdctest.c index ba5125a..c824626 100644 --- a/src/plugins/preauth/test/kdctest.c +++ b/src/plugins/preauth/test/kdctest.c @@ -31,12 +31,17 @@ */ /* - * This module is used to test preauth interface features. Currently, it - * retrieves the "teststring" attribute from the client principal and sends it - * to the client, encrypted in the reply key. (The plain text "no key" is sent - * if there is no reply key; the encrypted message "no attr" is sent if there - * is no string attribute.) Upon receiving padata from the client, it always - * succeeds in preauthenticating the request. + * This module is used to test preauth interface features. Currently, the + * kdcpreauth module does two things: + * + * - It retrieves the "teststring" attribute from the client principal and + * sends it to the client, encrypted in the reply key. (The plain text "no + * key" is sent if there is no reply key; the encrypted message "no attr" is + * sent if there is no string attribute.) + * + * - It receives a space-separated list from the clpreauth module and asserts + * each string as an authentication indicator. It always succeeds in + * pre-authenticating the request. * * To use this module, a test script should: * - Register this module and the corresponding clpreauth module @@ -98,6 +103,18 @@ test_verify(krb5_context context, krb5_data *req_pkt, krb5_kdc_req *request, krb5_kdcpreauth_moddata moddata, krb5_kdcpreauth_verify_respond_fn respond, void *arg) { + krb5_error_code ret; + char *str, *ind, *toksave = NULL; + + str = k5memdup0(data->contents, data->length, &ret); + if (ret) + abort(); + ind = strtok_r(str, " ", &toksave); + while (ind != NULL) { + cb->add_auth_indicator(context, rock, ind); + ind = strtok_r(NULL, " ", &toksave); + } + free(str); enc_tkt_reply->flags |= TKT_FLG_PRE_AUTH; (*respond)(arg, 0, NULL, NULL, NULL); } diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in index cd6fc4a..feeeb43 100644 --- a/src/tests/Makefile.in +++ b/src/tests/Makefile.in @@ -6,9 +6,9 @@ SUBDIRS = resolve asn.1 create hammer verify gssapi dejagnu shlib \ RUN_SETUP = @KRB5_RUN_ENV@ KRB5_KDC_PROFILE=kdc.conf KRB5_CONFIG=krb5.conf OBJS= adata.o etinfo.o gcred.o hist.o hrealm.o kdbtest.o plugorder.o \ - t_init_creds.o t_localauth.o rdreq.o responder.o s2p.o + t_init_creds.o t_localauth.o rdreq.o responder.o s2p.o s4u2proxy.o EXTRADEPSRCS= adata.c etinfo.c gcred.c hist.c hrealm.c kdbtest.c plugorder.c \ - t_init_creds.c t_localauth.c rdreq.o responder.c s2p.c + t_init_creds.c t_localauth.c rdreq.o responder.c s2p.c s4u2proxy.c TEST_DB = ./testdb TEST_REALM = FOO.TEST.REALM @@ -51,6 +51,9 @@ responder: responder.o $(KRB5_BASE_DEPLIBS) s2p: s2p.o $(KRB5_BASE_DEPLIBS) $(CC_LINK) -o $@ s2p.o $(KRB5_BASE_LIBS) +s4u2proxy: s4u2proxy.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ s4u2proxy.o $(KRB5_BASE_LIBS) + t_init_creds: t_init_creds.o $(KRB5_BASE_DEPLIBS) $(CC_LINK) -o $@ t_init_creds.o $(KRB5_BASE_LIBS) @@ -104,7 +107,7 @@ kdb_check: kdc.conf krb5.conf $(RM) $(TEST_DB)* stash_file check-pytests:: adata etinfo gcred hist hrealm kdbtest plugorder rdreq -check-pytests:: responder s2p t_init_creds t_localauth unlockiter +check-pytests:: responder s2p s4u2proxy t_init_creds t_localauth unlockiter $(RUNPYTEST) $(srcdir)/t_general.py $(PYTESTFLAGS) $(RUNPYTEST) $(srcdir)/t_dump.py $(PYTESTFLAGS) $(RUNPYTEST) $(srcdir)/t_iprop.py $(PYTESTFLAGS) @@ -155,6 +158,6 @@ check-pytests:: responder s2p t_init_creds t_localauth unlockiter clean:: $(RM) gcred hist hrealm kdbtest plugorder rdreq responder s2p $(RM) adata etinfo gcred hist hrealm kdbtest plugorder rdreq responder - $(RM) s2p t_init_creds t_localauth krb5.conf kdc.conf + $(RM) s2p s4u2proxy t_init_creds t_localauth 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 ec63044..77f1708 100644 --- a/src/tests/adata.c +++ b/src/tests/adata.c @@ -45,9 +45,9 @@ * Multiple prefixes may be specified for nested container. * * In the output, authdata containers will be flattened and displayed with the - * above prefixes, with AD-KDC-ISSUED containers verified using the ticket - * session key. Nested containers only display the prefix for the innermost - * container. + * above prefixes or '+' for an AD-CAMMAC container. AD-KDC-ISSUED and + * AD-CAMMAC containers will be verified with the appropriate key. Nested + * containers only display the prefix for the innermost container. */ #include <k5-int.h> @@ -80,6 +80,8 @@ get_type_for_prefix(int prefix_byte) return KRB5_AUTHDATA_MANDATORY_FOR_KDC; if (prefix_byte == '^') return KRB5_AUTHDATA_KDC_ISSUED; + if (prefix_byte == '+') + return KRB5_AUTHDATA_CAMMAC; abort(); } @@ -92,6 +94,8 @@ get_prefix_byte(krb5_authdata *ad) return '!'; if (ad->ad_type == KRB5_AUTHDATA_KDC_ISSUED) return '^'; + if (ad->ad_type == KRB5_AUTHDATA_CAMMAC) + return '+'; abort(); } @@ -142,6 +146,28 @@ make_authdata(const char *typestr, const char *contents) return ad; } +/* Verify a CAMMAC's svc_verifier and return its contents. */ +static krb5_authdata ** +unwrap_cammac(krb5_authdata *ad, krb5_keyblock *tktkey) +{ + krb5_data *der_elements, ad_data = make_data(ad->contents, ad->length); + krb5_authdata **elements; + krb5_cammac *cammac; + krb5_boolean valid; + + check(decode_krb5_cammac(&ad_data, &cammac)); + check(encode_krb5_authdata(cammac->elements, &der_elements)); + assert(cammac->svc_verifier != NULL); + krb5_c_verify_checksum(ctx, tktkey, KRB5_KEYUSAGE_CAMMAC, der_elements, + &cammac->svc_verifier->checksum, &valid); + assert(valid); + elements = cammac->elements; + cammac->elements = NULL; + krb5_free_data(ctx, der_elements); + k5_free_cammac(ctx, cammac); + return elements; +} + static krb5_authdata ** get_container_contents(krb5_authdata *ad, krb5_keyblock *skey, krb5_keyblock *tktkey) @@ -150,11 +176,30 @@ get_container_contents(krb5_authdata *ad, krb5_keyblock *skey, if (ad->ad_type == KRB5_AUTHDATA_KDC_ISSUED) check(krb5_verify_authdata_kdc_issued(ctx, skey, ad, NULL, &inner_ad)); + else if (ad->ad_type == KRB5_AUTHDATA_CAMMAC) + inner_ad = unwrap_cammac(ad, tktkey); else check(krb5_decode_authdata_container(ctx, ad->ad_type, ad, &inner_ad)); return inner_ad; } +/* Decode and display authentication indicator authdata. */ +static void +display_auth_indicator(krb5_authdata *ad) +{ + krb5_data **strs, **p, d = make_data(ad->contents, ad->length); + + check(decode_utf8_strings(&d, &strs)); + printf("["); + for (p = strs; *p != NULL; p++) { + printf("%.*s", (int)(*p)->length, (*p)->data); + if (*(p + 1) != NULL) + printf(", "); + } + printf("]"); + k5_free_data_ptr_list(strs); +} + /* Display ad as either a hex dump or ASCII text. */ static void display_binary_or_ascii(krb5_authdata *ad) @@ -184,7 +229,8 @@ display_authdata(krb5_authdata *ad, krb5_keyblock *skey, krb5_keyblock *tktkey, if (ad->ad_type == KRB5_AUTHDATA_IF_RELEVANT || ad->ad_type == KRB5_AUTHDATA_MANDATORY_FOR_KDC || - ad->ad_type == KRB5_AUTHDATA_KDC_ISSUED) { + ad->ad_type == KRB5_AUTHDATA_KDC_ISSUED || + ad->ad_type == KRB5_AUTHDATA_CAMMAC) { /* Decode and display the contents. */ inner_ad = get_container_contents(ad, skey, tktkey); display_authdata_list(inner_ad, skey, tktkey, get_prefix_byte(ad)); @@ -194,7 +240,11 @@ display_authdata(krb5_authdata *ad, krb5_keyblock *skey, krb5_keyblock *tktkey, printf("%c", prefix_byte); printf("%d: ", (int)ad->ad_type); - display_binary_or_ascii(ad); + + if (ad->ad_type == KRB5_AUTHDATA_AUTH_INDICATOR) + display_auth_indicator(ad); + else + display_binary_or_ascii(ad); printf("\n"); } diff --git a/src/tests/s4u2proxy.c b/src/tests/s4u2proxy.c new file mode 100644 index 0000000..a6baeb6 --- /dev/null +++ b/src/tests/s4u2proxy.c @@ -0,0 +1,110 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/s4u2proxy.c - S4U2Proxy test harness */ +/* + * Copyright (C) 2015 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: s4u2proxy evccname targetname + * + * evccname contains an evidence ticket. The default ccache contains a TGT for + * the intermediate service. The default keytab contains a key for the + * intermediate service. An S4U2Proxy request is made to get a ticket from + * evccname's default principal to the target service. The resulting cred is + * stored in the default ccache. + */ + +#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); + } +} + +int +main(int argc, char **argv) +{ + krb5_context context; + krb5_ccache defcc, evcc; + krb5_principal client_name, int_name, target_name; + krb5_keytab defkt; + krb5_creds mcred, ev_cred, *new_cred; + krb5_ticket *ev_ticket; + + assert(argc == 3); + check(krb5_init_context(&context)); + + /* Open the default ccache, evidence ticket ccache, and default keytab. */ + check(krb5_cc_default(context, &defcc)); + check(krb5_cc_resolve(context, argv[1], &evcc)); + check(krb5_kt_default(context, &defkt)); + + /* Determine the client name, intermediate name, and target name. */ + check(krb5_cc_get_principal(context, evcc, &client_name)); + check(krb5_cc_get_principal(context, defcc, &int_name)); + check(krb5_parse_name(context, argv[2], &target_name)); + + /* Retrieve and decrypt the evidence ticket. */ + memset(&mcred, 0, sizeof(mcred)); + mcred.client = client_name; + mcred.server = int_name; + check(krb5_cc_retrieve_cred(context, evcc, 0, &mcred, &ev_cred)); + check(krb5_decode_ticket(&ev_cred.ticket, &ev_ticket)); + check(krb5_server_decrypt_ticket_keytab(context, defkt, ev_ticket)); + + /* 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, ev_ticket, &new_cred)); + + /* Store the new cred in the default ccache. */ + check(krb5_cc_store_cred(context, defcc, new_cred)); + + krb5_cc_close(context, defcc); + krb5_cc_close(context, evcc); + krb5_kt_close(context, defkt); + krb5_free_principal(context, client_name); + krb5_free_principal(context, int_name); + krb5_free_principal(context, target_name); + krb5_free_cred_contents(context, &ev_cred); + krb5_free_ticket(context, ev_ticket); + krb5_free_creds(context, new_cred); + return 0; +} diff --git a/src/tests/t_authdata.py b/src/tests/t_authdata.py index 0b8aaa6..8da206d 100644 --- a/src/tests/t_authdata.py +++ b/src/tests/t_authdata.py @@ -75,6 +75,131 @@ else: if '512: ' in out or '-42: ' in out: fail('SIGNTICKET or greet authdata seen for anonymous request') +realm.stop() + +# Test authentication indicators. Load the test preauth module so we +# can control the indicators asserted. +testpreauth = os.path.join(buildtop, 'plugins', 'preauth', 'test', 'test.so') +krb5conf = {'plugins': {'kdcpreauth': {'module': 'test:' + testpreauth}, + 'clpreauth': {'module': 'test:' + testpreauth, + 'disable': 'encrypted_timestamp'}}} +realm, realm2 = cross_realms(2, args=({'realm': 'LOCAL'}, + {'realm': 'FOREIGN'}), + krb5_conf=krb5conf, get_creds=False) +realm.run([kadminl, 'modprinc', '+requires_preauth', '-maxrenewlife', '2 days', + realm.user_princ]) +realm.run([kadminl, 'modprinc', '-maxrenewlife', '2 days', realm.host_princ]) +realm.extract_keytab(realm.krbtgt_princ, realm.keytab) +realm.extract_keytab(realm.host_princ, realm.keytab) +realm.extract_keytab('krbtgt/FOREIGN', realm.keytab) +realm2.extract_keytab(realm2.krbtgt_princ, realm.keytab) +realm2.extract_keytab(realm2.host_princ, realm.keytab) +realm2.extract_keytab('krbtgt/LOCAL', realm.keytab) + +# AS request to local-realm service +realm.kinit(realm.user_princ, password('user'), + ['-X', 'indicators=indcl', '-r', '2d', '-S', realm.host_princ]) +out = realm.run(['./adata', realm.host_princ]) +if '+97: [indcl]' not in out: + fail('auth-indicator not seen for AS req to service') + +# Ticket modification request +realm.kinit(realm.user_princ, None, ['-R', '-S', realm.host_princ]) +out = realm.run(['./adata', realm.host_princ]) +if '+97: [indcl]' not in out: + fail('auth-indicator not seen for ticket modification request') + +# AS request to cross TGT +realm.kinit(realm.user_princ, password('user'), + ['-X', 'indicators=indcl', '-S', 'krbtgt/FOREIGN']) +out = realm.run(['./adata', 'krbtgt/FOREIGN']) +if '+97: [indcl]' not in out: + fail('auth-indicator not seen for AS req to cross-realm TGT') + +# AS request to local TGT (resulting creds are used for TGS tests) +realm.kinit(realm.user_princ, password('user'), ['-X', 'indicators=indcl']) +out = realm.run(['./adata', realm.krbtgt_princ]) +if '+97: [indcl]' not in out: + fail('auth-indicator not seen for normal AS req') + +# Local TGS request for local realm service +out = realm.run(['./adata', realm.host_princ]) +if '+97: [indcl]' not in out: + fail('auth-indicator not seen for local TGS req') + +# Local TGS request for cross TGT service +out = realm.run(['./adata', 'krbtgt/FOREIGN']) +if '+97: [indcl]' not in out: + fail('auth-indicator not seen for TGS req to cross-realm TGT') + +# We don't yet have support for passing auth indicators across realms, +# so just verify that indicators don't survive cross-realm requests. +out = realm.run(['./adata', realm2.krbtgt_princ]) +if '97:' in out: + fail('auth-indicator seen in cross TGT request to local TGT') +out = realm.run(['./adata', 'krbtgt/LOCAL@FOREIGN']) +if '97:' in out: + fail('auth-indicator seen in cross TGT request to cross TGT') +out = realm.run(['./adata', realm2.host_princ]) +if '97:' in out: + fail('auth-indicator seen in cross TGT request to service') + +# Test that the CAMMAC signature still works during a krbtgt rollover. +realm.run([kadminl, 'cpw', '-randkey', '-keepold', realm.krbtgt_princ]) +out = realm.run(['./adata', realm.host_princ]) +if '+97: [indcl]' not in out: + fail('auth-indicator not seen for local TGS req after krbtgt rotation') + +# Test indicator enforcement. +realm.addprinc('restricted') +realm.run([kadminl, 'setstr', 'restricted', 'require_auth', 'superstrong']) +out = realm.run([kvno, 'restricted'], expected_code=1) +if 'KDC policy rejects request' not in out: + fail('expected error not seen for auth indicator enforcement') +realm.run([kadminl, 'setstr', 'restricted', 'require_auth', 'indcl']) +realm.run([kvno, 'restricted']) +realm.kinit(realm.user_princ, password('user'), ['-X', 'indicators=ind1 ind2']) +realm.run([kvno, 'restricted'], expected_code=1) +realm.run([kadminl, 'setstr', 'restricted', 'require_auth', 'a b c ind2']) +realm.run([kvno, 'restricted']) + +realm.stop() + +# Load the test KDB module to allow successful S4U2Proxy +# auth-indicator requests. +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'}, + 'service/2': {'keys': 'aes128-cts'}} +kdcconf = {'realms': {'$realm': {'database_module': 'test'}}, + 'dbmodules': {'test': {'db_library': 'test', + 'princs': testprincs, + 'delegation': {'service/1': 'service/2'}}}} +realm = K5Realm(krb5_conf=krb5conf, kdc_conf=kdcconf, create_kdb=False) +usercache = 'FILE:' + os.path.join(realm.testdir, 'usercache') +realm.extract_keytab(realm.krbtgt_princ, realm.keytab) +realm.extract_keytab('krbtgt/FOREIGN', realm.keytab) +realm.extract_keytab(realm.user_princ, realm.keytab) +realm.extract_keytab('service/1', realm.keytab) +realm.extract_keytab('service/2', realm.keytab) +realm.start_kdc() + +# S4U2Self (should have no indicators since client did not authenticate) +realm.kinit('service/1', None, ['-k', '-f', '-X', 'indicators=inds1']) +realm.run([kvno, '-U', 'user', 'service/1']) +out = realm.run(['./adata', '-p', realm.user_princ, 'service/1']) +if '97:' in out: + fail('auth-indicator present in S4U2Self response') + +# S4U2Proxy (indicators should come from evidence ticket, not TGT) +realm.kinit(realm.user_princ, None, ['-k', '-f', '-X', 'indicators=indcl', + '-S', 'service/1', '-c', usercache]) +realm.run(['./s4u2proxy', usercache, 'service/2']) +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') + # KDB authdata is not tested here; we would need a test KDB module to # generate authdata, and also some additions to the test harness. The # current rules we would want to test are: |