krb5 commit: Introduce gss_export_cred and gss_import_cred

Greg Hudson ghudson at MIT.EDU
Tue Sep 11 01:18:58 EDT 2012


https://github.com/krb5/krb5/commit/abc6b8ce993c4c8393228ab5a01f26e7c5b251b2
commit abc6b8ce993c4c8393228ab5a01f26e7c5b251b2
Author: Greg Hudson <ghudson at mit.edu>
Date:   Sat Aug 18 23:40:29 2012 -0400

    Introduce gss_export_cred and gss_import_cred
    
    Add gss_export_cred and gss_import_cred mechglue functions to
    serialize and unserialize GSSAPI credential handles.  Mechanism
    implementations and tests will follow.
    
    ticket: 7354 (new)

 doc/rst_source/krb_appldev/gssapi.rst   |   48 +++++++++
 src/lib/gssapi/generic/gssapi_ext.h     |   12 +++
 src/lib/gssapi/libgssapi_krb5.exports   |    2 +
 src/lib/gssapi/mechglue/Makefile.in     |    6 +
 src/lib/gssapi/mechglue/g_export_cred.c |  116 ++++++++++++++++++++++
 src/lib/gssapi/mechglue/g_imp_cred.c    |  164 +++++++++++++++++++++++++++++++
 src/lib/gssapi/mechglue/mglueP.h        |   14 +++
 src/lib/gssapi32.def                    |    2 +
 8 files changed, 364 insertions(+), 0 deletions(-)

diff --git a/doc/rst_source/krb_appldev/gssapi.rst b/doc/rst_source/krb_appldev/gssapi.rst
index 214e3a0..29c06b5 100644
--- a/doc/rst_source/krb_appldev/gssapi.rst
+++ b/doc/rst_source/krb_appldev/gssapi.rst
@@ -164,6 +164,54 @@ If the *desired_name* is a krb5 principal name or a local system name
 type which is mapped to a krb5 principal name, clients will only be
 allowed to authenticate to that principal in the default keytab.
 
+
+Importing and exporting credentials
+-----------------------------------
+
+The following GSSAPI extensions can be used to import and export
+credentials (declared in ``<gssapi/gssapi_ext.h>``)::
+
+    OM_uint32 gss_export_cred(OM_uint32 *minor_status,
+                              gss_cred_id_t cred_handle,
+                              gss_buffer_t token);
+
+    OM_uint32 gss_import_cred(OM_uint32 *minor_status,
+                              gss_buffer_t token,
+                              gss_cred_id_t *cred_handle);
+
+The first function serializes a GSSAPI credential handle into a
+buffer; the second unseralizes a buffer into a GSSAPI credential
+handle.  Serializing a credential does not destroy it.  If any of the
+mechanisms used in *cred_handle* do not support serialization,
+gss_export_cred will return **GSS_S_UNAVAILABLE**.  As with other
+GSSAPI serialization functions, these extensions are only intended to
+work with a matching implementation on the other side; they do not
+serialize credentials in a standardized format.
+
+A serialized credential may contain secret information such as ticket
+session keys.  The serialization format does not protect this
+information from eavesdropping or tampering.  The calling application
+must take care to protect the serialized credential when communicating
+it over an insecure channel or to an untrusted party.
+
+A krb5 GSSAPI credential may contain references to a credential cache,
+a client keytab, an acceptor keytab, and a replay cache.  These
+resources are normally serialized as references to their external
+locations (such as the filename of the credential cache).  Because of
+this, a serialized krb5 credential can only be imported by a process
+with similar privileges to the exporter.  A serialized credential
+should not be trusted if it originates from a source with lower
+privileges than the importer, as it may contain references to external
+credential cache, keytab, or replay cache resources not accessible to
+the originator.
+
+An exception to the above rule applies when a krb5 GSSAPI credential
+refers to a memory credential cache, as is normally the case for
+delegated credentials received by gss_accept_sec_context_.  In this
+case, the contents of the credential cache are serialized, so that the
+resulting token may be imported even if the original memory credential
+cache no longer exists.
+
 .. _gss_accept_sec_context: http://tools.ietf.org/html/rfc2744.html#section-5.1
 .. _gss_acquire_cred: http://tools.ietf.org/html/rfc2744.html#section-5.2
 .. _gss_export_name: http://tools.ietf.org/html/rfc2744.html#section-5.13
diff --git a/src/lib/gssapi/generic/gssapi_ext.h b/src/lib/gssapi/generic/gssapi_ext.h
index dd12ffe..d8c8b6a 100644
--- a/src/lib/gssapi/generic/gssapi_ext.h
+++ b/src/lib/gssapi/generic/gssapi_ext.h
@@ -518,6 +518,18 @@ gss_store_cred_into(
     gss_OID_set *,             /* elements_stored */
     gss_cred_usage_t *);       /* cred_usage_stored */
 
+OM_uint32 KRB5_CALLCONV
+gss_export_cred(
+    OM_uint32 *,               /* minor_status */
+    gss_cred_id_t,             /* cred_handle */
+    gss_buffer_t);             /* token */
+
+OM_uint32 KRB5_CALLCONV
+gss_import_cred(
+    OM_uint32 *,               /* minor_status */
+    gss_buffer_t,              /* token */
+    gss_cred_id_t *);          /* cred_handle */
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/lib/gssapi/libgssapi_krb5.exports b/src/lib/gssapi/libgssapi_krb5.exports
index 3da3a23..242a3c0 100644
--- a/src/lib/gssapi/libgssapi_krb5.exports
+++ b/src/lib/gssapi/libgssapi_krb5.exports
@@ -60,11 +60,13 @@ gss_display_name_ext
 gss_display_status
 gss_duplicate_name
 gss_encapsulate_token
+gss_export_cred
 gss_export_name
 gss_export_name_composite
 gss_export_sec_context
 gss_get_mic
 gss_get_name_attribute
+gss_import_cred
 gss_import_name
 gss_import_sec_context
 gss_indicate_mechs
diff --git a/src/lib/gssapi/mechglue/Makefile.in b/src/lib/gssapi/mechglue/Makefile.in
index 63302f0..9987d15 100644
--- a/src/lib/gssapi/mechglue/Makefile.in
+++ b/src/lib/gssapi/mechglue/Makefile.in
@@ -29,10 +29,12 @@ SRCS = \
 	$(srcdir)/g_dup_name.c \
 	$(srcdir)/g_encapsulate_token.c \
 	$(srcdir)/g_exp_sec_context.c \
+	$(srcdir)/g_export_cred.c \
 	$(srcdir)/g_export_name.c \
 	$(srcdir)/g_export_name_comp.c \
 	$(srcdir)/g_get_name_attr.c \
 	$(srcdir)/g_glue.c \
+	$(srcdir)/g_imp_cred.c \
 	$(srcdir)/g_imp_name.c \
 	$(srcdir)/g_imp_sec_context.c \
 	$(srcdir)/g_init_sec_context.c \
@@ -91,10 +93,12 @@ OBJS = \
 	$(OUTPRE)g_dup_name.$(OBJEXT) \
 	$(OUTPRE)g_encapsulate_token.$(OBJEXT) \
 	$(OUTPRE)g_exp_sec_context.$(OBJEXT) \
+	$(OUTPRE)g_export_cred.$(OBJEXT) \
 	$(OUTPRE)g_export_name.$(OBJEXT) \
 	$(OUTPRE)g_export_name_comp.$(OBJEXT) \
 	$(OUTPRE)g_get_name_attr.$(OBJEXT) \
 	$(OUTPRE)g_glue.$(OBJEXT) \
+	$(OUTPRE)g_imp_cred.$(OBJEXT) \
 	$(OUTPRE)g_imp_name.$(OBJEXT) \
 	$(OUTPRE)g_imp_sec_context.$(OBJEXT) \
 	$(OUTPRE)g_init_sec_context.$(OBJEXT) \
@@ -153,10 +157,12 @@ STLIBOBJS = \
 	g_dup_name.o \
 	g_encapsulate_token.o \
 	g_exp_sec_context.o \
+	g_export_cred.o \
 	g_export_name.o \
 	g_export_name_comp.o \
 	g_get_name_attr.o \
 	g_glue.o \
+	g_imp_cred.o \
 	g_imp_name.o \
 	g_imp_sec_context.o \
 	g_init_sec_context.o \
diff --git a/src/lib/gssapi/mechglue/g_export_cred.c b/src/lib/gssapi/mechglue/g_export_cred.c
new file mode 100644
index 0000000..4994c9b
--- /dev/null
+++ b/src/lib/gssapi/mechglue/g_export_cred.c
@@ -0,0 +1,116 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/gssapi/mechglue/g_export_cred.c - gss_export_cred definition */
+/*
+ * Copyright (C) 2012 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 "mglueP.h"
+
+static OM_uint32
+val_exp_cred_args(OM_uint32 *minor_status, gss_cred_id_t cred_handle,
+                  gss_buffer_t token)
+{
+
+    /* Initialize outputs. */
+    if (minor_status != NULL)
+        *minor_status = 0;
+    if (token != GSS_C_NO_BUFFER) {
+        token->length = 0;
+        token->value = NULL;
+    }
+
+    /* Validate arguments. */
+    if (minor_status == NULL)
+        return GSS_S_CALL_INACCESSIBLE_WRITE;
+    if (cred_handle == GSS_C_NO_CREDENTIAL)
+        return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CRED;
+    if (token == GSS_C_NO_BUFFER)
+        return GSS_S_CALL_INACCESSIBLE_WRITE;
+    return GSS_S_COMPLETE;
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_export_cred(OM_uint32 * minor_status, gss_cred_id_t cred_handle,
+                gss_buffer_t token)
+{
+    OM_uint32 status, tmpmin;
+    gss_union_cred_t cred;
+    gss_OID mech_oid;
+    gss_mechanism mech;
+    gss_buffer_desc mech_token;
+    struct k5buf buf;
+    char lenbuf[4];
+    int i;
+
+    status = val_exp_cred_args(minor_status, cred_handle, token);
+    if (status != GSS_S_COMPLETE)
+        return status;
+
+    krb5int_buf_init_dynamic(&buf);
+
+    cred = (gss_union_cred_t) cred_handle;
+    for (i = 0; i < cred->count; i++) {
+        /* Get an export token for this mechanism. */
+        mech_oid = &cred->mechs_array[i];
+        mech = gssint_get_mechanism(mech_oid);
+        if (mech == NULL) {
+            status = GSS_S_DEFECTIVE_CREDENTIAL;
+            goto error;
+        }
+        if (mech->gss_export_cred == NULL) {
+            status = GSS_S_UNAVAILABLE;
+            goto error;
+        }
+        status = mech->gss_export_cred(minor_status, cred->cred_array[i],
+                                       &mech_token);
+        if (status != GSS_S_COMPLETE) {
+            map_error(minor_status, mech);
+            goto error;
+        }
+
+        /* Append the mech OID and token to buf. */
+        store_32_be(mech_oid->length, lenbuf);
+        krb5int_buf_add_len(&buf, lenbuf, 4);
+        krb5int_buf_add_len(&buf, mech_oid->elements, mech_oid->length);
+        store_32_be(mech_token.length, lenbuf);
+        krb5int_buf_add_len(&buf, lenbuf, 4);
+        krb5int_buf_add_len(&buf, mech_token.value, mech_token.length);
+        gss_release_buffer(&tmpmin, &mech_token);
+    }
+
+    if (krb5int_buf_data(&buf) == NULL) {
+        *minor_status = ENOMEM;
+        return GSS_S_FAILURE;
+    }
+    return k5buf_to_gss(minor_status, &buf, token);
+
+error:
+    krb5int_free_buf(&buf);
+    return status;
+}
diff --git a/src/lib/gssapi/mechglue/g_imp_cred.c b/src/lib/gssapi/mechglue/g_imp_cred.c
new file mode 100644
index 0000000..20083cb
--- /dev/null
+++ b/src/lib/gssapi/mechglue/g_imp_cred.c
@@ -0,0 +1,164 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/gssapi/mechglue/g_imp_cred.c - gss_import_cred definition */
+/*
+ * Copyright (C) 2012 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 "mglueP.h"
+
+static OM_uint32
+val_imp_cred_args(OM_uint32 *minor_status, gss_buffer_t token,
+                  gss_cred_id_t *cred_handle)
+{
+    /* Initialize outputs. */
+    if (minor_status != NULL)
+        *minor_status = 0;
+    if (cred_handle != NULL)
+        *cred_handle = GSS_C_NO_CREDENTIAL;
+
+    /* Validate arguments. */
+    if (minor_status == NULL)
+        return GSS_S_CALL_INACCESSIBLE_WRITE;
+    if (cred_handle == NULL)
+        return GSS_S_CALL_INACCESSIBLE_WRITE;
+    if (token == GSS_C_NO_BUFFER)
+        return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_DEFECTIVE_TOKEN;
+    if (GSS_EMPTY_BUFFER(token))
+        return GSS_S_DEFECTIVE_TOKEN;
+    return GSS_S_COMPLETE;
+}
+
+/* Populate mech_oid and mech_token with the next entry in token, using aliased
+ * memory from token.  Advance token by the amount consumed. */
+static OM_uint32
+get_entry(OM_uint32 *minor_status, gss_buffer_t token, gss_OID mech_oid,
+          gss_buffer_t mech_token)
+{
+    OM_uint32 len;
+
+    /* Get the mechanism OID. */
+    if (token->length < 4)
+        return GSS_S_DEFECTIVE_TOKEN;
+    len = load_32_be(token->value);
+    if (token->length - 4 < len)
+        return GSS_S_DEFECTIVE_TOKEN;
+    mech_oid->length = len;
+    mech_oid->elements = (char *)token->value + 4;
+    token->value = (char *)token->value + 4 + len;
+    token->length -= 4 + len;
+
+    /* Get the mechanism token. */
+    if (token->length < 4)
+        return GSS_S_DEFECTIVE_TOKEN;
+    len = load_32_be(token->value);
+    if (token->length - 4 < len)
+        return GSS_S_DEFECTIVE_TOKEN;
+    mech_token->length = len;
+    mech_token->value = (char *)token->value + 4;
+    token->value = (char *)token->value + 4 + len;
+    token->length -= 4 + len;
+
+    return GSS_S_COMPLETE;
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_import_cred(OM_uint32 *minor_status, gss_buffer_t token,
+                gss_cred_id_t *cred_handle)
+{
+    OM_uint32 status, tmpmin, count;
+    gss_union_cred_t cred = NULL;
+    gss_mechanism mech;
+    gss_buffer_desc tok, mech_token;
+    gss_OID_desc mech_oid;
+    gss_cred_id_t mech_cred;
+    void *elemcopy;
+
+    status = val_imp_cred_args(minor_status, token, cred_handle);
+    if (status != GSS_S_COMPLETE)
+        return status;
+
+    /* Count the entries in token. */
+    for (tok = *token, count = 0; tok.length > 0; count++) {
+        status = get_entry(minor_status, &tok, &mech_oid, &mech_token);
+        if (status != GSS_S_COMPLETE)
+            return status;
+    }
+
+    /* Allocate a union credential. */
+    cred = calloc(1, sizeof(*cred));
+    if (cred == NULL)
+        goto oom;
+    cred->loopback = cred;
+    cred->count = 0;
+    cred->mechs_array = calloc(count, sizeof(*cred->mechs_array));
+    if (cred->mechs_array == NULL)
+        goto oom;
+    cred->cred_array = calloc(count, sizeof(*cred->cred_array));
+    if (cred->cred_array == NULL)
+        goto oom;
+
+    tok = *token;
+    while (tok.length > 0) {
+        (void)get_entry(minor_status, &tok, &mech_oid, &mech_token);
+
+        /* Import this entry's mechanism token. */
+        mech = gssint_get_mechanism(&mech_oid);
+        if (mech == NULL || mech->gss_import_cred == NULL) {
+            status = GSS_S_DEFECTIVE_TOKEN;
+            goto error;
+        }
+        status = mech->gss_import_cred(minor_status, &mech_token, &mech_cred);
+        if (status != GSS_S_COMPLETE) {
+            map_error(minor_status, mech);
+            goto error;
+        }
+
+        /* Add the resulting mechanism cred to the union cred. */
+        elemcopy = malloc(mech_oid.length);
+        if (elemcopy == NULL) {
+            if (mech->gss_release_cred != NULL)
+                mech->gss_release_cred(&tmpmin, &mech_cred);
+            goto oom;
+        }
+        memcpy(elemcopy, mech_oid.elements, mech_oid.length);
+        cred->mechs_array[cred->count].length = mech_oid.length;
+        cred->mechs_array[cred->count].elements = elemcopy;
+        cred->cred_array[cred->count++] = mech_cred;
+    }
+
+    *cred_handle = cred;
+    return GSS_S_COMPLETE;
+
+oom:
+    status = GSS_S_FAILURE;
+    *minor_status = ENOMEM;
+error:
+    (void)gss_release_cred(&tmpmin, &cred);
+    return status;
+}
diff --git a/src/lib/gssapi/mechglue/mglueP.h b/src/lib/gssapi/mechglue/mglueP.h
index 17a9fbb..02a7d79 100644
--- a/src/lib/gssapi/mechglue/mglueP.h
+++ b/src/lib/gssapi/mechglue/mglueP.h
@@ -634,6 +634,20 @@ typedef struct gss_config {
 	    OM_uint32 *			/* time_rec */
 	/* */);
 
+	OM_uint32       (KRB5_CALLCONV *gss_export_cred)
+	(
+	    OM_uint32 *,		/* minor_status */
+	    gss_cred_id_t,		/* cred_handle */
+	    gss_buffer_t		/* token */
+	/* */);
+
+	OM_uint32       (KRB5_CALLCONV *gss_import_cred)
+	(
+		OM_uint32 *,		/* minor_status */
+		gss_buffer_t,		/* token */
+		gss_cred_id_t *		/* cred_handle */
+	/* */);
+
 } *gss_mechanism;
 
 /*
diff --git a/src/lib/gssapi32.def b/src/lib/gssapi32.def
index 296506d..00c7074 100644
--- a/src/lib/gssapi32.def
+++ b/src/lib/gssapi32.def
@@ -174,3 +174,5 @@ EXPORTS
 	gss_acquire_cred_from				@139
 	gss_add_cred_from				@140
 	gss_store_cred_into				@141
+	gss_export_cred					@142
+	gss_import_cred					@143


More information about the cvs-krb5 mailing list