]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Patch from kwc@citi.umich.edu to support
authorSam Hartman <hartmans@mit.edu>
Tue, 8 Jun 2004 21:50:17 +0000 (21:50 +0000)
committerSam Hartman <hartmans@mit.edu>
Tue, 8 Jun 2004 21:50:17 +0000 (21:50 +0000)
gss_krb5_export_lucid_sec_context and other facilities for NFSv4
implementations.

In order to apply this patch gss_krb5.h needs to be auto-generated so we can expose a 64-bit type for sequence numbers.

Ticket: 2587
status: open

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@16423 dc483132-0cff-0310-8789-dd5450dbe970

15 files changed:
src/lib/gssapi/ChangeLog
src/lib/gssapi/configure.in
src/lib/gssapi/generic/ChangeLog
src/lib/gssapi/generic/gssapiP_generic.h
src/lib/gssapi/generic/util_validate.c
src/lib/gssapi/generic/utl_nohash_validate.c
src/lib/gssapi/krb5/ChangeLog
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/gssapi_krb5.h [deleted file]
src/lib/gssapi/krb5/gssapi_krb5.hin [new file with mode: 0644]
src/lib/gssapi/krb5/init_sec_context.c
src/lib/gssapi/krb5/lucid_context.c [new file with mode: 0644]
src/lib/gssapi/krb5/set_allowable_enctypes.c [new file with mode: 0644]

index 2d90a0aba22e33c3b7e772fdd6b0e9f46ff820d4..9922cee1feb545e3c2e3680e22294cec3881e7a9 100644 (file)
@@ -1,3 +1,7 @@
+2004-06-08  Sam Hartman  <hartmans@mit.edu>
+
+       * configure.in: If stdint.h exists, include in gssapi_krb5.h
+
 2004-06-04  Ken Raeburn  <raeburn@mit.edu>
 
        * Makefile.in (LIBBASE): Renamed from LIB.
index 8852f05791b5274d4cb075226c78537d423cd600..72ab7983ad8cc17e489b6c6f00240de9cde75c42 100644 (file)
@@ -6,6 +6,9 @@ AC_TYPE_SIZE_T
 AC_CHECK_SIZEOF(short)
 AC_CHECK_SIZEOF(int)
 AC_CHECK_SIZEOF(long)
+AC_CHECK_HEADER(stdint.h,[
+       include_stdint="\\#include <stdint.h>"], )
+AC_SUBST(include_stdint)
 KRB5_BUILD_LIBOBJS
 KRB5_BUILD_LIBRARY_WITH_DEPS
 V5_AC_OUTPUT_MAKEFILE(. generic krb5)
index ec34f6b5a678c10e96050b719a4f77d74a853cd3..5c5c82ac015b8044c73355b097ff4b6f535632de 100644 (file)
@@ -1,3 +1,8 @@
+2004-06-08  Sam Hartman  <hartmans@mit.edu>
+
+       * util_validate.c utl_nohash_validate.c gssapiP_generic.h:
+       Support for lucid context validation 
+
 2004-06-02  Ken Raeburn  <raeburn@mit.edu>
 
        * disp_com_err_status.c (init_et): Variable deleted.
index e297862fe90301d4b891f95dfc8e2ca44040cb82..0af65df1b549ecd3b558dc634dd025841991602d 100644 (file)
@@ -111,12 +111,15 @@ typedef UINT64_TYPE gssint_uint64;
 #define        g_save_name             gssint_g_save_name
 #define        g_save_cred_id          gssint_g_save_cred_id
 #define        g_save_ctx_id           gssint_g_save_ctx_id
+#define        g_save_lucidctx_id      gssint_g_save_lucidctx_id
 #define        g_validate_name         gssint_g_validate_name
 #define        g_validate_cred_id      gssint_g_validate_cred_id
 #define        g_validate_ctx_id       gssint_g_validate_ctx_id
+#define        g_validate_lucidctx_id  gssint_g_validate_lucidctx_id
 #define        g_delete_name           gssint_g_delete_name
 #define        g_delete_cred_id        gssint_g_delete_cred_id
 #define        g_delete_ctx_id         gssint_g_delete_ctx_id
+#define        g_delete_lucidctx_id    gssint_g_delete_lucidctx_id
 #define        g_make_string_buffer    gssint_g_make_string_buffer
 #define        g_copy_OID_set          gssint_g_copy_OID_set
 #define        g_token_size            gssint_g_token_size
@@ -150,14 +153,17 @@ int g_set_entry_get (g_set_elt *s, void *key, void **value);
 int g_save_name (g_set *vdb, gss_name_t *name);
 int g_save_cred_id (g_set *vdb, gss_cred_id_t *cred);
 int g_save_ctx_id (g_set *vdb, gss_ctx_id_t *ctx);
+int g_save_lucidctx_id (g_set *vdb, void *lctx);
 
 int g_validate_name (g_set *vdb, gss_name_t *name);
 int g_validate_cred_id (g_set *vdb, gss_cred_id_t *cred);
 int g_validate_ctx_id (g_set *vdb, gss_ctx_id_t *ctx);
+int g_validate_lucidctx_id (g_set *vdb, void *lctx);
 
 int g_delete_name (g_set *vdb, gss_name_t *name);
 int g_delete_cred_id (g_set *vdb, gss_cred_id_t *cred);
 int g_delete_ctx_id (g_set *vdb, gss_ctx_id_t *ctx);
+int g_delete_lucidctx_id (g_set *vdb, void *lctx);
 
 int g_make_string_buffer (const char *str, gss_buffer_t buffer);
 
index 779260892e19de5c87a3916c32ca08e54edc5b3b..fffacabcb3edb961076e65a8cc28af2d2c574629 100644 (file)
@@ -52,6 +52,7 @@ typedef struct _vkey {
 #define V_NAME         1
 #define V_CRED_ID      2
 #define V_CTX_ID       3
+#define V_LCTX_ID      4
 
 /* All these functions return 0 on failure, and non-zero on success */
 
@@ -249,6 +250,13 @@ int g_save_ctx_id(vdb, ctx)
 {
    return(g_save(vdb, V_CTX_ID, (void *) ctx));
 }
+int g_save_lucidctx_id(vdb, lctx)
+     g_set *vdb;
+     void *lctx;
+{
+   return(g_save(vdb, V_LCTX_ID, (void *) lctx));
+}
+
 
 /* validate */
 
@@ -270,6 +278,12 @@ int g_validate_ctx_id(vdb, ctx)
 {
    return(g_validate(vdb, V_CTX_ID, (void *) ctx));
 }
+int g_validate_lucidctx_id(vdb, lctx)
+     g_set *vdb;
+     void *lctx;
+{
+   return(g_validate(vdb, V_LCTX_ID, (void *) lctx));
+}
 
 /* delete */
 
@@ -291,4 +305,10 @@ int g_delete_ctx_id(vdb, ctx)
 {
    return(g_delete(vdb, V_CTX_ID, (void *) ctx));
 }
+int g_delete_lucidctx_id(vdb, lctx)
+     g_set *vdb;
+     void *lctx;
+{
+   return(g_delete(vdb, V_LCTX_ID, (void *) lctx));
+}
 
index 1ed2008a52da254657a5c24470a8ad70e8c18298..da20b71d6f04d24534bec4dfa5f6a0244b3fdb76 100644 (file)
@@ -58,6 +58,12 @@ int g_save_ctx_id(vdb, ctx)
 {
        return 1;
 }
+int g_save_lucidctx_id(vdb, lctx)
+     void **vdb;
+     void *lctx;
+{
+       return 1;
+}
 
 /* validate */
 
@@ -79,6 +85,12 @@ int g_validate_ctx_id(vdb, ctx)
 {
        return 1;
 }
+int g_validate_lucidctx_id(vdb, lctx)
+     void **vdb;
+     void *lctx;
+{
+       return 1;
+}
 
 /* delete */
 
@@ -100,4 +112,10 @@ int g_delete_ctx_id(vdb, ctx)
 {
        return 1;
 }
+int g_delete_lucidctx_id(vdb, lctx)
+     void **vdb;
+     void *lctx;
+{
+       return 1;
+}
 
index 1be0a67a7e693260e1c54f06574acdf352f71afe..e4b2f720da6fcd02373d52df1e3714719ea86b58 100644 (file)
@@ -1,3 +1,13 @@
+2004-06-08  Sam Hartman  <hartmans@mit.edu>
+
+       * set_allowable_enctypes.c lucid_context.c:  new file
+
+       * gssapi_krb5.hin: Made file autogenerated; support  gss_uint64 type
+
+       * Makefile.in (gssapi_krb5.h): Include code to pull in stdint.h if available.
+
+       * gssapi_krb5.h: Add declarations for lucid_context support
+
 2004-04-24  Ken Raeburn  <raeburn@mit.edu>
 
        * gssapi_krb5.c (kg_get_ccache_name): Don't test err while it's
index 582bd802e590bcc9c093a12b5b084b7ce1ecb8ba..2eec3dc725065b6b948f055ad5643226b672bb57 100644 (file)
@@ -10,6 +10,8 @@ LOCALINCLUDES = -I. -I$(srcdir) -I../generic -I$(srcdir)/../generic
 
 ##DOS##DLL_EXP_TYPE=GSS
 
+include_stdint=@include_stdint@
+##DOS##include_stdint=
 ETSRCS= gssapi_err_krb5.c
 ETOBJS= $(OUTPRE)gssapi_err_krb5.$(OBJEXT)
 ETHDRS= gssapi_err_krb5.h
@@ -45,11 +47,13 @@ SRCS = \
        $(srcdir)/k5sealv3.c \
        $(srcdir)/k5unseal.c \
        $(srcdir)/krb5_gss_glue.c \
+       $(srcdir)/lucid_context.c \
        $(srcdir)/process_context_token.c \
        $(srcdir)/rel_cred.c \
        $(srcdir)/rel_oid.c \
        $(srcdir)/rel_name.c \
        $(srcdir)/seal.c \
+       $(srcdir)/set_allowable_enctypes.c \
        $(srcdir)/ser_sctx.c \
        $(srcdir)/set_ccache.c \
        $(srcdir)/sign.c \
@@ -93,11 +97,13 @@ OBJS = \
        $(OUTPRE)k5sealv3.$(OBJEXT) \
        $(OUTPRE)k5unseal.$(OBJEXT) \
        $(OUTPRE)krb5_gss_glue.$(OBJEXT) \
+       $(OUTPRE)lucid_context.$(OBJEXT) \
        $(OUTPRE)process_context_token.$(OBJEXT) \
        $(OUTPRE)rel_cred.$(OBJEXT) \
        $(OUTPRE)rel_oid.$(OBJEXT) \
        $(OUTPRE)rel_name.$(OBJEXT) \
        $(OUTPRE)seal.$(OBJEXT) \
+       $(OUTPRE)set_allowable_enctypes.$(OBJEXT) \
        $(OUTPRE)ser_sctx.$(OBJEXT) \
        $(OUTPRE)set_ccache.$(OBJEXT) \
        $(OUTPRE)sign.$(OBJEXT) \
@@ -141,11 +147,13 @@ STLIBOBJS = \
        k5sealv3.o \
        k5unseal.o \
        krb5_gss_glue.o \
+       lucid_context.o \
        process_context_token.o \
        rel_cred.o \
        rel_oid.o \
        rel_name.o \
        seal.o \
+       set_allowable_enctypes.o \
        ser_sctx.o \
        set_ccache.o \
        sign.o \
@@ -181,13 +189,14 @@ MK_EHDRDIR=if test -d $(EHDRDIR); then :; else (set -x; mkdir $(EHDRDIR)); fi
 
 $(GSSAPI_KRB5_HDR): gssapi_krb5.h
        @$(MK_EHDRDIR)
-       $(CP) $(srcdir)$(S)gssapi_krb5.h "$@"
+       $(CP) gssapi_krb5.h "$@"
 
 all-unix:: $(SRCS) $(HDRS) $(GSSAPI_KRB5_HDR) includes
 all-unix:: all-libobjs
 
 clean-unix::
        $(RM) $(BUILDTOP)/include/gssapi/gssapi_krb5.h
+       -$(RM) gssapi_krb5.h
 
 clean-unix:: clean-libobjs
        $(RM) $(ETHDRS) $(ETSRCS)
@@ -196,6 +205,15 @@ clean-windows::
        $(RM) $(EHDRDIR)\gssapi_krb5.h
        -if exist $(EHDRDIR)\nul rmdir $(EHDRDIR)
 
+gssapi_krb5.h: gssapi_krb5.hin
+       @echo "Creating gssapi.h" ; \
+       h=gss$$$$; $(RM) $$h; \
+       (echo "/* This is the gssapi_krb5.h prologue. */"; \
+       echo "$(include_stdint)" ; \
+       echo "/* End of gssapi_krb5.h prologue. */"; \
+       cat $(srcdir)/gssapi_krb5.hin )> $$h && \
+       (set -x; $(MV) $$h $@) ; e=$$?; $(RM) $$h; exit $$e
+
 install-headers-unix install::
        @set -x; for f in $(EXPORTED_HEADERS) ; \
        do $(INSTALL_DATA) $(srcdir)/$$f        \
@@ -204,7 +222,7 @@ install-headers-unix install::
 
 depend:: $(ETSRCS)
 
-includes:: 
+includes::  gssapi_krb5.h
 
 install::
 
index d207010c1f544229c96bce3b42120898f8dbd4f0..b5a24960ef8ddc9c9630cd4acf7f18f2bd6dcb67 100644 (file)
@@ -154,6 +154,7 @@ typedef struct _krb5_gss_cred_id_rec {
    /* ccache (init) data */
    krb5_ccache ccache;
    krb5_timestamp tgt_expire;
+   krb5_enctype *req_enctypes; /* limit negotiated enctypes to this list */
 } krb5_gss_cred_id_rec, *krb5_gss_cred_id_t; 
 
 typedef struct _krb5_gss_ctx_id_rec {
@@ -200,14 +201,17 @@ extern g_set kg_vdb;
 #define kg_save_name(name)             g_save_name(&kg_vdb,name)
 #define kg_save_cred_id(cred)          g_save_cred_id(&kg_vdb,cred)
 #define kg_save_ctx_id(ctx)            g_save_ctx_id(&kg_vdb,ctx)
+#define kg_save_lucidctx_id(lctx)      g_save_lucidctx_id(&kg_vdb,lctx)
 
 #define kg_validate_name(name)         g_validate_name(&kg_vdb,name)
 #define kg_validate_cred_id(cred)      g_validate_cred_id(&kg_vdb,cred)
 #define kg_validate_ctx_id(ctx)                g_validate_ctx_id(&kg_vdb,ctx)
+#define kg_validate_lucidctx_id(lctx)  g_validate_lucidctx_id(&kg_vdb,lctx)
 
 #define kg_delete_name(name)           g_delete_name(&kg_vdb,name)
 #define kg_delete_cred_id(cred)                g_delete_cred_id(&kg_vdb,cred)
 #define kg_delete_ctx_id(ctx)          g_delete_ctx_id(&kg_vdb,ctx)
+#define kg_delete_lucidctx_id(lctx)    g_delete_lucidctx_id(&kg_vdb,lctx)
 
 /** helper functions **/
 
index 3c9be6351fb3ebfd11cae9a226cfcca193725102..c2a705c84e59018ad0caaba9938546232c4d07ba 100644 (file)
@@ -36,4 +36,5 @@ error_code KG_ENC_DESC, "Bad magic number for krb5_gss_enc_desc"
 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"
 end
diff --git a/src/lib/gssapi/krb5/gssapi_krb5.h b/src/lib/gssapi/krb5/gssapi_krb5.h
deleted file mode 100644 (file)
index 3007a0f..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright 1993 by OpenVision Technologies, Inc.
- * 
- * Permission to use, copy, modify, distribute, and sell this software
- * and its documentation for any purpose is hereby granted without fee,
- * provided that the above copyright notice appears in all copies and
- * that both that copyright notice and this permission notice appear in
- * supporting documentation, and that the name of OpenVision not be used
- * in advertising or publicity pertaining to distribution of the software
- * without specific, written prior permission. OpenVision makes no
- * representations about the suitability of this software for any
- * purpose.  It is provided "as is" without express or implied warranty.
- * 
- * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
- * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
- * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _GSSAPI_KRB5_H_
-#define _GSSAPI_KRB5_H_
-
-#include <gssapi/gssapi.h>
-#include <krb5.h>
-
-/* C++ friendlyness */
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/* Reserved static storage for GSS_oids.  See rfc 1964 for more details. */
-
-/* 2.1.1. Kerberos Principal Name Form: */
-GSS_DLLIMP extern const gss_OID_desc * const GSS_KRB5_NT_PRINCIPAL_NAME;
-/* This name form shall be represented by the Object Identifier {iso(1)
- * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
- * krb5(2) krb5_name(1)}.  The recommended symbolic name for this type
- * is "GSS_KRB5_NT_PRINCIPAL_NAME". */
-
-/* 2.1.2. Host-Based Service Name Form */
-#define GSS_KRB5_NT_HOSTBASED_SERVICE_NAME GSS_C_NT_HOSTBASED_SERVICE
-/* This name form shall be represented by the Object Identifier {iso(1)
- * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
- * generic(1) service_name(4)}.  The previously recommended symbolic
- * name for this type is "GSS_KRB5_NT_HOSTBASED_SERVICE_NAME".  The
- * currently preferred symbolic name for this type is
- * "GSS_C_NT_HOSTBASED_SERVICE". */
-
-/* 2.2.1. User Name Form */
-#define GSS_KRB5_NT_USER_NAME GSS_C_NT_USER_NAME    
-/* This name form shall be represented by the Object Identifier {iso(1)
- * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
- * generic(1) user_name(1)}.  The recommended symbolic name for this
- * type is "GSS_KRB5_NT_USER_NAME". */
-
-/* 2.2.2. Machine UID Form */
-#define GSS_KRB5_NT_MACHINE_UID_NAME GSS_C_NT_MACHINE_UID_NAME
-/* This name form shall be represented by the Object Identifier {iso(1)
- * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
- * generic(1) machine_uid_name(2)}.  The recommended symbolic name for
- * this type is "GSS_KRB5_NT_MACHINE_UID_NAME". */
-
-/* 2.2.3. String UID Form */
-#define GSS_KRB5_NT_STRING_UID_NAME GSS_C_NT_STRING_UID_NAME
-/* This name form shall be represented by the Object Identifier {iso(1)
- * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
- * generic(1) string_uid_name(3)}.  The recommended symbolic name for
- * this type is "GSS_KRB5_NT_STRING_UID_NAME". */ 
-
-extern const gss_OID_desc * const gss_mech_krb5;
-extern const gss_OID_desc * const gss_mech_krb5_old;
-extern const gss_OID_set_desc * const gss_mech_set_krb5;
-extern const gss_OID_set_desc * const gss_mech_set_krb5_old;
-extern const gss_OID_set_desc * const gss_mech_set_krb5_both;
-
-extern const gss_OID_desc * const gss_nt_krb5_name;
-extern const gss_OID_desc * const gss_nt_krb5_principal;
-
-extern const gss_OID_desc krb5_gss_oid_array[];
-
-#define gss_krb5_nt_general_name       gss_nt_krb5_name
-#define gss_krb5_nt_principal          gss_nt_krb5_principal
-#define gss_krb5_nt_service_name       gss_nt_service_name
-#define gss_krb5_nt_user_name          gss_nt_user_name
-#define gss_krb5_nt_machine_uid_name   gss_nt_machine_uid_name
-#define gss_krb5_nt_string_uid_name    gss_nt_string_uid_name
-
-/* Alias for Heimdal compat. */
-#define gsskrb5_register_acceptor_identity krb5_gss_register_acceptor_identity
-
-OM_uint32 KRB5_CALLCONV krb5_gss_register_acceptor_identity(const char *);
-
-OM_uint32 KRB5_CALLCONV gss_krb5_get_tkt_flags 
-       (OM_uint32 *minor_status,
-                  gss_ctx_id_t context_handle,
-                  krb5_flags *ticket_flags);
-
-OM_uint32 KRB5_CALLCONV gss_krb5_copy_ccache
-       (OM_uint32 *minor_status,
-                  gss_cred_id_t cred_handle,
-                  krb5_ccache out_ccache);
-
-OM_uint32 KRB5_CALLCONV gss_krb5_ccache_name
-       (OM_uint32 *minor_status, const char *name,
-                  const char **out_name);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* _GSSAPI_KRB5_H_ */
diff --git a/src/lib/gssapi/krb5/gssapi_krb5.hin b/src/lib/gssapi/krb5/gssapi_krb5.hin
new file mode 100644 (file)
index 0000000..6fc4794
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _GSSAPI_KRB5_H_
+#define _GSSAPI_KRB5_H_
+
+#include <gssapi/gssapi.h>
+#include <krb5.h>
+
+/* C++ friendlyness */
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Reserved static storage for GSS_oids.  See rfc 1964 for more details. */
+
+/* 2.1.1. Kerberos Principal Name Form: */
+GSS_DLLIMP extern const gss_OID_desc * const GSS_KRB5_NT_PRINCIPAL_NAME;
+/* This name form shall be represented by the Object Identifier {iso(1)
+ * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
+ * krb5(2) krb5_name(1)}.  The recommended symbolic name for this type
+ * is "GSS_KRB5_NT_PRINCIPAL_NAME". */
+
+/* 2.1.2. Host-Based Service Name Form */
+#define GSS_KRB5_NT_HOSTBASED_SERVICE_NAME GSS_C_NT_HOSTBASED_SERVICE
+/* This name form shall be represented by the Object Identifier {iso(1)
+ * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
+ * generic(1) service_name(4)}.  The previously recommended symbolic
+ * name for this type is "GSS_KRB5_NT_HOSTBASED_SERVICE_NAME".  The
+ * currently preferred symbolic name for this type is
+ * "GSS_C_NT_HOSTBASED_SERVICE". */
+
+/* 2.2.1. User Name Form */
+#define GSS_KRB5_NT_USER_NAME GSS_C_NT_USER_NAME    
+/* This name form shall be represented by the Object Identifier {iso(1)
+ * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
+ * generic(1) user_name(1)}.  The recommended symbolic name for this
+ * type is "GSS_KRB5_NT_USER_NAME". */
+
+/* 2.2.2. Machine UID Form */
+#define GSS_KRB5_NT_MACHINE_UID_NAME GSS_C_NT_MACHINE_UID_NAME
+/* This name form shall be represented by the Object Identifier {iso(1)
+ * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
+ * generic(1) machine_uid_name(2)}.  The recommended symbolic name for
+ * this type is "GSS_KRB5_NT_MACHINE_UID_NAME". */
+
+/* 2.2.3. String UID Form */
+#define GSS_KRB5_NT_STRING_UID_NAME GSS_C_NT_STRING_UID_NAME
+/* This name form shall be represented by the Object Identifier {iso(1)
+ * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
+ * generic(1) string_uid_name(3)}.  The recommended symbolic name for
+ * this type is "GSS_KRB5_NT_STRING_UID_NAME". */ 
+
+extern const gss_OID_desc * const gss_mech_krb5;
+extern const gss_OID_desc * const gss_mech_krb5_old;
+extern const gss_OID_set_desc * const gss_mech_set_krb5;
+extern const gss_OID_set_desc * const gss_mech_set_krb5_old;
+extern const gss_OID_set_desc * const gss_mech_set_krb5_both;
+
+extern const gss_OID_desc * const gss_nt_krb5_name;
+extern const gss_OID_desc * const gss_nt_krb5_principal;
+
+extern const gss_OID_desc krb5_gss_oid_array[];
+
+#define gss_krb5_nt_general_name       gss_nt_krb5_name
+#define gss_krb5_nt_principal          gss_nt_krb5_principal
+#define gss_krb5_nt_service_name       gss_nt_service_name
+#define gss_krb5_nt_user_name          gss_nt_user_name
+#define gss_krb5_nt_machine_uid_name   gss_nt_machine_uid_name
+#define gss_krb5_nt_string_uid_name    gss_nt_string_uid_name
+
+
+#if defined(_WIN32)
+typedef  unsigned __int64 gss_uint64;
+#else /*windows*/
+#include <inttypes.h>
+typedef  uint64_t gss_uint64;
+#endif
+
+
+typedef struct gss_krb5_lucid_key {
+       OM_uint32       type;           /* key encryption type */
+       OM_uint32       length;         /* length of key data */
+       void *          data;           /* actual key data */
+} gss_krb5_lucid_key_t;
+
+typedef struct gss_krb5_rfc1964_keydata {
+       OM_uint32       sign_alg;       /* signing algorthm */
+       OM_uint32       seal_alg;       /* seal/encrypt algorthm */
+       gss_krb5_lucid_key_t    ctx_key;
+                                       /* Context key
+                                          (Kerberos session key or subkey) */
+} gss_krb5_rfc1964_keydata_t;
+
+typedef struct gss_krb5_cfx_keydata {
+       OM_uint32               have_acceptor_subkey;
+                                       /* 1 if there is an acceptor_subkey
+                                          present, 0 otherwise */
+       gss_krb5_lucid_key_t    ctx_key;
+                                       /* Context key
+                                          (Kerberos session key or subkey) */
+       gss_krb5_lucid_key_t    acceptor_subkey;
+                                       /* acceptor-asserted subkey or
+                                          0's if no acceptor subkey */
+} gss_krb5_cfx_keydata_t;
+
+typedef struct gss_krb5_lucid_context_v1 {
+       OM_uint32       version;        /* Structure version number (1)
+                                          MUST be at beginning of struct! */
+       OM_uint32       initiate;       /* Are we the initiator? */
+       OM_uint32       endtime;        /* expiration time of context */
+       gss_uint64      send_seq;       /* sender sequence number */
+       gss_uint64      recv_seq;       /* receive sequence number */
+       OM_uint32       protocol;       /* 0: rfc1964,
+                                          1: draft-ietf-krb-wg-gssapi-cfx-07 */
+       /*
+        * if (protocol == 0) rfc1964_kd should be used
+        * and cfx_kd contents are invalid and should be zero
+        * if (protocol == 1) cfx_kd should be used
+        * and rfc1964_kd contents are invalid and should be zero
+        */
+       gss_krb5_rfc1964_keydata_t rfc1964_kd;
+       gss_krb5_cfx_keydata_t     cfx_kd;
+} gss_krb5_lucid_context_v1_t;
+
+/*
+ * Mask for determining the returned structure version.
+ * See example below for usage.
+ */
+typedef struct gss_krb5_lucid_context_version {
+       OM_uint32       version;        /* Structure version number */
+} gss_krb5_lucid_context_version_t;
+
+
+
+
+/* Alias for Heimdal compat. */
+#define gsskrb5_register_acceptor_identity krb5_gss_register_acceptor_identity
+
+OM_uint32 KRB5_CALLCONV krb5_gss_register_acceptor_identity(const char *);
+
+OM_uint32 KRB5_CALLCONV gss_krb5_get_tkt_flags 
+       (OM_uint32 *minor_status,
+                  gss_ctx_id_t context_handle,
+                  krb5_flags *ticket_flags);
+
+OM_uint32 KRB5_CALLCONV gss_krb5_copy_ccache
+       (OM_uint32 *minor_status,
+                  gss_cred_id_t cred_handle,
+                  krb5_ccache out_ccache);
+
+OM_uint32 KRB5_CALLCONV gss_krb5_ccache_name
+       (OM_uint32 *minor_status, const char *name,
+                  const char **out_name);
+
+/*
+ * gss_krb5_set_allowable_enctypes
+ *
+ * This function may be called by a context initiator after calling
+ * gss_acquire_cred(), but before calling gss_init_sec_context(),
+ * to restrict the set of enctypes which will be negotiated during
+ * context establishment to those in the provided array.
+ *
+ * 'cred' must be a valid credential handle obtained via
+ * gss_acquire_cred().  It may not be GSS_C_NO_CREDENTIAL.
+ * gss_acquire_cred() may have been called to get a handle to
+ * the default credential.
+ *
+ * The purpose of this function is to limit the keys that may
+ * be exported via gss_krb5_export_lucid_sec_context(); thus it
+ * should limit the enctypes of all keys that will be needed
+ * after the security context has been established.
+ * (i.e. context establishment may use a session key with a
+ * stronger enctype than in the provided array, however a
+ * subkey must be established within the enctype limits
+ * established by this function.)
+ *
+ */
+OM_uint32 KRB5_CALLCONV
+gss_krb5_set_allowable_enctypes(OM_uint32 *minor_status, 
+                               gss_cred_id_t cred,
+                               OM_uint32 num_ktypes,
+                               krb5_enctype *ktypes);
+
+/*
+ * Returns a non-opaque (lucid) version of the internal context
+ * information.  
+ *
+ * Note that context_handle must not be used again by the caller
+ * after this call.  The GSS implementation is free to release any
+ * resources associated with the original context.  It is up to the
+ * GSS implementation whether it returns pointers to existing data,
+ * or copies of the data.  The caller should treat the returned
+ * lucid context as read-only.
+ * 
+ * The caller must call gss_krb5_free_lucid_context() to free
+ * the context and allocated resources when it is finished with it.
+ *
+ * 'version' is an integer indicating the highest version of lucid
+ * context understood by the caller.  The highest version
+ * understood by both the caller and the GSS implementation must
+ * be returned.  The caller can determine which version of the
+ * structure was actually returned by examining the version field
+ * of the returned structure.  gss_krb5_lucid_context_version_t
+ * may be used as a mask to examine the returned structure version.
+ *
+ * If there are no common versions, an error should be returned.
+ * (XXX Need error definition(s))
+ *
+ * For example:
+ *     void *return_ctx;
+ *     gss_krb5_lucid_context_v1_t *ctx;
+ *     OM_uint32 min_stat, maj_stat;
+ *     OM_uint32 vers;
+ *     gss_ctx_id_t *ctx_handle;
+ *
+ *     maj_stat = gss_krb5_export_lucid_sec_context(&min_stat,
+ *                     ctx_handle, 1, &return_ctx);
+ *     // Verify success 
+ *
+ *     vers = ((gss_krb5_lucid_context_version_t *)return_ctx)->version;
+ *     switch (vers) {
+ *     case 1:
+ *             ctx = (gss_krb5_lucid_context_v1_t *) return_ctx;
+ *             break;
+ *     default:
+ *             // Error, unknown version returned
+ *             break;
+ *     }
+ *
+ */
+
+OM_uint32 KRB5_CALLCONV
+gss_krb5_export_lucid_sec_context(OM_uint32 *minor_status,
+                                 gss_ctx_id_t *context_handle,
+                                 OM_uint32 version,
+                                 void **kctx);
+
+/*
+ * Frees the allocated storage associated with an
+ * exported struct gss_krb5_lucid_context.
+ */
+OM_uint32 KRB5_CALLCONV
+gss_krb5_free_lucid_sec_context(OM_uint32 *minor_status,
+                               void *kctx);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _GSSAPI_KRB5_H_ */
index 48015cccde5c5ccd13465a4fe02ba81968b74b05..63a9cb956e03393cdb0470bae3e7901ee1741fc2 100644 (file)
@@ -497,6 +497,15 @@ new_connection(
       goto fail;
    krb5_auth_con_setflags(context, ctx->auth_context,
                          KRB5_AUTH_CONTEXT_DO_SEQUENCE);
+
+   /* limit the encryption types negotiated (if requested) */
+   if (cred->req_enctypes) {
+       if ((code = krb5_set_default_tgs_enctypes(context,
+                                                 cred->req_enctypes))) {
+           goto fail;
+       }
+   }
+
    ctx->initiate = 1;
    ctx->gss_flags = (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG |
                      GSS_C_TRANS_FLAG | 
diff --git a/src/lib/gssapi/krb5/lucid_context.c b/src/lib/gssapi/krb5/lucid_context.c
new file mode 100644 (file)
index 0000000..ac81fff
--- /dev/null
@@ -0,0 +1,309 @@
+/*
+ * lib/gssapi/krb5/lucid_context.c
+ *
+ * Copyright 2004 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.
+ *
+ */
+
+/*
+ * lucid_context.c  -  Externalize a "lucid" security
+ * context from a krb5_gss_ctx_id_rec structure.
+ */
+#include "gssapiP_krb5.h"
+#include "gssapi_krb5.h"
+
+/*
+ * Local routine prototypes
+ */
+static void
+free_external_lucid_ctx_v1(
+    gss_krb5_lucid_context_v1_t *ctx);
+
+static void
+free_lucid_key_data(
+    gss_krb5_lucid_key_t *key);
+
+static krb5_error_code
+copy_keyblock_to_lucid_key(
+    krb5_keyblock *k5key,
+    gss_krb5_lucid_key_t *lkey);
+
+static krb5_error_code
+make_external_lucid_ctx_v1(
+    krb5_gss_ctx_id_rec * gctx,
+    unsigned int version,
+    void **out_ptr);
+
+
+/*
+ * Exported routines
+ */
+
+OM_uint32 KRB5_CALLCONV
+gss_krb5_export_lucid_sec_context(
+    OM_uint32          *minor_status,
+    gss_ctx_id_t       *context_handle,
+    OM_uint32          version,
+    void               **kctx)
+{
+    krb5_error_code    kret = 0;
+    OM_uint32          retval;
+    krb5_gss_ctx_id_t  ctx;
+    void               *lctx = NULL;
+
+    /* Assume failure */
+    retval = GSS_S_FAILURE;
+    *minor_status = 0;
+
+    if (kctx)
+       *kctx = NULL;
+    else {
+       kret = EINVAL;
+       goto error_out;
+    }
+
+    if (!kg_validate_ctx_id(*context_handle)) {
+           kret = (OM_uint32) G_VALIDATE_FAILED;
+           retval = GSS_S_NO_CONTEXT;
+           goto error_out;
+    }
+
+    ctx = (krb5_gss_ctx_id_t) *context_handle;
+    if (kret)
+       goto error_out;
+
+    /* Externalize a structure of the right version */
+    switch (version) {
+    case 1:
+       kret = make_external_lucid_ctx_v1((krb5_pointer)ctx,
+                                             version, &lctx);
+        break;
+    default:
+       kret = (OM_uint32) KG_LUCID_VERSION;
+       break;
+    }
+
+    if (kret)
+       goto error_out;
+
+    /* Success!  Record the context and return the buffer */
+    if (! kg_save_lucidctx_id((void *)lctx)) {
+       kret = G_VALIDATE_FAILED;
+       goto error_out;
+    }
+
+    *kctx = lctx;
+    *minor_status = 0;
+    retval = GSS_S_COMPLETE;
+
+    /* Clean up the context state (it is an error for
+     * someone to attempt to use this context again)
+     */
+    (void)krb5_gss_delete_sec_context(minor_status, context_handle, NULL);
+    *context_handle = GSS_C_NO_CONTEXT;
+
+    return (retval);
+
+error_out:
+    if (*minor_status == 0) 
+           *minor_status = (OM_uint32) kret;
+    return(retval);
+}
+
+/*
+ * Frees the storage associated with an
+ * exported lucid context structure.
+ */
+OM_uint32 KRB5_CALLCONV
+gss_krb5_free_lucid_sec_context(
+    OM_uint32 *minor_status,
+    void *kctx)
+{
+    OM_uint32          retval;
+    krb5_error_code    kret = 0;
+    int                        version;
+
+    /* Assume failure */
+    retval = GSS_S_FAILURE;
+    *minor_status = 0;
+
+    if (!kctx) {
+       kret = EINVAL;
+       goto error_out;
+    }
+
+    /* Verify pointer is valid lucid context */
+    if (! kg_validate_lucidctx_id(kctx)) {
+       kret = G_VALIDATE_FAILED;
+       goto error_out;
+    }
+
+    /* Determine version and call correct free routine */
+    version = ((gss_krb5_lucid_context_version_t *)kctx)->version;
+    switch (version) {
+    case 1:
+       free_external_lucid_ctx_v1((gss_krb5_lucid_context_v1_t*) kctx);
+       break;
+    default:
+       kret = EINVAL;
+       break;
+    }
+
+    if (kret)
+       goto error_out;
+
+    /* Success! */
+    (void)kg_delete_lucidctx_id(kctx);
+    *minor_status = 0;
+    retval = GSS_S_COMPLETE;
+
+    return (retval);
+
+error_out:
+    if (*minor_status == 0) 
+           *minor_status = (OM_uint32) kret;
+    return(retval);
+}
+
+/*
+ * Local routines
+ */
+
+static krb5_error_code
+make_external_lucid_ctx_v1(
+    krb5_gss_ctx_id_rec * gctx,
+    unsigned int version,
+    void **out_ptr)
+{
+    gss_krb5_lucid_context_v1_t *lctx = NULL;
+    unsigned int bufsize = sizeof(gss_krb5_lucid_context_v1_t);
+    krb5_error_code retval;
+
+    /* Allocate the structure */
+    if ((lctx = xmalloc(bufsize)) == NULL) {
+       retval = ENOMEM;
+       goto error_out;
+    }
+
+    memset(lctx, 0, bufsize);
+
+    lctx->version = 1;
+    lctx->initiate = gctx->initiate ? 1 : 0;
+    lctx->endtime = gctx->endtime;
+    lctx->send_seq = gctx->seq_send;
+    lctx->recv_seq = gctx->seq_recv;
+    lctx->protocol = gctx->proto;
+    /* gctx->proto == 0 ==> rfc1964-style key information
+       gctx->proto == 1 ==> cfx-style (draft-ietf-krb-wg-gssapi-cfx-07) keys */
+    if (gctx->proto == 0) {
+       lctx->rfc1964_kd.sign_alg = gctx->signalg;
+       lctx->rfc1964_kd.seal_alg = gctx->sealalg;
+       /* Copy key */
+       if ((retval = copy_keyblock_to_lucid_key(gctx->subkey,
+                                       &lctx->rfc1964_kd.ctx_key)))
+           goto error_out;
+    }
+    else if (gctx->proto == 1) {
+       /* Copy keys */
+       /* (subkey is always present, either a copy of the kerberos
+          session key or a subkey) */
+       if ((retval = copy_keyblock_to_lucid_key(gctx->subkey,
+                                       &lctx->cfx_kd.ctx_key)))
+           goto error_out;
+       if (gctx->have_acceptor_subkey) {
+           if ((retval = copy_keyblock_to_lucid_key(gctx->enc,
+                                       &lctx->cfx_kd.acceptor_subkey)))
+               goto error_out;
+           lctx->cfx_kd.have_acceptor_subkey = 1;
+       }
+    }
+    else {
+       return EINVAL;  /* XXX better error code? */
+    }
+
+    /* Success! */
+    *out_ptr = lctx;
+    return 0;
+
+error_out:
+    if (lctx) {
+       free_external_lucid_ctx_v1(lctx);
+    }
+    return retval;
+
+}
+
+/* Copy the contents of a krb5_keyblock to a gss_krb5_lucid_key_t structure */
+static krb5_error_code
+copy_keyblock_to_lucid_key(
+    krb5_keyblock *k5key,
+    gss_krb5_lucid_key_t *lkey)
+{
+    if (!k5key || !k5key->contents || k5key->length == 0)
+       return EINVAL;
+
+    memset(lkey, 0, sizeof(gss_krb5_lucid_key_t));
+
+    /* Allocate storage for the key data */
+    if ((lkey->data = xmalloc(k5key->length)) == NULL) {
+       return ENOMEM;
+    }
+    memcpy(lkey->data, k5key->contents, k5key->length);
+    lkey->length = k5key->length;
+    lkey->type = k5key->enctype;
+
+    return 0;
+}
+
+
+/* Free any storage associated with a gss_krb5_lucid_key_t structure */
+static void
+free_lucid_key_data(
+    gss_krb5_lucid_key_t *key)
+{
+    if (key) {
+       if (key->data && key->length) {
+           memset(key->data, 0, key->length);
+           xfree(key->data);
+           memset(key, 0, sizeof(gss_krb5_lucid_key_t));
+       }
+    }
+}
+/* Free any storage associated with a gss_krb5_lucid_context_v1 structure */
+static void
+free_external_lucid_ctx_v1(
+    gss_krb5_lucid_context_v1_t *ctx)
+{
+    if (ctx) {
+       if (ctx->protocol == 0) {
+           free_lucid_key_data(&ctx->rfc1964_kd.ctx_key);
+       }
+       if (ctx->protocol == 1) {
+           free_lucid_key_data(&ctx->cfx_kd.ctx_key);
+           if (ctx->cfx_kd.have_acceptor_subkey)
+               free_lucid_key_data(&ctx->cfx_kd.acceptor_subkey);
+       }
+       xfree(ctx);
+       ctx = NULL;
+    }
+}
diff --git a/src/lib/gssapi/krb5/set_allowable_enctypes.c b/src/lib/gssapi/krb5/set_allowable_enctypes.c
new file mode 100644 (file)
index 0000000..aa3636e
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * lib/gssapi/krb5/set_allowable_enctypes.c
+ *
+ * Copyright 2004  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.
+ *
+ * krb5_gss_set_allowable_enctypes()
+ */
+
+/*
+ * gss_krb5_set_allowable_enctypes
+ *
+ * This function may be called by a context initiator after calling
+ * gss_acquire_cred(), but before calling gss_init_sec_context(),
+ * to restrict the set of enctypes which will be negotiated during
+ * context establishment to those in the provided array.
+ *
+ * 'cred_handle' must be a valid credential handle obtained via
+ * gss_acquire_cred().  It may not be GSS_C_NO_CREDENTIAL.
+ * gss_acquire_cred() may be called with GSS_C_NO_CREDENTIAL
+ * to get a handle to the default credential.
+ *
+ * The purpose of this function is to limit the keys that may
+ * be exported via gss_krb5_export_lucid_sec_context(); thus it
+ * should limit the enctypes of all keys that will be needed
+ * after the security context has been established.
+ * (i.e. context establishment may use a session key with a
+ * stronger enctype than in the provided array, however a
+ * subkey must be established within the enctype limits
+ * established by this function.)
+ *
+ */
+
+#include "gssapiP_krb5.h"
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#include "gssapi_krb5.h"
+
+OM_uint32 KRB5_CALLCONV
+gss_krb5_set_allowable_enctypes(OM_uint32 *minor_status, 
+                                gss_cred_id_t cred_handle,
+                               OM_uint32 num_ktypes,
+                               krb5_enctype *ktypes)
+{
+    int i;
+    krb5_enctype * new_ktypes;
+    OM_uint32 major_status;
+    krb5_gss_cred_id_t cred;
+    krb5_error_code kerr = 0;
+    OM_uint32 temp_status;
+
+    /* Assume a failure */
+    *minor_status = 0;
+    major_status = GSS_S_FAILURE;
+
+    /* verify and valildate cred handle */
+    if (cred_handle == GSS_C_NO_CREDENTIAL) {
+       kerr = KRB5_NOCREDS_SUPPLIED;
+       goto error_out;
+    }
+    major_status = krb5_gss_validate_cred(&temp_status, cred_handle);
+    if (GSS_ERROR(major_status)) {
+       kerr = temp_status;
+       goto error_out;
+    }
+    cred = (krb5_gss_cred_id_t) cred_handle;
+
+    if (ktypes) {
+       for (i = 0; i < num_ktypes && ktypes[i]; i++) {
+           if (!krb5_c_valid_enctype(ktypes[i])) {
+               kerr = KRB5_PROG_ETYPE_NOSUPP;
+               goto error_out;
+           }
+       }
+    } else {
+       if (cred->req_enctypes)
+           free(cred->req_enctypes);
+       cred->req_enctypes = NULL;
+       return GSS_S_COMPLETE;
+    }
+
+    /* Copy the requested ktypes into the cred structure */
+    if ((new_ktypes = (krb5_enctype *)malloc(sizeof(krb5_enctype) * (i + 1)))) {
+       memcpy(new_ktypes, ktypes, sizeof(krb5_enctype) * i);
+       new_ktypes[i] = 0;      /* "null-terminate" the list */
+    }
+    else {
+       kerr = ENOMEM;
+       goto error_out;
+    }
+    if (cred->req_enctypes)
+       free(cred->req_enctypes);
+    cred->req_enctypes = new_ktypes;
+
+    /* Success! */
+    return GSS_S_COMPLETE;
+
+error_out:
+    *minor_status = kerr;
+    return(major_status);
+}