Skip to content

Commit

Permalink
Fix gss_krb5_set_allowable_enctypes for acceptor
Browse files Browse the repository at this point in the history
The acceptor implementation of gss_krb5_set_allowable_enctypes (added
in 1.9.1) is intended to restrict the acceptor subkey negotiated by
krb5_rd_req().  It uses the same approach as the initiator, calling
krb5_set_default_tgs_enctypes on the context.  This has the unwanted
side effect of restricting the encryption key of the ticket, because
krb5_decrypt_tkt_part has checked krb5_is_permitted_enctype on the
ticket encryption key since 1.8.

Instead, use krb5_auth_con_setpermetypes on the auth context.  This
list is only used for session key enctype negotiation.  Also add
automated tests to verify that gss_krb5_set_allowable_enctypes works
as desired.

ticket: 7688 (new)
target_version: 1.11.4
tags: pullup
  • Loading branch information
greghudson committed Aug 12, 2013
1 parent 941f3d9 commit 2e95607
Show file tree
Hide file tree
Showing 4 changed files with 383 additions and 2 deletions.
4 changes: 2 additions & 2 deletions src/lib/gssapi/krb5/accept_sec_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -625,8 +625,8 @@ kg_accept_krb5(minor_status, context_handle,

/* Limit the encryption types negotiated (if requested). */
if (cred->req_enctypes) {
if ((code = krb5_set_default_tgs_enctypes(context,
cred->req_enctypes))) {
if ((code = krb5_auth_con_setpermetypes(context, auth_context,
cred->req_enctypes))) {
major_status = GSS_S_FAILURE;
goto fail;
}
Expand Down
3 changes: 3 additions & 0 deletions src/tests/gssapi/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ check-pytests:: ccinit ccrefresh t_accname t_ccselect t_credstore \
$(RUNPYTEST) $(srcdir)/t_gssapi.py $(PYTESTFLAGS)
$(RUNPYTEST) $(srcdir)/t_ccselect.py $(PYTESTFLAGS)
$(RUNPYTEST) $(srcdir)/t_client_keytab.py $(PYTESTFLAGS)
$(RUNPYTEST) $(srcdir)/t_enctypes.py $(PYTESTFLAGS)
$(RUNPYTEST) $(srcdir)/t_export_cred.py $(PYTESTFLAGS)
$(RUNPYTEST) $(srcdir)/t_s4u.py $(PYTESTFLAGS)

Expand All @@ -45,6 +46,8 @@ t_ccselect: t_ccselect.o $(COMMON_DEPS)
$(CC_LINK) -o $@ t_ccselect.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)
$(CC_LINK) -o $@ t_enctypes.o $(COMMON_LIBS)
t_export_cred: t_export_cred.o $(COMMON_DEPS)
$(CC_LINK) -o $@ t_export_cred.o $(COMMON_LIBS)
t_export_name: t_export_name.o $(COMMON_DEPS)
Expand Down
229 changes: 229 additions & 0 deletions src/tests/gssapi/t_enctypes.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/* tests/gssapi/t_enctypes.c - gss_krb5_set_allowable_enctypes test */
/*
* Copyright (C) 2013 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 <string.h>
#include <getopt.h>
#include "k5-int.h"
#include "common.h"

/*
* This test program performs a gss_init_sec_context/gss_accept_sec_context
* exchange with the krb5 mech, the default initiator name, a specified
* principal name as target name, and the default acceptor name. Before the
* exchange, gss_set_allowable_enctypes is called for the initiator and the
* acceptor cred if requested. If the exchange is successful, the resulting
* contexts are exported with gss_krb5_export_lucid_sec_context, checked for
* mismatches, and the GSS protocol and keys are displayed. Exits with status
* 0 if all operations are successful, or 1 if not.
*
* Usage: ./t_enctypes [-i initenctypes] [-a accenctypes] targetname
*/

static void
usage()
{
errout("Usage: t_enctypes [-i initenctypes] [-a accenctypes] "
"targetname");
}

/* Error out if ikey is not the same as akey. */
static void
check_key_match(gss_krb5_lucid_key_t *ikey, gss_krb5_lucid_key_t *akey)
{
if (ikey->type != akey->type || ikey->length != akey->length ||
memcmp(ikey->data, akey->data, ikey->length) != 0)
errout("Initiator and acceptor keys do not match");
}

/* Display the name of enctype. */
static void
display_enctype(krb5_enctype enctype)
{
char ename[128];

if (krb5_enctype_to_name(enctype, FALSE, ename, sizeof(ename)) == 0)
fputs(ename, stdout);
else
fputs("(unknown)", stdout);
}

int
main(int argc, char *argv[])
{
krb5_error_code ret;
krb5_context kctx = NULL;
krb5_enctype *ienc = NULL, *aenc = NULL, zero = 0;
OM_uint32 minor, major, flags;
gss_name_t tname;
gss_cred_id_t icred = GSS_C_NO_CREDENTIAL, acred = GSS_C_NO_CREDENTIAL;
gss_ctx_id_t ictx = GSS_C_NO_CONTEXT, actx = GSS_C_NO_CONTEXT;
gss_buffer_desc itok, atok, tmp;
gss_krb5_lucid_context_v1_t *ilucid, *alucid;
gss_krb5_rfc1964_keydata_t *i1964, *a1964;
gss_krb5_cfx_keydata_t *icfx, *acfx;
size_t count;
void *lptr;
int c;

ret = krb5_init_context(&kctx);
check_k5err(kctx, "krb5_init_context", ret);

/* Parse arguments. */
while ((c = getopt(argc, argv, "i:a:")) != -1) {
switch (c) {
case 'i':
ret = krb5int_parse_enctype_list(kctx, "", optarg, &zero, &ienc);
check_k5err(kctx, "krb5_parse_enctype_list(initiator)", ret);
break;
case 'a':
ret = krb5int_parse_enctype_list(kctx, "", optarg, &zero, &aenc);
check_k5err(kctx, "krb5_parse_enctype_list(acceptor)", ret);
break;
default:
usage();
}
}
argc -= optind;
argv += optind;
if (argc != 1)
usage();
tname = import_name(*argv);

if (ienc != NULL) {
major = gss_acquire_cred(&minor, GSS_C_NO_NAME, GSS_C_INDEFINITE,
&mechset_krb5, GSS_C_INITIATE, &icred, NULL,
NULL);
check_gsserr("gss_acquire_cred(initiator)", major, minor);

for (count = 0; ienc[count]; count++);
major = gss_krb5_set_allowable_enctypes(&minor, icred, count, ienc);
check_gsserr("gss_krb5_set_allowable_enctypes(init)", major, minor);
}
if (aenc != NULL) {
major = gss_acquire_cred(&minor, GSS_C_NO_NAME, GSS_C_INDEFINITE,
&mechset_krb5, GSS_C_ACCEPT, &acred, NULL,
NULL);
check_gsserr("gss_acquire_cred(acceptor)", major, minor);

for (count = 0; aenc[count]; count++);
major = gss_krb5_set_allowable_enctypes(&minor, acred, count, aenc);
check_gsserr("gss_krb5_set_allowable_enctypes(acc)", major, minor);
}

/* Create initiator context and get the first token. */
itok.value = NULL;
itok.length = 0;
flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_MUTUAL_FLAG;
major = gss_init_sec_context(&minor, icred, &ictx, tname, &mech_krb5,
flags, GSS_C_INDEFINITE,
GSS_C_NO_CHANNEL_BINDINGS, GSS_C_NO_BUFFER,
NULL, &itok, NULL, NULL);
check_gsserr("gss_init_sec_context(1)", major, minor);
if (major != GSS_S_CONTINUE_NEEDED)
errout("gss_init_sec_context(1) unexpected complete");

/* Pass the initiator token to gss_accept_sec_context. */
atok.value = NULL;
atok.length = 0;
major = gss_accept_sec_context(&minor, &actx, acred, &itok,
GSS_C_NO_CHANNEL_BINDINGS, NULL, NULL,
&atok, NULL, NULL, NULL);
check_gsserr("gss_accept_sec_context", major, minor);
if (major != GSS_S_COMPLETE)
errout("gss_accept_sec_context unexpected continue");

/* Pass the return token to gss_init_sec_context again. */
tmp.value = NULL;
tmp.length = 0;
major = gss_init_sec_context(&minor, icred, &ictx, tname, &mech_krb5,
flags, GSS_C_INDEFINITE,
GSS_C_NO_CHANNEL_BINDINGS, &atok, NULL, &tmp,
NULL, NULL);
check_gsserr("gss_init_sec_context(2)", major, minor);
if (major != GSS_S_COMPLETE)
errout("gss_init_sec_context(2) unexpected continue");

/* Export to lucid contexts. */
major = gss_krb5_export_lucid_sec_context(&minor, &ictx, 1, &lptr);
check_gsserr("gss_export_lucid_sec_context(initiator)", major, minor);
ilucid = lptr;
major = gss_krb5_export_lucid_sec_context(&minor, &actx, 1, &lptr);
check_gsserr("gss_export_lucid_sec_context(acceptor)", major, minor);
alucid = lptr;

/* Grab the session keys and make sure they match. */
if (ilucid->protocol != alucid->protocol)
errout("Initiator/acceptor protocol mismatch");
if (ilucid->protocol) {
icfx = &ilucid->cfx_kd;
acfx = &alucid->cfx_kd;
if (icfx->have_acceptor_subkey != acfx->have_acceptor_subkey)
errout("Initiator/acceptor have_acceptor_subkey mismatch");
check_key_match(&icfx->ctx_key, &acfx->ctx_key);
if (icfx->have_acceptor_subkey)
check_key_match(&icfx->acceptor_subkey, &acfx->acceptor_subkey);
fputs("cfx ", stdout);
display_enctype(icfx->ctx_key.type);
if (icfx->have_acceptor_subkey) {
fputs(" ", stdout);
display_enctype(icfx->acceptor_subkey.type);
}
fputs("\n", stdout);
} else {
i1964 = &ilucid->rfc1964_kd;
a1964 = &alucid->rfc1964_kd;
if (i1964->sign_alg != a1964->sign_alg ||
i1964->seal_alg != a1964->seal_alg)
errout("Initiator/acceptor sign or seal alg mismatch");
check_key_match(&i1964->ctx_key, &a1964->ctx_key);
fputs("rfc1964 ", stdout);
display_enctype(i1964->ctx_key.type);
fputs("\n", stdout);
}

krb5_free_context(kctx);
free(ienc);
free(aenc);
(void)gss_release_name(&minor, &tname);
(void)gss_release_cred(&minor, &icred);
(void)gss_release_cred(&minor, &acred);
(void)gss_delete_sec_context(&minor, &ictx, NULL);
(void)gss_delete_sec_context(&minor, &actx, NULL);
(void)gss_release_buffer(&minor, &itok);
(void)gss_release_buffer(&minor, &atok);
(void)gss_release_buffer(&minor, &tmp);
(void)gss_krb5_free_lucid_sec_context(&minor, ilucid);
(void)gss_krb5_free_lucid_sec_context(&minor, alucid);
return 0;
}

0 comments on commit 2e95607

Please sign in to comment.