Skip to content

Commit

Permalink
Test KDC host-based referral support
Browse files Browse the repository at this point in the history
Test the KDC host-based referral support in t_referral.py, using a new
harness to call krb5_get_credentials with a specified server name
type.  Also use this new harness for the #7483 regression test, to
avoid relying on an undocumented kvno extension.
  • Loading branch information
greghudson committed Jan 11, 2013
1 parent a3cada9 commit 9b472cc
Show file tree
Hide file tree
Showing 4 changed files with 234 additions and 11 deletions.
7 changes: 6 additions & 1 deletion src/tests/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ KRB5_RUN_ENV= @KRB5_RUN_ENV@
PROG_LIBPATH=-L$(TOPLIBD)
PROG_RPATH=$(KRB5_LIBDIR)

EXTRADEPSRCS= gcred.c hist.c kdbtest.c

TEST_DB = ./testdb
TEST_REALM = FOO.TEST.REALM
TEST_MKEY = footes
Expand All @@ -18,6 +20,9 @@ TEST_PREFIX = "foo bar"
KADMIN_OPTS= -d $(TEST_DB) -r $(TEST_REALM) -P $(TEST_MKEY)
KTEST_OPTS= $(KADMIN_OPTS) -p $(TEST_PREFIX) -n $(TEST_NUM) -D $(TEST_DEPTH)

gcred: gcred.o $(KRB5_BASE_DEPLIBS)
$(CC_LINK) -o $@ gcred.o $(KRB5_BASE_LIBS)

hist: hist.o $(KDB5_DEPLIBS) $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIBS)
$(CC_LINK) -o $@ hist.o $(KDB5_LIBS) $(KADMSRV_LIBS) $(KRB5_BASE_LIBS)

Expand Down Expand Up @@ -67,7 +72,7 @@ kdb_check: kdc.conf krb5.conf
$(RUN_SETUP) $(VALGRIND) ../kadmin/dbutil/kdb5_util $(KADMIN_OPTS) destroy -f
$(RM) $(TEST_DB)* stash_file

check-pytests:: hist kdbtest
check-pytests:: gcred hist kdbtest
$(RUNPYTEST) $(srcdir)/t_general.py $(PYTESTFLAGS)
$(RUNPYTEST) $(srcdir)/t_iprop.py $(PYTESTFLAGS)
$(RUNPYTEST) $(srcdir)/t_anonpkinit.py $(PYTESTFLAGS)
Expand Down
44 changes: 43 additions & 1 deletion src/tests/deps
Original file line number Diff line number Diff line change
@@ -1 +1,43 @@
# No dependencies here.
#
# Generated makefile dependencies follow.
#
$(OUTPRE)gcred.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
$(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
$(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \
$(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
$(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
$(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
$(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
$(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
$(top_srcdir)/include/krb5/clpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \
$(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
gcred.c
$(OUTPRE)hist.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
$(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
$(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
$(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \
$(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
$(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \
$(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \
$(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \
$(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \
$(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \
$(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \
$(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
$(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
$(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
$(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
$(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \
$(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/clpreauth_plugin.h \
$(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
$(top_srcdir)/include/socket-utils.h hist.c
$(OUTPRE)kdbtest.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \
$(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \
$(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \
$(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \
$(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \
$(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \
$(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \
$(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \
$(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/kdb.h \
$(top_srcdir)/include/krb5.h kdbtest.c
103 changes: 103 additions & 0 deletions src/tests/gcred.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/* tests/gcred.c - Test harness for referrals */
/*
* Copyright (C) 2012 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.
*/

/*
* This program is intended to be run from a python script as:
*
* gcred nametype princname
*
* where nametype is one of "unknown", "principal", "srv-inst", and "srv-hst",
* and princname is the name of the service principal. gcred acquires
* credentials for the specified server principal. On success, gcred displays
* the server principal name of the obtained credentials to stdout and exits
* with status 0. On failure, gcred displays the error message for the failed
* operation to stderr and exits with status 1.
*/

#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_principal client, server;
krb5_ccache ccache;
krb5_creds in_creds, *creds;
char *name;

check(krb5_init_context(&ctx));

/* Parse arguments. */
assert(argc == 3);
check(krb5_parse_name(ctx, argv[2], &server));
if (strcmp(argv[1], "unknown") == 0)
server->type = KRB5_NT_UNKNOWN;
else if (strcmp(argv[1], "principal") == 0)
server->type = KRB5_NT_PRINCIPAL;
else if (strcmp(argv[1], "srv-inst") == 0)
server->type = KRB5_NT_SRV_INST;
else if (strcmp(argv[1], "srv-hst") == 0)
server->type = KRB5_NT_SRV_HST;
else
abort();

check(krb5_cc_default(ctx, &ccache));
check(krb5_cc_get_principal(ctx, ccache, &client));
memset(&in_creds, 0, sizeof(in_creds));
in_creds.client = client;
in_creds.server = server;
check(krb5_get_credentials(ctx, 0, ccache, &in_creds, &creds));
check(krb5_unparse_name(ctx, creds->server, &name));
printf("%s\n", name);

krb5_free_unparsed_name(ctx, name);
krb5_free_creds(ctx, creds);
krb5_free_principal(ctx, client);
krb5_free_principal(ctx, server);
krb5_cc_close(ctx, ccache);
krb5_free_context(ctx);
return 0;
}
91 changes: 82 additions & 9 deletions src/tests/t_referral.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,89 @@
#!/usr/bin/python
from k5test import *

# We should have a comprehensive suite of KDC host referral tests
# here, based on the tests in the kdc_realm subdir. For now, we just
# have a regression test for #7483.

# A KDC should not return a host referral to its own realm.
krb5_conf = {'domain_realm': {'y': 'KRBTEST.COM'}}
kdc_conf = {'realms': {'$realm': {'host_based_services': 'x'}}}
realm = K5Realm(krb5_conf=krb5_conf, kdc_conf=kdc_conf, create_host=False)
# Create a realm where the KDC has a [domain_realm] mapping for 'd'
# and clients will not try to use DNS to look up KDC addresses. The
# KDC believes it has a cross-realm TGT for REFREALM, but we won't
# actually create REFREALM.
nodns = {'libdefaults': {'dns_lookup_kdc': 'false'}}
drealm = {'domain_realm': {'d': 'REFREALM'}}
realm = K5Realm(krb5_conf=nodns, kdc_conf=drealm, create_host=False)
realm.addprinc('krbtgt/REFREALM')

# Get credentials for a/x.d and check whether the KDC returned a referral.
def test(realm, nametype, expected_ref, msg):
out = realm.run(['./gcred', nametype, 'a/x.d'], expected_code=1)
if ((expected_ref and 'Cannot find KDC for realm "REFREALM"' not in out) or
(not expected_ref and 'not found in Kerberos database' not in out)):
fail(msg)

# Create a modified KDC environment and restart the KDC.
def restart_kdc(realm, kdc_conf):
env = realm.special_env('extravars', True, kdc_conf=kdc_conf)
realm.stop_kdc()
realm.start_kdc(env=env)

# With no KDC configuration besides [domain_realm], we should get a
# referral for a NT-SRV-HST or NT-SRV-INST server name, but not an
# NT-UNKNOWN or NT-PRINCIPAL server name.
test(realm, 'srv-hst', True, 'srv-hst, no variables')
test(realm, 'srv-inst', True, 'srv-inst, no variables')
test(realm, 'principal', False, 'principal, no variables')
test(realm, 'unknown', False, 'unknown, no variables')

# With host_based_services matching the first server name component
# ("a"), we should get a referral for an NT-UNKNOWN server name.
# host_based_services can appear in either [kdcdefaults] or the realm
# section, with the realm value supplementing the kdcdefaults value.
# NT-SRV-HST server names should be unaffected by host_based_services,
# and NT-PRINCIPAL server names shouldn't get a referral regardless.
restart_kdc(realm, {'kdcdefaults': {'host_based_services': '*'}})
test(realm, 'unknown', True, 'unknown, kdcdefaults hostbased *')
test(realm, 'principal', False, 'principal, kdcdefaults hostbased *')
restart_kdc(realm, {'kdcdefaults': {'host_based_services': 'b,a,c'}})
test(realm, 'unknown', True, 'unknown, kdcdefaults hostbased b,a,c')
restart_kdc(realm, {'realms': {'$realm': {'host_based_services': 'a b c'}}})
test(realm, 'unknown', True, 'unknown, realm hostbased a b c')
restart_kdc(realm, {'kdcdefaults': {'host_based_services': 'a'},
'realms': {'$realm': {'host_based_services': 'b c'}}})
test(realm, 'unknown', True, 'unknown, kdcdefaults hostbased a (w/ realm)')
restart_kdc(realm, {'kdcdefaults': {'host_based_services': 'b,c'},
'realms': {'$realm': {'host_based_services': 'a,b'}}})
test(realm, 'unknown', True, 'unknown, realm hostbased a,b (w/ kdcdefaults)')
restart_kdc(realm, {'kdcdefaults': {'host_based_services': 'b,c'}})
test(realm, 'unknown', False, 'unknown, kdcdefaults hostbased b,c')
test(realm, 'srv-hst', True, 'srv-hst, kdcdefaults hostbased b,c')

# With no_host_referrals matching the first server name component, we
# should not get a referral even for NT-SRV-HOST server names
restart_kdc(realm, {'kdcdefaults': {'no_host_referral': '*'}})
test(realm, 'srv-hst', False, 'srv-hst, kdcdefaults nohost *')
restart_kdc(realm, {'kdcdefaults': {'no_host_referral': 'b,a,c'}})
test(realm, 'srv-hst', False, 'srv-hst, kdcdefaults nohost b,a,c')
restart_kdc(realm, {'realms': {'$realm': {'no_host_referral': 'a b c'}}})
test(realm, 'srv-hst', False, 'srv-hst, realm nohost a b c')
restart_kdc(realm, {'kdcdefaults': {'no_host_referral': 'a'},
'realms': {'$realm': {'no_host_referral': 'b c'}}})
test(realm, 'srv-hst', False, 'srv-hst, kdcdefaults nohost a (w/ realm)')
restart_kdc(realm, {'kdcdefaults': {'no_host_referral': 'b,c'},
'realms': {'$realm': {'no_host_referral': 'a,b'}}})
test(realm, 'srv-hst', False, 'srv-hst, realm nohost a,b (w/ kdcdefaults)')
restart_kdc(realm, {'kdcdefaults': {'no_host_referral': 'b,c'}})
test(realm, 'srv-hst', True, 'srv-hst, kdcdefaults nohost b,c')

# no_host_referrals should override host_based_services for NT-UNKNWON
# server names.
restart_kdc(realm, {'kdcdefaults': {'no_host_referral': '*',
'host_based_services': '*'}})
test(realm, 'unknown', False, 'srv-hst, kdcdefaults nohost * hostbased *')

# Regression test for #7483: a KDC should not return a host referral
# to its own realm.
drealm = {'domain_realm': {'d': 'KRBTEST.COM'}}
realm.stop()
realm = K5Realm(kdc_conf=drealm, create_host=False)
tracefile = os.path.join(realm.testdir, 'trace')
realm.run(['env', 'KRB5_TRACE=' + tracefile, kvno, '-u', 'x/z.y@'],
realm.run(['env', 'KRB5_TRACE=' + tracefile, './gcred', 'srv-hst', 'a/x.d@'],
expected_code=1)
f = open(tracefile, 'r')
trace = f.read()
Expand Down

0 comments on commit 9b472cc

Please sign in to comment.