]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Add acceptor-side IAKERB realm discovery 1357/head
authorGreg Hudson <ghudson@mit.edu>
Tue, 9 Jul 2024 19:14:03 +0000 (15:14 -0400)
committerGreg Hudson <ghudson@mit.edu>
Mon, 22 Jul 2024 21:10:26 +0000 (17:10 -0400)
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
src/lib/gssapi/krb5/iakerb.c
src/tests/gssapi/Makefile.in
src/tests/gssapi/t_gssapi.py
src/tests/gssapi/t_iakerb.c [new file with mode: 0644]

index db1478fed9c86691a675e8dede3442bc455ba9cb..90bfa0e206d2faff0f87f2e68b2c777dc38c4c3d 100644 (file)
@@ -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
index 9e8bc05dabafc182901dd644a0e406e7c0971544..69c3445d6bd2da9e04ba537b53d56f33238b66ae 100644 (file)
@@ -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)
index ee65a65f34d57e18828eeca38e4a7c3f7767cdd5..97a6ac3f3f78db8c2d3b262333c7e4d940a00e07 100644 (file)
@@ -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
index 5f093a198cc53971155442fa0ed1ef5c44141c2c..e1ed571fdd8fa6509c208817ef3f1e65bd17c644 100755 (executable)
@@ -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 (file)
index 0000000..a81b526
--- /dev/null
@@ -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;
+}