krb5 commit: Add acceptor-side IAKERB realm discovery

ghudson at mit.edu ghudson at mit.edu
Mon Jul 22 17:25:34 EDT 2024


https://github.com/krb5/krb5/commit/6e20892369a9fafa09294529fb4d331e4fcbb97a
commit 6e20892369a9fafa09294529fb4d331e4fcbb97a
Author: Greg Hudson <ghudson at mit.edu>
Date:   Tue Jul 9 15:14:03 2024 -0400

    Add acceptor-side IAKERB realm discovery
    
    draft-ietf-kitten-iakerb-03 section 3.1 specifies a way for the
    initiator to query the acceptor's realm.  Implement this facility in
    the IAKERB acceptor.
    
    ticket: 9133 (new)

 .gitignore                   |  1 +
 src/lib/gssapi/krb5/iakerb.c | 66 +++++++++++++++++++++++++++++----
 src/tests/gssapi/Makefile.in | 32 ++++++++--------
 src/tests/gssapi/t_gssapi.py |  2 +
 src/tests/gssapi/t_iakerb.c  | 88 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 167 insertions(+), 22 deletions(-)

diff --git a/.gitignore b/.gitignore
index db1478fed..90bfa0e20 100644
--- a/.gitignore
+++ b/.gitignore
@@ -463,6 +463,7 @@ local.properties
 /src/tests/gssapi/t_export_cred
 /src/tests/gssapi/t_export_name
 /src/tests/gssapi/t_gssexts
+/src/tests/gssapi/t_iakerb
 /src/tests/gssapi/t_imp_cred
 /src/tests/gssapi/t_imp_name
 /src/tests/gssapi/t_invalid
diff --git a/src/lib/gssapi/krb5/iakerb.c b/src/lib/gssapi/krb5/iakerb.c
index 9e8bc05da..69c3445d6 100644
--- a/src/lib/gssapi/krb5/iakerb.c
+++ b/src/lib/gssapi/krb5/iakerb.c
@@ -283,6 +283,53 @@ cleanup:
     return code;
 }
 
+/* Generate a response to a realm discovery request. */
+static krb5_error_code
+iakerb_acceptor_realm(iakerb_ctx_id_t ctx, gss_cred_id_t verifier_cred,
+                      gss_buffer_t output_token)
+{
+    krb5_error_code ret;
+    OM_uint32 dummy;
+    krb5_gss_cred_id_t cred = (krb5_gss_cred_id_t)verifier_cred;
+    krb5_data realm = empty_data(), reply = empty_data();
+    krb5_error error = { 0 };
+    char *defrealm = NULL;
+
+    /* Get the acceptor realm from the verifier cred if we can; otherwise try
+     * to use the default realm. */
+    if (cred != NULL && cred->name != NULL &&
+        cred->name->princ->realm.length > 0) {
+        realm = cred->name->princ->realm;
+    } else {
+        ret = krb5_get_default_realm(ctx->k5c, &defrealm);
+        if (ret) {
+            /* Generate an error reply if there is no default realm. */
+            error.error = KRB_ERR_GENERIC;
+            ret = krb5_mk_error(ctx->k5c, &error, &reply);
+            if (ret)
+                goto cleanup;
+        } else {
+            realm = string2data(defrealm);
+        }
+    }
+
+    ret = iakerb_make_token(ctx, &realm, NULL, &reply, output_token);
+    if (ret)
+        goto cleanup;
+    ret = iakerb_save_token(ctx, output_token);
+    if (ret)
+        goto cleanup;
+
+    ctx->count++;
+
+cleanup:
+    if (ret)
+        gss_release_buffer(&dummy, output_token);
+    krb5_free_default_realm(ctx->k5c, defrealm);
+    krb5_free_data_contents(ctx->k5c, &reply);
+    return ret;
+}
+
 /*
  * Parse the IAKERB token in input_token and send the contained KDC
  * request to the KDC for the realm.
@@ -290,7 +337,7 @@ cleanup:
  * Wrap the KDC reply in output_token.
  */
 static krb5_error_code
-iakerb_acceptor_step(iakerb_ctx_id_t ctx,
+iakerb_acceptor_step(iakerb_ctx_id_t ctx, gss_cred_id_t verifier_cred,
                      const gss_buffer_t input_token,
                      gss_buffer_t output_token)
 {
@@ -313,15 +360,19 @@ iakerb_acceptor_step(iakerb_ctx_id_t ctx,
     if (code != 0)
         goto cleanup;
 
-    if (realm.length == 0 || request.length == 0) {
-        code = KRB5_BAD_MSIZE;
-        goto cleanup;
-    }
-
     code = iakerb_save_token(ctx, input_token);
     if (code != 0)
         goto cleanup;
 
+    if (realm.length == 0 && request.length == 0) {
+        /* This is a realm discovery request. */
+        code = iakerb_acceptor_realm(ctx, verifier_cred, output_token);
+        goto cleanup;
+    } else if (realm.length == 0 || request.length == 0) {
+        code = KRB5_BAD_MSIZE;
+        goto cleanup;
+    }
+
     for (tcp_only = 0; tcp_only <= 1; tcp_only++) {
         use_primary = 0;
         code = krb5_sendto_kdc(ctx->k5c, &request, &realm,
@@ -770,7 +821,8 @@ iakerb_gss_accept_sec_context(OM_uint32 *minor_status,
             major_status = GSS_S_DEFECTIVE_TOKEN;
             goto cleanup;
         }
-        code = iakerb_acceptor_step(ctx, input_token, output_token);
+        code = iakerb_acceptor_step(ctx, verifier_cred_handle, input_token,
+                                    output_token);
         if (code == (OM_uint32)KRB5_BAD_MSIZE)
             major_status = GSS_S_DEFECTIVE_TOKEN;
         if (code != 0)
diff --git a/src/tests/gssapi/Makefile.in b/src/tests/gssapi/Makefile.in
index ee65a65f3..97a6ac3f3 100644
--- a/src/tests/gssapi/Makefile.in
+++ b/src/tests/gssapi/Makefile.in
@@ -13,9 +13,9 @@ SRCS=	$(srcdir)/ccinit.c $(srcdir)/ccrefresh.c $(srcdir)/common.c \
 	$(srcdir)/t_bindings.c $(srcdir)/t_ccselect.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_gssexts.c $(srcdir)/t_iakerb.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 \
 	$(srcdir)/t_s4u2proxy_krb5.c $(srcdir)/t_saslname.c \
@@ -24,20 +24,20 @@ SRCS=	$(srcdir)/ccinit.c $(srcdir)/ccrefresh.c $(srcdir)/common.c \
 OBJS=	ccinit.o ccrefresh.o common.o reload.o t_accname.o t_add_cred.o \
 	t_bindings.o t_ccselect.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 t_store_cred.o
+	t_iakerb.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_store_cred.o t_iakerb.o
 
 COMMON_DEPS= common.o $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS)
 COMMON_LIBS= common.o $(GSS_LIBS) $(KRB5_BASE_LIBS)
 
 all: ccinit ccrefresh reload t_accname t_add_cred t_bindings 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 \
-	t_store_cred
+	t_export_name t_gssexts t_iakerb 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 t_store_cred
 
 check-unix: t_invalid t_oid t_prf t_imp_name reload
 	$(RUN_TEST) ./t_invalid
@@ -93,6 +93,8 @@ t_export_name: t_export_name.o $(COMMON_DEPS)
 	$(CC_LINK) -o $@ t_export_name.o $(COMMON_LIBS)
 t_gssexts: t_gssexts.o $(COMMON_DEPS)
 	$(CC_LINK) -o $@ t_gssexts.o $(COMMON_LIBS)
+t_iakerb: t_iakerb.o $(COMMON_DEPS)
+	$(CC_LINK) -o $@ t_iakerb.o $(COMMON_LIBS)
 t_imp_cred: t_imp_cred.o $(COMMON_DEPS)
 	$(CC_LINK) -o $@ t_imp_cred.o $(COMMON_LIBS)
 t_imp_name: t_imp_name.o $(COMMON_DEPS)
@@ -133,7 +135,7 @@ t_store_cred: t_store_cred.o $(COMMON_DEPS)
 clean:
 	$(RM) ccinit ccrefresh reload t_accname t_add_cred t_bindings
 	$(RM) t_ccselect t_ciflags t_context t_credstore t_enctypes t_err
-	$(RM) t_export_cred t_export_name t_gssexts t_imp_cred t_imp_name
-	$(RM) t_invalid 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 t_store_cred
+	$(RM) t_export_cred t_export_name t_gssexts t_iakerb t_imp_cred
+	$(RM) t_imp_name t_invalid t_inq_cred t_inq_ctx t_inq_mechs_name t_iov
+	$(RM) t_lifetime t_namingexts t_oid t_pcontok t_prf t_s4u
+	$(RM) t_s4u2proxy_krb5 t_saslname t_spnego t_srcattrs t_store_cred
diff --git a/src/tests/gssapi/t_gssapi.py b/src/tests/gssapi/t_gssapi.py
index 5f093a198..e1ed571fd 100755
--- a/src/tests/gssapi/t_gssapi.py
+++ b/src/tests/gssapi/t_gssapi.py
@@ -13,6 +13,8 @@ realm = K5Realm()
 # Test gss_add_cred().
 realm.run(['./t_add_cred'])
 
+realm.run(['./t_iakerb'])
+
 ### Test acceptor name behavior.
 
 # Create some host-based principals and put most of them into the
diff --git a/src/tests/gssapi/t_iakerb.c b/src/tests/gssapi/t_iakerb.c
new file mode 100644
index 000000000..a81b526e7
--- /dev/null
+++ b/src/tests/gssapi/t_iakerb.c
@@ -0,0 +1,88 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* tests/gssapi/t_iakerb.c - IAKERB tests */
+/*
+ * Copyright (C) 2024 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 <string.h>
+#include <assert.h>
+#include "common.h"
+
+static uint8_t
+realm_query[] = {
+    /* ASN.1 wrapper for IAKERB mech */
+    0x60, 0x10,
+    0x06, 0x06, 0x2B, 0x06, 0x01, 0x05, 0x02, 0x05,
+    /* IAKERB_PROXY token type */
+    0x05, 0x01,
+    /* IAKERB-HEADER with empty target-realm */
+    0x30, 0x04,
+    0xA1, 0x02, 0x0C, 0x00
+};
+
+static uint8_t
+realm_response[] = {
+    /* ASN.1 wrapper for IAKERB mech */
+    0x60, 0x1B,
+    0x06, 0x06, 0x2B, 0x06, 0x01, 0x05, 0x02, 0x05,
+    /* IAKERB_PROXY token type */
+    0x05, 0x01,
+    /* IAKERB-HEADER with configured realm */
+    0x30, 0x0F,
+    0xA1, 0x0D, 0x0C, 0x0B,
+    'K', 'R', 'B', 'T', 'E', 'S', 'T', '.', 'C', 'O', 'M'
+};
+
+int
+main(void)
+{
+    OM_uint32 major, minor;
+    gss_cred_id_t cred;
+    gss_buffer_desc in, out;
+    gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
+
+    major = gss_acquire_cred(&minor, GSS_C_NO_NAME, 0, &mechset_iakerb,
+                             GSS_C_ACCEPT, &cred, NULL, NULL);
+    check_gsserr("gss_acquire_cred", major, minor);
+
+    in.value = realm_query;
+    in.length = sizeof(realm_query);
+    major = gss_accept_sec_context(&minor, &ctx, cred, &in,
+                                   GSS_C_NO_CHANNEL_BINDINGS, NULL, NULL, &out,
+                                   NULL, NULL, NULL);
+    check_gsserr("gss_accept_sec_context", major, minor);
+    assert(out.length == sizeof(realm_response));
+    assert(memcmp(out.value, realm_response, out.length) == 0);
+
+    gss_release_buffer(&minor, &out);
+    gss_delete_sec_context(&minor, &ctx, NULL);
+    gss_release_cred(&minor, &cred);
+    return 0;
+}


More information about the cvs-krb5 mailing list