AUTOMAKE_OPTIONS = foreign
gssdir = $(libdir)/gss
+gss_LTLIBRARIES = mech_eap.la
-gss_LTLIBRARIES = libmech_eap.la
+mech_eap_la_CPPFLAGS = -DBUILD_GSSEAP_LIB -DSYSCONFDIR=\"${sysconfdir}\"
+mech_eap_la_CFLAGS = -g -Wall -fno-strict-aliasing \
+ @EAP_CFLAGS@ @KRB5_CFLAGS@ @TARGET_CFLAGS@
+mech_eap_la_CXXFLAGS = -g -Wall \
+ @EAP_CFLAGS@ @KRB5_CFLAGS@ @SHIBSP_CXXFLAGS@ \
+ @SHIBRESOLVER_CXXFLAGS@ @TARGET_CFLAGS@
+mech_eap_la_LDFLAGS = -avoid-version -module \
+ -export-symbols mech_eap.exports -no-undefined \
+ @EAP_LDFLAGS@ @KRB5_LDFLAGS@ @TARGET_LDFLAGS@
+mech_eap_la_LIBADD = @EAP_LIBS@ @KRB5_LIBS@ @SHIBSP_LIBS@ \
+ @SHIBRESOLVER_LIBS@ -lfreeradius-client
-libmech_eap_la_CPPFLAGS = -DBUILD_GSSEAP_LIB -DSYSCONFDIR=\"${sysconfdir}\"
-libmech_eap_la_CFLAGS = -g -Wall -fno-strict-aliasing \
- @EAP_CFLAGS@ @KRB5_CFLAGS@ @TARGET_CFLAGS@
-libmech_eap_la_CXXFLAGS = -g -Wall \
- @EAP_CFLAGS@ @KRB5_CFLAGS@ @SHIBSP_CXXFLAGS@ \
- @SHIBRESOLVER_CXXFLAGS@ @TARGET_CFLAGS@
-libmech_eap_la_LDFLAGS = -export-symbols mech_eap.exports -version-info 0:0:0 \
- -no-undefined \
- @EAP_LDFLAGS@ @KRB5_LDFLAGS@ @TARGET_LDFLAGS@
-libmech_eap_la_LIBADD = @EAP_LIBS@ @KRB5_LIBS@ @SHIBSP_LIBS@ @SHIBRESOLVER_LIBS@ -lfreeradius-client
-
-libmech_eap_la_SOURCES = \
+mech_eap_la_SOURCES = \
accept_sec_context.c \
acquire_cred.c \
acquire_cred_with_password.c \
wrap_iov_length.c \
wrap_size_limit.c
+krb5pluginsdir = $(libdir)/krb5/plugins/authdata
+krb5plugins_LTLIBRARIES = radius_ad.la
+
+radius_ad_la_CFLAGS = -g -Wall -fno-strict-aliasing \
+ @EAP_CFLAGS@ @KRB5_CFLAGS@ @TARGET_CFLAGS@
+radius_ad_la_LDFLAGS = -avoid-version -module \
+ -export-symbols radius_ad.exports -no-undefined
+radius_ad_la_LIBADD = @KRB5_LIBS@
+radius_ad_la_SOURCES = util_adshim.c
if (GSS_ERROR(major))
goto cleanup;
- ctx->state = EAP_STATE_GSS_CHANNEL_BINDINGS;
+ ctx->state = EAP_STATE_EXTENSIONS_REQ;
}
major = GSS_S_CONTINUE_NEEDED;
}
static OM_uint32
-eapGssSmAcceptGssChannelBindings(OM_uint32 *minor,
- gss_ctx_id_t ctx,
- gss_cred_id_t cred,
- gss_buffer_t inputToken,
- gss_channel_bindings_t chanBindings,
- gss_buffer_t outputToken)
+acceptGssChannelBindings(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ gss_cred_id_t cred,
+ gss_buffer_t inputToken,
+ gss_channel_bindings_t chanBindings)
{
- OM_uint32 major;
+ OM_uint32 major, tmpMinor;
gss_iov_buffer_desc iov[2];
- outputToken->length = 0;
- outputToken->value = NULL;
-
- if (chanBindings != GSS_C_NO_CHANNEL_BINDINGS) {
- if (inputToken->length < 14) {
- return GSS_S_DEFECTIVE_TOKEN;
- }
-
- iov[0].type = GSS_IOV_BUFFER_TYPE_DATA;
- iov[0].buffer.length = 0;
- iov[0].buffer.value = NULL;
-
- if (chanBindings != GSS_C_NO_CHANNEL_BINDINGS)
- iov[0].buffer = chanBindings->application_data;
+ iov[0].type = GSS_IOV_BUFFER_TYPE_DATA | GSS_IOV_BUFFER_FLAG_ALLOCATE;
+ iov[0].buffer.length = 0;
+ iov[0].buffer.value = NULL;
- iov[1].type = GSS_IOV_BUFFER_TYPE_HEADER;
- iov[1].buffer.length = 16;
- iov[1].buffer.value = (unsigned char *)inputToken->value - 2;
+ iov[1].type = GSS_IOV_BUFFER_TYPE_STREAM;
+ iov[1].buffer = *inputToken;
- assert(load_uint16_be(iov[1].buffer.value) == TOK_TYPE_GSS_CB);
-
- iov[2].type = GSS_IOV_BUFFER_TYPE_TRAILER;
- iov[2].buffer.length = inputToken->length - 14;
- iov[2].buffer.value = (unsigned char *)inputToken->value + 14;
+ major = gssEapUnwrapOrVerifyMIC(minor, ctx, NULL, NULL,
+ iov, 2, TOK_TYPE_WRAP);
+ if (GSS_ERROR(major))
+ return major;
- major = gssEapUnwrapOrVerifyMIC(minor, ctx, NULL, NULL,
- iov, 3, TOK_TYPE_GSS_CB);
- if (GSS_ERROR(major))
- return major;
+ if (chanBindings != GSS_C_NO_CHANNEL_BINDINGS &&
+ !bufferEqual(&iov[0].buffer, &chanBindings->application_data)) {
+ major = GSS_S_BAD_BINDINGS;
+ } else {
+ major = GSS_S_CONTINUE_NEEDED;
}
- ctx->state = EAP_STATE_KRB_REAUTH_CRED;
+ gss_release_buffer(&tmpMinor, &iov[0].buffer);
- return GSS_S_CONTINUE_NEEDED;
+ return major;
}
static OM_uint32
-eapGssSmAcceptKrbReauthCred(OM_uint32 *minor,
+eapGssSmAcceptExtensionsReq(OM_uint32 *minor,
gss_ctx_id_t ctx,
gss_cred_id_t cred,
gss_buffer_t inputToken,
{
OM_uint32 major;
- major = gssEapMakeReauthCreds(minor, ctx, cred, outputToken);
+ outputToken->length = 0;
+ outputToken->value = NULL;
+
+ major = acceptGssChannelBindings(minor, ctx, cred, inputToken,
+ chanBindings);
+ if (GSS_ERROR(major))
+ return major;
+
+ ctx->state = EAP_STATE_EXTENSIONS_RESP;
+
+ return GSS_S_CONTINUE_NEEDED;
+}
+
+static OM_uint32
+eapGssSmAcceptExtensionsResp(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ gss_cred_id_t cred,
+ gss_buffer_t inputToken,
+ gss_channel_bindings_t chanBindings,
+ gss_buffer_t outputToken)
+{
+ OM_uint32 major, tmpMinor;
+ gss_buffer_desc credsToken = GSS_C_EMPTY_BUFFER;
+
+ major = gssEapMakeReauthCreds(minor, ctx, cred, &credsToken);
if (GSS_ERROR(major))
return major;
ctx->state = EAP_STATE_ESTABLISHED;
+ major = duplicateBuffer(minor, &credsToken, outputToken);
+ if (GSS_ERROR(major)) {
+ gss_release_buffer(&tmpMinor, &credsToken);
+ return major;
+ }
+
+ gss_release_buffer(&tmpMinor, &credsToken);
+
return GSS_S_COMPLETE;
}
const gss_OID mech,
OM_uint32 timeRec)
{
- OM_uint32 major, tmpMinor;
- gss_buffer_desc authData = GSS_C_EMPTY_BUFFER;
+ OM_uint32 major;
major = gssEapGlueToMechName(minor, initiator, &ctx->initiatorName);
if (GSS_ERROR(major))
- goto cleanup;
-
- major = gssKrbExtractAuthzDataFromSecContext(minor, ctx->kerberosCtx,
- KRB5_AUTHDATA_RADIUS_AVP,
- &authData);
- if (GSS_ERROR(major))
- goto cleanup;
-
- major = gssEapImportAttrContext(minor, &authData, ctx->initiatorName);
- if (GSS_ERROR(major))
- goto cleanup;
+ return major;
if (cred != GSS_C_NO_CREDENTIAL && cred->name != GSS_C_NO_NAME) {
major = gssEapDuplicateName(minor, cred->name, &ctx->acceptorName);
if (GSS_ERROR(major))
- goto cleanup;
+ return major;
}
major = gssEapReauthComplete(minor, ctx, cred, mech, timeRec);
if (GSS_ERROR(major))
- goto cleanup;
+ return major;
ctx->state = EAP_STATE_ESTABLISHED;
-cleanup:
- gss_release_buffer(&tmpMinor, &authData);
-
- return major;
+ return GSS_S_COMPLETE;
}
static OM_uint32
} eapGssAcceptorSm[] = {
{ TOK_TYPE_EAP_RESP, TOK_TYPE_EAP_REQ, eapGssSmAcceptIdentity },
{ TOK_TYPE_EAP_RESP, TOK_TYPE_EAP_REQ, eapGssSmAcceptAuthenticate },
- { TOK_TYPE_GSS_CB, TOK_TYPE_NONE, eapGssSmAcceptGssChannelBindings },
- { TOK_TYPE_NONE, TOK_TYPE_KRB_CRED, eapGssSmAcceptKrbReauthCred },
+ { TOK_TYPE_EXT_REQ, TOK_TYPE_NONE, eapGssSmAcceptExtensionsReq },
+ { TOK_TYPE_NONE, TOK_TYPE_EXT_RESP, eapGssSmAcceptExtensionsResp },
{ TOK_TYPE_NONE, TOK_TYPE_NONE, eapGssSmAcceptEstablished },
{ TOK_TYPE_GSS_REAUTH, TOK_TYPE_GSS_REAUTH, eapGssSmAcceptGssReauth },
};
--- /dev/null
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * krb5/authdata_plugin.h
+ *
+ * Copyright (C) 2007 Apple Inc. 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.
+ *
+ * AuthorizationData plugin definitions for Kerberos 5.
+ */
+
+/*
+ * This is considered an INTERNAL interface at this time.
+ *
+ * Some work is needed before exporting it:
+ *
+ * + Documentation.
+ * + Sample code.
+ * + Test cases (preferably automated testing under "make check").
+ * + Hook into TGS exchange too; will change API.
+ * + Examine memory management issues, especially for Windows; may
+ * change API.
+ *
+ * Other changes that would be nice to have, but not necessarily
+ * before making this interface public:
+ *
+ * + Library support for AD-IF-RELEVANT and similar wrappers. (We can
+ * make the plugin construct them if it wants them.)
+ * + KDC could combine/optimize wrapped AD elements provided by
+ * multiple plugins, e.g., two IF-RELEVANT sequences could be
+ * merged. (The preauth plugin API also has this bug, we're going
+ * to need a general fix.)
+ */
+
+#ifndef KRB5_AUTHDATA_PLUGIN_H_INCLUDED
+#define KRB5_AUTHDATA_PLUGIN_H_INCLUDED
+#include <krb5/krb5.h>
+
+/*
+ * While arguments of these types are passed-in, for the most part a
+ * authorization data module can treat them as opaque. If we need
+ * keying data, we can ask for it directly.
+ */
+struct _krb5_db_entry_new;
+
+/*
+ * The function table / structure which an authdata server module must export as
+ * "authdata_server_0". NOTE: replace "0" with "1" for the type and
+ * variable names if this gets picked up by upstream. If the interfaces work
+ * correctly, future versions of the table will add either more callbacks or
+ * more arguments to callbacks, and in both cases we'll be able to wrap the v0
+ * functions.
+ */
+/* extern krb5plugin_authdata_ftable_v0 authdata_server_0; */
+typedef struct krb5plugin_authdata_server_ftable_v0 {
+ /* Not-usually-visible name. */
+ char *name;
+
+ /*
+ * Per-plugin initialization/cleanup. The init function is called
+ * by the KDC when the plugin is loaded, and the fini function is
+ * called before the plugin is unloaded. Both are optional.
+ */
+ krb5_error_code (*init_proc)(krb5_context, void **);
+ void (*fini_proc)(krb5_context, void *);
+ /*
+ * Actual authorization data handling function. If this field
+ * holds a null pointer, this mechanism will be skipped, and the
+ * init/fini functions will not be run.
+ *
+ * This function should only modify the field
+ * enc_tkt_reply->authorization_data. All other values should be
+ * considered inputs only. And, it should *modify* the field, not
+ * overwrite it and assume that there are no other authdata
+ * plugins in use.
+ *
+ * Memory management: authorization_data is a malloc-allocated,
+ * null-terminated sequence of malloc-allocated pointers to
+ * authorization data structures. This plugin code currently
+ * assumes the libraries, KDC, and plugin all use the same malloc
+ * pool, which may be a problem if/when we get the KDC code
+ * running on Windows.
+ *
+ * If this function returns a non-zero error code, a message
+ * is logged, but no other action is taken. Other authdata
+ * plugins will be called, and a response will be sent to the
+ * client (barring other problems).
+ */
+ krb5_error_code (*authdata_proc)(krb5_context,
+ struct _krb5_db_entry_new *client,
+ krb5_data *req_pkt,
+ krb5_kdc_req *request,
+ krb5_enc_tkt_part *enc_tkt_reply);
+} krb5plugin_server_authdata_ftable_v0;
+
+typedef krb5plugin_server_authdata_ftable_v0 krb5plugin_authdata_ftable_v0;
+
+typedef struct krb5plugin_authdata_server_ftable_v2 {
+ /* Not-usually-visible name. */
+ char *name;
+
+ /*
+ * Per-plugin initialization/cleanup. The init function is called
+ * by the KDC when the plugin is loaded, and the fini function is
+ * called before the plugin is unloaded. Both are optional.
+ */
+ krb5_error_code (*init_proc)(krb5_context, void **);
+ void (*fini_proc)(krb5_context, void *);
+ /*
+ * Actual authorization data handling function. If this field
+ * holds a null pointer, this mechanism will be skipped, and the
+ * init/fini functions will not be run.
+ *
+ * This function should only modify the field
+ * enc_tkt_reply->authorization_data. All other values should be
+ * considered inputs only. And, it should *modify* the field, not
+ * overwrite it and assume that there are no other authdata
+ * plugins in use.
+ *
+ * Memory management: authorization_data is a malloc-allocated,
+ * null-terminated sequence of malloc-allocated pointers to
+ * authorization data structures. This plugin code currently
+ * assumes the libraries, KDC, and plugin all use the same malloc
+ * pool, which may be a problem if/when we get the KDC code
+ * running on Windows.
+ *
+ * If this function returns a non-zero error code, a message
+ * is logged, but no other action is taken. Other authdata
+ * plugins will be called, and a response will be sent to the
+ * client (barring other problems).
+ */
+ krb5_error_code (*authdata_proc)(krb5_context,
+ unsigned int flags,
+ struct _krb5_db_entry_new *client,
+ struct _krb5_db_entry_new *server,
+ struct _krb5_db_entry_new *tgs,
+ krb5_keyblock *client_key,
+ krb5_keyblock *server_key,
+ krb5_keyblock *tgs_key,
+ krb5_data *req_pkt,
+ krb5_kdc_req *request,
+ krb5_const_principal for_user_princ,
+ krb5_enc_tkt_part *enc_tkt_request,
+ krb5_enc_tkt_part *enc_tkt_reply);
+} krb5plugin_authdata_server_ftable_v2;
+
+typedef krb5plugin_authdata_server_ftable_v2 krb5plugin_authdata_ftable_v2;
+
+typedef krb5_error_code
+(*authdata_client_plugin_init_proc)(krb5_context context,
+ void **plugin_context);
+
+#define AD_USAGE_AS_REQ 0x01
+#define AD_USAGE_TGS_REQ 0x02
+#define AD_USAGE_AP_REQ 0x04
+#define AD_USAGE_KDC_ISSUED 0x08
+#define AD_USAGE_MASK 0x0F
+#define AD_INFORMATIONAL 0x10
+
+struct _krb5_authdata_context;
+
+typedef void
+(*authdata_client_plugin_flags_proc)(krb5_context kcontext,
+ void *plugin_context,
+ krb5_authdatatype ad_type,
+ krb5_flags *flags);
+
+typedef void
+(*authdata_client_plugin_fini_proc)(krb5_context kcontext,
+ void *plugin_context);
+
+typedef krb5_error_code
+(*authdata_client_request_init_proc)(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void **request_context);
+
+typedef void
+(*authdata_client_request_fini_proc)(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context);
+
+typedef krb5_error_code
+(*authdata_client_import_authdata_proc)(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context,
+ krb5_authdata **authdata,
+ krb5_boolean kdc_issued_flag,
+ krb5_const_principal issuer);
+
+typedef krb5_error_code
+(*authdata_client_export_authdata_proc)(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context,
+ krb5_flags usage,
+ krb5_authdata ***authdata);
+
+typedef krb5_error_code
+(*authdata_client_get_attribute_types_proc)(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context,
+ krb5_data **attrs);
+
+typedef krb5_error_code
+(*authdata_client_get_attribute_proc)(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context,
+ const krb5_data *attribute,
+ krb5_boolean *authenticated,
+ krb5_boolean *complete,
+ krb5_data *value,
+ krb5_data *display_value,
+ int *more);
+
+typedef krb5_error_code
+(*authdata_client_set_attribute_proc)(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context,
+ krb5_boolean complete,
+ const krb5_data *attribute,
+ const krb5_data *value);
+
+typedef krb5_error_code
+(*authdata_client_delete_attribute_proc)(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context,
+ const krb5_data *attribute);
+
+typedef krb5_error_code
+(*authdata_client_export_internal_proc)(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context,
+ krb5_boolean restrict_authenticated,
+ void **ptr);
+
+typedef void
+(*authdata_client_free_internal_proc)(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context,
+ void *ptr);
+
+typedef krb5_error_code
+(*authdata_client_verify_proc)(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context,
+ const krb5_auth_context *auth_context,
+ const krb5_keyblock *key,
+ const krb5_ap_req *req);
+
+typedef krb5_error_code
+(*authdata_client_size_proc)(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context,
+ size_t *sizep);
+
+typedef krb5_error_code
+(*authdata_client_externalize_proc)(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context,
+ krb5_octet **buffer,
+ size_t *lenremain);
+
+typedef krb5_error_code
+(*authdata_client_internalize_proc)(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context,
+ krb5_octet **buffer,
+ size_t *lenremain);
+
+typedef krb5_error_code
+(*authdata_client_copy_proc)(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context,
+ void *dst_plugin_context,
+ void *dst_request_context);
+
+typedef struct krb5plugin_authdata_client_ftable_v0 {
+ char *name;
+ krb5_authdatatype *ad_type_list;
+ authdata_client_plugin_init_proc init;
+ authdata_client_plugin_fini_proc fini;
+ authdata_client_plugin_flags_proc flags;
+ authdata_client_request_init_proc request_init;
+ authdata_client_request_fini_proc request_fini;
+ authdata_client_get_attribute_types_proc get_attribute_types;
+ authdata_client_get_attribute_proc get_attribute;
+ authdata_client_set_attribute_proc set_attribute;
+ authdata_client_delete_attribute_proc delete_attribute;
+ authdata_client_export_authdata_proc export_authdata;
+ authdata_client_import_authdata_proc import_authdata;
+ authdata_client_export_internal_proc export_internal;
+ authdata_client_free_internal_proc free_internal;
+ authdata_client_verify_proc verify;
+ authdata_client_size_proc size;
+ authdata_client_externalize_proc externalize;
+ authdata_client_internalize_proc internalize;
+ authdata_client_copy_proc copy; /* optional */
+} krb5plugin_authdata_client_ftable_v0;
+
+#endif /* KRB5_AUTHDATA_PLUGIN_H_INCLUDED */
enum gss_eap_state {
EAP_STATE_IDENTITY = 0,
EAP_STATE_AUTHENTICATE,
- EAP_STATE_GSS_CHANNEL_BINDINGS,
- EAP_STATE_KRB_REAUTH_CRED,
+ EAP_STATE_EXTENSIONS_REQ,
+ EAP_STATE_EXTENSIONS_RESP,
EAP_STATE_ESTABLISHED,
EAP_STATE_KRB_REAUTH_GSS
};
int *conf_state,
gss_iov_buffer_desc *iov,
int iov_count);
+OM_uint32
+gssEapWrap(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ int conf_req_flag,
+ gss_qop_t qop_req,
+ gss_buffer_t input_message_buffer,
+ int *conf_state,
+ gss_buffer_t output_message_buffer);
unsigned char
rfc4121Flags(gss_ctx_id_t ctx, int receiving);
ctx->flags &= ~(CTX_FLAG_EAP_SUCCESS);
major = GSS_S_CONTINUE_NEEDED;
- ctx->state = EAP_STATE_GSS_CHANNEL_BINDINGS;
+ ctx->state = EAP_STATE_EXTENSIONS_REQ;
} else if (ctx->flags & CTX_FLAG_EAP_FAIL) {
major = GSS_S_DEFECTIVE_CREDENTIAL;
} else if (code == 0 && initialContextToken) {
}
static OM_uint32
-eapGssSmInitGssChannelBindings(OM_uint32 *minor,
- gss_cred_id_t cred,
- gss_ctx_id_t ctx,
- gss_name_t target,
- gss_OID mech,
- OM_uint32 reqFlags,
- OM_uint32 timeReq,
- gss_channel_bindings_t chanBindings,
- gss_buffer_t inputToken,
- gss_buffer_t outputToken)
+initGssChannelBindings(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ gss_channel_bindings_t chanBindings,
+ gss_buffer_t outputToken)
{
OM_uint32 major;
- gss_iov_buffer_desc iov[2];
- gss_buffer_desc buf;
+ gss_buffer_desc buffer = GSS_C_EMPTY_BUFFER;
- iov[0].type = GSS_IOV_BUFFER_TYPE_DATA;
- iov[0].buffer.length = 0;
- iov[0].buffer.value = NULL;
-
- iov[1].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_FLAG_ALLOCATE;
- iov[1].buffer.length = 0;
- iov[1].buffer.value = NULL;
if (chanBindings != GSS_C_NO_CHANNEL_BINDINGS)
- iov[0].buffer = chanBindings->application_data;
+ buffer = chanBindings->application_data;
- major = gssEapWrapOrGetMIC(minor, ctx, FALSE, FALSE, iov, 2,
- TOK_TYPE_GSS_CB);
+ major = gssEapWrap(minor, ctx, TRUE, GSS_C_QOP_DEFAULT,
+ &buffer, NULL, outputToken);
if (GSS_ERROR(major))
- goto cleanup;
-
- /* Skip past token ID */
- assert(iov[1].buffer.length > 2);
- assert(load_uint16_be(iov[1].buffer.value) == TOK_TYPE_GSS_CB);
-
- buf.length = iov[1].buffer.length - 2;
- buf.value = (unsigned char *)iov[1].buffer.value + 2;
-
- major = duplicateBuffer(minor, &buf, outputToken);
- if (GSS_ERROR(major))
- goto cleanup;
+ return major;
- major = GSS_S_CONTINUE_NEEDED;
- ctx->state = EAP_STATE_KRB_REAUTH_CRED;
-
-cleanup:
- gssEapReleaseIov(iov, 2);
-
- return major;
+ return GSS_S_CONTINUE_NEEDED;
}
static OM_uint32
-eapGssSmInitKrbReauthCred(OM_uint32 *minor,
+eapGssSmInitExtensionsReq(OM_uint32 *minor,
gss_cred_id_t cred,
gss_ctx_id_t ctx,
gss_name_t target,
gss_buffer_t inputToken,
gss_buffer_t outputToken)
{
+ OM_uint32 major, tmpMinor;
+ gss_buffer_desc cbToken = GSS_C_EMPTY_BUFFER;
+
+ major = initGssChannelBindings(minor, ctx, chanBindings, &cbToken);
+ if (GSS_ERROR(major))
+ return major;
+
+ ctx->state = EAP_STATE_EXTENSIONS_RESP;
+
+ major = duplicateBuffer(minor, &cbToken, outputToken);
+ if (GSS_ERROR(major)) {
+ gss_release_buffer(&tmpMinor, &cbToken);
+ return major;
+ }
+
+ gss_release_buffer(&tmpMinor, &cbToken);
+
+ return GSS_S_CONTINUE_NEEDED;
+}
+
+static OM_uint32
+eapGssSmInitExtensionsResp(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ gss_ctx_id_t ctx,
+ gss_name_t target,
+ gss_OID mech,
+ OM_uint32 reqFlags,
+ OM_uint32 timeReq,
+ gss_channel_bindings_t chanBindings,
+ gss_buffer_t inputToken,
+ gss_buffer_t outputToken)
+{
OM_uint32 major;
major = gssEapStoreReauthCreds(minor, ctx, cred, inputToken);
} eapGssInitiatorSm[] = {
{ TOK_TYPE_NONE, TOK_TYPE_EAP_RESP, eapGssSmInitIdentity },
{ TOK_TYPE_EAP_REQ, TOK_TYPE_EAP_RESP, eapGssSmInitAuthenticate },
- { TOK_TYPE_NONE, TOK_TYPE_GSS_CB, eapGssSmInitGssChannelBindings },
- { TOK_TYPE_KRB_CRED,TOK_TYPE_NONE, eapGssSmInitKrbReauthCred },
+ { TOK_TYPE_NONE, TOK_TYPE_EXT_REQ, eapGssSmInitExtensionsReq },
+ { TOK_TYPE_EXT_RESP,TOK_TYPE_NONE, eapGssSmInitExtensionsResp },
{ TOK_TYPE_NONE, TOK_TYPE_NONE, eapGssSmInitEstablished },
{ TOK_TYPE_GSS_REAUTH, TOK_TYPE_GSS_REAUTH, eapGssSmInitGssReauth },
};
# Any encryption type supported by Kerberos can be defined as the
# last element of the OID arc.
#
-eap 1.3.6.1.4.1.5322.21.1 libmech_eap.dylib
-eap-des3-cbc-sha1 1.3.6.1.4.1.5322.21.1.16 libmech_eap.dylib
-eap-aes128 1.3.6.1.4.1.5322.21.1.17 libmech_eap.dylib
-eap-aes256 1.3.6.1.4.1.5322.21.1.18 libmech_eap.dylib
-eap-rc4-hmac 1.3.6.1.4.1.5322.21.1.23 libmech_eap.dylib
+eap 1.3.6.1.4.1.5322.21.1 mech_eap.so
+eap-des3-cbc-sha1 1.3.6.1.4.1.5322.21.1.16 mech_eap.so
+eap-aes128 1.3.6.1.4.1.5322.21.1.17 mech_eap.so
+eap-aes256 1.3.6.1.4.1.5322.21.1.18 mech_eap.so
+eap-rc4-hmac 1.3.6.1.4.1.5322.21.1.23 mech_eap.so
--- /dev/null
+authdata_client_0
OM_uint32 major, tmpMinor;
gss_iov_buffer_desc iov[2];
+ if (!CTX_IS_ESTABLISHED(ctx))
+ return GSS_S_NO_CONTEXT;
+
iov[0].type = GSS_IOV_BUFFER_TYPE_STREAM;
iov[0].buffer = *input_message_buffer;
flags = rfc4121Flags(ctx, TRUE);
- switch (toktype) {
- case TOK_TYPE_WRAP:
+ if (toktype == TOK_TYPE_WRAP) {
keyUsage = !CTX_IS_INITIATOR(ctx)
? KEY_USAGE_INITIATOR_SEAL
: KEY_USAGE_ACCEPTOR_SEAL;
- break;
- case TOK_TYPE_GSS_CB:
- keyUsage = KEY_USAGE_CHANNEL_BINDINGS;
- break;
- case TOK_TYPE_MIC:
- default:
+ } else {
keyUsage = !CTX_IS_INITIATOR(ctx)
? KEY_USAGE_INITIATOR_SIGN
: KEY_USAGE_ACCEPTOR_SIGN;
- break;
}
gssEapIovMessageLength(iov, iov_count, &dataLen, &assocDataLen);
}
code = sequenceCheck(minor, &ctx->seqState, seqnum);
- } else if (toktype == TOK_TYPE_MIC || toktype == TOK_TYPE_GSS_CB) {
+ } else if (toktype == TOK_TYPE_MIC) {
if (load_uint16_be(ptr) != toktype)
goto defective;
*minor = code;
return GSS_S_BAD_SIG;
}
- if (toktype != TOK_TYPE_GSS_CB)
- code = sequenceCheck(minor, &ctx->seqState, seqnum);
+ code = sequenceCheck(minor, &ctx->seqState, seqnum);
} else if (toktype == TOK_TYPE_DELETE_CONTEXT) {
if (load_uint16_be(ptr) != TOK_TYPE_DELETE_CONTEXT)
goto defective;
{
OM_uint32 major;
- if (!CTX_IS_ESTABLISHED(ctx))
- return GSS_S_NO_CONTEXT;
-
if (ctx->encryptionType == ENCTYPE_NULL)
return GSS_S_UNAVAILABLE;
gss_iov_buffer_desc *iov,
int iov_count)
{
+ if (!CTX_IS_ESTABLISHED(ctx))
+ return GSS_S_NO_CONTEXT;
+
return gssEapUnwrapOrVerifyMIC(minor, ctx, conf_state, qop_state,
iov, iov_count, TOK_TYPE_WRAP);
}
TOK_TYPE_DELETE_CONTEXT = 0x0405, /* RFC 2743 delete context */
TOK_TYPE_EAP_RESP = 0x0601, /* draft-howlett-eap-gss */
TOK_TYPE_EAP_REQ = 0x0602, /* draft-howlett-eap-gss */
- TOK_TYPE_GSS_CB = 0x0603, /* draft-howlett-eap-gss */
- TOK_TYPE_KRB_CRED = 0x0604, /* to be specified */
+ TOK_TYPE_EXT_REQ = 0x0603, /* draft-howlett-eap-gss */
+ TOK_TYPE_EXT_RESP = 0x0604, /* to be specified */
TOK_TYPE_GSS_REAUTH = 0x0605, /* to be specified */
};
--- /dev/null
+/*
+ * Copyright (c) 2010, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * 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 "gssapiP_eap.h"
+#include "authdata_plugin.h"
+
+/*
+ * This rubbish is necessary because MIT doesn't provide another way
+ * to access verified AD-KDCIssued elements. We can't verify them
+ * ourselves because they're signed in the ticket session key, which
+ * is destroyed immediately after the AP-REQ is processed.
+ */
+
+struct radius_ad_context {
+ krb5_data avpdata;
+ krb5_boolean verified;
+};
+
+static krb5_data radius_ad_attr = {
+ KV5M_DATA, sizeof("urn:authdata-radius-avp") - 1, "urn:authdata-radius-avp" };
+
+static krb5_error_code
+radius_ad_init(krb5_context kcontext, void **plugin_context)
+{
+ *plugin_context = 0;
+ return 0;
+}
+
+static void
+radius_ad_flags(krb5_context kcontext,
+ void *plugin_context,
+ krb5_authdatatype ad_type,
+ krb5_flags *flags)
+{
+ *flags = AD_USAGE_KDC_ISSUED | AD_INFORMATIONAL;
+}
+
+static void
+radius_ad_fini(krb5_context kcontext, void *plugin_context)
+{
+ return;
+}
+
+static krb5_error_code
+radius_ad_request_init(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void **request_context)
+{
+ struct radius_ad_context *ctx;
+
+ ctx = GSSEAP_CALLOC(1, sizeof(*ctx));
+ if (ctx == NULL)
+ return ENOMEM;
+
+ *request_context = ctx;
+
+ return 0;
+}
+
+static krb5_error_code
+radius_ad_export_authdata(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context,
+ krb5_flags usage,
+ krb5_authdata ***out_authdata)
+{
+ struct radius_ad_context *radius_ad = (struct radius_ad_context *)request_context;
+ krb5_authdata *data[2];
+ krb5_authdata datum;
+
+ datum.ad_type = KRB5_AUTHDATA_RADIUS_AVP;
+ datum.length = radius_ad->avpdata.length;
+ datum.contents = (krb5_octet *)radius_ad->avpdata.data;
+
+ data[0] = &datum;
+ data[1] = NULL;
+
+ return krb5_copy_authdata(kcontext, data, out_authdata);
+}
+
+static krb5_error_code
+radius_ad_import_authdata(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context,
+ krb5_authdata **authdata,
+ krb5_boolean kdc_issued_flag,
+ krb5_const_principal issuer)
+{
+ struct radius_ad_context *radius_ad = (struct radius_ad_context *)request_context;
+
+ krb5_free_data_contents(kcontext, &radius_ad->avpdata);
+ radius_ad->verified = FALSE;
+
+ assert(authdata[0] != NULL);
+
+ radius_ad->avpdata.data = GSSEAP_MALLOC(authdata[0]->length);
+ if (radius_ad->avpdata.data == NULL)
+ return ENOMEM;
+
+ memcpy(radius_ad->avpdata.data, authdata[0]->contents,
+ authdata[0]->length);
+ radius_ad->avpdata.length = authdata[0]->length;
+
+ radius_ad->verified = kdc_issued_flag;
+
+ return 0;
+}
+
+static void
+radius_ad_request_fini(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context)
+{
+ struct radius_ad_context *radius_ad = (struct radius_ad_context *)request_context;
+
+ if (radius_ad != NULL) {
+ krb5_free_data_contents(kcontext, &radius_ad->avpdata);
+ GSSEAP_FREE(radius_ad);
+ }
+}
+
+static krb5_error_code
+radius_ad_get_attribute(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context,
+ const krb5_data *attribute,
+ krb5_boolean *authenticated,
+ krb5_boolean *complete,
+ krb5_data *value,
+ krb5_data *display_value,
+ int *more)
+{
+ struct radius_ad_context *radius_ad = (struct radius_ad_context *)request_context;
+
+ if (attribute->length != radius_ad_attr.length ||
+ memcmp(attribute->data, radius_ad_attr.data,
+ radius_ad_attr.length) != 0)
+ return ENOENT;
+
+ *authenticated = radius_ad->verified;
+ *complete = TRUE;
+ *more = 0;
+
+ value->data = GSSEAP_MALLOC(radius_ad->avpdata.length);
+ if (value->data == NULL)
+ return ENOMEM;
+
+ memcpy(value->data, radius_ad->avpdata.data, radius_ad->avpdata.length);
+ value->length = radius_ad->avpdata.length;
+
+ return 0;
+}
+
+static krb5_error_code
+radius_ad_copy(krb5_context kcontext,
+ struct _krb5_authdata_context *context,
+ void *plugin_context,
+ void *request_context,
+ void *dst_plugin_context,
+ void *dst_request_context)
+{
+ struct radius_ad_context *radius_ad_src =
+ (struct radius_ad_context *)request_context;
+ struct radius_ad_context *radius_ad_dst =
+ (struct radius_ad_context *)dst_request_context;
+
+ radius_ad_dst->avpdata.data = GSSEAP_MALLOC(radius_ad_src->avpdata.length);
+ if (radius_ad_dst->avpdata.data == NULL)
+ return ENOMEM;
+
+ memcpy(radius_ad_dst->avpdata.data, radius_ad_src->avpdata.data,
+ radius_ad_src->avpdata.length);
+ radius_ad_dst->avpdata.length = radius_ad_src->avpdata.length;
+ radius_ad_dst->verified = radius_ad_src->verified;
+
+ return 0;
+}
+
+static krb5_authdatatype radius_ad_ad_types[] =
+ { KRB5_AUTHDATA_RADIUS_AVP, 0 };
+
+krb5plugin_authdata_client_ftable_v0 authdata_client_0 = {
+ "radius_ad",
+ radius_ad_ad_types,
+ radius_ad_init,
+ radius_ad_fini,
+ radius_ad_flags,
+ radius_ad_request_init,
+ radius_ad_request_fini,
+ NULL,
+ radius_ad_get_attribute,
+ NULL,
+ NULL,
+ radius_ad_export_authdata,
+ radius_ad_import_authdata,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ radius_ad_copy
+};
if (cred != GSS_C_NO_CREDENTIAL && cred->name != GSS_C_NO_NAME) {
code = krb5_kt_get_entry(krbContext, keytab,
- cred->name->krbPrincipal, 0,
+ cred->name->krbPrincipal, 0,
ctx->encryptionType, &ktent);
if (code != 0)
goto cleanup;
memset(key, 0, sizeof(key));
}
- return code;
+ return code;
}
OM_uint32
krb5_data *ticketData = NULL, *credsData = NULL;
krb5_creds creds = { 0 };
krb5_auth_context authContext = NULL;
-
+
credBuf->length = 0;
credBuf->value = NULL;
-
+
GSSEAP_KRB_INIT(&krbContext);
code = getAcceptorKey(krbContext, ctx, cred,
authDatum.contents = attrBuf.value;
authData[0] = &authDatum;
authData[1] = NULL;
- enc_part.authorization_data = authData;
+
+ code = krb5_make_authdata_kdc_issued(krbContext, &session,
+ ticket.server, authData,
+ &enc_part.authorization_data);
+ if (code != 0)
+ goto cleanup;
ticket.enc_part2 = &enc_part;
gss_release_buffer(minor, &attrBuf);
krb5_free_data(krbContext, ticketData);
krb5_auth_con_free(krbContext, authContext);
+ krb5_free_authdata(krbContext, enc_part.authorization_data);
if (credsData != NULL)
GSSEAP_FREE(credsData);
gss_OID_set *elements_stored,
gss_cred_usage_t *cred_usage_stored);
+static OM_uint32 (*gssGetNameAttributeNext)(
+ OM_uint32 *minor,
+ gss_name_t name,
+ gss_buffer_t attr,
+ int *authenticated,
+ int *complete,
+ gss_buffer_t value,
+ gss_buffer_t display_value,
+ int *more);
+
#define NEXT_SYMBOL(local, global) ((local) = dlsym(RTLD_NEXT, (global)))
OM_uint32
NEXT_SYMBOL(gssImportNameNext, "gss_import_name");
NEXT_SYMBOL(gssKrbExtractAuthzDataFromSecContextNext, "gsskrb5_extract_authz_data_from_sec_context");
NEXT_SYMBOL(gssStoreCredNext, "gss_store_cred");
+ NEXT_SYMBOL(gssGetNameAttributeNext, "gss_get_name_attribute");
return GSS_S_COMPLETE;
}
}
OM_uint32
+gssGetNameAttribute(OM_uint32 *minor,
+ gss_name_t name,
+ gss_buffer_t attr,
+ int *authenticated,
+ int *complete,
+ gss_buffer_t value,
+ gss_buffer_t display_value,
+ int *more)
+{
+ if (gssGetNameAttributeNext == NULL)
+ return GSS_S_UNAVAILABLE;
+
+ return gssGetNameAttributeNext(minor, name, attr, authenticated, complete,
+ value, display_value, more);
+}
+
+static gss_buffer_desc radiusAvpKrbAttr = {
+ sizeof("urn:authdata-radius-avp") - 1, "urn:authdata-radius-avp"
+};
+
+/*
+ * Unfortunately extracting an AD-KDCIssued authorization data element
+ * is pretty implementation-dependent. It's not possible to verify the
+ * signature ourselves because the ticket session key is not exposed
+ * outside GSS. In an ideal world, all AD-KDCIssued elements would be
+ * verified by the Kerberos library and authentication would fail if
+ * verification failed. We're not quite there yet and as a result have
+ * to go through some hoops to get this to work. The alternative would
+ * be to sign the authorization data with our long-term key, but it
+ * seems a pity to compromise the design because of current implementation
+ * limitations.
+ */
+OM_uint32
+defrostAttrContext(OM_uint32 *minor,
+ gss_name_t glueName,
+ gss_name_t mechName)
+{
+ OM_uint32 major, tmpMinor;
+ gss_buffer_desc authData = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc authDataDisplay = GSS_C_EMPTY_BUFFER;
+ int more = -1;
+ int authenticated, complete;
+
+ major = gssGetNameAttribute(minor, glueName, &radiusAvpKrbAttr,
+ &authenticated, &complete,
+ &authData, &authDataDisplay, &more);
+ if (major == GSS_S_COMPLETE) {
+ if (authenticated == 0)
+ major = GSS_S_BAD_NAME;
+ else
+ major = gssEapImportAttrContext(minor, &authData, mechName);
+ } else if (major == GSS_S_UNAVAILABLE) {
+ major = GSS_S_COMPLETE;
+ }
+
+ gss_release_buffer(&tmpMinor, &authData);
+ gss_release_buffer(&tmpMinor, &authDataDisplay);
+
+ return major;
+}
+
+OM_uint32
gssEapGlueToMechName(OM_uint32 *minor,
gss_name_t glueName,
gss_name_t *pMechName)
if (GSS_ERROR(major))
goto cleanup;
+ major = defrostAttrContext(minor, glueName, *pMechName);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
cleanup:
+ if (GSS_ERROR(major)) {
+ gssReleaseName(&tmpMinor, pMechName);
+ *pMechName = GSS_C_NO_NAME;
+ }
+
gss_release_buffer(&tmpMinor, &nameBuf);
return major;
return major;
}
+
gss_cred_usage_t *cred_usage_stored);
OM_uint32
+gssGetNameAttribute(OM_uint32 *minor,
+ gss_name_t name,
+ gss_buffer_t attr,
+ int *authenticated,
+ int *complete,
+ gss_buffer_t value,
+ gss_buffer_t display_value,
+ int *more);
+
+OM_uint32
gssEapMakeReauthCreds(OM_uint32 *minor,
gss_ctx_id_t ctx,
gss_cred_id_t cred,
int *conf_state,
gss_buffer_t output_message_buffer)
{
+ if (!CTX_IS_ESTABLISHED(ctx))
+ return GSS_S_NO_CONTEXT;
+
+ return gssEapWrap(minor, ctx, conf_req_flag, qop_req,
+ input_message_buffer,
+ conf_state, output_message_buffer);
+}
+
+OM_uint32
+gssEapWrap(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ int conf_req_flag,
+ gss_qop_t qop_req,
+ gss_buffer_t input_message_buffer,
+ int *conf_state,
+ gss_buffer_t output_message_buffer)
+{
OM_uint32 major, tmpMinor;
gss_iov_buffer_desc iov[4];
unsigned char *p;
int i;
- if (!CTX_IS_ESTABLISHED(ctx))
- return GSS_S_NO_CONTEXT;
iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
iov[0].buffer.value = NULL;
flags = rfc4121Flags(ctx, FALSE);
- switch (toktype) {
- case TOK_TYPE_WRAP:
+ if (toktype == TOK_TYPE_WRAP) {
keyUsage = CTX_IS_INITIATOR(ctx)
? KEY_USAGE_INITIATOR_SEAL
: KEY_USAGE_ACCEPTOR_SEAL;
- break;
- case TOK_TYPE_GSS_CB:
- keyUsage = KEY_USAGE_CHANNEL_BINDINGS;
- break;
- case TOK_TYPE_MIC:
- default:
+ } else {
keyUsage = CTX_IS_INITIATOR(ctx)
? KEY_USAGE_INITIATOR_SIGN
: KEY_USAGE_ACCEPTOR_SIGN;
- break;
}
gssEapIovMessageLength(iov, iov_count, &dataLen, &assocDataLen);
if (code != 0)
goto cleanup;
- if (toktype != TOK_TYPE_GSS_CB)
- ctx->sendSeq++;
+ ctx->sendSeq++;
if (toktype == TOK_TYPE_WRAP) {
/* Fix up EC field */
/* Fix up RRC field */
store_uint16_be(rrc, outbuf + 6);
}
- } else if (toktype == TOK_TYPE_MIC || toktype == TOK_TYPE_GSS_CB) {
+ } else if (toktype == TOK_TYPE_MIC) {
trailer = NULL;
goto wrap_with_checksum;
} else if (toktype == TOK_TYPE_DELETE_CONTEXT) {
if (qop_req != GSS_C_QOP_DEFAULT)
return GSS_S_FAILURE;
- if (!CTX_IS_ESTABLISHED(ctx))
- return GSS_S_NO_CONTEXT;
+ if (ctx->encryptionType == ENCTYPE_NULL)
+ return GSS_S_UNAVAILABLE;
GSSEAP_KRB_INIT(&krbContext);