summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib/gssapi/ChangeLog4
-rw-r--r--src/lib/gssapi/configure.in3
-rw-r--r--src/lib/gssapi/generic/ChangeLog5
-rw-r--r--src/lib/gssapi/generic/gssapiP_generic.h6
-rw-r--r--src/lib/gssapi/generic/util_validate.c20
-rw-r--r--src/lib/gssapi/generic/utl_nohash_validate.c18
-rw-r--r--src/lib/gssapi/krb5/ChangeLog10
-rw-r--r--src/lib/gssapi/krb5/Makefile.in22
-rw-r--r--src/lib/gssapi/krb5/gssapiP_krb5.h4
-rw-r--r--src/lib/gssapi/krb5/gssapi_err_krb5.et1
-rw-r--r--src/lib/gssapi/krb5/gssapi_krb5.h114
-rw-r--r--src/lib/gssapi/krb5/gssapi_krb5.hin271
-rw-r--r--src/lib/gssapi/krb5/init_sec_context.c9
-rw-r--r--src/lib/gssapi/krb5/lucid_context.c309
-rw-r--r--src/lib/gssapi/krb5/set_allowable_enctypes.c123
15 files changed, 803 insertions, 116 deletions
diff --git a/src/lib/gssapi/ChangeLog b/src/lib/gssapi/ChangeLog
index 2d90a0aba..9922cee1f 100644
--- a/src/lib/gssapi/ChangeLog
+++ b/src/lib/gssapi/ChangeLog
@@ -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.
diff --git a/src/lib/gssapi/configure.in b/src/lib/gssapi/configure.in
index 8852f0579..72ab7983a 100644
--- a/src/lib/gssapi/configure.in
+++ b/src/lib/gssapi/configure.in
@@ -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)
diff --git a/src/lib/gssapi/generic/ChangeLog b/src/lib/gssapi/generic/ChangeLog
index ec34f6b5a..5c5c82ac0 100644
--- a/src/lib/gssapi/generic/ChangeLog
+++ b/src/lib/gssapi/generic/ChangeLog
@@ -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.
diff --git a/src/lib/gssapi/generic/gssapiP_generic.h b/src/lib/gssapi/generic/gssapiP_generic.h
index e297862fe..0af65df1b 100644
--- a/src/lib/gssapi/generic/gssapiP_generic.h
+++ b/src/lib/gssapi/generic/gssapiP_generic.h
@@ -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);
diff --git a/src/lib/gssapi/generic/util_validate.c b/src/lib/gssapi/generic/util_validate.c
index 779260892..fffacabcb 100644
--- a/src/lib/gssapi/generic/util_validate.c
+++ b/src/lib/gssapi/generic/util_validate.c
@@ -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));
+}
diff --git a/src/lib/gssapi/generic/utl_nohash_validate.c b/src/lib/gssapi/generic/utl_nohash_validate.c
index 1ed2008a5..da20b71d6 100644
--- a/src/lib/gssapi/generic/utl_nohash_validate.c
+++ b/src/lib/gssapi/generic/utl_nohash_validate.c
@@ -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;
+}
diff --git a/src/lib/gssapi/krb5/ChangeLog b/src/lib/gssapi/krb5/ChangeLog
index 1be0a67a7..e4b2f720d 100644
--- a/src/lib/gssapi/krb5/ChangeLog
+++ b/src/lib/gssapi/krb5/ChangeLog
@@ -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
diff --git a/src/lib/gssapi/krb5/Makefile.in b/src/lib/gssapi/krb5/Makefile.in
index 582bd802e..2eec3dc72 100644
--- a/src/lib/gssapi/krb5/Makefile.in
+++ b/src/lib/gssapi/krb5/Makefile.in
@@ -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::
diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h
index d207010c1..b5a24960e 100644
--- a/src/lib/gssapi/krb5/gssapiP_krb5.h
+++ b/src/lib/gssapi/krb5/gssapiP_krb5.h
@@ -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 **/
diff --git a/src/lib/gssapi/krb5/gssapi_err_krb5.et b/src/lib/gssapi/krb5/gssapi_err_krb5.et
index 3c9be6351..c2a705c84 100644
--- a/src/lib/gssapi/krb5/gssapi_err_krb5.et
+++ b/src/lib/gssapi/krb5/gssapi_err_krb5.et
@@ -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
index 3007a0fd8..000000000
--- a/src/lib/gssapi/krb5/gssapi_krb5.h
+++ /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
index 000000000..6fc47949d
--- /dev/null
+++ b/src/lib/gssapi/krb5/gssapi_krb5.hin
@@ -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_ */
diff --git a/src/lib/gssapi/krb5/init_sec_context.c b/src/lib/gssapi/krb5/init_sec_context.c
index 48015cccd..63a9cb956 100644
--- a/src/lib/gssapi/krb5/init_sec_context.c
+++ b/src/lib/gssapi/krb5/init_sec_context.c
@@ -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
index 000000000..ac81fff60
--- /dev/null
+++ b/src/lib/gssapi/krb5/lucid_context.c
@@ -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
index 000000000..aa3636e13
--- /dev/null
+++ b/src/lib/gssapi/krb5/set_allowable_enctypes.c
@@ -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);
+}