diff options
author | Greg Hudson <ghudson@mit.edu> | 2019-09-27 11:04:45 -0400 |
---|---|---|
committer | Greg Hudson <ghudson@mit.edu> | 2019-12-06 13:28:08 -0500 |
commit | 02b3171380d5683212ae1deae67a8c6cd19e290a (patch) | |
tree | 12cfc3748a0615130a50134fa9cd51611bf53beb /src/tests/gssapi | |
parent | c2ca2f26eaf817a6a7ed42257c380437ab802bd9 (diff) | |
download | krb5-02b3171380d5683212ae1deae67a8c6cd19e290a.zip krb5-02b3171380d5683212ae1deae67a8c6cd19e290a.tar.gz krb5-02b3171380d5683212ae1deae67a8c6cd19e290a.tar.bz2 |
Add NegoEx tests
Add a mock NegoEx-only GSS module, a test program which establishes a
SPNEGO context, and a Python script to exercise a variety of NegoEx
negotiation scenarios.
ticket: 8851
Diffstat (limited to 'src/tests/gssapi')
-rw-r--r-- | src/tests/gssapi/Makefile.in | 47 | ||||
-rw-r--r-- | src/tests/gssapi/deps | 4 | ||||
-rw-r--r-- | src/tests/gssapi/t_context.c | 60 | ||||
-rw-r--r-- | src/tests/gssapi/t_negoex.py | 142 |
4 files changed, 232 insertions, 21 deletions
diff --git a/src/tests/gssapi/Makefile.in b/src/tests/gssapi/Makefile.in index a7b8da4..5cc1e0f 100644 --- a/src/tests/gssapi/Makefile.in +++ b/src/tests/gssapi/Makefile.in @@ -10,10 +10,11 @@ LOCALINCLUDES = -I$(srcdir)/../../lib/gssapi/mechglue \ SRCS= $(srcdir)/ccinit.c $(srcdir)/ccrefresh.c $(srcdir)/common.c \ $(srcdir)/t_accname.c $(srcdir)/t_add_cred.c $(srcdir)/t_ccselect.c \ - $(srcdir)/t_ciflags.c $(srcdir)/t_credstore.c $(srcdir)/t_enctypes.c \ - $(srcdir)/t_err.c $(srcdir)/t_export_cred.c $(srcdir)/t_export_name.c \ - $(srcdir)/t_gssexts.c $(srcdir)/t_imp_cred.c $(srcdir)/t_imp_name.c \ - $(srcdir)/t_invalid.c $(srcdir)/t_inq_cred.c $(srcdir)/t_inq_ctx.c \ + $(srcdir)/t_ciflags.c $(srcdir)/t_context.c $(srcdir)/t_credstore.c \ + $(srcdir)/t_enctypes.c $(srcdir)/t_err.c $(srcdir)/t_export_cred.c \ + $(srcdir)/t_export_name.c $(srcdir)/t_gssexts.c \ + $(srcdir)/t_imp_cred.c $(srcdir)/t_imp_name.c $(srcdir)/t_invalid.c \ + $(srcdir)/t_inq_cred.c $(srcdir)/t_inq_ctx.c \ $(srcdir)/t_inq_mechs_name.c $(srcdir)/t_iov.c \ $(srcdir)/t_lifetime.c $(srcdir)/t_namingexts.c $(srcdir)/t_oid.c \ $(srcdir)/t_pcontok.c $(srcdir)/t_prf.c $(srcdir)/t_s4u.c \ @@ -21,20 +22,20 @@ SRCS= $(srcdir)/ccinit.c $(srcdir)/ccrefresh.c $(srcdir)/common.c \ $(srcdir)/t_spnego.c $(srcdir)/t_srcattrs.c OBJS= ccinit.o ccrefresh.o common.o t_accname.o t_add_cred.o t_ccselect.o \ - t_ciflags.o t_credstore.o t_enctypes.o t_err.o t_export_cred.o \ - t_export_name.o t_gssexts.o t_imp_cred.o t_imp_name.o t_invalid.o \ - t_inq_cred.o t_inq_ctx.o t_inq_mechs_name.o t_iov.o t_lifetime.o \ - t_namingexts.o t_oid.o t_pcontok.o t_prf.o t_s4u.o t_s4u2proxy_krb5.o \ - t_saslname.o t_spnego.o t_srcattrs.o + t_ciflags.o t_context.o t_credstore.o t_enctypes.o t_err.o \ + t_export_cred.o t_export_name.o t_gssexts.o t_imp_cred.o t_imp_name.o \ + t_invalid.o t_inq_cred.o t_inq_ctx.o t_inq_mechs_name.o t_iov.o \ + t_lifetime.o t_namingexts.o t_oid.o t_pcontok.o t_prf.o t_s4u.o \ + t_s4u2proxy_krb5.o t_saslname.o t_spnego.o t_srcattrs.o COMMON_DEPS= common.o $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS) COMMON_LIBS= common.o $(GSS_LIBS) $(KRB5_BASE_LIBS) -all: ccinit ccrefresh t_accname t_add_cred t_ccselect t_ciflags t_credstore \ - t_enctypes t_err t_export_cred t_export_name t_gssexts t_imp_cred \ - t_imp_name t_invalid t_inq_cred t_inq_ctx t_inq_mechs_name t_iov \ - t_lifetime t_namingexts t_oid t_pcontok t_prf t_s4u t_s4u2proxy_krb5 \ - t_saslname t_spnego t_srcattrs +all: ccinit ccrefresh t_accname t_add_cred t_ccselect t_ciflags t_context \ + t_credstore t_enctypes t_err t_export_cred t_export_name t_gssexts \ + t_imp_cred t_imp_name t_invalid t_inq_cred t_inq_ctx t_inq_mechs_name \ + t_iov t_lifetime t_namingexts t_oid t_pcontok t_prf t_s4u \ + t_s4u2proxy_krb5 t_saslname t_spnego t_srcattrs check-unix: t_oid $(RUN_TEST) ./t_invalid @@ -43,9 +44,9 @@ check-unix: t_oid $(RUN_TEST) ./t_imp_name check-pytests: ccinit ccrefresh t_accname t_add_cred t_ccselect t_ciflags \ - t_credstore t_enctypes t_err t_export_cred t_export_name t_imp_cred \ - t_inq_cred t_inq_ctx t_inq_mechs_name t_iov t_lifetime t_pcontok \ - t_s4u t_s4u2proxy_krb5 t_spnego t_srcattrs + t_context t_credstore t_enctypes t_err t_export_cred t_export_name \ + t_imp_cred t_inq_cred t_inq_ctx t_inq_mechs_name t_iov t_lifetime \ + t_pcontok t_s4u t_s4u2proxy_krb5 t_spnego t_srcattrs $(RUNPYTEST) $(srcdir)/t_gssapi.py $(PYTESTFLAGS) $(RUNPYTEST) $(srcdir)/t_ccselect.py $(PYTESTFLAGS) $(RUNPYTEST) $(srcdir)/t_client_keytab.py $(PYTESTFLAGS) @@ -53,6 +54,7 @@ check-pytests: ccinit ccrefresh t_accname t_add_cred t_ccselect t_ciflags \ $(RUNPYTEST) $(srcdir)/t_export_cred.py $(PYTESTFLAGS) $(RUNPYTEST) $(srcdir)/t_s4u.py $(PYTESTFLAGS) $(RUNPYTEST) $(srcdir)/t_authind.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_negoex.py $(PYTESTFLAGS) ccinit: ccinit.o $(KRB5_BASE_DEPLIBS) $(CC_LINK) -o ccinit ccinit.o $(KRB5_BASE_LIBS) @@ -66,6 +68,8 @@ t_ccselect: t_ccselect.o $(COMMON_DEPS) $(CC_LINK) -o $@ t_ccselect.o $(COMMON_LIBS) t_ciflags: t_ciflags.o $(COMMON_DEPS) $(CC_LINK) -o $@ t_ciflags.o $(COMMON_LIBS) +t_context: t_context.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_context.o $(COMMON_LIBS) t_credstore: t_credstore.o $(COMMON_DEPS) $(CC_LINK) -o $@ t_credstore.o $(COMMON_LIBS) t_enctypes: t_enctypes.o $(COMMON_DEPS) @@ -115,7 +119,8 @@ t_srcattrs: t_srcattrs.o $(COMMON_DEPS) clean: $(RM) ccinit ccrefresh t_accname t_add_cred t_ccselect t_ciflags - $(RM) t_credstore t_enctypes t_err t_export_cred t_export_name - $(RM) t_gssexts t_imp_cred t_imp_name t_invalid t_inq_cred t_inq_ctx - $(RM) t_inq_mechs_name t_iov t_lifetime t_namingexts t_oid t_pcontok - $(RM) t_prf t_s4u t_s4u2proxy_krb5 t_saslname t_spnego t_srcattrs + $(RM) t_context t_credstore t_enctypes t_err t_export_cred + $(RM) t_export_name t_gssexts t_imp_cred t_imp_name t_invalid + $(RM) t_inq_cred t_inq_ctx t_inq_mechs_name t_iov t_lifetime + $(RM) t_namingexts t_oid t_pcontok t_prf t_s4u t_s4u2proxy_krb5 + $(RM) t_saslname t_spnego t_srcattrs diff --git a/src/tests/gssapi/deps b/src/tests/gssapi/deps index c8905c9..acd0e96 100644 --- a/src/tests/gssapi/deps +++ b/src/tests/gssapi/deps @@ -41,6 +41,10 @@ $(OUTPRE)t_ciflags.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ common.h t_ciflags.c +$(OUTPRE)t_context.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + common.h t_context.c $(OUTPRE)t_credstore.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ diff --git a/src/tests/gssapi/t_context.c b/src/tests/gssapi/t_context.c new file mode 100644 index 0000000..65381ac --- /dev/null +++ b/src/tests/gssapi/t_context.c @@ -0,0 +1,60 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/gssapi/t_context.c - Simple context establishment harness */ +/* + * 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. + */ + +#include <stdio.h> +#include <stdlib.h> + +#include "common.h" + +int +main(int argc, char *argv[]) +{ + OM_uint32 minor, flags; + gss_name_t tname; + gss_ctx_id_t ictx, actx; + + if (argc < 2) { + fprintf(stderr, "Usage: %s targetname [acceptorname]\n", argv[0]); + return 1; + } + + tname = import_name(argv[1]); + + flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG; + establish_contexts(&mech_spnego, GSS_C_NO_CREDENTIAL, GSS_C_NO_CREDENTIAL, + tname, flags, &ictx, &actx, NULL, NULL, NULL); + + (void)gss_release_name(&minor, &tname); + (void)gss_delete_sec_context(&minor, &ictx, NULL); + (void)gss_delete_sec_context(&minor, &actx, NULL); + return 0; +} diff --git a/src/tests/gssapi/t_negoex.py b/src/tests/gssapi/t_negoex.py new file mode 100644 index 0000000..88470d2 --- /dev/null +++ b/src/tests/gssapi/t_negoex.py @@ -0,0 +1,142 @@ +from k5test import * + +# The next arc after 2.25 is supposed to be a single-integer UUID, but +# since our gss_str_to_oid() can't handle arc values that don't fit in +# an unsigned long, we use random unsigned 32-bit integers instead. +# The final octet if the OID encoding will be used to identify the +# mechanism when changing the behavior of just one mech. +nxtest_oid1 = '2.25.1414534758' # final octet is 102 (0x66) +nxtest_oid2 = '2.25.1175737388' # final octet is 44 (0x2C) +nxtest_path = os.path.join(buildtop, 'plugins', 'gssapi', 'negoextest', + 'gss_negoextest.so') + +# Test gss_add_cred(). +realm = K5Realm(create_kdb=False) +with open(realm.gss_mech_config, 'w') as f: + f.write('negoextest %s %s\n' % (nxtest_oid1, nxtest_path)) + f.write('negoextest %s %s\n' % (nxtest_oid2, nxtest_path)) + +def test(envvars, **kw): + # Python 3.5: e = {**realm.env, **vars} + e = realm.env.copy() + e.update(envvars) + realm.run(['./t_context', 'h:host'], env=e, **kw) + +# Test varying numbers of hops, and spot-check that messages are sent +# in the appropriate sequence. + +mark('One hop') +msgs = ('sending [0]INITIATOR_NEGO: c0a28569-66ac-0000-0000-000000000000 ' + 'd1b08469-2ca8-0000-0000-000000000000', + 'sending [1]INITIATOR_META_DATA: c0a28569-66ac', + 'sending [2]INITIATOR_META_DATA: d1b08469-2ca8', + 'sending [3]AP_REQUEST: c0a28569-66ac', + 'sending [4]VERIFY: c0a28569-66ac', + 'received [0]INITIATOR_NEGO: c0a28569-66ac-0000-0000-000000000000 ' + 'd1b08469-2ca8-0000-0000-000000000000', + 'received [1]INITIATOR_META_DATA: c0a28569-66ac', + 'received [2]INITIATOR_META_DATA: d1b08469-2ca8', + 'received [3]AP_REQUEST: c0a28569-66ac', + 'received [4]VERIFY: c0a28569-66ac', + 'sending [5]ACCEPTOR_NEGO: c0a28569-66ac-0000-0000-000000000000 ' + 'd1b08469-2ca8-0000-0000-000000000000', + 'sending [6]ACCEPTOR_META_DATA: c0a28569-66ac', + 'sending [7]ACCEPTOR_META_DATA: d1b08469-2ca8', + 'sending [8]VERIFY: c0a28569-66ac', + 'received [5]ACCEPTOR_NEGO: c0a28569-66ac-0000-0000-000000000000 ' + 'd1b08469-2ca8-0000-0000-000000000000', + 'received [6]ACCEPTOR_META_DATA: c0a28569-66ac', + 'received [7]ACCEPTOR_META_DATA: d1b08469-2ca8', + 'received [8]VERIFY: c0a28569-66ac') +test({'HOPS': '1'}, expected_trace=msgs) + +mark('Two hops') +msgs = ('sending [7]CHALLENGE', 'sending [8]VERIFY', 'received [8]VERIFY', + 'sending [9]VERIFY') +test({'HOPS': '2'}, expected_trace=msgs) + +mark('Three hops') +msgs = ('sending [8]AP_REQUEST', 'sending [9]VERIFY', 'received [8]AP_REQUEST', + 'sending [10]VERIFY') +test({'HOPS': '3'}, expected_trace=msgs) + +mark('Four hops') +msgs = ('sending [9]CHALLENGE', 'sending [10]VERIFY', 'received [9]CHALLENGE', + 'sending [11]VERIFY') +test({'HOPS': '4'}, expected_trace=msgs) + +mark('Early keys, three hops') +msgs = ('sending [4]VERIFY', 'sending [9]VERIFY', 'sending [10]AP_REQUEST') +test({'HOPS': '3', 'KEY': 'always'}, expected_trace=msgs) + +mark('Early keys, four hops') +msgs = ('sending [4]VERIFY', 'sending [9]VERIFY', 'sending [10]AP_REQUEST', + 'sending [11]CHALLENGE') +test({'HOPS': '4', 'KEY': 'always'}, expected_trace=msgs) + +mark('No keys') +test({'KEY': 'never'}, expected_code=1, expected_msg='No NegoEx verify key') + +mark('No optimistic token') +msgs = ('sending [3]ACCEPTOR_NEGO', 'sending [6]AP_REQUEST', + 'sending [7]VERIFY', 'sending [8]VERIFY') +test({'NEGOEX_NO_OPTIMISTIC_TOKEN': ''}, expected_trace=msgs) + +mark('First mech initiator query fail') +msgs = ('sending [0]INITIATOR_NEGO: d1b08469-2ca8-0000-0000-000000000000', + 'sending [2]AP_REQUEST', 'sending [3]VERIFY', + 'sending [4]ACCEPTOR_NEGO: d1b08469-2ca8-0000-0000-000000000000', + 'sending [6]VERIFY') +test({'INIT_QUERY_FAIL': '102'}, expected_trace=msgs) + +mark('First mech acceptor query fail') +msgs = ('sending [0]INITIATOR_NEGO: c0a28569-66ac-0000-0000-000000000000 ' + 'd1b08469-2ca8-0000-0000-000000000000', + 'sending [3]AP_REQUEST: c0a28569-66ac', + 'sending [4]VERIFY: c0a28569-66ac', + 'sending [5]ACCEPTOR_NEGO: d1b08469-2ca8-0000-0000-000000000000', + 'sending [7]AP_REQUEST: d1b08469-2ca8', + 'sending [8]VERIFY: d1b08469-2ca8', + 'sending [9]VERIFY: d1b08469-2ca8') +test({'ACCEPT_QUERY_FAIL': '102'}, expected_trace=msgs) + +# Same messages as previous test. +mark('First mech acceptor exchange fail') +test({'ACCEPT_EXCHANGE_FAIL': '102'}, expected_trace=msgs) + +# Fail the optimistic mech's gss_exchange_meta_data() in the +# initiator. Since the acceptor has effectively selected the +# optimistic mech, this causes the authentication to fail. +mark('First mech initiator exchange fail, one hop') +test({'HOPS': '1', 'INIT_EXCHANGE_FAIL': '102'}, expected_code=1, + expected_msg='No mutually supported NegoEx authentication schemes') +mark('First mech initiator exchange fail, two hops, early keys') +test({'HOPS': '2', 'INIT_EXCHANGE_FAIL': '102', 'KEY': 'always'}, + expected_code=1, + expected_msg='No mutually supported NegoEx authentication schemes') +mark('First mech initiator exchange fail, two hops') +test({'HOPS': '2', 'INIT_EXCHANGE_FAIL': '102'}, expected_code=1, + expected_msg='No mutually supported NegoEx authentication schemes') + +mark('First mech init_sec_context fail') +msgs = ('sending [0]INITIATOR_NEGO: d1b08469-2ca8-0000-0000-000000000000', + 'sending [2]AP_REQUEST', 'sending [3]VERIFY', 'sending [6]VERIFY') +test({'INIT_FAIL': '102'}, expected_trace=msgs) + +mark('First mech accept_sec_context fail') +test({'HOPS': '2', 'ACCEPT_FAIL': '102'}, expected_code=1, + expected_msg='failure from acceptor') + +mark('ALERT from acceptor to initiator') +msgs = ('sending [3]AP_REQUEST', 'sending [4]VERIFY', 'sending [8]CHALLENGE', + 'sending [9]ALERT', 'received [9]ALERT', 'sending [10]AP_REQUEST', + 'sending [11]VERIFY', 'sending [12]VERIFY') +test({'HOPS': '3', 'KEY': 'init-always'}, expected_trace=msgs) + +mark('ALERT from initiator to acceptor') +msgs = ('sending [3]AP_REQUEST', 'sending [7]CHALLENGE', 'sending [8]VERIFY', + 'sending [9]AP_REQUEST', 'sending [10]ALERT', 'received [10]ALERT', + 'sending [11]CHALLENGE', 'sending [12]VERIFY', 'sending [13]VERIFY') +test({'HOPS': '4', 'KEY': 'accept-always'}, expected_trace=()) + +success('NegoEx tests') |