]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
implement gss_pseudo_random()
authorLuke Howard <lukeh@padl.com>
Sun, 22 Nov 2009 11:33:00 +0000 (11:33 +0000)
committerLuke Howard <lukeh@padl.com>
Sun, 22 Nov 2009 11:33:00 +0000 (11:33 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/users/lhoward/gssextras@23302 dc483132-0cff-0310-8789-dd5450dbe970

12 files changed:
src/lib/gssapi/generic/gssapi.hin
src/lib/gssapi/krb5/Makefile.in
src/lib/gssapi/krb5/gssapiP_krb5.h
src/lib/gssapi/krb5/gssapi_err_krb5.et
src/lib/gssapi/krb5/prf.c [new file with mode: 0644]
src/lib/gssapi/libgssapi_krb5.exports
src/lib/gssapi/mechglue/Makefile.in
src/lib/gssapi/mechglue/g_initialize.c
src/lib/gssapi/mechglue/g_prf.c [new file with mode: 0644]
src/lib/gssapi/mechglue/mglueP.h
src/lib/gssapi/spnego/gssapiP_spnego.h
src/lib/gssapi/spnego/spnego_mech.c

index 422b4dbef8c83b4ea18a5dac693094ad2294f2df..d0ccb38c315e84c04527410e07886da71842eac1 100644 (file)
@@ -780,6 +780,21 @@ gss_canonicalize_name(
     const gss_OID,      /* mech_type */
     gss_name_t *);      /* output_name */
 
+/* RFC 4401 */
+
+#define GSS_C_PRF_KEY_FULL      0
+#define GSS_C_PRF_KEY_PARTIAL   1
+
+OM_uint32 KRB5_CALLCONV
+gss_pseudo_random(
+    OM_uint32 *,        /* minor_status */
+    gss_ctx_id_t,       /* context */
+    int,                /* prf_key */
+    const gss_buffer_t, /* prf_in */
+    ssize_t,            /* desired_output_len */
+    gss_buffer_t);      /* prf_out */
+
+
 #if TARGET_OS_MAC
 #    pragma pack(pop)
 #endif
index b84efa1769d981ee015143626c9ed20189666559..70bea386fe702a9133485f8f6005eb8514b9f79b 100644 (file)
@@ -70,6 +70,7 @@ SRCS = \
        $(srcdir)/krb5_gss_glue.c \
        $(srcdir)/lucid_context.c \
        $(srcdir)/naming_exts.c \
+       $(srcdir)/prf.c \
        $(srcdir)/process_context_token.c \
        $(srcdir)/rel_cred.c \
        $(srcdir)/rel_oid.c \
@@ -122,6 +123,7 @@ OBJS = \
        $(OUTPRE)krb5_gss_glue.$(OBJEXT) \
        $(OUTPRE)lucid_context.$(OBJEXT) \
        $(OUTPRE)naming_exts.$(OBJEXT) \
+       $(OUTPRE)prf.$(OBJEXT) \
        $(OUTPRE)process_context_token.$(OBJEXT) \
        $(OUTPRE)rel_cred.$(OBJEXT) \
        $(OUTPRE)rel_oid.$(OBJEXT) \
@@ -177,6 +179,7 @@ STLIBOBJS = \
        krb5_gss_glue.o \
        lucid_context.o \
        naming_exts.o \
+       prf.o \
        process_context_token.o \
        rel_cred.o \
        rel_oid.o \
index 13413b972e4f7f8c812771fd4f26fdab2f74fd71..14ad1265bf9684159814fe519b50842ec8238a28 100644 (file)
@@ -909,6 +909,14 @@ krb5_gss_release_any_name_mapping(OM_uint32 *minor_status,
                                   gss_buffer_t type_id,
                                   gss_any_t *input);
 
+OM_uint32
+krb5_gss_pseudo_random(OM_uint32 *minor_status,
+                       gss_ctx_id_t context,
+                       int prf_key,
+                       const gss_buffer_t prf_in,
+                       ssize_t desired_output_len,
+                       gss_buffer_t prf_out);
+
 /* s4u_gss_glue.c */
 OM_uint32
 kg_compose_deleg_cred(OM_uint32 *minor_status,
index c2a705c84e59018ad0caaba9938546232c4d07ba..4cfd68a00e05e8ff8c58dc52524bde7fde0e144d 100644 (file)
@@ -37,4 +37,5 @@ error_code KG_BAD_SEQ, "Sequence number in token is corrupt"
 error_code KG_EMPTY_CCACHE, "Credential cache is empty"
 error_code KG_NO_CTYPES, "Acceptor and Initiator share no checksum types"
 error_code KG_LUCID_VERSION, "Requested lucid context version not supported"
+error_code KG_INPUT_TOO_LONG, "PRF input too long"
 end
diff --git a/src/lib/gssapi/krb5/prf.c b/src/lib/gssapi/krb5/prf.c
new file mode 100644 (file)
index 0000000..2c0f37e
--- /dev/null
@@ -0,0 +1,140 @@
+/* -*- mode: c; indent-tabs-mode: nil -*- */
+/*
+ * lib/gssapi/krb5/prf.c
+ *
+ * Copyright 2009 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 <assert.h>
+#include "k5-int.h"          /* for zap() */
+#include "gssapiP_krb5.h"
+#include <stdarg.h>
+
+OM_uint32
+krb5_gss_pseudo_random(OM_uint32 *minor_status,
+                       gss_ctx_id_t context,
+                       int prf_key,
+                       const gss_buffer_t prf_in,
+                       ssize_t desired_output_len,
+                       gss_buffer_t prf_out)
+{
+    krb5_error_code code;
+    krb5_key key = NULL;
+    krb5_gss_ctx_id_t ctx;
+    int i;
+    krb5_keyblock *keyblock = NULL;
+    OM_uint32 minor;
+    size_t prflen;
+    krb5_data t, ns;
+    unsigned char *p;
+
+    t.length = 0;
+    t.data = NULL;
+    ns.length = 0;
+    ns.data = NULL;
+
+    prf_out->length = 0;
+    prf_out->value = NULL;
+
+    if (!kg_validate_ctx_id(context)) {
+        *minor_status = G_VALIDATE_FAILED;
+        return GSS_S_NO_CONTEXT;
+    }
+
+    ctx = (krb5_gss_ctx_id_t)context;
+
+    switch (prf_key) {
+    case GSS_C_PRF_KEY_FULL:
+        if (ctx->have_acceptor_subkey) {
+            key = ctx->acceptor_subkey;
+            break;
+        }
+        /* fallthrough */
+    case GSS_C_PRF_KEY_PARTIAL:
+        key = ctx->subkey;
+        break;
+    default:
+        code = EINVAL;
+        goto cleanup;
+    }
+
+    if (key == NULL) {
+        code = EINVAL;
+        goto cleanup;
+    }
+
+    prf_out->value = k5alloc(desired_output_len, &code);
+    if (prf_out->value == NULL) {
+        code = KG_INPUT_TOO_LONG;
+        goto cleanup;
+    }
+
+    code = krb5_c_prf_length(ctx->k5_context,
+                             krb5_k_key_enctype(ctx->k5_context, key),
+                             &prflen);
+    if (code != 0)
+        goto cleanup;
+
+    code = krb5_k_key_keyblock(ctx->k5_context, key, &keyblock);
+    if (code != 0)
+        goto cleanup;
+
+    ns.length = 4 + prf_in->length;
+    ns.data = k5alloc(ns.length, &code);
+    if (ns.data == NULL) {
+        code = KG_INPUT_TOO_LONG;
+        goto cleanup;
+    }
+
+    memcpy(ns.data + 4, prf_in->value, prf_in->length);
+    i = 0;
+    p = (unsigned char *)prf_out->value;
+    while (desired_output_len > 0) {
+        store_32_be(i, ns.data);
+
+        code = krb5_c_prf(ctx->k5_context, keyblock, &ns, &t);
+        if (code != 0)
+            goto cleanup;
+
+        memcpy(p, t.data, MIN(t.length, desired_output_len));
+
+        p += t.length;
+        desired_output_len -= t.length;
+        i++;
+
+        krb5_free_data_contents(ctx->k5_context, &t);
+    }
+
+cleanup:
+    if (code != 0)
+        gss_release_buffer(&minor, prf_out);
+    krb5_free_data_contents(ctx->k5_context, &ns);
+    krb5_free_data_contents(ctx->k5_context, &t);
+    krb5_free_keyblock(ctx->k5_context, keyblock);
+
+    *minor_status = (OM_uint32)code;
+    return (code == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE;
+}
+
index 60754df7a768d2414cda145efc154b9d3e9e3b1b..de063da3abdb4ed22e9d02d193088cba4bd67819 100644 (file)
@@ -68,6 +68,7 @@ gss_nt_service_name_v2
 gss_nt_string_uid_name
 gss_nt_user_name
 gss_oid_to_str
+gss_pseudo_random
 gss_process_context_token
 gss_release_any_name_mapping
 gss_release_buffer_set
index 61972ab759028ceddc2f6ceb19c934f6533dc426..8edacf66382800ff6b0954f63d2a2e5d023716ee 100644 (file)
@@ -45,6 +45,7 @@ SRCS = \
        $(srcdir)/g_mech_invoke.c \
        $(srcdir)/g_mechname.c \
        $(srcdir)/g_oid_ops.c \
+       $(srcdir)/g_prf.c \
        $(srcdir)/g_process_context.c \
        $(srcdir)/g_rel_buffer.c \
        $(srcdir)/g_rel_cred.c \
@@ -98,6 +99,7 @@ OBJS = \
        $(OUTPRE)g_mech_invoke.$(OBJEXT) \
        $(OUTPRE)g_mechname.$(OBJEXT) \
        $(OUTPRE)g_oid_ops.$(OBJEXT) \
+       $(OUTPRE)g_prf.$(OBJEXT) \
        $(OUTPRE)g_process_context.$(OBJEXT) \
        $(OUTPRE)g_rel_buffer.$(OBJEXT) \
        $(OUTPRE)g_rel_cred.$(OBJEXT) \
@@ -151,6 +153,7 @@ STLIBOBJS = \
        g_mech_invoke.o \
        g_mechname.o \
        g_oid_ops.o \
+       g_prf.o \
        g_process_context.o \
        g_rel_buffer.o \
        g_rel_cred.o \
index 3929f761bb0e1dc92dd98cf4b5437a15f5982b0e..e01d174742cd8a27108361363a4a87776a53c732 100644 (file)
@@ -773,6 +773,8 @@ build_dynamicMech(void *dl, const gss_OID mech_type)
        GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_export_name_composite);
        GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_map_name_to_any);
        GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_release_any_name_mapping);
+        /* RFC 4401 (introduced in 1.8) */
+       GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_pseudo_random);
 
        assert(mech_type != GSS_C_NO_OID);
 
diff --git a/src/lib/gssapi/mechglue/g_prf.c b/src/lib/gssapi/mechglue/g_prf.c
new file mode 100644 (file)
index 0000000..74a3a21
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2009 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.
+ *
+ */
+
+/*
+ *  glue routine for gss_pseudo_random
+ */
+
+#include "mglueP.h"
+
+OM_uint32 KRB5_CALLCONV
+gss_pseudo_random (OM_uint32 *minor_status,
+                  gss_ctx_id_t context_handle,
+                  int prf_key,
+                  const gss_buffer_t prf_in,
+                  ssize_t desired_output_len,
+                  gss_buffer_t prf_out)
+{
+    OM_uint32          status;
+    gss_union_ctx_id_t ctx;
+    gss_mechanism      mech;
+
+    if (minor_status == NULL)
+       return GSS_S_CALL_INACCESSIBLE_WRITE;
+
+    if (context_handle == GSS_C_NO_CONTEXT)
+       return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT;
+
+    if (prf_in == GSS_C_NO_BUFFER)
+       return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT;
+
+    if (prf_out == GSS_C_NO_BUFFER)
+       return GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CONTEXT;
+
+    prf_out->length = 0;
+    prf_out->value = NULL;
+
+    /*
+     * select the approprate underlying mechanism routine and
+     * call it.
+     */
+
+    ctx = (gss_union_ctx_id_t) context_handle;
+    mech = gssint_get_mechanism (ctx->mech_type);
+
+    if (mech != NULL) {
+       if (mech->gss_pseudo_random != NULL) {
+           status = mech->gss_pseudo_random(minor_status,
+                                            ctx->internal_ctx_id,
+                                            prf_key,
+                                            prf_in,
+                                            desired_output_len,
+                                            prf_out);
+           if (status != GSS_S_COMPLETE)
+               map_error(minor_status, mech);
+       } else
+           status = GSS_S_UNAVAILABLE;
+
+       return status;
+    }
+
+    return GSS_S_BAD_MECH;
+}
index f35ac144742e1838b5db4a4782ee09f6107d5c11..517ca481b99c245b853f9b055a380381786a8bcd 100644 (file)
@@ -573,6 +573,16 @@ typedef struct gss_config {
            gss_any_t *                 /* input */
        /* */);
 
+        OM_uint32       (*gss_pseudo_random)
+        (
+            OM_uint32 *,                /* minor_status */
+            gss_ctx_id_t,               /* context */
+            int,                        /* prf_key */
+            const gss_buffer_t,         /* prf_in */
+            ssize_t,                    /* desired_output_len */
+            gss_buffer_t                /* prf_out */
+        /* */);
+
 } *gss_mechanism;
 
 /* This structure MUST NOT be used by any code outside libgss */
index 43b0049313d805f8d34f4bedbc104f2ed4d0fc1d..80c23e2838b3c50f5e8e4d24f22b1ba93d862678 100644 (file)
@@ -519,6 +519,17 @@ spnego_gss_release_any_name_mapping
        gss_any_t *input
 );
 
+OM_uint32
+spnego_gss_pseudo_random
+(
+       OM_uint32 *minor_status,
+       gss_ctx_id_t context,
+       int prf_key,
+       const gss_buffer_t prf_in,
+       ssize_t desired_output_len,
+       gss_buffer_t prf_out
+);
+
 #ifdef __cplusplus
 }
 #endif
index 2aa8ad5dd8e9ae2d907a46deb77a5a5598972390..6357f1691a1e4039116a5be1490c1bb6d42333eb 100644 (file)
@@ -268,6 +268,7 @@ static struct gss_config spnego_mechanism =
        spnego_gss_export_name_composite,
        spnego_gss_map_name_to_any,
        spnego_gss_release_any_name_mapping,
+       spnego_gss_pseudo_random,
 };
 
 #ifdef _GSS_STATIC_LINK
@@ -2485,6 +2486,24 @@ spnego_gss_release_any_name_mapping(OM_uint32 *minor_status,
        return (ret);
 }
 
+OM_uint32
+spnego_gss_pseudo_random(OM_uint32 *minor_status,
+                         gss_ctx_id_t context,
+                        int prf_key,
+                        const gss_buffer_t prf_in,
+                        ssize_t desired_output_len,
+                        gss_buffer_t prf_out)
+{
+        OM_uint32 ret;
+        ret = gss_pseudo_random(minor_status,
+                                context,
+                                prf_key,
+                                prf_in,
+                                desired_output_len,
+                                prf_out);
+        return (ret);
+}
+
 /*
  * We will release everything but the ctx_handle so that it
  * can be passed back to init/accept context. This routine should