diff options
| author | Greg Hudson <ghudson@mit.edu> | 2011-09-05 16:35:40 +0000 |
|---|---|---|
| committer | Greg Hudson <ghudson@mit.edu> | 2011-09-05 16:35:40 +0000 |
| commit | 1cd2821c19b2b95e39d5fc2f451a035585a40fa5 (patch) | |
| tree | da78b3780a8cbf0c57977ad4504c5336b03fb49b /src/tests | |
| parent | 7c5926d866b1874e66ef5d05416ff024faab01ff (diff) | |
| download | krb5-1cd2821c19b2b95e39d5fc2f451a035585a40fa5.tar.gz krb5-1cd2821c19b2b95e39d5fc2f451a035585a40fa5.tar.xz krb5-1cd2821c19b2b95e39d5fc2f451a035585a40fa5.zip | |
Make gss-krb5 use cache collection
For default credentials, defer ccache resolution until we need the
information. If this happens in init_sec_context when we have the
target principal in hand, use krb5_cc_select() to pick a cache. If
the target principal is not known, use the default cache.
For credentials with a specified principal, use krb5_cc_cache_match()
to find the cache. If no cache is found and a password is specified,
create a new cache within the collection to hold the new credentials,
if the default cache type supports a collection.
ticket: 6958
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25160 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/tests')
| -rw-r--r-- | src/tests/gssapi/Makefile.in | 19 | ||||
| -rw-r--r-- | src/tests/gssapi/deps | 4 | ||||
| -rw-r--r-- | src/tests/gssapi/t_ccselect.c | 170 | ||||
| -rw-r--r-- | src/tests/gssapi/t_ccselect.py | 122 |
4 files changed, 307 insertions, 8 deletions
diff --git a/src/tests/gssapi/Makefile.in b/src/tests/gssapi/Makefile.in index 2bf390106..5b6765b59 100644 --- a/src/tests/gssapi/Makefile.in +++ b/src/tests/gssapi/Makefile.in @@ -4,21 +4,24 @@ DEFINES = -DUSE_AUTOCONF_H PROG_LIBPATH=-L$(TOPLIBD) PROG_RPATH=$(KRB5_LIBDIR) -SRCS= $(srcdir)/t_accname.c $(srcdir)/t_imp_cred.c $(srcdir)/t_imp_name.c \ - $(srcdir)/t_s4u.c $(srcdir)/t_namingexts.c $(srcdir)/t_gssexts.c \ - $(srcdir)/t_saslname.c +SRCS= $(srcdir)/t_accname.c $(srcdir)/t_ccselect.c $(srcdir)/t_imp_cred.c \ + $(srcdir)/t_imp_name.c $(srcdir)/t_s4u.c $(srcdir)/t_namingexts.c \ + $(srcdir)/t_gssexts.c $(srcdir)/t_saslname.c -OBJS= t_accname.o t_imp_cred.o t_imp_name.o t_s4u.o t_namingexts.o \ - t_gssexts.o t_spnego.o t_saslname.o +OBJS= t_accname.o t_ccselect.o t_imp_cred.o t_imp_name.o t_s4u.o \ + t_namingexts.o t_gssexts.o t_spnego.o t_saslname.o -all:: t_accname t_imp_cred t_imp_name t_s4u t_namingexts t_gssexts t_spnego \ - t_saslname +all:: t_accname t_ccselect t_imp_cred t_imp_name t_s4u t_namingexts t_gssexts \ + t_spnego t_saslname -check-pytests:: t_accname t_imp_cred t_spnego +check-pytests:: t_accname t_ccselect t_imp_cred t_spnego $(RUNPYTEST) $(srcdir)/t_gssapi.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_ccselect.py $(PYTESTFLAGS) t_accname: t_accname.o $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS) $(CC_LINK) -o t_accname t_accname.o $(GSS_LIBS) $(KRB5_BASE_LIBS) +t_ccselect: t_ccselect.o $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o t_ccselect t_ccselect.o $(GSS_LIBS) $(KRB5_BASE_LIBS) t_imp_cred: t_imp_cred.o $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS) $(CC_LINK) -o t_imp_cred t_imp_cred.o $(GSS_LIBS) $(KRB5_BASE_LIBS) t_imp_name: t_imp_name.o $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS) diff --git a/src/tests/gssapi/deps b/src/tests/gssapi/deps index 8838e240d..a87f6e0e0 100644 --- a/src/tests/gssapi/deps +++ b/src/tests/gssapi/deps @@ -5,6 +5,10 @@ $(OUTPRE)t_accname.$(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 \ t_accname.c +$(OUTPRE)t_ccselect.$(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 \ + t_ccselect.c $(OUTPRE)t_imp_cred.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ $(BUILDTOP)/include/gssapi/gssapi_krb5.h $(BUILDTOP)/include/krb5/krb5.h \ diff --git a/src/tests/gssapi/t_ccselect.c b/src/tests/gssapi/t_ccselect.c new file mode 100644 index 000000000..8acf045ba --- /dev/null +++ b/src/tests/gssapi/t_ccselect.c @@ -0,0 +1,170 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* tests/gssapi/t_ccselect.c - Test program for GSSAPI cred selection */ +/* + * Copyright 2011 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <gssapi/gssapi_krb5.h> + +/* + * Test program for client credential selection, intended to be run from a + * Python test script. Performs a one-token + * gss_init_sec_context/gss_accept_sec_context exchange, optionally with a + * specified principal as the initiator name, a specified principal name as + * target name, the default acceptor cred. If the exchange is successful, + * prints the initiator name as seen by the acceptor. If any call is + * unsuccessful, displays an error message. Exits with status 0 if all + * operations are successful, or 1 if not. + * + * Usage: ./t_ccselect [targetprinc|gss:service@host] [initiatorprinc|-] + */ + +static void +display_status_1(const char *m, OM_uint32 code, int type) +{ + OM_uint32 maj_stat, min_stat; + gss_buffer_desc msg; + OM_uint32 msg_ctx; + + msg_ctx = 0; + while (1) { + maj_stat = gss_display_status(&min_stat, code, + type, GSS_C_NULL_OID, + &msg_ctx, &msg); + fprintf(stderr, "%s: %s\n", m, (char *)msg.value); + (void) gss_release_buffer(&min_stat, &msg); + + if (!msg_ctx) + break; + } +} + +static void +gsserr(const char *msg, OM_uint32 maj_stat, OM_uint32 min_stat) +{ + display_status_1(msg, maj_stat, GSS_C_GSS_CODE); + display_status_1(msg, min_stat, GSS_C_MECH_CODE); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + OM_uint32 minor, major; + gss_cred_id_t initiator_cred; + gss_buffer_desc buf; + gss_name_t target_name, initiator_name = GSS_C_NO_NAME; + gss_name_t real_initiator_name; + gss_buffer_desc token, tmp, namebuf; + gss_ctx_id_t initiator_context = GSS_C_NO_CONTEXT; + gss_ctx_id_t acceptor_context = GSS_C_NO_CONTEXT; + + if (argc < 2 || argc > 3) { + fprintf(stderr, "Usage: %s targetprinc [initiatorprinc|-]\n", argv[0]); + return 1; + } + + /* Import the target name. */ + if (strncmp(argv[1], "gss:", 4) == 0) { + /* Import as host-based service. */ + buf.value = argv[1] + 4; + buf.length = strlen((char *)buf.value); + major = gss_import_name(&minor, &buf, + (gss_OID)GSS_C_NT_HOSTBASED_SERVICE, + &target_name); + } else { + /* Import as krb5 principal name. */ + buf.value = argv[1]; + buf.length = strlen((char *)buf.value); + major = gss_import_name(&minor, &buf, + (gss_OID)GSS_KRB5_NT_PRINCIPAL_NAME, + &target_name); + } + if (GSS_ERROR(major)) + gsserr("gss_import_name(target_name)", major, minor); + + /* Import the initiator name as a krb5 principal and get creds, maybe. */ + if (argc >= 3) { + if (strcmp(argv[2], "-") != 0) { + buf.value = argv[2]; + buf.length = strlen((char *)buf.value); + major = gss_import_name(&minor, &buf, + (gss_OID)GSS_KRB5_NT_PRINCIPAL_NAME, + &initiator_name); + if (GSS_ERROR(major)) + gsserr("gss_import_name(initiator_name)", major, minor); + } + + /* Get acceptor cred. */ + major = gss_acquire_cred(&minor, initiator_name, GSS_C_INDEFINITE, + GSS_C_NO_OID_SET, GSS_C_INITIATE, + &initiator_cred, NULL, NULL); + if (GSS_ERROR(major)) + gsserr("gss_acquire_cred", major, minor); + } + + + /* Create krb5 initiator context and get the first token. */ + token.value = NULL; + token.length = 0; + major = gss_init_sec_context(&minor, initiator_cred, &initiator_context, + target_name, (gss_OID)gss_mech_krb5, + GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG, + GSS_C_INDEFINITE, GSS_C_NO_CHANNEL_BINDINGS, + GSS_C_NO_BUFFER, NULL, &token, NULL, NULL); + if (GSS_ERROR(major)) + gsserr("gss_init_sec_context", major, minor); + + /* Pass the token to gss_accept_sec_context. */ + tmp.value = NULL; + tmp.length = 0; + major = gss_accept_sec_context(&minor, &acceptor_context, + GSS_C_NO_CREDENTIAL, &token, + GSS_C_NO_CHANNEL_BINDINGS, + &real_initiator_name, NULL, &tmp, + NULL, NULL, NULL); + if (major != GSS_S_COMPLETE) + gsserr("gss_accept_sec_context", major, minor); + + namebuf.value = NULL; + namebuf.length = 0; + major = gss_display_name(&minor, real_initiator_name, &namebuf, NULL); + if (GSS_ERROR(major)) + gsserr("gss_display_name(initiator)", major, minor); + printf("%.*s\n", (int)namebuf.length, (char *)namebuf.value); + + (void)gss_release_name(&minor, &target_name); + (void)gss_release_name(&minor, &initiator_name); + (void)gss_release_name(&minor, &real_initiator_name); + (void)gss_release_cred(&minor, &initiator_cred); + (void)gss_delete_sec_context(&minor, &initiator_context, NULL); + (void)gss_delete_sec_context(&minor, &acceptor_context, NULL); + (void)gss_release_buffer(&minor, &token); + (void)gss_release_buffer(&minor, &tmp); + (void)gss_release_buffer(&minor, &namebuf); + return 0; +} diff --git a/src/tests/gssapi/t_ccselect.py b/src/tests/gssapi/t_ccselect.py new file mode 100644 index 000000000..2722873fc --- /dev/null +++ b/src/tests/gssapi/t_ccselect.py @@ -0,0 +1,122 @@ +# Copyright (C) 2011 by the Massachusetts Institute of Technology. +# All rights reserved. + +# Export of this software from the United States of America may +# require a specific license from the United States Government. +# It is the responsibility of any person or organization contemplating +# export to obtain such a license before exporting. +# +# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +# distribute this software and its documentation for any purpose and +# without fee is hereby granted, provided that the above copyright +# notice appear in all copies and that both that copyright notice and +# this permission notice appear in supporting documentation, and that +# the name of M.I.T. not be used in advertising or publicity pertaining +# to distribution of the software without specific, written prior +# permission. Furthermore if you modify this software you must label +# your software as modified software and not distribute it in such a +# fashion that it might be confused with the original M.I.T. software. +# M.I.T. makes no representations about the suitability of +# this software for any purpose. It is provided "as is" without express +# or implied warranty. + +#!/usr/bin/python +from k5test import * + +# Create two independent realms (no cross-realm TGTs). +r1 = K5Realm(start_kadmind=False, create_user=False) +r2 = K5Realm(start_kadmind=False, create_user=False, realm='KRBTEST2.COM', + testdir=os.path.join(r1.testdir, 'r2'), portbase=62000) + +# gsserver specifies the target as a GSS name. The resulting +# principal will have the host-based type, but the realm won't be +# known before the client cache is selected (since k5test realms have +# no domain-realm mapping by default). +gssserver = 'gss:host@' + hostname + +# refserver specifies the target as a principal in the referral realm. +# The principal won't be treated as a host principal by the +# .k5identity rules since it has unknown type. +refserver = 'host/' + hostname + '@' + +# Make each realm's keytab contain entries for both realm's servers. +#r1.run_as_client(['/bin/sh', '-c', '(echo rkt %s; echo wkt %s) | %s' % +# (r2.keytab, r1.keytab, ktutil)]) +#r1.run_as_client(['/bin/sh', '-c', '(echo rkt %s; echo wkt %s) | %s' % +# (r1.keytab, r2.keytab, ktutil)]) + +# Make a directory collection and use it for client commands in both realms. +ccdir = os.path.join(r1.testdir, 'cc') +ccname = 'DIR:' + ccdir +os.mkdir(ccdir) +r1.env_client['KRB5CCNAME'] = ccname +r2.env_client['KRB5CCNAME'] = ccname + +# Use .k5identity from testdir and not from the tester's homedir. +r1.env_client['HOME'] = r1.testdir +r2.env_client['HOME'] = r1.testdir + +# Create two users in r1 and one in r2. +alice='alice@KRBTEST.COM' +bob='bob@KRBTEST.COM' +zaphod='zaphod@KRBTEST2.COM' +r1.addprinc(alice, password('alice')) +r1.addprinc(bob, password('bob')) +r2.addprinc(zaphod, password('zaphod')) + +# Get tickets for one user in each realm (zaphod will be primary). +r1.kinit(alice, password('alice')) +r2.kinit(zaphod, password('zaphod')) + +# Check that we can find a cache for a specified client principal. +output = r1.run_as_client(['./t_ccselect', r1.host_princ, alice]) +if output != (alice + '\n'): + fail('alice not chosen when specified') +output = r2.run_as_client(['./t_ccselect', r2.host_princ, zaphod]) +if output != (zaphod + '\n'): + fail('zaphod not chosen when specified') + +# Check that we can guess a cache based on the service realm. +output = r1.run_as_client(['./t_ccselect', r1.host_princ]) +if output != (alice + '\n'): + fail('alice not chosen as default initiator cred for server in r1') +output = r1.run_as_client(['./t_ccselect', r1.host_princ, '-']) +if output != (alice + '\n'): + fail('alice not chosen as default initiator name for server in r1') +output = r2.run_as_client(['./t_ccselect', r2.host_princ]) +if output != (zaphod + '\n'): + fail('zaphod not chosen as default initiator cred for server in r1') +output = r2.run_as_client(['./t_ccselect', r2.host_princ, '-']) +if output != (zaphod + '\n'): + fail('zaphod not chosen as default initiator name for server in r1') + +# Check that primary cache is used if server realm is unknown. +output = r2.run_as_client(['./t_ccselect', gssserver]) +if output != (zaphod + '\n'): + fail('zaphod not chosen via primary cache for unknown server realm') +r1.run_as_client(['./t_ccselect', gssserver], expected_code=1) + +# Get a second cred in r1 (bob will be primary). +r1.kinit(bob, password('bob')) + +# Try some cache selections using .k5identity. +k5id = open(os.path.join(r1.testdir, '.k5identity'), 'w') +k5id.write('%s realm=%s\n' % (alice, r1.realm)) +k5id.write('%s service=ho*t host=%s\n' % (zaphod, hostname)) +k5id.write('noprinc service=bogus') +k5id.close() +output = r1.run_as_client(['./t_ccselect', r1.host_princ]) +if output != (alice + '\n'): + fail('alice not chosen via .k5identity realm line.') +output = r2.run_as_client(['./t_ccselect', gssserver]) +if output != (zaphod + '\n'): + fail('zaphod not chosen via .k5identity service/host line.') +output = r1.run_as_client(['./t_ccselect', refserver]) +if output != (bob + '\n'): + fail('bob not chosen via primary cache when no .k5identity line matches.') +output = r1.run_as_client(['./t_ccselect', 'gss:bogus@' + hostname], + expected_code=1) +if 'does not match desired' not in output: + fail('Expected error not seen when k5identity selects bad principal.') + +success('GSSAPI credential selection tests.') |
